Android Popupwindow 拖動

來源:互聯網
上載者:User

標籤:android   des   style   blog   http   java   

版本: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; @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);btnOpenPopup = (Button) findViewById(R.id.openpopup);btnOpenPopup.setOnClickListener(new Button.OnClickListener() {@Overridepublic 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() {@Overridepublic void onClick(View v) {popupWindow.dismiss();}});popupWindow.showAsDropDown(btnOpenPopup, 50, 50);popupView.setOnTouchListener(new OnTouchListener() {int orgX, orgY;int offsetX, offsetY;@Overridepublic 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定義好的。





相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.