package com.qin.scrollerview;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Bundle;
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.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Scroller;
import android.widget.TextView;
//自定义ViewGroup , 包含了三个LinearLayout控件,存放在不同的布局位置,通过scrollBy或者scrollTo方法切换
public class MultiViewGroup extends ViewGroup {
private Context mContext;
private static String TAG = "MultiViewGroup";
private int curScreen = 0 ; //当前屏
private Scroller mScroller = null ;
public MultiViewGroup(Context context) {
super(context);
mContext = context;
init();
}
public MultiViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
init();
}
//startScroll 滑屏
public void startMove(){
curScreen ++ ;
Log.i(TAG, "----startMove---- curScreen " + curScreen);
Log.i(TAG, "----width " + getWidth());
//采用Scroller类控制滑动过程
mScroller.startScroll((curScreen-1) *getWidth(), 0,
getWidth(), 0,3000);
//暴力点直接到目标出
//scrollTo(curScreen * getWidth(), 0);
//其实在点击按钮的时候,就回触发View绘制流程,这儿我们在强制绘制下View
invalidate();
}
//停止滑屏
public void stopMove(){
Log.v(TAG, "----stopMove ----");
if(mScroller != null){
//如果动画还没结束,我们就按下了结束的按钮,那我们就结束该动画,即马上滑动指定位置
if(!mScroller.isFinished()){
int scrollCurX= mScroller.getCurrX() ;
//判断是否达到下一屏的中间位置,如果达到就抵达下一屏,否则保持在原屏幕
//int moveX = scrollCurX - mScroller.getStartX() ;
// Log.i(TAG, "----mScroller.is not finished ---- shouldNext" + shouldNext);
//boolean shouldNext = moveX >= getWidth() / 2 ;
int descScreen = ( scrollCurX + getWidth() / 2) / getWidth() ;
Log.i(TAG, "----mScroller.is not finished ---- shouldNext" + descScreen);
Log.i(TAG, "----mScroller.is not finished ---- scrollCurX " + scrollCurX);
mScroller.abortAnimation();
//停止了动画,我们马上滑倒目标位置
scrollTo(descScreen * getWidth() , 0);
mScroller.forceFinished(true);
curScreen = descScreen ;
}
}
else
Log.i(TAG, "----OK mScroller.is finished ---- ");
}
// 只有当前LAYOUT中的某个CHILD导致SCROLL发生滚动,才会致使自己的COMPUTESCROLL被调用
@Override
public void computeScroll() {
// TODO Auto-generated method stub
Log.e(TAG, "computeScroll");
// 如果返回true,表示动画还没有结束
// 因为前面startScroll,所以只有在startScroll完成时 才会为false
if (mScroller.computeScrollOffset()) {
Log.e(TAG, mScroller.getCurrX() + "======" + mScroller.getCurrY());
// 产生了动画效果 每次滚动一点
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
Log.e(TAG, "### getleft is " + getLeft() + " ### getRight is " + getRight());
//刷新View 否则效果可能有误差
postInvalidate();
}
else
Log.i(TAG, "have done the scoller -----");
}
/////以上可以演示Scroller类的使用
//// --------------------------------
/////--------------------------------
private static final int TOUCH_STATE_REST = 0;
private static final int TOUCH_STATE_SCROLLING = 1;
private int mTouchState = TOUCH_STATE_REST;
//--------------------------
//处理触摸事件 ~
public static int SNAP_VELOCITY = 600 ;
private int mTouchSlop = 0 ;
private float mLastionMotionX = 0 ;
private float mLastMotionY = 0 ;
//处理触摸的速率
private VelocityTracker mVelocityTracker = null ;
// 这个感觉没什么作用 不管true还是false 都是会执行onTouchEvent的 因为子view里面onTouchEvent返回false了
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
Log.e(TAG, "onInterceptTouchEvent-slop:" + mTouchSlop);
final int action = ev.getAction();
//表示已经开始滑动了,不需要走该Action_MOVE方法了(第一次时可能调用)。
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:
Log.e(TAG, "onInterceptTouchEvent move");
final int xDiff = (int) Math.abs(mLastionMotionX - x);
//超过了最小滑动距离
if (xDiff > mTouchSlop) {
mTouchState = TOUCH_STATE_SCROLLING;
}
break;
case MotionEvent.ACTION_DOWN:
Log.e(TAG, "onInterceptTouchEvent down");
mLastionMotionX = x;
mLastMotionY = y;
Log.e(TAG, mScroller.isFinished() + "");
mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING;
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
Log.e(TAG, "onInterceptTouchEvent up or cancel");
mTouchState = TOUCH_STATE_REST;
break;
}
Log.e(TAG, mTouchState + "====" + TOUCH_STATE_REST);
return mTouchState != TOUCH_STATE_REST;
}
public boolean onTouchEvent(MotionEvent event){
Log.i(TAG, "--- onTouchEvent--> " );
// TODO Auto-generated method stub
Log.e(TAG, "onTouchEvent start");
if (mVelocityTracker == null) {
Log.e(TAG, "onTouchEvent start-------** VelocityTracker.obtain");
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(event);
super.onTouchEvent(event);
//手指位置地点
float x = event.getX();
float y = event.getY();
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
//如果屏幕的动画还没结束,你就按下了,我们就结束该动画
if(mScroller != null){
if(!mScroller.isFinished()){
mScroller.abortAnimation();
}
}
mLastionMotionX = x ;
break ;
case MotionEvent.ACTION_MOVE:
int detaX = (int)(mLastionMotionX - x );
scrollBy(detaX, 0);
Log.e(TAG, "--- MotionEvent.ACTION_MOVE--> detaX is " + detaX );
mLastionMotionX = x ;
break ;
case MotionEvent.ACTION_UP:
final VelocityTracker velocityTracker = mVelocityTracker ;
velocityTracker.computeCurrentVelocity(1000);
int velocityX = (int) velocityTracker.getXVelocity() ;
Log.e(TAG , "---velocityX---" + velocityX);
//滑动速率达到了一个标准(快速向右滑屏,返回上一个屏幕) 马上进行切屏处理
if (velocityX > SNAP_VELOCITY && curScreen > 0) {
// Fling enough to move left
Log.e(TAG, "snap left");
snapToScreen(curScreen - 1);
}
//快速向左滑屏,返回下一个屏幕)
else if(velocityX < -SNAP_VELOCITY && curScreen < (getChildCount()-1)){
Log.e(TAG, "snap right");
snapToScreen(curScreen + 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 ;
}
////我们是缓慢移动的
private void snapToDestination(){
//当前的偏移位置
int scrollX = getScrollX() ;
int scrollY = getScrollY() ;
Log.e(TAG, "### onTouchEvent snapToDestination ### scrollX is " + scrollX);
//判断是否超过下一屏的中间位置,如果达到就抵达下一屏,否则保持在原屏幕
//直接使用这个公式判断是哪一个屏幕 前后或者自己
//判断是否超过下一屏的中间位置,如果达到就抵达下一屏,否则保持在原屏幕
// 这样的一个简单公式意思是:假设当前滑屏偏移值即 scrollCurX 加上每个屏幕一半的宽度,除以每个屏幕的宽度就是
// �
没有合适的资源?快使用搜索试试~ 我知道了~
Android中Scroller滑屏实现
共26个文件
class:9个
xml:4个
java:4个
需积分: 10 9 下载量 86 浏览量
2013-11-18
14:45:35
上传
评论
收藏 61KB RAR 举报
温馨提示
Android中滑屏实现----如何实现触摸滑屏以及Scroller类详解
资源推荐
资源详情
资源评论
收起资源包目录
D_ScrollerView.rar (26个子文件)
D_ScrollerView
bin
D_ScrollerView.apk 19KB
classes.dex 11KB
com
qin
scrollerview
MultiViewGroup.class 8KB
MainActivity.class 2KB
MultiScreenActivity.class 2KB
R$layout.class 433B
R$id.class 540B
R$drawable.class 406B
R$attr.class 346B
R.class 545B
R$string.class 433B
qom
qin
scrollerview
resources.ap_ 12KB
res
drawable-ldpi
icon.png 2KB
drawable-hdpi
icon.png 4KB
values
strings.xml 174B
drawable-mdpi
icon.png 3KB
layout
main.xml 1KB
multiview.xml 1KB
assets
default.properties 364B
gen
com
qin
scrollerview
R.java 1KB
qom
qin
scrollerview
src
com
qin
scrollerview
MultiViewGroup.java 11KB
MultiScreenActivity.java 2KB
MainActivity.java 1KB
.project 850B
.classpath 280B
AndroidManifest.xml 982B
共 26 条
- 1
资源评论
Loong.xu
- 粉丝: 9614
- 资源: 68
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功