Android开发仿QQ空间根据位置弹出PopupWindow显示更多操作效果
程序员文章站
2024-02-26 14:05:04
我们打开qq空间的时候有个箭头按钮点击之后弹出popupwindow会根据位置的变化显示在箭头的上方还是下方,比普通的popupwindow弹在屏幕中间显示好看的多。
先...
我们打开qq空间的时候有个箭头按钮点击之后弹出popupwindow会根据位置的变化显示在箭头的上方还是下方,比普通的popupwindow弹在屏幕中间显示好看的多。
先看qq空间效果图:
这个要实现这个效果可以分几步进行
1.第一步自定义popupwindow,实现如图的样式,这个继承popupwindow自定义布局很容易实现
2.得到点击按钮的位置,根据位置是否在屏幕的中间的上方还是下方,将popupwindow显示在控件的上方或者下方
3.适配问题,因为popupwindow上面的操作列表是动态的所以要自定义listview
4.动画效果+背景变暗
通过步骤分析,我们就很清晰的了解我们要做什么,话不多说,从第一步开始吧
下面自定义popupwindow实现效果
1.重写listview,重新计算高度(一般也应用于解决scrollview嵌套listview只显示一行的问题)
public class mylistview extends listview { public mylistview(context context, attributeset attrs) { super(context, attrs); } public mylistview(context context) { super(context); } public mylistview(context context, attributeset attrs, int defstyle) { super(context, attrs, defstyle); } @override public void onmeasure(int widthmeasurespec, int heightmeasurespec) { super.onmeasure(widthmeasurespec, measurespec.makemeasurespec(integer.max_value >> 2, measurespec.at_most)); } }
2.自定义popupwindow的布局文件
<?xml version="1.0" encoding="utf-8"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="right"> <imageview android:id="@+id/arrow_up" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginright="28dp" android:src="@drawable/arrow_up_white" android:visibility="visible"/> <com.widget.mylistview android:id="@+id/lv_list" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="@dimen/normal_margin8" android:layout_margintop="-1dp" android:layout_marginbottom="-1dp" android:dividerheight="0dp" android:layout_marginleft="@dimen/normal_margin8" android:layout_marginright="@dimen/normal_margin8" android:scrollbars="none" android:background="@drawable/custom_white" android:divider="@null"></com.widget.mylistview> <imageview android:id="@+id/arrow_down" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginright="28dp" android:src="@drawable/arrow_down_white" android:visibility="visible"/> </linearlayout>
2.popupwindow弹出动画以及消失动画
popshow_operation_anim_down.xml
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <scale android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:fromxscale="0.0" android:toxscale="1.0" android:fromyscale="0.0" android:toyscale="1.0" android:pivotx="90%" android:pivoty="0%" android:fillafter="false" android:duration="300" > </scale> </set>
popshow_operation_anim_up.xml
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <scale android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:fromxscale="0.0" android:toxscale="1.0" android:fromyscale="0.0" android:toyscale="1.0" android:pivotx="90%" android:pivoty="100%" android:fillafter="false" android:duration="250" > </scale> </set>
消失动画是渐隐动画可以自己定义,同理。
3.重写popupwindow了
public class customoperationpopwindow extends popupwindow { private context context; private view conentview; private view backgroundview; private animation anim_backgroundview; private mylistview listview; private typeselectpopuadapter selectadapter; imageview arrow_up, arrow_down; list<typeselect> typeselectlist = new arraylist<>(); int[] location = new int[2]; private onitemlistener onitemlistener; private adapterview.onitemclicklistener onitemclicklistener; public interface onitemlistener { public void onitemlistener(int position, typeselect typeselect); } ; public void setonitemmylistener(onitemlistener onitemlistener) { this.onitemlistener = onitemlistener; } public customoperationpopwindow(context context) { this.context = context; initview(); } public customoperationpopwindow(context context, list<typeselect> typeselectlist) { this.context = context; this.typeselectlist = typeselectlist; initview(); } private void initview() { this.anim_backgroundview = animationutils.loadanimation(context, r.anim.alpha_show_anim); layoutinflater inflater = (layoutinflater) context .getsystemservice(context.layout_inflater_service); this.conentview = inflater.inflate(r.layout.view_operation_popupwindow, null); // 设置selectpicpopupwindow的view this.setcontentview(conentview); // 设置selectpicpopupwindow弹出窗体的宽 this.setwidth(layoutparams.match_parent); // 设置selectpicpopupwindow弹出窗体的高 this.setheight(layoutparams.wrap_content); // 设置selectpicpopupwindow弹出窗体可点击 this.setfocusable(true); this.setoutsidetouchable(true); // 刷新状态 this.update(); // 实例化一个colordrawable颜色为半透明 colordrawable dw = new colordrawable(0000000000); // 点back键和其他地方使其消失,设置了这个才能触发ondismisslistener ,设置其他控件变化等操作 this.setbackgrounddrawable(dw); // 设置selectpicpopupwindow弹出窗体动画效果 this.setanimationstyle(r.style.operation_popwindow_anim_style_up); this.listview = (mylistview) conentview.findviewbyid(r.id.lv_list); this.arrow_up = (imageview) conentview.findviewbyid(r.id.arrow_up); this.arrow_down = (imageview) conentview.findviewbyid(r.id.arrow_down); //设置适配器 this.selectadapter = new typeselectpopuadapter(context, typeselectlist, r.layout.item_operation_popu); this.listview.setadapter(selectadapter); this.listview.setonitemclicklistener(new adapterview.onitemclicklistener() { @override public void onitemclick(adapterview<?> parent, view view, int position, long id) { if (isshowing()) { dismiss(); } onitemlistener.onitemlistener(position, typeselectlist.get(position)); } }); this.setondismisslistener(new ondismisslistener() { @override public void ondismiss() { if (backgroundview != null) { backgroundview.setvisibility(view.gone); } } }); } //设置数据 public void setdatasource(list<typeselect> typeselectlist) { this.typeselectlist = typeselectlist; this.selectadapter.notifydatasetchanged(); } /** * 没有半透明背景 显示popupwindow * * @param */ public void showpopupwindow(view v) { v.getlocationonscreen(location); //获取控件的位置坐标 //获取自身的长宽高 conentview.measure(view.measurespec.unspecified, view.measurespec.unspecified); if (location[1] > mainapplication.screen_h / 2 + 100) { //mainapplication.screen_h 为屏幕的高度,方法可以自己写 this.setanimationstyle(r.style.operation_popwindow_anim_style_up); arrow_up.setvisibility(view.gone); arrow_down.setvisibility(view.visible); this.showatlocation(v, gravity.no_gravity, (location[0]), location[1] - conentview.getmeasuredheight()); } else { this.setanimationstyle(r.style.operation_popwindow_anim_style_down); arrow_up.setvisibility(view.visible); arrow_down.setvisibility(view.gone); this.showasdropdown(v, 0, 0); } } /** * 携带半透明背景 显示popupwindow * * @param */ public void showpopupwindow(view v, view backgroundview) { this.backgroundview = backgroundview; v.getlocationonscreen(location); //获取控件的位置坐标 //获取自身的长宽高 conentview.measure(view.measurespec.unspecified, view.measurespec.unspecified); backgroundview.setvisibility(view.visible); //对view执行动画 backgroundview.startanimation(anim_backgroundview); if (location[1] > mainapplication.screen_h / 2 + 100) { //若是控件的y轴位置大于屏幕高度的一半,向上弹出 this.setanimationstyle(r.style.operation_popwindow_anim_style_up); arrow_up.setvisibility(view.gone); arrow_down.setvisibility(view.visible); this.showatlocation(v, gravity.no_gravity, (location[0]), location[1] - conentview.getmeasuredheight()); //显示指定控件的上方 } else { this.setanimationstyle(r.style.operation_popwindow_anim_style_down); //反之向下弹出 arrow_up.setvisibility(view.visible); arrow_down.setvisibility(view.gone); this.showasdropdown(v, 0, 0); //显示指定控件的下方 } } /** * 显示popupwindow 根据特殊要求高度显示位置 * * @param */ public void showpopupwindow(view v, view backgroundview,int hight) { this.backgroundview = backgroundview; v.getlocationonscreen(location); //获取自身的长宽高 conentview.measure(view.measurespec.unspecified, view.measurespec.unspecified); backgroundview.setvisibility(view.visible); //对view执行动画 backgroundview.startanimation(anim_backgroundview); if (location[1] > mainapplication.screen_h / 2 + 100) { this.setanimationstyle(r.style.operation_popwindow_anim_style_up); arrow_up.setvisibility(view.gone); arrow_down.setvisibility(view.visible); this.showatlocation(v, gravity.no_gravity, (location[0]), location[1] - conentview.getmeasuredheight()-hight); } else { this.setanimationstyle(r.style.operation_popwindow_anim_style_down); arrow_up.setvisibility(view.visible); arrow_down.setvisibility(view.gone); this.showasdropdown(v, 0, 0); } } }
4.代码中的用法
1.
customoperationpopwindow customoperationpopwindow = new customoperationpopwindow(this, operationtypeselectlist); customoperationpopwindow.setonitemmylistener(new customoperationpopwindow.onitemlistener() { @override public void onitemlistener(int position, typeselect typeselect) { //此处实现列表点击所要进行的操作 } });
2.
textview.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { customoperationpopwindow.showpopupwindow(textview);//可以传个半透明view v_background过去根据业务需要显示隐藏 } });
5.最终实际效果
以上代码为几乎主要全部代码,主要是popupwindow的用法,思路清晰一步一步实现很简单。
以上所述是小编给大家介绍的android开发仿qq空间根据位置弹出popupwindow显示更多操作效果,希望对大家有所帮助
上一篇: 详解Java中wait和sleep的区别