Android Popupwindow 拖动
版本号:1.0
日期:2014.4.29
版权:© 2014 kince 转载注明出处
关于View的拖动大家应该比較了解了,比方对一个控件IamgeView拖动,或者一个视图View拖动,实现方式也非常easy,继承OnTouchListener接口,然后重写onTouch方法,在触屏事件进行处理就可以。可是Popupwindow怎样实现拖动呢,我们都知道它和普通的View不一样,由于它不是继承于View类的,可是它的实现却是和View密切相关的,由于我们都知道Android视图的显示都是由View来处理的,所以一定离不开它。从Popupwindow的实现就能够看出来,
import com.android.internal.R; import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.StateListDrawable;
import android.os.Build;
import android.os.IBinder;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnScrollChangedListener;
import android.view.WindowManager; import java.lang.ref.WeakReference;
上面是它的导包情况,基本上不是和View相关,就是和画图相关。因此关于Popupwindow的拖动这一块,也和View有联系。首先看一下它的API,看一看有没有和View移动、变化相关的方法,果然在最后有几个update()方法,例如以下:
update()方法用来更新Popupwindow的位置和大小的,那么问题就好攻克了。看代码:
package com.example.drag_and_drop_movablepopupwindow; import android.support.v7.app.ActionBarActivity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.PopupWindow;
import android.widget.TextView; public class MainActivity extends ActionBarActivity { private Button btnOpenPopup; private int mCurrentX;
private int mCurrentY; private PopupWindow mPopup; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
btnOpenPopup = (Button) findViewById(R.id.openpopup);
btnOpenPopup.setOnClickListener(new Button.OnClickListener() { @Override
public void onClick(View arg0) {
creatPopubWindow_1();
}
});
} /**
* 1
*/
private void creatPopubWindow_1() {
LayoutInflater layoutInflater = (LayoutInflater) getBaseContext()
.getSystemService(LAYOUT_INFLATER_SERVICE);
View popupView = layoutInflater.inflate(R.layout.popup, null);
final PopupWindow popupWindow = new PopupWindow(popupView,
200, 200); Button btnDismiss = (Button) popupView.findViewById(R.id.dismiss);
btnDismiss.setOnClickListener(new Button.OnClickListener() { @Override
public void onClick(View v) {
popupWindow.dismiss();
}
}); popupWindow.showAsDropDown(btnOpenPopup, 50, 50); popupView.setOnTouchListener(new OnTouchListener() {
int orgX, orgY;
int offsetX, offsetY; @Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
orgX = (int) event.getX();
orgY = (int) event.getY();
break;
case MotionEvent.ACTION_MOVE:
offsetX = (int) event.getRawX() - orgX;
offsetY = (int) event.getRawY() - orgY;
popupWindow.update(offsetX, offsetY, -1, -1, true);
break;
}
return true;
}
});
}
}
效果如图:
首先对Popupwindow设置触摸事件,然后在回调方法中进行计算,假设手指拖动了Popupwindow,那么就调用update()方法来更新它的位置。有些同学可能不太理解參数-1是什么意思,在上面的API中,写明的是宽和高,这里怎么变成-1了呢,看一下Popupwindow源码就明确了。
/**
* <p>Updates the position and the dimension of the popup window. Width and
* height can be set to -1 to update location only. Calling this function
* also updates the window with the current popup state as
* described for {@link #update()}.</p>
*
* @param x the new x location
* @param y the new y location
* @param width the new width, can be -1 to ignore
* @param height the new height, can be -1 to ignore
* @param force reposition the window even if the specified position
* already seems to correspond to the LayoutParams
*/
public void update(int x, int y, int width, int height, boolean force) {
if (width != -1) {
mLastWidth = width;
setWidth(width);
} if (height != -1) {
mLastHeight = height;
setHeight(height);
} if (!isShowing() || mContentView == null) {
return;
} WindowManager.LayoutParams p = (WindowManager.LayoutParams) mPopupView.getLayoutParams(); boolean update = force; final int finalWidth = mWidthMode < 0 ? mWidthMode : mLastWidth;
if (width != -1 && p.width != finalWidth) {
p.width = mLastWidth = finalWidth;
update = true;
} final int finalHeight = mHeightMode < 0 ? mHeightMode : mLastHeight;
if (height != -1 && p.height != finalHeight) {
p.height = mLastHeight = finalHeight;
update = true;
} if (p.x != x) {
p.x = x;
update = true;
} if (p.y != y) {
p.y = y;
update = true;
} final int newAnim = computeAnimationResource();
if (newAnim != p.windowAnimations) {
p.windowAnimations = newAnim;
update = true;
} final int newFlags = computeFlags(p.flags);
if (newFlags != p.flags) {
p.flags = newFlags;
update = true;
} if (update) {
setLayoutDirectionFromAnchor();
mWindowManager.updateViewLayout(mPopupView, p);
}
}
前两个if推断已经说得非常清楚了,假设參数是-1的话,就不改变Popupwindow的大小了,由于我们仅仅是移动位置,所以才这样写。那关于Popupwindow的移动最后是怎么实现的呢,能够看出就是调用WindowManager的updateViewLayout()方法,这种方法在WindowManager中并没有实现,它是ViewManager接口里面的方法,WindowManager继承了ViewManager。说到ViewManager,它里面定义的方法都非经常常使用,看代码:
/** Interface to let you add and remove child views to an Activity. To get an instance
* of this class, call {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
*/
public interface ViewManager
{
/**
* Assign the passed LayoutParams to the passed View and add the view to the window.
* <p>Throws {@link android.view.WindowManager.BadTokenException} for certain programming
* errors, such as adding a second view to a window without removing the first view.
* <p>Throws {@link android.view.WindowManager.InvalidDisplayException} if the window is on a
* secondary {@link Display} and the specified display can't be found
* (see {@link android.app.Presentation}).
* @param view The view to be added to this window.
* @param params The LayoutParams to assign to view.
*/
public void addView(View view, ViewGroup.LayoutParams params);
public void updateViewLayout(View view, ViewGroup.LayoutParams params);
public void removeView(View view);
}
这下大家应该明了,我们经经常使用的addView、removeView方法就是在这里面定义的,那么谁去实现呢?就是Layout控件,比方LinearLayout、RelativeLayout等,所以我们刚才用的updateViewLayout()方法也是在xml布局文件里的layout定义好的。
Android Popupwindow 拖动的更多相关文章
- Android PopupWindow Dialog 关于 is your activity running 崩溃详解
Android PopupWindow Dialog 关于 is your activity running 崩溃详解 [TOC] 起因 对于 PopupWindow Dialog 需要 Activi ...
- Android PopupWindow的使用和分析
Android PopupWindow的使用和分析 PopupWindow使用 PopupWindow这个类用来实现一个弹出框,可以使用任意布局的View作为其内容,这个弹出框是悬浮在当前activi ...
- Android PopupWindow的使用技巧(转)
Android PopupWindow的使用技巧 PopupWindow是Android上自定义弹出窗口,使用起来很方便. PopupWindow的构造函数为 public PopupWindow(V ...
- [Android实例] 拖动滑块进行图片拼合验证方式的实现
该篇文章从eoeAndroid搬迁过来的,原文地址:[Android实例] 拖动滑块进行图片拼合验证方式的实现 现在网站上有各种各样的验证码验证方式,比如计算大小,输入图片内容等,今天在一家网站上看到 ...
- android 可拖动控件 ontouchevent
首先附上文章的转载内容的链接: 学习android 可拖动事件首先需要对android的屏幕和touchevent参数建立一个详细的知识结构. 1.android坐标系统 一.首先明确一下 andro ...
- Android popupwindow使用心得(一)
最近项目中好多地方用到popupwindow,感觉这个控件还是非常重要的.所以把使用心得总结下,废话不多说,直接上代码. public class MainActivity extends Activ ...
- 不得不吐槽的Android PopupWindow的几个痛点(实现带箭头的上下文菜单遇到的坑)
说到PopupWindow,我个人感觉是又爱又恨,没有深入使用之前总觉得这个东西应该很简单,很好用,但是真正使用PopupWindow实现一些效果的时候总会遇到一些问题,但是即便是人家的api有问题, ...
- Android -- PopupWindow(其中嵌套ListView 可以被点击)
1. 效果图
- android PopupWindow使用实例
注:点空白或菜单外隐藏popupwindow菜单: 但是,若点击有点击事件的组件则要再写代码手动隐藏: @Override public boolean onTouchEvent(MotionEven ...
随机推荐
- NET Core 介绍
NET Core 介绍 标签: ASP.NETCore 1. 前言 2. ASP.NET Core 简介 2.1 什么是ASP.NET Core 2.2 ASP.NET Core的特点 2.3 ASP ...
- ASP.NET自定义控件加载资源WebResource问题
最近项目用日期控件,想把My97的资源文件跟TextBox封装成一个DatePicker控件,其实很简单的意见事情,但是还是用了一天多的时间,主要的问题就是解决资源文件加载的问题.通过一天多的努力,得 ...
- 快学Scala习题解答—第一章 基础
1 简介 近期对Scala比较感兴趣,买了本<快学Scala>,感觉不错.比<Programming Scala:Tackle Multi-Core Complexity on th ...
- 解决svn: Cannot negotiate authentication mechanism错误问题
解决svn: Cannot negotiate authentication mechanism错误问题 作者:wangzz 原文地址:http://blog.csdn.net/wzzvictory/ ...
- mssql中得到当天数据的语句
一条例子: 关键语句:
- click through rate prediction
包括内容如下图: 使用直接估计法,置信区间置信率的估计: 1.使用二项分布直接估计 $p(0.04<\hat{p}<0.06) = \sum_{0.04n\leq k \leq 0.06n ...
- 解决Boost.Regex对中文支持不好的问题
解决Boost.Regex对中文支持不好的问题 - k.m.Cao - 博客频道 - CSDN.NET 解决Boost.Regex对中文支持不好的问题 k.m.Caov0.1 问题的提出: Boo ...
- SEO人员应该突破的5大思想误区
1.外链误区 很多人在做网站优化的时候容易陷入外链怪圈,认为外链就是网站优化的一切,只要做好外链排名就会上去,让他不做外链了他将不知道做什么.特别是外链专员和一些初级SEO人员,优化网站只知道到哪里发 ...
- Hibernate 、继承关联映射
一个继承树一张表(subclass) 一个继承树一张表是指将一个类和他下面的所有派生类的所有的属性都放在一张表中,举例有Employee这个实体,在他下面分别派生了两个类skill和sell,通过Hi ...
- C# System.Guid.NewGuid() 【转】
概念 GUID: 即Globally Unique Identifier(全球唯一标识符) 也称作 UUID(Universally Unique IDentifier) . GUID是一个通过特定算 ...