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 ...
随机推荐
- Spring、AOP详解
如何配置AOP查看:Spring.Hello AOP 1.对于拦截规则@Pointcut的介绍: @Pointcut("execution (* cn.raffaello.service.. ...
- wx.ToolBar
wx.ToolBar A toolbar is a bar of buttons and/or other controls usually placed below the menu bar in ...
- BestCoder Round #14
Harry And Physical Teacher Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Ja ...
- cocos2d-x3.0 SpriteFrameCache
bool HelloWorld::init() { ////////////////////////////// // 1. super init first if ( !Layer::init() ...
- JavaScript-1.最简单的程序之网页弹出对话框,显示为Warning---ShinePans
代码: <html> <head> <meta http-equiv="content-type" content="text/html;c ...
- kindeditor更改图片上传时网络图片的路径
当我们想要使用kindeditor的图片上传功能时,有两种选择图片方式,一种是本地选择,一种是在图片空间中选择,图片空间的默认地址是server上的/kindeditor/attached/image ...
- C++Primer 中间Sales_items.h头文件
#ifndef SALESITEM_H #define SALESITEM_H #include <iostream> #include <string> class Sale ...
- bootstarp(carousel)组件
##### 1.5.1.Bootstrap中轮播图插件叫作Carousel ##### 1.5.2.基本的轮播图实现 ```html <!-- 以下容器就是整个轮播图组件的整体, 注意该盒子必须 ...
- T-SQL开窗函数
开窗函数over() 用途一:排序order by ,row_number select *,RANK() over(order by english desc) from Score --根据英语成 ...
- Deep Clone 常用方式总结
Deep Clone Example 总结 Deep Clone 一般有如下几种实现方式: 纯手工每个类实现赋值 (ps: 不做介绍,一般都不想这么玩) 序列化和反序列化 纯反射 emit 或 Exp ...