Android 實現View滑動幾種方式
關於View的滑動,Android中提供了許多方法,具體可以分為一下幾類:
layout
在ACTION_MOVE中通過獲取x、y的偏移量動態佈局view,並禁止向父控制元件傳遞事件:
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastX = x;
mLastY = y;
break ;
case MotionEvent.ACTION_MOVE:
int offsetX = x - mLastX;
int offsetY = y - mLastY;
layout(
getLeft() + offsetX,
getTop() + offsetY,
getRight() + offsetX,
getBottom() + offsetY
);
break ;
}
return true;
}
offsetLeftAndRight和offsetTopAndBottom
將上述layout方法改為該兩個方法的組合,偏移量計算同上:
case MotionEvent.ACTION_MOVE:
int offsetX = x - mLastX;
int offsetY = y - mLastY;
offsetLeftAndRight(offsetX);
offsetTopAndBottom(offsetY);
break ;
LayoutParams
實現方法和layout相似,動態設定佈局引數,缺點是如果view引數加了rules,會導致無法滑動:
case MotionEvent.ACTION_MOVE:
int offsetX = x - mLastX;
int offsetY = y - mLastY;
ViewGroup.MarginLayoutParams params
= (ViewGroup.MarginLayoutParams) getLayoutParams();
params.leftMargin = getLeft() + offsetX;
params.topMargin = getTop() + offsetY;
setLayoutParams(params);
break;
ScrollBy
scrollBy移動的是view中的內容或者ViewGroup中的所有子view,故需先獲得父控制元件的例項;同時scrollBy引數的正負是和android座標軸的正負方向相反的,故需隊offset值取反:
case MotionEvent.ACTION_MOVE:
int offsetX = x - mLastX;
int offsetY = y - mLastY;
((View) getParent()).scrollBy(-offsetX, -offsetY);
break;
ViewDragHelper
該類非常強大,基本可以各種不同的滑動、拖放需求。support庫中DragLayout也是基於此類實現側滑效果。使用該類一般需要如下幾個步驟:
- 繼承自ViewGroup,在構造中初始化ViewDragHelper物件,傳入的兩個引數分別為當前容器物件和ViewDragHelper中的回撥介面,該回調中封裝了子view的滑動操作相關api
public DragLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mViewDragHelper = ViewDragHelper.create(this, mCallBack);
}
- 觸控事件攔截與處理,需要將事件傳遞給ViewDragHelper處理
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mViewDragHelper.shouldInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mViewDragHelper.processTouchEvent(event);
return true;
}
- 處理ViewDragHelper中回撥Callback
private ViewDragHelper.Callback mCallBack = new ViewDragHelper.Callback() {
/**
* 指定可以滑動的子View,比如當前只有mMainView可以滑動
* @param child
* @param pointerId
* @return true 指定的子view可以滑動
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child == mMainView;
}
/**
* 控制子view水平滑動的距離,預設是0 不可以滑動
* @param child
* @param left
* @param dx
* @return
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
return left;
}
/**
* 功能同上,垂直方向滑動的距離
* @param child
* @param top
* @param dy
* @return
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
return top;
}
/**
* 當拖拽子view之後手指離開螢幕時觸發;
* @param releasedChild
* @param xvel
* @param yvel
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
}
};
以上程式碼即可實現view滑動的功能。但如果想要實現手指離開螢幕view自動滑動到指定位置的功能時,需要在Callback中重寫onViewReleased()
方法。ViewDragHelper提供了smoothSlideViewTo()
方法,可以實現view的自動滑動效果,當然其內部也是通過Scroller類實現的,故需要重寫computeScroll()
方法。
如下是一個模擬google DragLayout的一個Demo,當然只實現了其中側滑的一個小功能,其他事件分發處理邏輯都沒有具體實現。
package com.ts.test.widget;
import android.content.Context;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
/**
* Created by tiansen on 17-11-18.
*/
public class MyDragLayout extends FrameLayout {
private static final String TAG = "MyDragLayout";
private ViewDragHelper mViewDragHelper;
/**
* 側邊欄View
*/
private View mMenuView;
/**
* 主View
*/
private View mMainView;
/**
* 側邊欄View寬度
*/
private int mMenuWidth;
/**
* 主View寬度
*/
private int mMainWidth;
private ViewDragHelper.Callback mCallBack = new ViewDragHelper.Callback() {
/**
* 指定可以滑動的子View
* @param child
* @param pointerId
* @return true 指定的子view可以滑動
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child == mMainView;
}
/**
* 控制子view水平滑動的距離,預設是0 不可以滑動
* @param child
* @param left
* @param dx
* @return
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
// 控制滑動邊界
return (left < 0 ? 0 : left) < mMenuWidth ? left : mMenuWidth;
}
/**
* 功能同上,垂直方向滑動的距離
* @param child
* @param top
* @param dy
* @return
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
return 0;
}
/**
* 當拖拽子view之後手指離開螢幕時觸發;
* @param releasedChild
* @param xvel
* @param yvel
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
if (mMainView.getLeft() < mMenuWidth / 2) {
mViewDragHelper.smoothSlideViewTo(mMainView, 0, 0);
ViewCompat.postInvalidateOnAnimation(MyDragLayout.this);
} else {
mViewDragHelper.smoothSlideViewTo(mMainView, mMenuWidth, 0);
ViewCompat.postInvalidateOnAnimation(MyDragLayout.this);
}
}
};
public MyDragLayout(Context context) {
this(context, null);
}
public MyDragLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyDragLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mViewDragHelper = ViewDragHelper.create(this, mCallBack);
}
@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);
mMainWidth = mMainView.getMeasuredWidth();
mMenuWidth = mMenuView.getMeasuredWidth();
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mViewDragHelper.shouldInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mViewDragHelper.processTouchEvent(event);
return true;
}
@Override
public void computeScroll() {
if (mViewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(this);
}
}
}
相關推薦
Android 實現View滑動幾種方式
關於View的滑動,Android中提供了許多方法,具體可以分為一下幾類: layout 在ACTION_MOVE中通過獲取x、y的偏移量動態佈局view,並禁止向父控制元件傳遞事件: @Override public boolean onTo
Android 實現懸浮的幾種方式(一)AppBarLayout+PtrFrameLayout
先上個圖: 我所知道的有兩種實現方式: AppBarLayout巢狀控制滾動區實現(目前使用的) 給RecyclerView增加HeaderView顯示隱藏切換實現 先把引用的包放出來: compile 'com.android.su
android自定義view的幾種方式
convertView = LayoutInflater.from(mContext).inflate(R.layout.list_view_item, null); XXXX = (ItemView)convertView; 假如我想自定義一個listview,我之前的
Android 實現 View 滑動的七種方法
記錄下系統提供的 View 滑動的 API 方法。不管採用哪一種方式,本質的思想基本上都是一致的,當觸控 View 的時候,記錄下當前觸控點的座標,當手指移動的時候,記錄移動後的觸控點座標,從而獲取相對上一次座標點的偏移量,通過偏移量來修改 View 的座標,這
Android中實現IPC的幾種方式詳細分析及比較
1.使用Bundle ----> 用於android四大元件間的程序間通訊android的四大元件都可使用Bundle傳遞資料 所以如果要實現四大元件間的程序間通訊 完全可以使用Bundle來實現 簡單方便 2.使用檔案共享 ---->用於單執行緒讀寫
06.實現servlet的幾種方式,以及接口或者類之間的關系
ssa 圖片 servlet 容器 實例化 設備 blog public ide 接口:Servlet、ServletConfig、ServletRequest、ServletResponse、HttpServletRequest、HttpServletResponse、S
JS實現繼承的幾種方式(轉)
多繼承 logs 影響 .cn sta 初始化 定義 附錄 style 轉自:幻天芒的博客 前言 JS作為面向對象的弱類型語言,繼承也是其非常強大的特性之一。那麽如何在JS中實現繼承呢?讓我們拭目以待。 JS繼承的實現方式 既然要實現繼承,那麽首先我們得有一個父類,
JS實現繼承的幾種方式
簡單 成員 類構造 缺陷 屬性 con html 但是 內存 JS實現繼承的幾種方式 前言 JS作為面向對象的弱類型語言,繼承也是其非常強大的特性之一。那麽如何在JS中實現繼承呢?讓我們拭目以待。 JS繼承的實現方式 既然要實現繼承,那麽首先我們得有一個父類,代碼如
JavaScript實現繼承的幾種方式總結一
相同 實踐 extend sta 執行 instance () class new 雖然在ES6中有了繼承,使用extends關鍵字就能實現。本篇講的不是這種,而是ES6之前的幾種實現繼承的方式。 (一)原型鏈 ECMAScript中將原型鏈作為實現繼承的主要方法。其基本思
java實現同步的幾種方式(總結)
副本 增刪改 否則 都是 fin ret 語義 value art 為何要使用同步? java允許多線程並發控制,當多個線程同時操作一個可共享的資源變量時(如數據的增刪改查), 將會導致數據不準確,相互之間產生沖突,因此加入同步鎖以避免在該線程沒有完成操
JS類對象實現繼續的幾種方式
var test 子類實例化 傳參 blog spa sim func prototype 0. ES6可以直接使用class,extends來繼承. 1. 原型繼承 1 2 父類: 3 4 function Persio
JAVASCRIPT實現繼承的幾種方式
JAVASCRIPT實現繼承的幾種方式 對象冒充(多繼承):a. 代碼: function ClassA(sColor) { this.color = sColor; this.sayColor = function () { console.log(this.color); }; } functio
javascript中實現繼承的幾種方式
eat 共享 all cto 原型 構造 child 構造函數 java javascript中實現繼承的幾種方式 1、借用構造函數實現繼承 function Parent1(){ this.name = "parent1" } function Child1()
Android activity間通訊幾種方式
read flag 進程 destroy ads sage on() sting ogl Activity 通訊 Bundle 我們可以通過將數據封裝在Bundle對象中 ,然後在Intent跳轉的時候攜帶Bundle對象 bundle 本質上是使用 arrayMap實現
Android程序間通訊 - 幾種方式的對比總結
什麼是RPC RPC(Remote Procedure Call)即遠端過程呼叫,它是一種通過網路從遠端計算機程式上請求服務,在不需要了解底層網路技術的協議下,即可獲取計算機程序中的資料。RPC使得開發包括網路分散式多程式在內的應用程式更加容易。 RPC在OSI網路通訊7層模型中
javascript 面向物件(實現繼承的幾種方式)
1、原型鏈繼承 核心: 將父類的例項作為子類的原型 缺點: 父類新增原型方法/原型屬性,子類都能訪問到,父類一變其它的都變了 function Person (name) { this.name =
Android 隱士跳轉幾種方式
1、只有 配置 action 進行跳轉 <intent-filter> <action android:name="testarouter"></action> <category android:name="android.i
WPF實現動畫的幾種方式及其小案例
WPF實現動畫的方式: 基於計時器的動畫 建立一個定時器,然後根據其頻率迴圈呼叫函式或者一個事件處理函式,在這個函式中可以手工更新目標屬性,直到達到最終值,這時可以停止計時器。 案例: 效果圖:
實現同步的幾種方式
1.同步方法即有synchronized關鍵字修飾的方法;由於Java的每個物件都有一個內建鎖,當用此關鍵字修飾方法時,內建鎖會保護整個方法。在呼叫該方法之前,需要獲取內建鎖,否則就處於阻塞狀態。2.同步程式碼塊即有synchronized關鍵字修飾的語句塊;程式碼如:synchronized(object)
Android實現延遲的幾種方法小結
本文例項總結了Android實現延遲的幾種方法。分享給大家供大家參考,具體如下: 一、通過Thread new Thread(){ public void run(){ sleep(***); } }.start(); 通過ProgressDialog的使用來