47.Android 自己定义PopupWindow技巧
47.Android 自己定义PopupWindow技巧
前言
事实上PopupWindow自己定义过程是非常easy的,唯一头疼的是:PopupWindow显示的定位问题。
定位问题尤为恶心一点:有时候要涉及到PopupWindow的宽高问题。我们都知道,在没show之前是拿不到宽高的,show的时候定位须要宽高。如此矛盾。
下面,都给予回答。
其次的问题也有:PopupWindow的显示、消失动画设计问题。
下面也在我自己定义的PopupWindow中提供了三个简单的定位方法:
显示在控件的下左位置
显示在控件的下中位置
显示在控件的下右位置
PopupWindow的宽高
我们能够在PopupWindow初始化的时候。强制绘制Layout,而拿到PopupWindow的宽高。
// 用于保存PopupWindow的宽度
private int width;
// 用于保存PopupWindow的高度
private int height;
public CustomPopupWindow(Activity activity) {
super(activity);
this.activity = activity;
this.initPopupWindow();
}
private void initPopupWindow() {
LayoutInflater inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.contentView = inflater.inflate(R.layout.popupwindow_custom, null);
this.setContentView(contentView);
// 设置弹出窗口的宽
this.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
// 设置弹出窗口的高
this.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
// 设置弹出窗口可点击
this.setTouchable(true);
this.setFocusable(true);
// 设置点击是否消失
this.setOutsideTouchable(true);
//设置弹出窗口动画效果
this.setAnimationStyle(R.style.PopupAnimation);
//实例化一个ColorDrawable颜色为半透明
ColorDrawable background = new ColorDrawable(0x4f000000);
//设置弹出窗口的背景
this.setBackgroundDrawable(background);
// 绘制
this.mandatoryDraw();
}
/**
* 强制绘制popupWindowView,而且初始化popupWindowView的尺寸
*/
private void mandatoryDraw() {
this.contentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
/**
* 强制刷新后拿到PopupWindow的宽高
*/
this.width = this.contentView.getMeasuredWidth();
this.height = this.contentView.getMeasuredHeight();
}
PopupWindow定位在下左位置
/**
* 显示在控件的下左方
*
* @param parent parent
*/
public void showAtDropDownLeft(View parent) {
if (parent.getVisibility() == View.GONE) {
this.showAtLocation(parent, 0, 0, 0);
} else {
// x y
int[] location = new int[2];
//获取在整个屏幕内的绝对坐标
parent.getLocationOnScreen(location);
this.showAtLocation(parent, 0, location[0], location[1] + parent.getHeight());
}
}
PopupWindow定位在下中位置
/**
* 显示在控件的下中方
*
* @param parent parent
*/
public void showAtDropDownCenter(View parent) {
if (parent.getVisibility() == View.GONE) {
this.showAtLocation(parent, 0, 0, 0);
} else {
// x y
int[] location = new int[2];
//获取在整个屏幕内的绝对坐标
parent.getLocationOnScreen(location);
this.showAtLocation(parent, 0, location[0] / 2 + parent.getWidth() / 2 - this.width / 6, location[1] + parent.getHeight());
}
}
PopupWindow定位在下右位置
/**
* 显示在控件的下右方
*
* @param parent parent
*/
public void showAtDropDownRight(View parent) {
if (parent.getVisibility() == View.GONE) {
this.showAtLocation(parent, 0, 0, 0);
} else {
// x y
int[] location = new int[2];
//获取在整个屏幕内的绝对坐标
parent.getLocationOnScreen(location);
this.showAtLocation(parent, 0, location[0] + parent.getWidth() - this.width, location[1] + parent.getHeight());
}
}
PopupWindow动画
设计一个从PopWindow開始的时候右上角逐步展示,然后结束的时候往右上角逐步收起的动画:
styles.xml
<style name="PopupAnimation" parent="android:Animation" mce_bogus="1">
<item name="android:windowEnterAnimation">@anim/popwindow_in</item>
<item name="android:windowExitAnimation">@anim/popwindow_out</item>
</style>
popwindow_in.xml
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/decelerate_interpolator">
<!--
时间 0.2秒
開始的时候 x y 全是0 没有大小
结束的时候 x y 全是1 实际大小
pivotX 100% 表示最右边
pivotY 0% 表示最顶边
以上定位右上角 缩放时不变位置
-->
<scale
android:duration="200"
android:fromXScale="0.0"
android:fromYScale="0.0"
android:pivotX="100%"
android:pivotY="0%"
android:toXScale="1.0"
android:toYScale="1.0" />
<!--
时间 0.2秒
開始全透明
结束一点都不透明
-->
<alpha
android:duration="200"
android:fromAlpha="0.0"
android:toAlpha="1.0" />
</set>
popwindow_out.xml
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/decelerate_interpolator">
<!--
时间 0.2秒
開始的时候 x y 全是1 实际大小
结束的时候 x y 全是0 没有大小
pivotX 100% 表示最右边
pivotY 0% 表示最顶边
以上定位右上角 缩放时不变位置
-->
<scale
android:duration="200"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:pivotX="100%"
android:pivotY="0%"
android:toXScale="0.0"
android:toYScale="0.0" />
<!--
时间 0.2秒
開始一点都不透明
结束全透明
-->
<alpha
android:duration="200"
android:fromAlpha="1.0"
android:toAlpha="0.0" />
</set>
自己定义PopupWindow
public class CustomPopupWindow extends android.widget.PopupWindow {
private Activity activity;
private View contentView;
// 用于保存PopupWindow的宽度
private int width;
// 用于保存PopupWindow的高度
private int height;
public CustomPopupWindow(Activity activity) {
super(activity);
this.activity = activity;
this.initPopupWindow();
}
private void initPopupWindow() {
LayoutInflater inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.contentView = inflater.inflate(R.layout.popupwindow_custom, null);
this.setContentView(contentView);
// 设置弹出窗口的宽
this.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
// 设置弹出窗口的高
this.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
// 设置弹出窗口可点击
this.setTouchable(true);
this.setFocusable(true);
// 设置点击是否消失
this.setOutsideTouchable(true);
//设置弹出窗口动画效果
this.setAnimationStyle(R.style.PopupAnimation);
//实例化一个ColorDrawable颜色为半透明
ColorDrawable background = new ColorDrawable(0x4f000000);
//设置弹出窗口的背景
this.setBackgroundDrawable(background);
// 绘制
this.mandatoryDraw();
}
/**
* 强制绘制popupWindowView。而且初始化popupWindowView的尺寸
*/
private void mandatoryDraw() {
this.contentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
/**
* 强制刷新后拿到PopupWindow的宽高
*/
this.width = this.contentView.getMeasuredWidth();
this.height = this.contentView.getMeasuredHeight();
}
/**
* 显示在控件的下右方
*
* @param parent parent
*/
public void showAtDropDownRight(View parent) {
if (parent.getVisibility() == View.GONE) {
this.showAtLocation(parent, 0, 0, 0);
} else {
// x y
int[] location = new int[2];
//获取在整个屏幕内的绝对坐标
parent.getLocationOnScreen(location);
this.showAtLocation(parent, 0, location[0] + parent.getWidth() - this.width, location[1] + parent.getHeight());
}
}
/**
* 显示在控件的下左方
*
* @param parent parent
*/
public void showAtDropDownLeft(View parent) {
if (parent.getVisibility() == View.GONE) {
this.showAtLocation(parent, 0, 0, 0);
} else {
// x y
int[] location = new int[2];
//获取在整个屏幕内的绝对坐标
parent.getLocationOnScreen(location);
this.showAtLocation(parent, 0, location[0], location[1] + parent.getHeight());
}
}
/**
* 显示在控件的下中方
*
* @param parent parent
*/
public void showAtDropDownCenter(View parent) {
if (parent.getVisibility() == View.GONE) {
this.showAtLocation(parent, 0, 0, 0);
} else {
// x y
int[] location = new int[2];
//获取在整个屏幕内的绝对坐标
parent.getLocationOnScreen(location);
this.showAtLocation(parent, 0, location[0] / 2 + parent.getWidth() / 2 - this.width / 6, location[1] + parent.getHeight());
}
}
public static class PopupWindowBuilder {
private static String activityHashCode;
private static CustomPopupWindow popupWindow;
public static PopupWindowBuilder ourInstance;
public static PopupWindowBuilder getInstance(Activity activity) {
if (ourInstance == null) ourInstance = new PopupWindowBuilder();
String hashCode = String.valueOf(activity.hashCode());
/**
* 不同一个Activity
*/
if (!hashCode.equals(String.valueOf(activityHashCode))) {
activityHashCode = hashCode;
popupWindow = new CustomPopupWindow(activity);
}
return ourInstance;
}
public PopupWindowBuilder setTouchable(boolean touchable) {
popupWindow.setTouchable(touchable);
return this;
}
public PopupWindowBuilder setAnimationStyle(int animationStyle) {
popupWindow.setAnimationStyle(animationStyle);
return this;
}
public PopupWindowBuilder setBackgroundDrawable(Drawable background) {
popupWindow.setBackgroundDrawable(background);
return this;
}
public CustomPopupWindow getPopupWindow() {
popupWindow.update();
return popupWindow;
}
}
}
效果图
47.Android 自己定义PopupWindow技巧的更多相关文章
- 最强 Android Studio 使用小技巧和快捷键
写在前面 本文翻译自 Android Studio Tips by Philippe Breault,一共收集了62个 Android Studio 使用小技巧和快捷键. 根据这些小技巧的使用场景,本 ...
- 最强 Android Studio 使用小技巧和快捷键总结
最强 Android Studio 使用小技巧和快捷键总结 写在前面 本文翻译自 Android Studio Tips by Philippe Breault,一共收集了62个 Android ...
- Android Studio 使用小技巧和快捷键
Android Studio 使用小技巧和快捷键 Alt+回车 导入包,自己主动修正 Ctrl+N 查找类 Ctrl+Shift+N 查找文件 Ctrl+Alt+L 格式化代码 Ctrl+Alt ...
- Android开发之PopupWindow
/* * Android开发之PopupWindow * * Created on: 2011-8-8 * Author: blueeagle * Email: liujiaxiang@g ...
- Android-自己定义PopupWindow
Android-自己定义PopupWindow 2014年5月12日 PopupWindow在应用中应该是随处可见的,非经常常使用到,比方在旧版本号的微信其中就用到下拉的PopupWindow.那是自 ...
- Android课程---Android Studio使用小技巧:提取方法代码片段
这篇文章主要介绍了Android Studio使用小技巧:提取方法代码片段,本文分享了一个快速复制粘贴方法代码片段的小技巧,并用GIF图演示,需要的朋友可以参考下 今天来给大家介绍一个非常有用的Stu ...
- Android自己定义DataTimePicker(日期选择器)
Android自己定义DataTimePicker(日期选择器) 笔者有一段时间没有发表关于Android的文章了,关于Android自己定义组件笔者有好几篇想跟大家分享的,后期会记录在博客中.本篇 ...
- Android UI--自定义ListView(实现下拉刷新+加载更多)
Android UI--自定义ListView(实现下拉刷新+加载更多) 关于实现ListView下拉刷新和加载更多的实现,我想网上一搜就一堆.不过我就没发现比较实用的,要不就是实现起来太复杂,要不就 ...
- Android自己定义组件系列【7】——进阶实践(4)
上一篇<Android自己定义组件系列[6]--进阶实践(3)>中补充了关于Android中事件分发的过程知识.这一篇我们接着来分析任老师的<可下拉的PinnedHeaderExpa ...
随机推荐
- CF949C Data Center Maintenance(建图+强联通分量)
题意 有 n 个信息中心,第 i 个信息中心要在第 ti 个小时维护,维护期间信息不能被获得. 每个用户的数据都有两份备份,第 i 个用户的数据放在信息中心 c(i,1) 和 c(i,2). 现在要挑 ...
- shell应用之批量添加用户实例
这里要实现功能介绍 读取一个用户列表文件 给列表中的用户添加随机密码需要包含大小写字符和数字 保存对应的用户和密码文件 这些用户属于同个用户组 1.列表文件 [root@mail ~]# cat li ...
- HYSBZ1061题解
- DATA_PUMP_DIR impdp 指定导出目录
1.mkdir /tdms1/oracle/dump 2.sqlplus / as sysdba 3.create directory udir as '/tdms1/oracle/dump'; 4. ...
- WEB前端,混合排版,有的宽有的窄,滚动会出现空白处,怎么办。
多数时候出现空白都是由于有滚动栏滚到一边就会产生空白. overflow-x: hidden; 在最大图的那个div里写这句.
- uip UDP server广播模式(client能够随意port,而且主动向client发送数据)
眼下移植uip,发现UDP server模式下,必须指定本地port以及clientport,否则仅仅能讲clientport设置为0,才干接收随意port的数据,可是无法发送数据,由于此时clien ...
- CODE ---代码助手 (保存代码、搜代码、生成网页、自由界面)
四大功能 1 保存代码 2 搜索代码 3 生成网页 4 自由界面 www.gudianxiaoshuo.com
- vue.2.0-路由
vue2.0 路由: http://router.vuejs.org/zh-cn/index.html 基本使用: 1. 布局 <router-link to="/home" ...
- HMACSHA256 Class
https://msdn.microsoft.com/en-us/library/system.security.cryptography.hmacsha256(v=vs.110).aspx Comp ...
- Redis的安装与启动(doc和本地客户端)
官网 安装都是老生长谈了(这个也不错),这里推荐俩个文章看看把.:打开一个cmd窗口 使用cd命令切换目录到 C:\redis 运行 redis-server.exe redis.conf(安装的关键 ...