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技巧的更多相关文章

  1. 最强 Android Studio 使用小技巧和快捷键

    写在前面 本文翻译自 Android Studio Tips by Philippe Breault,一共收集了62个 Android Studio 使用小技巧和快捷键. 根据这些小技巧的使用场景,本 ...

  2. 最强 Android Studio 使用小技巧和快捷键总结

    最强 Android Studio 使用小技巧和快捷键总结   写在前面 本文翻译自 Android Studio Tips by Philippe Breault,一共收集了62个 Android ...

  3. Android Studio 使用小技巧和快捷键

    Android Studio 使用小技巧和快捷键 Alt+回车 导入包,自己主动修正 Ctrl+N   查找类 Ctrl+Shift+N 查找文件 Ctrl+Alt+L  格式化代码 Ctrl+Alt ...

  4. Android开发之PopupWindow

      /* *  Android开发之PopupWindow * *  Created on: 2011-8-8 *  Author: blueeagle *  Email: liujiaxiang@g ...

  5. Android-自己定义PopupWindow

    Android-自己定义PopupWindow 2014年5月12日 PopupWindow在应用中应该是随处可见的,非经常常使用到,比方在旧版本号的微信其中就用到下拉的PopupWindow.那是自 ...

  6. Android课程---Android Studio使用小技巧:提取方法代码片段

    这篇文章主要介绍了Android Studio使用小技巧:提取方法代码片段,本文分享了一个快速复制粘贴方法代码片段的小技巧,并用GIF图演示,需要的朋友可以参考下 今天来给大家介绍一个非常有用的Stu ...

  7. Android自己定义DataTimePicker(日期选择器)

    Android自己定义DataTimePicker(日期选择器)  笔者有一段时间没有发表关于Android的文章了,关于Android自己定义组件笔者有好几篇想跟大家分享的,后期会记录在博客中.本篇 ...

  8. Android UI--自定义ListView(实现下拉刷新+加载更多)

    Android UI--自定义ListView(实现下拉刷新+加载更多) 关于实现ListView下拉刷新和加载更多的实现,我想网上一搜就一堆.不过我就没发现比较实用的,要不就是实现起来太复杂,要不就 ...

  9. Android自己定义组件系列【7】——进阶实践(4)

    上一篇<Android自己定义组件系列[6]--进阶实践(3)>中补充了关于Android中事件分发的过程知识.这一篇我们接着来分析任老师的<可下拉的PinnedHeaderExpa ...

随机推荐

  1. Timestamp 转 date

    Timestamp startTime = new Timestamp(new Date().getTime());

  2. Android Studio的Signature Versions选择,分别是什么意思

    转自原文 Android Studio的Signature Versions选择,分别是什么意思 打包一个文件的签名版本, 选V1打包出来的app是jar的(一般这种就是当做第三方导入项目来用的), ...

  3. ArcGIS api for javascript——地理处理任务-服务区域任务

    描述 本例展示了如何发送一些输入值到ArcGIS Server上的GIS模型并获得结果反馈给web应用.本例中,模型计算自在地图上单击点起始的驱动时间多边形. 例如,这个分析类型可用于想要知道多少人生 ...

  4. 分别改动Cube每一个面的贴图UV(Unity3D开发之十八)

    猴子原创.欢迎转载.转载请注明: 转载自Cocos2Der-CSDN,谢谢! 原文地址: http://blog.csdn.net/cocos2der/article/details/46611169 ...

  5. 怎样安装Windows7操作系统

     1. 打开电脑,插入Windows7安装光盘. 2. 又一次启动电脑: 3. 依据提示按下对应的键.进入选择启动项菜单选择光驱引导.在"Boot Menu"界面按键盘上下键选 ...

  6. TRIZ系列-创新原理-7-嵌套原理

    原理表述例如以下: 1)把一个物体嵌入另外一个物体.然后将这两个物体再嵌入第三个物体,以此类推. 这个原理又叫俄罗斯娃原理,目的是在不影响原有功能的情况下: A) 在须要时.能够降低系统的体积和便于携 ...

  7. ADO.Net数据库帮助类

    public interface IDBHelper { /// <summary> /// 执行sql语句 /// </summary> /// <param name ...

  8. ES6学习笔记(五)函数的扩展

    1.函数参数的默认值 1.1基本用法 ES6 之前,不能直接为函数的参数指定默认值,只能采用变通的方法. function log(x, y) { y = y || 'World'; console. ...

  9. Python——Pygame实现生命游戏(game of life)

    模块:pygame import pygame,sys,time,random from pygame.locals import * """Color"&qu ...

  10. Centos6.5 安装lnmp环境

    最近项目要配置在nginx上,所以搜索了下具体nginx的安装,看到这篇文章简洁明了而且测试成功就借用了,作品出处:http://www.cnblogs.com/xiaoit/p/3991037.ht ...