Android Popupwindow 拖动

版本:1.0

日期:2014.4.29

版权:© 2014 kince 转载注明出处

关于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;

上面是它的导包情况,基本上不是和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 拖动,码迷,mamicode.com

时间: 2024-10-08 19:35:18

Android Popupwindow 拖动的相关文章

Android popupwindow以及windowManager总结——实现悬浮效果

Android有三类窗口 应用程序窗口 (Application Window): 包括所有应用程序自己创建的窗口,以及在应用起来之前系统负责显示的窗口. 子窗口(Sub Window):比如应用自定义的对话框,或者输入法窗口,子窗口必须依附于某个应用窗口(设置相同的token). 系 统窗口(System Window): 系统设计的,不依附于任何应用的窗口,比如说,状态栏(Status Bar), 导航栏(Navigation Bar), 壁纸(Wallpaper), 来电显示窗口(Phon

【Android】android PopupWindow实现从底部弹出或滑出选择菜单或窗口

转载自:android PopupWindow实现从底部弹出或滑出选择菜单或窗口 Android PopupWindow的使用和分析 Popupwindow的使用 PopupWindow用法

android 可拖动控件 ontouchevent

首先附上文章的转载内容的链接: 学习android 可拖动事件首先需要对android的屏幕和touchevent参数建立一个详细的知识结构. 1.android坐标系统 一.首先明确一下 android中的坐标系统 :屏幕的左上角是坐标系统原点(0,0),原点向右延伸是X轴正方向,原点向下延伸是Y轴正方向. 1.View的坐标     需要注意view的坐标是相对父容器而言的,包括:getTop().getBottom(),getLeft(),getRight().以getTop为例,函数源代

Android PopupWindow显示位置和显示大小

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:bac

Android PopupWindow 仿微信弹出效果

项目中,我需要PopupWindow的时候特别多,这个东西也特别的好使,所以我今天给大家写一款PopupWindow 仿微信弹出效果,这样大家直接拿到项目里就可以用了!首先让我们先看效果: 那么我首先先看下布局代码非常简单:如下 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/pop_layout" android:layout_

关于Android PopupWindow中实用Spinner控件点击APP Crash情况整理!

场景异常信息如下: android.view.WindowManager$BadTokenException: Unable to add window -- token [email protected] is not valid; is your activity running? at android.view.ViewRootImpl.setView(ViewRootImpl.java:646) at android.view.WindowManagerGlobal.addView(Wi

android动画-拖动

先上图看效果 实质上说是动画有点不妥,确切的说应该是手势的处理,废话不多说看代码 SimpleDragSample.java public class SimpleDragSample extends Activity { protected int contentTop; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate

android popupwindow 位置显示

1.在控件的上方: private void showPopUp(View v) { LinearLayout layout = new LinearLayout(this); layout.setBackgroundColor(Color.GRAY); TextView tv = new TextView(this); tv.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT

android:PopupWindow的使用场景和注意事项

1.PopupWindow的特点 借用Google官方的说法: "A popup window that can be used to display an arbitrary view. The popup window is a floating container that appears on top of the current activity." 也就是说.popupwindow是activity上方的一个悬浮容器.它能够显示随意的视图View,非常霸气的样子. 以下看一