首页 技术 正文
技术 2022年11月14日
0 收藏 416 点赞 2,713 浏览 5757 个字

版本号: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()方法,例如以下:

Android Popupwindow 拖动

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;
}
});
}
}

效果如图:

Android Popupwindow 拖动

首先对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定义好的。

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,495
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,909
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,741
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,496
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:8,134
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:5,298