声明:转载自http://blog.csdn.net/wangjinyu501/article/details/24697229
关于View的拖动大家应该比较了解了,比如对一个控件IamgeView拖动,或者一个视图View拖动,实现方式也很容易,继承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;
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);
- }
- }
- /** 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);
- }