最近比較閑,想起墨蹟左右滑屏的效果該如何實現,如是在網上搜索資料,都沒看到理想的效果,於是參照別人的例子自己加以修改,最終效果還行。左右滑屏是通過ViewGroup結合手勢劃屏來實現,代碼如下:

ScrollLayoutTest.java
package com.scroll.test;


import com.yao_guet.test.R;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.widget.Button;

public class ScrollLayoutTest extends Activity {
private ScrollLayout sl;
private Button btn1;
private PageControlView pageControlView;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        sl = (ScrollLayout)findViewById(R.id.ScrollLayoutTest);
        pageControlView = (PageControlView) findViewById(R.id.pageControl);
        btn1 = (Button)findViewById(R.id.btn1);
        btn1.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
sl.snapToScreen(1);
}
});
        sl.setOnFocusChangeListener(new OnFocusChangeListener() {

@Override
public void onFocusChange(View v, boolean hasFocus) {
int i = v.getVisibility();
Log.v("=sl.i=", i+"=");
}
});
        Log.v("=sl.getCurScreen()=", sl.getCurScreen()+"=");
        pageControlView.bindScrollLayout(sl);
    }
}
ScrollLayout.java

package com.scroll.test;

import android.content.Context;
import android.graphics.Canvas;
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 {

 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;
 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();
 }

 @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() {
     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)*2);
      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;
    }
   
 @Override
 public void computeScroll() {
  // TODO Auto-generated method stub
  if (mScroller.computeScrollOffset()) {
   scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
   postInvalidate();
  }
 }

 @Override
 public boolean onTouchEvent(MotionEvent event) {
  // TODO Auto-generated method stub
  
  if (mVelocityTracker == null) {
   mVelocityTracker = VelocityTracker.obtain();
  }
  mVelocityTracker.addMovement(event);
  
  final int action = event.getAction();
  final float x = event.getX();
  final float y = event.getY();
  
  switch (action) {
  case MotionEvent.ACTION_DOWN:
   Log.e(TAG, "event down!");
   if (!mScroller.isFinished()){
    mScroller.abortAnimation();
   }
   mLastMotionX = x;
   break;
   
  case MotionEvent.ACTION_MOVE:
   int deltaX = (int)(mLastMotionX - x);
   mLastMotionX = x;
   
            scrollBy(deltaX, 0);
   break;
   
  case MotionEvent.ACTION_UP:
   Log.e(TAG, "event : up");  
            // if (mTouchState == TOUCH_STATE_SCROLLING) {  
            final VelocityTracker velocityTracker = mVelocityTracker;  
            velocityTracker.computeCurrentVelocity(1000);  
            int velocityX = (int) velocityTracker.getXVelocity();  

            Log.e(TAG, "velocityX:"+velocityX);
           
            if (velocityX > SNAP_VELOCITY && mCurScreen > 0) {  
                // Fling enough to move left  
//             onScreenChangeListener.onScreenChange(mCurScreen - 1);
             Log.e(TAG, "snap left");
                snapToScreen(mCurScreen - 1);  
            } else if (velocityX < -SNAP_VELOCITY  
                    && mCurScreen < getChildCount() - 1) {  
                // Fling enough to move right  
             Log.e(TAG, "snap right");
//             onScreenChangeListener.onScreenChange(mCurScreen + 1);
                snapToScreen(mCurScreen + 1);  
            } else {  
                snapToDestination();  
            }  

            if (mVelocityTracker != null) {  
                mVelocityTracker.recycle();  
                mVelocityTracker = null;  
            }  
            // }  
            mTouchState = TOUCH_STATE_REST;  
   break;
  case MotionEvent.ACTION_CANCEL:
   mTouchState = TOUCH_STATE_REST;
   break;
  }
  
  return true;
 }

 @Override
 public boolean onInterceptTouchEvent(MotionEvent ev) {
  // TODO Auto-generated method stub
  Log.e(TAG, "onInterceptTouchEvent-slop:"+mTouchSlop);
  
  final int action = ev.getAction();
  if ((action == MotionEvent.ACTION_MOVE) &&
    (mTouchState != TOUCH_STATE_REST)) {
   return true;
  }
  
  final float x = ev.getX();
  final float y = ev.getY();
  
  switch (action) {
  case MotionEvent.ACTION_MOVE:
   final int xDiff = (int)Math.abs(mLastMotionX-x);
   if (xDiff>mTouchSlop) {
    mTouchState = TOUCH_STATE_SCROLLING;
    
   }
   break;
   
  case MotionEvent.ACTION_DOWN:
   mLastMotionX = x;
   mLastMotionY = y;
   mTouchState = mScroller.isFinished()? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING;
   break;
   
  case MotionEvent.ACTION_CANCEL:
  case MotionEvent.ACTION_UP:
   mTouchState = TOUCH_STATE_REST;
   break;
  }
  
  return mTouchState != TOUCH_STATE_REST;
 }
 
 //监听页面变动
 public interface OnScreenChangeListener{
  void onScreenChange(int currentIndex);
 }
 private OnScreenChangeListener onScreenChangeListener;

 public void setOnScreenChangeListener(
   OnScreenChangeListener onScreenChangeListener) {
  this.onScreenChangeListener = onScreenChangeListener;
 }
 
 
}
PageControlView.java

 package com.scroll.test;

import com.scroll.test.ScrollLayout.OnScreenChangeListener;
import com.yao_guet.test.R;

import android.R.integer;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;

public class PageControlView extends LinearLayout {

 private Context context;
 private int count;
 
 public PageControlView(Context context){
  super(context);
  this.context = context;
 }
 public PageControlView(Context context, AttributeSet attrs) {
  super(context, attrs);
  this.context = context;
 }
 
 public void bindScrollLayout(ScrollLayout scrollLayout){
  this.count = scrollLayout.getChildCount();
  Log.v("=count==", count+"=");
  //初始化第一屏
  generatePageControl(0);
  scrollLayout.setOnScreenChangeListener(new OnScreenChangeListener() {
   
   @Override
   public void onScreenChange(int currentIndex) {
    
    generatePageControl(currentIndex);
   }
  });
 }
 
 private void generatePageControl(int currentIndex){
  this.removeAllViews();
  for(int i = 0;i < this.count ;i ++ ){
   Log.v("=i==", i+"=");
   ImageView imageView = new ImageView(context);
   if(i==currentIndex){
    imageView.setImageResource(R.drawable.page_indicator_focused);
   }else{
    
    imageView.setImageResource(R.drawable.page_indicator);
   }
   this.addView(imageView);
  }
 }

}
main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent">
<com.scroll.test.ScrollLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/ScrollLayoutTest"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">

<LinearLayout
  android:background="#FF00"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"></LinearLayout>
 
<FrameLayout
  android:background="#F0F0"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"></FrameLayout>
 
<FrameLayout
  android:background="#F00F"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
  </FrameLayout>
 
<LinearLayout
  android:background="#FF00"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
  <Button
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:text="Button1"
   android:id="@+id/btn1"/>
  </LinearLayout>


<LinearLayout
  android:layout_width="wrap_content"
  android:layout_height="wrap_content">
  <Button
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:text="Button2" />
  </LinearLayout>
</com.scroll.test.ScrollLayout>
 <com.scroll.test.PageControlView
    android:id="@+id/pageControl"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_alignParentBottom="true">
  </com.scroll.test.PageControlView>
</RelativeLayout>

 

如果想设置循环:

 

设置循环滑屏:
1.在ScrollLayout.java类中的snapToDestination()方法中添加:
//设置使循环(5表示总共有多少屏)
     if(destScreen == 0){
      setToScreen(5);
     }else if(destScreen == 5){
      setToScreen(0);
     }else{
        //设置不循环
         snapToScreen(destScreen);
     }

2.在setToScreen(int whichScreen)方法中添加:
//设置使循环
onScreenChangeListener.onScreenChange(mCurScreen);

 

 

http://static.apk.hiapk.com/html/2012/02/404824.html

http://static.apk.hiapk.com/html/2011/11/325301.html

http://static.apk.hiapk.com/html/2011/12/374423.html

 

創作者介紹
創作者 shadow 的頭像
shadow

資訊園

shadow 發表在 痞客邦 留言(0) 人氣()