关于Scroller的学习及相关的知识笔记get
来源:互联网 发布:赈灾晚会的数据统计 编辑:程序博客网 时间:2024/04/30 13:37
<span style="font-size:24px;">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绘制流程,这儿我们在强制绘制下Viewinvalidate();}//停止滑屏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 ;} }elseLog.i(TAG, "----OK mScroller.is finished ---- ");}// 只有当前LAYOUT中的某个CHILD导致SCROLL发生滚动,才会致使自己的COMPUTESCROLL被调用@Overridepublic void computeScroll() {// TODO Auto-generated method stubLog.e(TAG, "computeScroll");// 如果返回true,表示动画还没有结束// 因为前面startScroll,所以只有在startScroll完成时 才会为falseif (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();}elseLog.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了@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {// TODO Auto-generated method stubLog.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;}Log.i("-------onInterceptTouchEvent--------------", "ACTION_MOVE");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;Log.i("-------onInterceptTouchEvent--------------", "ACTION_DOWN");break;case MotionEvent.ACTION_CANCEL:case MotionEvent.ACTION_UP:Log.e(TAG, "onInterceptTouchEvent up or cancel");mTouchState = TOUCH_STATE_REST;Log.i("-------onInterceptTouchEvent--------------", "ACTION_UP");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 stubLog.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 ; Log.i("-------onTouchEvent--------------", "ACTION_DOWN");break ;case MotionEvent.ACTION_MOVE:int detaX = (int)(mLastionMotionX - x );scrollBy(detaX, 0);//在当前的位置移动detaX个单位Log.e(TAG, "--- MotionEvent.ACTION_MOVE--> detaX is " + detaX );mLastionMotionX = x ;Log.i("-------onTouchEvent--------------", "ACTION_MOVE");break ;case MotionEvent.ACTION_UP:final VelocityTracker velocityTracker = mVelocityTracker ;velocityTracker.computeCurrentVelocity(1000);int velocityX = (int) velocityTracker.getXVelocity() ;Log.e("###############################" , "---velocityX---" + velocityX);//滑动速率达到了一个标准(快速向右滑屏,返回上一个屏幕) 马上进行切屏处理if (velocityX > SNAP_VELOCITY && curScreen > 0) {// Fling enough to move leftLog.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 ;Log.i("-------onTouchEvent--------------", "ACTION_UP"); 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 加上每个屏幕一半的宽度,除以每个屏幕的宽度就是// 我们目标屏所在位置了。 假如每个屏幕宽度为320dip, 我们滑到了500dip处,很显然我们应该到达第二屏int destScreen = (getScrollX() + getWidth() / 2 ) / getWidth() ; Log.e(TAG, "### onTouchEvent ACTION_UP### dx destScreen " + destScreen);snapToScreen(destScreen);} private void snapToScreen(int whichScreen){ //简单的移到目标屏幕,可能是当前屏或者下一屏幕 //直接跳转过去,不太友好 //scrollTo(mLastScreen * getWidth(), 0); //为了友好性,我们在增加一个动画效果 //需要再次滑动的距离 屏或者下一屏幕的继续滑动距离 curScreen = whichScreen ; if(curScreen > getChildCount() - 1) curScreen = getChildCount() - 1 ; int dx = curScreen*getWidth() - getScrollX() ; Log.e(TAG, "### onTouchEvent ACTION_UP### dx is " + dx); mScroller.startScroll(getScrollX(), 0, dx, 0,Math.abs(dx) * 2); //此时需要手动刷新View 否则没效果 invalidate(); } private void init() {mScroller = new Scroller(mContext);// 初始化3个 LinearLayout控件LinearLayout oneLL = new LinearLayout(mContext);oneLL.setBackgroundColor(Color.RED); addView(oneLL);LinearLayout twoLL = new LinearLayout(mContext);twoLL.setBackgroundColor(Color.YELLOW);addView(twoLL);LinearLayout threeLL = new LinearLayout(mContext);threeLL.setBackgroundColor(Color.BLUE);addView(threeLL);//初始化一个最小滑动距离mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();}// measure过程@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {Log.i(TAG, "--- start onMeasure --");// 设置该ViewGroup的大小int width = MeasureSpec.getSize(widthMeasureSpec);int height = MeasureSpec.getSize(heightMeasureSpec);setMeasuredDimension(width, height);int childCount = getChildCount();Log.i(TAG, "--- onMeasure childCount is -->" + childCount);for (int i = 0; i < childCount; i++) {View child = getChildAt(i);// 设置每个子视图的大小 , 即全屏child.measure(getWidth(), MultiScreenActivity.scrrenHeight);}}private int curPage = 0 ;// layout过程@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {// TODO Auto-generated method stubLog.i(TAG, "--- start onLayout --");int startLeft = 0; // 每个子视图的起始布局坐标int startTop = 10; // 间距设置为10px 相当于 android:marginTop= "10px"int childCount = getChildCount();Log.i(TAG, "--- onLayout childCount is -->" + childCount );for (int i = 0; i < childCount; i++) {View child = getChildAt(i);//即使可见的,才划到屏幕上if(child.getVisibility() != View.GONE) child.layout(startLeft, startTop, startLeft + getWidth(), startTop + MultiScreenActivity.scrrenHeight ); startLeft = startLeft + getWidth() ; //校准每个子View的起始布局位置 //三个子视图的在屏幕中的分布如下 [0 , 320] / [320,640] / [640,960]}}}</span>
Android中滑屏初探 ---- scrollTo 以及 scrollBy方法使用说明
http://blog.csdn.net/qinjuning/article/details/7247126
Android中滑屏实现----手把手教你如何实现触摸滑屏以及Scroller类详解
http://www.cnblogs.com/wanqieddy/archive/2012/05/05/2484534.html
//笔记
scrollby(x,y)在x,y轴平移x,y个单位,如果x为负数,手势是往右触摸移动,正数则相反
Scroller 的 getCurX()值没有正负之分,表示移动距离
void android.widget.Scroller.startScroll(int startX,int startY, int dx, int dy, int duration)从某个坐标位置滚动多少个像素startX: X轴方向滚动起始位置startY: Y轴方向滚动的起始位置dx: X轴方向的滚动像素 ,dx为正数向屏幕左边滚动,反之则相反dy:Y轴方向的滚动像素,dy为正数向屏幕上方移动,反之则相反
0 0
- 关于Scroller的学习及相关的知识笔记get
- 关于struts1的相关知识学习
- 学习BMP相关知识的笔记
- 关于Scroller的理解
- 关于 Scroller的
- Android View学习笔记(三):Scroller的原理剖析及使用(上)
- Android View学习笔记(四):Scroller的原理剖析及使用(下)
- C/C++及相关知识学习笔记
- 算法及相关知识学习笔记
- Scroller的学习
- 学习笔记——HashMap的底层结构及相关知识
- 关于umask及相关权限知识的整理
- 关于eternal blue virus的预防操作及相关知识
- 关于Struts2的相关知识总结及应用
- 关于Android初学者的学习线路的相关知识
- 关于GTK的相关知识
- 关于流的相关知识
- 关于IHttpModule的相关知识
- eclipse下tomcat热部署(无需插件)
- HDOJ 2401 Baskets of Gold Coins
- Java基础知识1
- 用户注册信息的验证与数据回显
- Cordova 5.1.1在Mac终端创建iOS工程并添加插件
- 关于Scroller的学习及相关的知识笔记get
- XFire发布Web Services
- 移动开发的软件开发生命周期介绍(一)
- 杭州电子科技大学acm--2090
- 【软考】-数据库
- Android:对ListView原理的理解
- 简单理解Java异常处理机制
- PHP的常量及变量
- [LeetCode-88] Merge Sorted Array(合并有序数组)