當前位置:編程學習大全網 - 源碼下載 - android 左右滑屏怎麽實現 哪位大神教教我

android 左右滑屏怎麽實現 哪位大神教教我

代碼如下:

package kexc.scroll;

import android.content.Context;

import android.util.AttributeSet;

import android.util.Log;

import android.view.MotionEvent;

import android.view.VelocityTracker;

import android.view.View;

import android.view.ViewConfiguration;

import android.view.ViewGroup;

import android.widget.Scroller;

/**

* 仿Launcher中的WorkSapce,可以左右滑動切換屏幕的類

*

*/

public class ScrollLayout extends ViewGroup {

/*

* onMeasure方法在控件的父元素正要放置它的子控件時調用。它會問壹個問題,“妳想要用多大地方啊?”,然後傳入兩個參數——

* widthMeasureSpec和heightMeasureSpec。它們指明控件可獲得的空間以及關於這個空間描述的元數據。

* 比返回壹個結果要好的方法是妳傳遞View的高度和寬度到setMeasuredDimension方法裏。

* 壹個MeasureSpec包含壹個尺寸和模式。

* 有三種可能的模式:

* UNSPECIFIED:父布局沒有給子布局任何限制,子布局可以任意大小。

* EXACTLY:父布局決定子布局的確切大小。不論子布局多大,它都必須限制在這個界限裏。

* AT_MOST:子布局可以根據自己的大小選擇任意大小。

*/

/*

* VelocityTracker類

*

* 功能: 根據觸摸位置計算每像素的移動速率。

*

* 常用方法有:

*

* public void addMovement (MotionEvent ev) 功能:添加觸摸對象MotionEvent , 用於計算觸摸速率。

* public void computeCurrentVelocity (int units)

* 功能:以每像素units單位考核移動速率。額,其實我也不太懂,賦予值1000即可。 參照源碼 該units的意思如下: 參數 units :

* The units you would like the velocity in. A value of 1 provides pixels

* per millisecond, 1000 provides pixels per second, etc. public float

* getXVelocity () 功能:獲得X軸方向的移動速率。

*/

/*

* ViewConfiguration類

*

* 功能: 獲得壹些關於timeouts(時間)、sizes(大小)、distances(距離)的標準常量值 。

*

* 常用方法:

*

* public int getScaledEdgeSlop()

*

* 說明:獲得壹個觸摸移動的最小像素值。也就是說,只有超過了這個值,才代表我們該滑屏處理了。

*

* public static int getLongPressTimeout()

*

* 說明:獲得壹個執行長按事件監聽(onLongClickListener)的值。也就是說,對某個View按下觸摸時,只有超過了

*

* 這個時間值在,才表示我們該對該View回調長按事件了;否則,小於這個時間點松開手指,只執行onClick監聽

*/

private static final String TAG = "ScrollLayout";

private Scroller mScroller;

private VelocityTracker mVelocityTracker;

private int mCurScreen;//當前屏幕

private int mDefaultScreen = 0;

//兩種狀態: 是否處於滑屏狀態

private static final int TOUCH_STATE_REST = 0;//靜止狀態

private static final int TOUCH_STATE_SCROLLING = 1;//滑屏狀態

private static final int SNAP_VELOCITY = 600; //最小的滑動速率

private int mTouchState = TOUCH_STATE_REST;

private int mTouchSlop;// change 多少像素算是發生move操作

private float mLastMotionX;

private float mLastMotionY;

public ScrollLayout(Context context, AttributeSet attrs) {

this(context, attrs, 0);

// TODO Auto-generated constructor stub

}

public ScrollLayout(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);

// TODO Auto-generated constructor stub

mScroller = new Scroller(context);

mCurScreen = mDefaultScreen;

//初始化壹個最小滑動距離

mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();

}

/**

* 生成view

*/

@Override

protected void onLayout(boolean changed, int l, int t, int r, int b) {

// TODO Auto-generated method stub

if (changed) {

int childLeft = 0;

final int childCount = getChildCount();

for (int i = 0; i < childCount; i++) {

final View childView = getChildAt(i);

if (childView.getVisibility() != View.GONE) {

final int childWidth = childView.getMeasuredWidth();

childView.layout(childLeft, 0, childLeft + childWidth,

childView.getMeasuredHeight());

childLeft += childWidth;

}

}

}

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

Log.e(TAG, "onMeasure");

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

final int width = MeasureSpec.getSize(widthMeasureSpec);

final int widthMode = MeasureSpec.getMode(widthMeasureSpec);

if (widthMode != MeasureSpec.EXACTLY) {

throw new IllegalStateException(

"ScrollLayout only canmCurScreen run at EXACTLY mode!");

}

final int heightMode = MeasureSpec.getMode(heightMeasureSpec);

if (heightMode != MeasureSpec.EXACTLY) {

throw new IllegalStateException(

"ScrollLayout only can run at EXACTLY mode!");

}

// The children are given the same width and height as the scrollLayout

final int count = getChildCount();

for (int i = 0; i < count; i++) {

getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);

}

// Log.e(TAG, "moving to screen "+mCurScreen);

scrollTo(mCurScreen * width, 0);

}

/**

* According to the position of current layout scroll to the destination

* page.

*/

public void snapToDestination() {

// 判斷是否超過下壹屏的中間位置,如果達到就抵達下壹屏,否則保持在原屏幕

// 這樣的壹個簡單公式意思是:假設當前滑屏偏移值即 scrollCurX 加上每個屏幕壹半的寬度,除以每個屏幕的寬度就是

// 我們目標屏所在位置了。 假如每個屏幕寬度為320dip, 我們滑到了500dip處,很顯然我們應該到達第二屏,索引值為1

// 即(500 + 320/2)/320 = 1

final int screenWidth = getWidth();

final int destScreen = (getScrollX() + screenWidth / 2) / screenWidth;

snapToScreen(destScreen);

}

public void snapToScreen(int whichScreen) {

// get the valid layout page

whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));

if (getScrollX() != (whichScreen * getWidth())) {

final int delta = whichScreen * getWidth() - getScrollX();

mScroller.startScroll(getScrollX(), 0, delta, 0,

Math.abs(delta) * 5);

mCurScreen = whichScreen;

onScreenChangeListener.onScreenChange(mCurScreen);

invalidate(); // Redraw the layout

}

}

public void setToScreen(int whichScreen) {

whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));

mCurScreen = whichScreen;

scrollTo(whichScreen * getWidth(), 0);

}

public int getCurScreen() {

return mCurScreen;

}

/**

* 控制view跟隨手指滑動 由父視圖調用用來請求子視圖根據偏移值 mScrollX,mScrollY重新繪制

*/

@Override

public void computeScroll() {

// 如果返回true,表示動畫還沒有結束

// 因為前面startScroll,所以只有在startScroll完成時 才會為false

if (mScroller.computeScrollOffset()) {

// 產生了動畫效果,根據當前值 每次滾動壹點

scrollTo(mScroller.getCurrX(), mScroller.getCurrY());

postInvalidate();

}

}

/*

* 其中:onInterceptTouchEvent()主要功能是控制觸摸事件的分發,例如是子視圖的點擊事件還是滑動事件。

* 其他所有處理過程均在onTouchEvent()方法裏實現了。 1、屏幕的滑動要根據手指的移動而移動 ----

* 主要實現在onTouchEvent()方法中

*

  • 上一篇:F-16戰鬥機有哪些型號
  • 下一篇:常見的三維建模軟件有哪些?
  • copyright 2024編程學習大全網