|
前言: 今天要给大家展示安卓弹出菜单的效果,当然并非原创,仿写别人的,写得不好的地方,请见谅~ 概述:- 环境:Android Studio 3.42
- 语言:Java
- 特点:简单,易懂,效果爆炸
展示:
one.gif 简要说明:这里重写了
,实现了popupWindow里图片
的点击效果,而这个demo里的难点就在这两个地方 进入代码部分 private final int CONST_R = 100;//圆半径
private final int CONST_ICON_SIZE = 35;//dpValue值
private int itempadding = 0;
private Context context;
private FrameLayout frameLayout;
//自定义圆形背景
private View circle;
//保存控件对象
private List<View> itemViews = new ArrayList<>();
//圆心显示的图行控件
private ImageView imageView;
private OnPathItemClickListener mOnPathItemClickListener;//记录监听对象
//设置监听对象的方法
public void setOnPathItemClickListener(OnPathItemClickListener onPathItemClickListener){
this.mOnPathItemClickListener = onPathItemClickListener;
}
//默认构造方法
protected PathPopupWindow(){}
//覆盖默认的构造方法
public PathPopupWindow(Context context, List<PathItem> items){
//实现构造方法的传递 执行下面的构造方法
this(context,items, Color.BLACK,12,Color.TRANSPARENT);
}
//具体执行的构造方法
public PathPopupWindow(Context context, List<PathItem> items, int textColor, int textSize, int itembgResId) {
super(context);
this.context = context;
//设置获取焦点
setFocusable(true);
//计算item之间的间距 使得效果显示一致
itempadding = DensityUtil.dip2px(context, 8);
//计算控件的宽度
int itemWidth = DensityUtil.dip2px(context,CONST_ICON_SIZE + textSize + 4) + itempadding * 2;
//计算宽高
int width = DensityUtil.dip2px(context, CONST_R * 2 + 30) + itemWidth;
int height = DensityUtil.dip2px(context, CONST_R * 2 + 30 + textSize) + itemWidth;
//设置宽高
setWidth(width);
setHeight(height);
setBackgroundDrawable(new ColorDrawable());
frameLayout = new FrameLayout(context);
circle = new View(context);
circle.setBackgroundResource(R.drawable.bg_circle);
//计算半径
int Radius = DensityUtil.dip2px(context,CONST_R);
//计算circle与frameLayout之间的间距
int padding = (width - Radius * 2)/2;
//设置布局参数 大小为半径的2倍
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(Radius*2,Radius*2);
params.leftMargin = params.topMargin = (width - Radius * 2) / 2;
//将圆添加到frameLayout里
frameLayout.addView(circle,params);
for (int i = 0;i<items.size();i++){
//创建线性布局对象 里面包含了所需要的图片控件
LinearLayout linearLayout =createItem(i,items.get(i),textColor,textSize,itembgResId);
int x = (int) (Math.cos(2 * Math.PI / items.size()*i + Math.PI/2)*Radius);
int y = (int) (Math.sin(2 * Math.PI / items.size() * i + Math.PI / 2) * Radius);
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(itemWidth,itemWidth);
lp.leftMargin = Radius + x + padding - itemWidth / 2;
lp.topMargin = Radius - y + padding - itemWidth /2;
//将线性布局对象添加到frameLayout里
frameLayout.addView(linearLayout,lp);
//保存线性布局对象
itemViews.add(linearLayout);
}
//设置圆心显示的控件图片 这里是天猫
imageView = new ImageView(context);
imageView.setImageResource(R.drawable.tianmao);
FrameLayout.LayoutParams iv_lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
iv_lp.gravity = Gravity.CENTER;
iv_lp.topMargin = -DensityUtil.dip2px(context,textSize) / 2;
frameLayout.addView(imageView,iv_lp);
setContentView(frameLayout);
frameLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//自定义方法设置动画效果隐藏控件图片
dismiss();
}
});
} |
public void show(View view){
showAtLocation(view, Gravity.CENTER, 0, 0);
//这是一个代码块 执行完以后才能执行下一个
{
// 旋转动画 对应圆心处天猫的动画演示效果
RotateAnimation rotate = new RotateAnimation(360, 0,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
//设置动画时间
rotate.setDuration(500);
//设置动画结束保持结束时的画面
rotate.setFillAfter(true);
//开启动画
imageView.startAnimation(rotate);
}
{
//放大动画 对应圆一开始逐渐变大的演示效果
ScaleAnimation scaleAnimation = new ScaleAnimation(0.3f, 1f, 0.3f, 1f, Animation.RELATIVE_TO_SELF,0.5f,
Animation.RELATIVE_TO_SELF,0.5f);
scaleAnimation.setDuration(300);
scaleAnimation.setFillAfter(true);
circle.startAnimation(scaleAnimation);
}
int Radius = DensityUtil.dip2px(context, CONST_R);
//平移动画 对应圆形边缘的控件图片演示效果
for(int i = 0;i<itemViews.size();i++){
int x = (int) (Math.cos(2 * Math.PI / itemViews.size() * i + Math.PI / 2) * Radius);
int y = (int) (Math.sin(2 * Math.PI / itemViews.size() * i + Math.PI / 2) * Radius);
TranslateAnimation translateAnimation = new TranslateAnimation(-x, 0F, y, 0F);
translateAnimation.setDuration(500);
translateAnimation.setFillAfter(true);
translateAnimation.setInterpolator(new OvershootInterpolator(2F));
itemViews.get(i).startAnimation(translateAnimation);
}
} |
//默认未隐藏
private boolean isdimissing = false;
@Override
public void dismiss() {
//如果点击天猫成功隐藏图片 自动返回 结束
if(isdimissing || !isShowing()){
return;
}
isdimissing = true;
{
RotateAnimation rotate = new RotateAnimation(0, 360,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotate.setDuration(500);
rotate.setFillAfter(false);
imageView.startAnimation(rotate);
}
{
ScaleAnimation scaleAnimation = new ScaleAnimation(1f, 0.3f, 1f, 0.3f, Animation.RELATIVE_TO_SELF,0.5f,
Animation.RELATIVE_TO_SELF,0.5f);
scaleAnimation.setDuration(500);
scaleAnimation.setFillAfter(false);
circle.startAnimation(scaleAnimation);
}
int Radius = DensityUtil.dip2px(context, CONST_R);
for(int i = 0;i<itemViews.size();i++){
int x = (int) (Math.cos(2 * Math.PI / itemViews.size() * i + Math.PI / 2) * Radius);
int y = (int) (Math.sin(2 * Math.PI / itemViews.size() * i + Math.PI / 2) * Radius);
TranslateAnimation translateAnimation = new TranslateAnimation(0F, -x, 0F, y);
translateAnimation.setDuration(300);
translateAnimation.setFillAfter(false);
if(i == itemViews.size() - 1){
translateAnimation.setAnimationListener(new Animation.AnimationListener() {
public void onAnimationStart(Animation animation) {
}
public void onAnimationRepeat(Animation animation) {
}
public void onAnimationEnd(Animation animation) {
//隐藏popupWindow
PathPopupWindow.super.dismiss();
isdimissing = false;
}
});
}
itemViews.get(i).startAnimation(translateAnimation);
}
} |
- pathItem类
这个类定义了三个属性 以及 三个构造方法
public class PathItem {
//控件名字
public String name;
//控件图片资源RedId
public int imageResId;
//控件背景资源
public int backgroundResId;
//构造方法
public PathItem name(String name){
this.name = name;
return this;
}
public PathItem imageResId(int imageResId){
this.imageResId = imageResId;
return this;
}
public PathItem backgroundResId(int backgroundResId){
this.backgroundResId = backgroundResId;
return this;
}
} |
这个类定义了许多静态方法 当然不是所有的方法都会用到
public class DensityUtil {
//默认构造方法
public DensityUtil(){}
/*获取屏幕像素点scale来保证控件在不同设备里的相对位置一致,方法的具体使用
int itempadding = DensityUtil.dip2px(context, 8);*/
public static int dip2px(Context context,float dpValue){
float scale = context.getResources().getDisplayMetrics().density;
return (int)(dpValue*scale + 0.5f);
}
public static int px2dip(Context context, float pxValue) {
float scale = context.getResources().getDisplayMetrics().density;
return (int)(pxValue / scale + 0.5F);
}
public static float dip2pxf(Context context, int dpValue) {
float scale = context.getResources().getDisplayMetrics().density;
return (float)dpValue * scale + 0.5F;
}
public static float dip2pxf(Context context, float dpValue) {
float scale = context.getResources().getDisplayMetrics().density;
return dpValue * scale + 0.5F;
} |
最后回到
实现popupWindow的显示- MainActivity类
首先给
布局文件默认的控件TextView设置id号
<TextView
android:id="@+id/tv_hello"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" /> |
然后回到MainActivity里通过设置的id号找到对应的TextView并设置点击事件,实现popupWindow的显示,以及对应控件图片的点击效果,当然也包括pathItemList的初始化
public class MainActivity extends AppCompatActivity {
private TextView tv_hello;
private List<PathItem> pathItemList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv_hello = findViewById(R.id.tv_hello);
pathItemList = new ArrayList<>();
pathItemList.add(new PathItem().name("苏宁易购").imageResId(R.drawable.ic_snyg).backgroundResId(R.drawable.bg_blue_oval));
pathItemList.add(new PathItem().name("天猫超市").imageResId(R.drawable.ic_tmcs).backgroundResId(R.drawable.bg_blue_oval));
pathItemList.add(new PathItem().name("天猫国际").imageResId(R.drawable.ic_tmgj).backgroundResId(R.drawable.bg_blue_oval));
pathItemList.add(new PathItem().name("聚划算").imageResId(R.drawable.ic_jhs).backgroundResId(R.drawable.bg_blue_oval));
tv_hello.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
PathPopupWindow popupWindow = new PathPopupWindow(MainActivity.this,pathItemList);
popupWindow.setOnPathItemClickListener(new PathPopupWindow.OnPathItemClickListener() {
@Override
public void onItemClick(int position, PathItem item) {
Toast.makeText(MainActivity.this,"点击了--->"+item.name,Toast.LENGTH_LONG).show();
}
});
popupWindow.show(view);
}
});
}
} |
总结:这个项目让我了解了popupWindow的使用,感觉自己在小白的基础上又进了一步,感谢原文博主的分享,也感谢大家的阅读
博文地址:https://blog.csdn.net/xu_coding/article/details/81515421
----------------------------
原文链接:https://www.jianshu.com/p/ad7893672123
[这个贴子最后由 flybird 在 2020-01-01 23:28:25 重新编辑]
|
|