我们在使用手机QQ时,点击菜单键,会d出如本案例说演示的效果图似的菜单选项。
实现方式有很多种,在这里我们来演示下如何通过自定义PopupWindow的方式一步一步的实现如上效果。
关于PopupWindow的基本知识点请查看 PopupWindow
分析UI部分shape的使用-corners solID等中间的使用VIEw分割背景的处理……功能点响应点击事件–通过接口回调的方式点击外部,PopupWindow可消失……实现自定义PopupWindowUI编写位于父布局的底部距边框有一定的距离,根布局使用layout_margin即可ListVIEw(四个圆角+白色背景) + VIEw分割(透明色) +底部文字(圆角+白色背景)
蓝色字体 居中显示(ListVIEw中的 在Item设置即可,底部文字设置gravity即可)
…….布局文件如下所示:
List_popupwindow.xml
<relativeLayout xmlns:androID="http://schemas.androID.com/apk/res/androID" androID:ID="@+ID/ID_rl_relativeLayout" androID:layout_wIDth="match_parent" androID:layout_height="match_parent" androID:layout_margin="16dp" androID:padding="16dp"> <ListVIEw androID:ID="@+ID/ID_lv_popupWindowListVIEw" androID:layout_wIDth="match_parent" androID:layout_height="wrap_content" androID:layout_above="@+ID/vIEw" androID:background="@drawable/bg_menu" /> <VIEw androID:ID="@+ID/vIEw" androID:layout_wIDth="match_parent" androID:layout_height="20dp" androID:layout_above="@+ID/ID_tv_bottom" androID:background="@color/transparent" /> <TextVIEw androID:ID="@+ID/ID_tv_bottom" androID:layout_wIDth="match_parent" androID:layout_height="50dp" androID:layout_alignParentBottom="true" androID:background="@drawable/bg_menu" androID:gravity="center" androID:text="取消" androID:textcolor="@color/skyblue" androID:textSize="20dp" />relativeLayout>
其中用到的几个背景xml如下,都在drawable目录下
bg_menu.xml
<shape xmlns:androID="http://schemas.androID.com/apk/res/androID" androID:shape="rectangle"> <stroke androID:color="@color/transparent" androID:wIDth="2dp"/> <solID androID:color="@color/bg_white" /> <corners androID:radius="10dp" />shape>自定义PopupWindow编写 +接口回调+监听Ontouch事件实现点击外部消失
加载自定义的xml文件,然后获取ListVIEw组件,设置adapter 即可显示UI布局。代码中的注释已经非常详细了,再此就不多涉及了。
import androID.content.Context;import androID.graphics.drawable.colorDrawable;import androID.vIEw.LayoutInflater;import androID.vIEw.MotionEvent;import androID.vIEw.VIEw;import androID.vIEw.VIEwGroup;import androID.Widget.AdapterVIEw;import androID.Widget.ListVIEw;import androID.Widget.PopupWindow;import androID.Widget.TextVIEw;import com.turing.base.R;import com.turing.nutritIoUsSerial.ListPopupWindow.adapter.CustomPopupWindowAdpater;import com.turing.nutritIoUsSerial.ListPopupWindow.beans.PopupItemBean;import java.util.List;/** * MyApp * * @author Mr.Yang on 2016-04-25 10:12. * @version 1.0 * @desc */public class ListPopupWindow extends PopupWindow { //上下文 private Context context; //父视图 private VIEw parentVIEw; //item数据源 private ListdataList; //适配器 private CustomPopupWindowAdpater adapter; //声明接口对象 private OnPopubItemClickListener popupItemListener; private OnBottomTextVIEwClickListener bottomTextVIEwListener; /** * 定义接口用于PopupItem回调点击事件处理 */ public interface OnPopubItemClickListener { voID onPopupItemClick(VIEw vIEw, int postion); } /** * 定义接口用于底部TextVIEw回调点击事件处理 */ public interface OnBottomTextVIEwClickListener { voID onBottomClick(); } /** * 构造函数 */ public ListPopupWindow(Context context, ListdataList, VIEw parentVIEw, OnPopubItemClickListener popupItemListener, OnBottomTextVIEwClickListener bottomTextVIEwListener) { this.context = context; this.dataList = dataList; this.parentVIEw = parentVIEw; this.popupItemListener = popupItemListener; this.bottomTextVIEwListener = bottomTextVIEwListener; initCustomPopupWindow(); } /** * 初始化自定义的PopupWindow */ private voID initCustomPopupWindow() { // 加载自定义布局文件,转化为组件 parentVIEw = LayoutInflater.from(context).inflate(R.layout.List_popupwindow, null); // 设置显示的vIEw setContentVIEw(parentVIEw); // 初始化控件 ListVIEw lv = (ListVIEw) parentVIEw.findVIEwByID(R.ID.ID_lv_popupWindowListVIEw); TextVIEw tv = (TextVIEw) parentVIEw.findVIEwByID(R.ID.ID_tv_bottom); // 设置d出窗体的高 this.setWIDth(VIEwGroup.LayoutParams.MATCH_PARENT); this.setHeight(VIEwGroup.LayoutParams.MATCH_PARENT); // 设置d出窗体可点击 this.setFocusable(true); // 设置SelectPicPopupWindowd出窗体的背景 this.setBackgroundDrawable(new colorDrawable(0xb0000000)); // vIEw添加OntouchListener监听判断获取触屏位置如果在布局外面则销毁d出框 parentVIEw.setontouchListener(new VIEw.OntouchListener() { @OverrIDe public boolean ontouch(VIEw v, MotionEvent event) { // gettop VIEw自身的顶边到其父布局顶边的距离,因为是根目录所以为0 int height = parentVIEw.findVIEwByID(R.ID.ID_rl_relativeLayout).gettop(); // getY 点击事件距离控件顶边的举例 int y = (int) event.getY(); // 当抬起 并且 y>height时(也就是 只要不点击ListVIEw范围内),dismiss popupWindow if (event.getAction() == MotionEvent.ACTION_UP) { if (y > height) { dismiss(); } } return true; } }); // 更新位置和大小(不加这行代码也行) update(); // 实例化适配器 adapter = new CustomPopupWindowAdpater(context, dataList); // 设置适配器 lv.setAdapter(adapter); // ListVIEw设置点击事件 lv.setonItemClickListener(new AdapterVIEw.OnItemClickListener() { @OverrIDe public voID onItemClick(AdapterVIEw parent, VIEw vIEw, int position, long ID) { // 回调onPopupItemClick popupItemListener.onPopupItemClick(vIEw, position); } }); // TextVIEw设置点击事件 tv.setonClickListener(new VIEw.OnClickListener() { @OverrIDe public voID onClick(VIEw v) { // 回调onBottomClick bottomTextVIEwListener.onBottomClick(); } }); }}
CustomPopupWindowAdpater.java
import androID.content.Context;import androID.vIEw.LayoutInflater;import androID.vIEw.VIEw;import androID.vIEw.VIEwGroup;import androID.Widget.BaseAdapter;import androID.Widget.TextVIEw;import com.turing.base.R;import com.turing.nutritIoUsSerial.ListPopupWindow.beans.PopupItemBean;import java.util.List;/** * MyApp * * @author Mr.Yang on 2016-04-25 11:04. * @version 1.0 * @desc */public class CustomPopupWindowAdpater extends BaseAdapter { private Context context; private Listdatas; private LayoutInflater layoutInflater; /** * 构造函数 */ public CustomPopupWindowAdpater(Context context, Listdatas) { this.context = context; this.datas = datas ; layoutInflater = LayoutInflater.from(context); } @OverrIDe public int getCount() { return datas.size(); } @OverrIDe public Object getItem(int position) { return datas.get(position); } @OverrIDe public long getItemID(int position) { return position; } @OverrIDe public VIEw getVIEw(int position, VIEw convertVIEw, VIEwGroup parent) { // 声明VIEwHolder VIEwHolder vIEwHolder; if (convertVIEw == null) { // 加载Item布局,转换为VIEw布局 convertVIEw = layoutInflater.inflate(R.layout.popup_item, parent, false); // 实例化VIEwHolder vIEwHolder = new VIEwHolder(); // 查找组件赋值给VIEwHolder vIEwHolder.textVIEw = (TextVIEw) convertVIEw.findVIEwByID(R.ID.ID_tv_popupItemText); // 设置TAG convertVIEw.setTag(vIEwHolder); } else { vIEwHolder = (VIEwHolder) convertVIEw.getTag(); } // 设置Item中的值 vIEwHolder.textVIEw.setText(datas.get(position).getText() ); return convertVIEw; } /** * 对应Item布局中的组件 */ class VIEwHolder { private TextVIEw textVIEw; }}调用
因为PopupWindow需要依赖父组件来显示,所以实例话PopupWindow的时候,传入根布局VIEw,实现接口回调Activity类实现自定义的两个接口,并传入到PopupWindow中。
import androID.os.Bundle;import androID.support.v7.app.AppCompatActivity;import androID.vIEw.Gravity;import androID.vIEw.VIEw;import androID.Widget.relativeLayout;import com.turing.base.R;import com.turing.base.utils.AlertUtil;import com.turing.nutritIoUsSerial.ListPopupWindow.beans.PopupItemBean;import com.turing.nutritIoUsSerial.ListPopupWindow.customPopupWindow.ListPopupWindow;import java.util.ArrayList;import java.util.List;public class ListPopupWindowDemoActivity extends AppCompatActivity implements ListPopupWindow.OnPopubItemClickListener, ListPopupWindow.OnBottomTextVIEwClickListener { // 定义父VIEw即PopupWindow依赖浮动的VIEw private relativeLayout relativeLayout; private ListPopupWindow popWindow; @OverrIDe protected voID onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentVIEw(R.layout.activity_List_popup_window_demo); // 父VIEw relativeLayout = (relativeLayout) findVIEwByID(R.ID.ID_rl_relativeLayout); } /** * 按钮监听事件 * * @param vIEw */ public voID showCustomListPopupWindow(VIEw vIEw) { // 展示数据集合 ListdataLists = new ArrayList<>(); // List集合中的数据 PopupItemBean itemBean1 = new PopupItemBean("版本更新"); PopupItemBean itemBean2 = new PopupItemBean("反馈"); PopupItemBean itemBean3 = new PopupItemBean("退出QQ"); // 添加到List集合中 dataLists.add(itemBean1); dataLists.add(itemBean2); dataLists.add(itemBean3); // 实例化自定义ListPopupWindow popWindow = new ListPopupWindow(ListPopupWindowDemoActivity.this, dataLists, relativeLayout, this, this); // 居中并且靠底部显示 popWindow.showAtLocation(relativeLayout, Gravity.CENTER | Gravity.BottOM, 0, 0); } @OverrIDe public voID onBottomClick() { popWindow.dismiss(); AlertUtil.showToastShort(ListPopupWindowDemoActivity.this, "点击取消"); } @OverrIDe public voID onPopupItemClick(VIEw vIEw, int postion) { switch (postion) { case 0: AlertUtil.showToastShort(ListPopupWindowDemoActivity.this, String.valueOf(postion) + " 被点击"); break; case 1: AlertUtil.showToastShort(ListPopupWindowDemoActivity.this, String.valueOf(postion) + " 被点击"); break; case 2: AlertUtil.showToastShort(ListPopupWindowDemoActivity.this, String.valueOf(postion) + " 被点击"); break; default: break; } }}总结
以上是内存溢出为你收集整理的干货一:通过自定义PopupWindow实现QQ菜单选项功能全部内容,希望文章能够帮你解决干货一:通过自定义PopupWindow实现QQ菜单选项功能所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)