編輯:關於Android編程
5.1 滑動效果是如何產生的
5.1.1 Android坐標系 5.1.2 視圖坐標系 5.1.3 觸控事件——MotionEvent 5.2 實現滑動的七種方法
5.2.1 layout方法 5.2.2 offsetLeftAndRight()與offsetTopAndBottom() 5.2.3 LayoutParams 5.2.4 scrollTo與scrollBy 5.2.5 Scroller 5.2.6 屬性動畫 5.2.7 ViewDragHelper
要實現View的滑動,就必須監聽用戶觸摸的事件,並根據事件傳入的坐標,動態且不斷地改變View的坐標,從而實現View跟隨用戶觸摸的滑動而滑動
特別注意:View.getX()和event.getX()兩個不同的位置獲取的區別
Android坐標系以屏幕左上角作為原點,可通過以下方法獲得x和y的坐標:
getRawX():獲取Android坐標系的x坐標,請注意這裡和event.getRawX()的區別 getRawY():獲取Android坐標系的y坐標,請注意這裡和event.getRawY()的區別
視圖坐標系由子控件以父控件的左上角作為原點,可通過以下方法獲得x和y的坐標:
getX():獲取視圖坐標系的x坐標,請注意這裡和event.getX()的區別 getY():獲取視圖坐標系的y坐標,請注意這裡和event.getY()的區別
MotionEvent封裝的一些常用的事件常量:
ACTION_DOWN:單點觸摸按下的動作 ACTION_UP:單點觸摸離開的動作 ACTION_MOVE:單點觸摸移動的動作 ACTION_CANCEL:單點觸摸取消 ACTION_OUTSIDE:單點觸摸超出邊界 ACTION_POINTER_DOWN:多點觸摸按下的動作 ACTION_POINTER_UP:多點觸摸離開的動作通常會在onTouchEvent(MotionEvent event)方法中通過event.getAction()方法獲取觸控事件類型,以下代碼為模板式子:
@Override public boolean onTouchEvent(MotionEvent event) { //獲取當前輸入點的X,Y坐標(視圖坐標) int x = (int) event.getX(); int y = (int) event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: //處理輸入的按下動作 break; case MotionEvent.ACTION_MOVE: //處理輸入的移動動作 break; case MotionEvent.ACTION_UP: //處理輸入的離開動作 break; } return true; }
系統海提供了非常多的方法來獲取坐標值、相對距離等:
View提供的獲取坐標方法:
getTop():獲取到的是View自身的頂邊到其父布局頂邊的距離 getLeft():獲取到的是View自身的左邊到其父布局左邊的距離 getRight():獲取到的是View自身的右邊到其父布局右邊的距離 getBottom():獲取到的是View自身的底邊到其父布局底邊的距離MotionEvent提供的方法:
getX():獲取點擊事件距離控件左邊的距離,即視圖坐標 getY():獲取點擊事件距離控件頂邊的距離,即視圖坐標 getRawX:獲取點擊事件距離整個屏幕左邊的距離,即絕對坐標 getRawY:獲取點擊事件距離整個屏幕頂邊的距離,即絕對坐標
無知識點
當我們手指觸摸時記錄下觸摸點,在滑動時也記錄下觸摸點,通過兩次的差值,計算出偏移量,使用View本身的layout方法,讓他不斷的位移偏移量即可
Layout滑動……見經典代碼回顧案例一
offsetLeftAndRight滑動……見經典代碼回顧案例二
通過getLayoutParams()方法來獲取布局參數,需要注意的是:
不同的View應采用不同的View的getLayoutParams()方法 前提必須要有一個父布局,否則系統無法獲取LayoutParams 使用ViewGroup.MarginLayoutParams不需要考慮父布局類型LayoutParams滑動……見經典代碼回顧案例三
scrollTo與scrollBy滑動……見經典代碼回顧案例四
scrollTo:移動到一個具體的坐標點(x,y) scrollBy:表示移動的增量dx,dyscrollTo、scrollBy方法移動的是View的content,即讓View的內容移動了,如果在ViewGroup中使用scrollTo、scrollBy方法,那麼移動的將是所有子View,例如:
TextView,content就是它的文本 ImageView,content就是它的drawable對象也就是說我們要用getParent()來使用scrollTo、scrollBy方法,否則,TextView只是偏移它的文本,ImageView只是偏移它的圖片
Scroller使用步驟:
初始化Scroller 重寫computeScroll()方法 startScroll開啟滑動Scroller滑動……見經典代碼回顧案例五
無知識點
ViewDragHelper使用步驟:
初始化ViewDragHelper 重寫攔截事件,將事件傳遞給ViewDragHelper處理 處理computeScroll() 處理回調ViewDragHelper.Callback 開啟滑動,並更新UI在ViewDragHelper.Callback中,系統定義了大量的監聽事件來幫助我們處理各種事件:
onViewCaptured() :用戶觸摸到view回調 onViewDragStateChanged():拖拽狀態改變時回調,比如idle,dragging等狀態 onViewPositionChanged():位置改變時回調,常用於滑動時更改scale進行縮放等效果ViewDragHelper滑動……見經典代碼回顧案例六
public class DragView2 extends View { private int lastX; private int lastY; public DragView2(Context context) { super(context); ininView(); } public DragView2(Context context, AttributeSet attrs) { super(context, attrs); ininView(); } public DragView2(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); ininView(); } private void ininView() { setBackgroundColor(Color.BLUE); } // 絕對坐標方式 @Override public boolean onTouchEvent(MotionEvent event) { int rawX = (int) (event.getRawX()); int rawY = (int) (event.getRawY()); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 記錄觸摸點坐標 lastX = rawX; lastY = rawY; break; case MotionEvent.ACTION_MOVE: // 計算偏移量 int offsetX = rawX - lastX; int offsetY = rawY - lastY; // 在當前left、top、right、bottom的基礎上加上偏移量 layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY); // 重新設置初始坐標 lastX = rawX; lastY = rawY; break; } return true; } }
一定要重新設置初始坐標,這樣才能准確地獲取偏移量
public class DragView1 extends View { private int lastX; private int lastY; public DragView1(Context context) { super(context); ininView(); } public DragView1(Context context, AttributeSet attrs) { super(context, attrs); ininView(); } public DragView1(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); ininView(); } private void ininView() { // 給View設置背景顏色,便於觀察 setBackgroundColor(Color.BLUE); } // 視圖坐標方式 @Override public boolean onTouchEvent(MotionEvent event) { int x = (int) event.getX(); int y = (int) event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 記錄觸摸點坐標 lastX = x; lastY = y; break; case MotionEvent.ACTION_MOVE: // 計算偏移量 int offsetX = x - lastX; int offsetY = y - lastY; // 在當前left、top、right、bottom的基礎上加上偏移量 layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY); offsetLeftAndRight(offsetX); offsetTopAndBottom(offsetY); break; } return true; } }
public class DragView3 extends View { private int lastX; private int lastY; public DragView3(Context context) { super(context); ininView(); } public DragView3(Context context, AttributeSet attrs) { super(context, attrs); ininView(); } public DragView3(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); ininView(); } private void ininView() { setBackgroundColor(Color.BLUE); } @Override public boolean onTouchEvent(MotionEvent event) { int x = (int) event.getX(); int y = (int) event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 記錄觸摸點坐標 lastX = (int) event.getX(); lastY = (int) event.getY(); break; case MotionEvent.ACTION_MOVE: // 計算偏移量 int offsetX = x - lastX; int offsetY = y - lastY; ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) getLayoutParams(); // LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) getLayoutParams(); layoutParams.leftMargin = getLeft() + offsetX; layoutParams.topMargin = getTop() + offsetY; setLayoutParams(layoutParams); break; } return true; } }
public class DragView4 extends View { private int lastX; private int lastY; public DragView4(Context context) { super(context); ininView(); } public DragView4(Context context, AttributeSet attrs) { super(context, attrs); ininView(); } public DragView4(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); ininView(); } private void ininView() { setBackgroundColor(Color.BLUE); } @Override public boolean onTouchEvent(MotionEvent event) { int x = (int) event.getX(); int y = (int) event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: lastX = (int) event.getX(); lastY = (int) event.getY(); break; case MotionEvent.ACTION_MOVE: int offsetX = x - lastX; int offsetY = y - lastY; ((View) getParent()).scrollBy(-offsetX, -offsetY); break; } return true; } }
要注意的是,scrollTo、scrollBy是以Android坐標系移動的,所以要使用我們正常的坐標系,則在x和y加一個負號
public class DragView5 extends View { private int lastX; private int lastY; private Scroller mScroller; public DragView5(Context context) { super(context); ininView(context); } public DragView5(Context context, AttributeSet attrs) { super(context, attrs); ininView(context); } public DragView5(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); ininView(context); } private void ininView(Context context) { setBackgroundColor(Color.BLUE); // 初始化Scroller mScroller = new Scroller(context); } @Override public void computeScroll() { super.computeScroll(); // 判斷Scroller是否執行完畢 if (mScroller.computeScrollOffset()) { ((View) getParent()).scrollTo( mScroller.getCurrX(), mScroller.getCurrY()); // 通過重繪來不斷調用computeScroll invalidate(); } } @Override public boolean onTouchEvent(MotionEvent event) { int x = (int) event.getX(); int y = (int) event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: lastX = (int) event.getX(); lastY = (int) event.getY(); break; case MotionEvent.ACTION_MOVE: int offsetX = x - lastX; int offsetY = y - lastY; ((View) getParent()).scrollBy(-offsetX, -offsetY); break; case MotionEvent.ACTION_UP: // 手指離開時,執行滑動過程 View viewGroup = ((View) getParent()); mScroller.startScroll( viewGroup.getScrollX(), viewGroup.getScrollY(), -viewGroup.getScrollX(), -viewGroup.getScrollY()); invalidate(); break; } return true; } }
public class DragViewGroup extends FrameLayout { private ViewDragHelper mViewDragHelper; private View mMenuView, mMainView; private int mWidth; public DragViewGroup(Context context) { super(context); initView(); } public DragViewGroup(Context context, AttributeSet attrs) { super(context, attrs); initView(); } public DragViewGroup(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initView(); } @Override protected void onFinishInflate() { super.onFinishInflate(); mMenuView = getChildAt(0); mMainView = getChildAt(1); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mWidth = mMenuView.getMeasuredWidth(); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return mViewDragHelper.shouldInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { //將觸摸事件傳遞給ViewDragHelper,此操作必不可少 mViewDragHelper.processTouchEvent(event); return true; } private void initView() { mViewDragHelper = ViewDragHelper.create(this, callback); } private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() { // 何時開始檢測觸摸事件 @Override public boolean tryCaptureView(View child, int pointerId) { //如果當前觸摸的child是mMainView時開始檢測 return mMainView == child; } // 觸摸到View後回調 @Override public void onViewCaptured(View capturedChild, int activePointerId) { super.onViewCaptured(capturedChild, activePointerId); } // 當拖拽狀態改變,比如idle,dragging @Override public void onViewDragStateChanged(int state) { super.onViewDragStateChanged(state); } // 當位置改變的時候調用,常用與滑動時更改scale等 @Override public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { super.onViewPositionChanged(changedView, left, top, dx, dy); } // 處理垂直滑動 @Override public int clampViewPositionVertical(View child, int top, int dy) { return 0; } // 處理水平滑動 @Override public int clampViewPositionHorizontal(View child, int left, int dx) { return left; } // 拖動結束後調用 @Override public void onViewReleased(View releasedChild, float xvel, float yvel) { super.onViewReleased(releasedChild, xvel, yvel); //手指抬起後緩慢移動到指定位置 if (mMainView.getLeft() < 500) { //關閉菜單 //相當於Scroller的startScroll方法 mViewDragHelper.smoothSlideViewTo(mMainView, 0, 0); ViewCompat.postInvalidateOnAnimation(DragViewGroup.this); } else { //打開菜單 mViewDragHelper.smoothSlideViewTo(mMainView, 300, 0); ViewCompat.postInvalidateOnAnimation(DragViewGroup.this); } } }; @Override public void computeScroll() { if (mViewDragHelper.continueSettling(true)) { ViewCompat.postInvalidateOnAnimation(this); } } }
布局文件必須放置兩個子View
<framelayout android:background="@android:color/holo_blue_light" android:layout_height="match_parent" android:layout_width="match_parent"></framelayout>
經典回顧源碼下載
github:https://github.com/CSDNHensen/QunYingZhuang
Android網絡編程之獲取網絡上的Json 請尊重他人的勞動成果,轉載請注明出處:Android網絡編程之獲取網絡上的Json 為要獲取網絡上的Json所以需要
我們知道,ImageView有一個屬性叫做scaleType,它的取值一共有八種,分別是:matrix,fitXY,fitStart,fitCenter,fitEnd,c
如何避開在ListView等AdapterView上動態添加刪除項的陷阱,下面就為大家分享,具體內容如下首先,定義如下array資源,作為列表的加載內容:<reso
首先明確流程 既然實現自動更新,我們首先必須讓我們的應用知道是否存在新版本的軟件,因此我們可以在自己的網站上放置配置文件,存放軟件的版本信息: 2