PopupWindow 使用详解(二) Popwindow 制作常见花哨效果
帝都几日降温,终于被撂倒了。but 只要一息尚存就得不断进步!于是,写出 《PopupWindow 使用详解》的第二篇 笔记,先奉上 第一篇链接: 《PopupWindow 使用详解(一) 中文API 文档 赠送 ListPopupWindow 中文 API》 。下面给大家展示一下制作的效果gif。
下面进行一个样式一个样式的肢解哈,对了,所有效果笔者都没有制作载入动画和退出动画。有需要的小伙伴可以通过 这个方法 public void setAnimationStyle(int animationStyle)
进行设置,也是很简单、很常用的。
效果一、图片选取功能(带阴影)
1、布局设置
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/ll_pic"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@drawable/shape_pic_select"android:gravity="bottom"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginStart="5dp"android:layout_marginEnd="5dp"android:orientation="vertical"><Buttonandroid:id="@+id/btn_pic_photo"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginBottom="1dp"android:background="#ffffff"android:text="相 册"android:textColor="#3c3c3c"android:textSize="16sp" /><Buttonandroid:id="@+id/btn_pic_camera"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginBottom="1dp"android:background="#ffffff"android:text="拍 照"android:textColor="#3c3c3c"android:textSize="16sp" /><Buttonandroid:id="@+id/btn_pic_cancel"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginBottom="1dp"android:background="#ffffff"android:text="取 消"android:textColor="#3c3c3c"android:textSize="16sp" /></LinearLayout>
</LinearLayout>
2、Java 逻辑代码
/*** 照片选择器*/@SuppressLint("InflateParams")private void showPicSelect() {view = LayoutInflater.from(this).inflate(R.layout.item_pic_select, null, false);LinearLayout llPop = view.findViewById(R.id.ll_pic);Button btnCamera = view.findViewById(R.id.btn_pic_camera);Button btnPhoto = view.findViewById(R.id.btn_pic_photo);Button btnCancel = view.findViewById(R.id.btn_pic_cancel);btnCamera.setOnClickListener(this);btnPhoto.setOnClickListener(this);btnCancel.setOnClickListener(this);llPop.setOnClickListener(this);myPop = new PopupWindow(view, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);myPop.setBackgroundDrawable(new ColorDrawable());myPop.showAtLocation(rlMain, Gravity.BOTTOM, 0, 0);}@Overridepublic void onBackPressed() {if (myPop.isShowing()) {myPop.dismiss();} else {super.onBackPressed();}}
3、实现思路
之前笔者看了看网上百度来的答案,实现阴影效果的思路大概是,当 PopupWindow 弹出时将 Activity 设置为半透明,但是这种思路的弊端是 Activity 透明了,你懂得,你可以在 A Activity 界面直接看到了 桌面或者是 B Activity 界面的东西,很蛋疼。
笔者的思路是:为 PopupWindow 设置一个半透明的背景色,然后监听这不背景 layout 的点击事件,和物理键的返回事件。否则会出现点击无效果的现象。具体逻辑如上。
二、仿qq和微信的长按置顶删除功能
1、布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:id="@+id/ll_qq"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerHorizontal="true"android:background="@drawable/shape_qq"android:orientation="horizontal"tools:ignore="UselessParent"><TextViewandroid:id="@+id/tv_delete"android:layout_width="wrap_content"android:layout_height="wrap_content"android:padding="10dp"android:text="删除"android:textColor="#ffffff"android:textSize="16sp" /><Viewandroid:layout_width="2dp"android:layout_height="match_parent"android:layout_marginTop="5dp"android:layout_marginBottom="5dp"android:background="#666666" /><TextViewandroid:id="@+id/tv_be_top"android:layout_width="wrap_content"android:layout_height="wrap_content"android:padding="10dp"android:text="置顶"android:textColor="#ffffff"android:textSize="16sp" /></LinearLayout><ImageViewandroid:id="@+id/iv_three"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@+id/ll_qq"android:layout_centerHorizontal="true"android:background="@null"android:layout_marginTop="-5dp"android:contentDescription="@string/app_name"android:src="@mipmap/ic_three" />
</RelativeLayout>
2、Java 逻辑
/*** 仿qq 产生水滴按钮*/@SuppressLint("InflateParams")private void showQq() {view = LayoutInflater.from(this).inflate(R.layout.item_qq, null, false);TextView tvTop = view.findViewById(R.id.tv_be_top);TextView tvDelete = view.findViewById(R.id.tv_delete);tvDelete.setOnClickListener(this);tvTop.setOnClickListener(this);myPop = new PopupWindow(view, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);myPop.setBackgroundDrawable(new ColorDrawable());myPop.setOutsideTouchable(true);myPop.getContentView().measure(0, 0);myPop.showAsDropDown(cvMain, (cvMain.getWidth() - myPop.getContentView().getMeasuredWidth()) / 2,-(cvMain.getHeight() + myPop.getContentView().getMeasuredHeight()));}
3、实现思路
这个其实没什么好说的,但是需要注意的两点是:(1)、ui 一定要有的或者是自己会个ps 也行,仔细看笔者布局,有一个地方,设置 margin 属性居然用了 负值 否则无法保证 下面的shape 背景与三角标进行无缝衔接;(2)、注意这个方法一定要设置即便是不设置值 public void setBackgroundDrawable(Drawable background)
否则会导致 public void setOutsideTouchable(boolean touchable)
这个方法不起作用,即出现点击 PopupWindow 外部区域无法隐藏 PopupWindow 的尴尬局面
三、实现悬浮图片轮播
1、布局代码
<!--布局 1-->
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="#00000000"app:cardCornerRadius="10dp"><android.support.v4.view.ViewPagerandroid:id="@+id/vp_pop"android:layout_width="200dp"android:layout_height="300dp"android:background="#48BAFF" /></android.support.v7.widget.CardView><!--布局 2-->
<?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:gravity="center"android:orientation="vertical"><ImageViewandroid:layout_width="200dp"android:layout_height="300dp"android:contentDescription="@string/app_name"android:src="@mipmap/pic_1" />
</LinearLayout>
2、Java 逻辑代码
/*** 轮播效果*/@SuppressLint("InflateParams")private void showPager() {views = new ArrayList<>();view = LayoutInflater.from(this).inflate(R.layout.item_pager, null, false);ViewPager vpPop = view.findViewById(R.id.vp_pop);picView01 = LayoutInflater.from(this).inflate(R.layout.item_pop_vp_01, null, false);picView02 = LayoutInflater.from(this).inflate(R.layout.item_pop_vp_02, null, false);picView03 = LayoutInflater.from(this).inflate(R.layout.item_pop_vp_03, null, false);picView04 = LayoutInflater.from(this).inflate(R.layout.item_pop_vp_04, null, false);views.add(picView01);views.add(picView02);views.add(picView03);views.add(picView04);vpPop.setAdapter(new MyPopAdapter());myPop = new PopupWindow(view, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);myPop.setOutsideTouchable(true);//悬浮效果myPop.setElevation(5);myPop.setBackgroundDrawable(new ColorDrawable(0x00ffffff));myPop.showAtLocation(rlMain, Gravity.CENTER, 0, 0);}/*** 配置 adapter*/class MyPopAdapter extends PagerAdapter {@Overridepublic int getCount() {return views.size();}@Overridepublic boolean isViewFromObject(@NonNull View view, @NonNull Object o) {return view == o;}@NonNull@Overridepublic Object instantiateItem(@NonNull ViewGroup container, int position) {container.addView(views.get(position));return views.get(position);}@Overridepublic void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {container.removeView(views.get(position));}}@Overrideprotected void onDestroy() {super.onDestroy();if (views != null) {views.remove(picView01);views.remove(picView02);views.remove(picView03);views.remove(picView04);}if (myPop.isShowing()) {myPop.dismiss();}}
3、实现思路及注意事项
首先,加载图片需要进行相关处理,比如说用过Picasso 或者是 Glide 等框架,当然了也可将进行自己压缩;
其次,由于为了突出美观,笔者用了一个 CardView 可以设置圆角,但是 CardView 的阴影属性失效了,为了凸显层次感可以设置 PopupWindow 的这个方法 public void setElevation(float elevation)
该方法可以是你感觉出一种悬浮的效果;
最后,没用的 view 需要进行清理,否则会留在内存哦。
四、向下弹出水滴效果
1、布局源码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="wrap_content"android:layout_height="wrap_content"><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignBottom="@+id/iv_beauty"android:layout_toEndOf="@+id/iv_beauty"android:src="@mipmap/ic_right" /><ImageViewandroid:id="@+id/iv_beauty"android:layout_width="150dp"android:layout_height="200dp"android:background="#669"android:src="@mipmap/pic_5" />
</RelativeLayout>
2、Java 逻辑
/*** 向下弹出*/@SuppressLint("InflateParams")private void showDown() {view = LayoutInflater.from(this).inflate(R.layout.item_anywhere, null, false);myPop = new PopupWindow(view, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);myPop.setBackgroundDrawable(new ColorDrawable());myPop.setOutsideTouchable(true);myPop.getContentView().measure(0, 0);myPop.showAsDropDown(btnPopDown, -((myPop.getContentView().getMeasuredWidth() - btnPopDown.getWidth()) / 2), 0);}
3、注意事项
这个没什么可说的了,和 上面 小标题二 相同 ,具体查看上方即可。
五、实现屏幕右侧向左弹出
1、布局代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="wrap_content"android:layout_height="wrap_content"><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignBottom="@+id/iv_beauty"android:layout_toEndOf="@+id/iv_beauty"android:src="@mipmap/ic_right" /><ImageViewandroid:id="@+id/iv_beauty"android:layout_width="150dp"android:layout_height="200dp"android:background="#669"android:src="@mipmap/pic_5" />
</RelativeLayout>
2、Java 逻辑代码
/*** 向左弹出*/@SuppressLint("InflateParams")private void showStart() {view = LayoutInflater.from(this).inflate(R.layout.item_pop_start, null, false);myPop = new PopupWindow(view, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);myPop.setBackgroundDrawable(new ColorDrawable());myPop.setOutsideTouchable(true);myPop.getContentView().measure(0, 0);myPop.showAsDropDown(fabStart, -(myPop.getContentView().getMeasuredWidth()), -(fabStart.getHeight() / 2 + myPop.getContentView().getMeasuredHeight()));}
3、注意事项
这里比较复杂的 就是 PopupWindow 的锚点位置 为 其寄生的 控件的 左下角,而 Popwindow 的起始点为 左上角,但是 PopupWindow 默认不超出界面。这就导致了 PopupWindow 明明在 控件则左侧,但是却无法到达自己的想要位置。
所以 对于该现象,我们只能 在计算偏移量的时候 需要向左 移动 (控件长度+PopupWindow的长度 +其他长度)
六、实现需要获取焦点的控件使用
1、布局代码
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="#00000000"app:cardCornerRadius="10dp"><RelativeLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="#00000000"android:padding="10dp"><TextViewandroid:id="@+id/tv_name_p"android:layout_width="wrap_content"android:layout_height="40dp"android:gravity="center_vertical"android:text="账户:"android:textSize="16sp" /><EditTextandroid:layout_width="200dp"android:layout_height="40dp"android:layout_toEndOf="@+id/tv_name_p"android:background="@null"android:gravity="center_vertical"android:inputType="number"android:paddingStart="10dp"android:paddingEnd="10dp"android:singleLine="true"android:textSize="16sp"tools:text="123" /><TextViewandroid:id="@+id/tv_password_p"android:layout_width="wrap_content"android:layout_height="40dp"android:layout_below="@+id/tv_name_p"android:gravity="center_vertical"android:text="密码:"android:textSize="16sp" /><EditTextandroid:layout_width="200dp"android:layout_height="40dp"android:layout_below="@+id/tv_name_p"android:layout_toEndOf="@+id/tv_password_p"android:background="@null"android:gravity="center_vertical"android:inputType="numberPassword"android:paddingStart="10dp"android:paddingEnd="10dp"android:singleLine="true"android:textSize="16sp"tools:text="123" /></RelativeLayout>
</android.support.v7.widget.CardView>
2、逻辑代码
/*** 向右弹出 输入框*/@SuppressLint("InflateParams")private void showEnd() {view = LayoutInflater.from(this).inflate(R.layout.item_end_input, null, false);myPop = new PopupWindow(view, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);myPop.setBackgroundDrawable(new ColorDrawable(0x00ffffff));myPop.setElevation(10);myPop.setOutsideTouchable(true);myPop.setFocusable(true);myPop.getContentView().measure(0, 0);myPop.showAsDropDown(fadEnd, (int) (fadEnd.getWidth() * 1.3), -((fadEnd.getHeight() + myPop.getContentView().getMeasuredHeight()) / 2));}
3、注意事项
这里一定要 设置该方法 public void setFocusable(boolean focusable)
否则 在切换EditText 的时候只是光标进行了移动,但是 无法召唤软键盘。
七、总结
1、笔者认为,上面的大概可以满足比较简单的开发需求了,笔者很菜,这些已经足可以满足笔者了目前;
2、关于偏移量这个会涉及导到一些小小的计算和一点点逻辑想法,所以不要只是做 cv 战士,作为文雅的程序员,我们还是需要有点自己的想法的哈;
3、代码上传 github 地址为:PopupWindow
4、希望可以帮到你,批评和建议,望各位大佬留言,小生在这里谢过了。
PopupWindow 使用详解(二) Popwindow 制作常见花哨效果相关推荐
- PopUpWindow使用详解(二)——进阶及答疑
相关文章: 1.<PopUpWindow使用详解(一)--基本使用> 2.<PopUpWindow使用详解(二)--进阶及答疑> 上篇为大家基本讲述了有关PopupWindow ...
- PopWindow 制作常见的6种花哨效果
作者:吾乃韩小呆 链接: https://www.jianshu.com/p/8e7b339d7a78 帝都几日降温,终于被撂倒了.but 只要一息尚存就得不断进步!于是,写出 <PopupW ...
- from mysql partition select_爬虫(九十九)mysql详解二
**mysql中字段的常见类型: ** 二进制位 bit(长度) tinyint[(长度)] [有无符号unsigned] [位数低于长度时候是否填充零zerofill] 有符号表示范围-128 ~ ...
- 爬虫入门之urllib库详解(二)
爬虫入门之urllib库详解(二) 1 urllib模块 urllib模块是一个运用于URL的包 urllib.request用于访问和读取URLS urllib.error包括了所有urllib.r ...
- 汉堡按钮html写法,ProtoPie 详解 — 汉堡按钮制作
原标题:ProtoPie 详解 - 汉堡按钮制作 每周一期的 ProtoPie 详解教程又来啦,上期马克笔设计留学的MUzi老师主要介绍了 ProtoPie 的交互动作原理<ProtoPie详解 ...
- Android面试Hash原理详解二
Hash系列目录 Android面试Hash原理详解一 Android面试Hash原理详解二 Android面试Hash常见算法 Android面试Hash算法案例 Android面试Hash原理详解 ...
- MQTT协议详解 二、MQTT控制包格式
文章目录 系列文章目录 前言 一.MQTT控制包格式 二.固定包头 控制包类型 控制包类型标识 剩余长度 三.可变包头 数据包标识 四.载荷 系列文章目录 MQTT协议详解 一.MQTT简介 MQTT ...
- Unicode编码详解(二):编码预备知识
Unicode编码详解(二):编码预备知识 本文为原创文章,转载请注明出处,或注明转载自"黄邦勇帅(原名:黄勇) 本文是对<C++语法详解>一书相关章节的增补,以增强读者对字符的 ...
- PackageManagerService启动详解(二)之怎么通过packages.xml对已安装应用信息进行持久化管理?
PKMS启动详解(二)之怎么通过packages.xml对已安装应用信息进行持久化管理? Android PackageManagerService系列博客目录: PKMS启动详解系列博客概要 PKM ...
最新文章
- 【测试面试题】显示输入数字中的最大值
- 485 九针头_张元英安宥真还是孩子,手臂还有疫苗接种痕迹,九针头太吓人
- viewpager的使用
- 黑马程序员_面向对象的三大特征
- python垃圾回收机制与很多_你了解Python的 垃圾回收 机制吗?
- ecmobile php开发文档,ecmobile PHP接口说明文档之购物车(cart/create|list|detele|update)
- 云服务器内存占用多少,腾讯云云服务器CPU或内存占用过高怎么办?
- socks5 python_用Python写socks5服务器端
- 方法重载时,需要遵循以下三条原则
- deepin 系统 微信登录提示版本过低解决方法
- Android中使用自定义的view实现圆形图片的效果
- android自动登录简书,android 手机号实现登录功能
- java 连接不上数据库
- ZDNS联合发起创建的“粤港大数据图像和通信应用联合实验室”成功获批
- 损失函数,mse,cee
- 2022研究生学术与职业素养讲座(MOOC)期末答案
- 全球十大半导体企业,美国独占七席
- 如何将xls批量转换成xlsx
- DjangoMTV学习1
- 影响力:社会认同原理
热门文章
- macos安装低版本php,mac下安装多个版本PHP及切换
- php的符号的排序大小
- 1.java的基础和数据类型
- jsoncpp-src-0.5.0.tar.gz 源码错误!!!!
- LinCode落单的数
- windows下安装zabbix_agent
- CVE-2009-3459
- Warning: Attempt to present on whose view is not in模态跳转问题
- 使用javasript 遍历页面CheckBox
- 【vue报错】——listen EADDRINUSE :::8080 解决方案