Android学习Scroller(四)——实现拉动后回弹的布局

简介: PS:该篇博客已经deprecated,不再维护,详情请参见 站在源码的肩膀上全解Scroller工作机制 http://blog.csdn.net/lfdfhl/article/details/53143114MainActivity如下:package cc.



PS:

该篇博客已经deprecated,不再维护,详情请参见 

站在源码的肩膀上全解Scroller工作机制

 http://blog.csdn.net/lfdfhl/article/details/53143114


MainActivity如下:

package cc.testscroller2;

import android.os.Bundle;
import android.app.Activity;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
	}

	
}


BounceableLinearLayout如下:

package cc.testscroller2;
import android.content.Context;  
import android.util.AttributeSet;  
import android.view.GestureDetector;  
import android.view.MotionEvent;  
import android.widget.LinearLayout;  
import android.widget.Scroller;  
/**
 * 总体思路:
 * 处理View的Touch事件,即重写onTouchEvent()方法:
 * 当手指抬起时将其回到原点,其余情况交给GestureDetector处理.
 * 
 * 在GestureDetector中重点是覆写onScroll()方法.在该方法中得到
 * Y方向滑动的距离,从而设置 mScroller.startScroll()方法,准备滑动.
 * 随之刷新界面invalidate()从而执行方法computeScroll().
 * 在computeScroll()方法中调用 scrollTo()方法实现真正的滑动.
 * 
 * 注意事项:
 * 1 scrollTo()方法的参数:
 *   scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
 *   并且在此之后也要调用postInvalidate()进行刷新 
 * 
 * 
 * 方法说明:
 * 1 mScroller.getFinalX(Y)()
 *   The final X(Y) offset as an absolute distance from the origin.
 *   返回滚动结束位置(得到当前X(Y)距离原始位置的值).仅针对"fling"滚动有效.
 *   也就是说该方法是针对滚动结束而言的.
 *   
 *   坐标方向:
 *   X方向的距离,正数向左,负数向右
 *   Y方向的距离,正数向上,负数向下
 *   
 * 2 mScroller.getCurrX(Y)()
 *   The new X offset as an absolute distance from the origin.
 *   The new Y offset as an absolute distance from the origin.
 *   返回当前滚动 X(Y)方向的偏移
 *   也就是说该方法是针对滚动中而言的.
 *   
 *   坐标方向:
 *   X方向的距离,正数向左,负数向右
 *   Y方向的距离,正数向上,负数向下
 *   
 *   
 * 3 startScroll(int startX, int startY, int dx, int dy, int duration)
 *   第一,二个参数起始位置;第三,四个滚动的偏移量;第五个参数持续时间
 *   
 *
 */
public class BounceableLinearLayout extends LinearLayout {  
    private Scroller mScroller;  
    private GestureDetector mGestureDetector;  
      
    public BounceableLinearLayout(Context context) {  
        this(context, null);  
    }  
      
    public BounceableLinearLayout(Context context, AttributeSet attrs) {  
        super(context, attrs);  
        setClickable(true);  
        setLongClickable(true);  
        mScroller = new Scroller(context);  
        mGestureDetector = new GestureDetector(context, new GestureListenerImpl());  
    }  
  
      
    @Override  
    public void computeScroll() {  
        if (mScroller.computeScrollOffset()) {  
        	System.out.println("computeScroll()---> "+
        	                   "mScroller.getCurrX()="+mScroller.getCurrX()+","+
        			           "mScroller.getCurrY()="+mScroller.getCurrY());
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());  
            //必须执行postInvalidate()从而调用computeScroll()
            //其实,在此调用invalidate();亦可
            postInvalidate(); 
        }  
        super.computeScroll();  
    }  
      
    @Override  
    public boolean onTouchEvent(MotionEvent event) {  
        switch (event.getAction()) {  
       case MotionEvent.ACTION_UP :  
    	   //手指抬起时回到最初位置
           prepareScroll(0, 0);  
            break;  
        default:  
        	//其余情况交给GestureDetector手势处理
            return mGestureDetector.onTouchEvent(event);  
      }  
       return super.onTouchEvent(event);  
   }  
    
  
	class GestureListenerImpl implements GestureDetector.OnGestureListener {
		@Override
		public boolean onDown(MotionEvent e) {
			return true;
		}

		@Override
		public void onShowPress(MotionEvent e) {

		}

		@Override
		public boolean onSingleTapUp(MotionEvent e) {
			return false;
		}

		//控制拉动幅度:
		//int disY=(int)((distanceY - 0.5)/2);
		//亦可直接调用:
		//smoothScrollBy(0, (int)distanceY);
		@Override
		public boolean onScroll(MotionEvent e1, MotionEvent e2,float distanceX, float distanceY) {
			int disY = (int) ((distanceY - 0.5) / 2);
			beginScroll(0, disY);
			return false;
		}

		public void onLongPress(MotionEvent e) {

		}

		@Override
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) {
			return false;
		}

	}  
	
	  
    //滚动到目标位置 
    protected void prepareScroll(int fx, int fy) {  
        int dx = fx - mScroller.getFinalX();  
        int dy = fy - mScroller.getFinalY();  
        beginScroll(dx, dy);  
    }  
  
    
     //设置滚动的相对偏移 
    protected void beginScroll(int dx, int dy) {  
    	System.out.println("smoothScrollBy()---> dx="+dx+",dy="+dy);
    	//第一,二个参数起始位置;第三,四个滚动的偏移量
        mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), dx, dy);  
        System.out.println("smoothScrollBy()---> " +
        		           "mScroller.getFinalX()="+mScroller.getFinalX()+","+
        		           "mScroller.getFinalY()="+mScroller.getFinalY());
        
        //必须执行invalidate()从而调用computeScroll()
        invalidate();
    } 
    
      
	
	
}  

 


main.xml如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <cc.testscroller2.BounceableLinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="向下拉动后松开" 
        />
        
    </cc.testscroller2.BounceableLinearLayout>

</RelativeLayout>


PS:

该篇博客已经deprecated,不再维护,详情请参见 

站在源码的肩膀上全解Scroller工作机制

 http://blog.csdn.net/lfdfhl/article/details/53143114

相关文章
|
2月前
|
ARouter Android开发
Android不同module布局文件重名被覆盖
Android不同module布局文件重名被覆盖
|
4月前
|
移动开发 监控 前端开发
构建高效Android应用:从优化布局到提升性能
【7月更文挑战第60天】在移动开发领域,一个流畅且响应迅速的应用程序是用户留存的关键。针对Android平台,开发者面临的挑战包括多样化的设备兼容性和性能优化。本文将深入探讨如何通过改进布局设计、内存管理和多线程处理来构建高效的Android应用。我们将剖析布局优化的细节,并讨论最新的Android性能提升策略,以帮助开发者创建更快速、更流畅的用户体验。
76 10
|
3月前
|
Java Maven 开发工具
第一个安卓项目 | 中国象棋demo学习
本文是作者关于其第一个安卓项目——中国象棋demo的学习记录,展示了demo的运行结果、爬坑记录以及参考资料,包括解决Android Studio和maven相关问题的方法。
第一个安卓项目 | 中国象棋demo学习
|
2月前
|
Web App开发 编解码 视频直播
视频直播技术干货(十二):从入门到放弃,快速学习Android端直播技术
本文详细介绍了Android端直播技术的全貌,涵盖了从实时音视频采集、编码、传输到解码与播放的各个环节。文章还探讨了直播中音视频同步、编解码器选择、传输协议以及直播延迟优化等关键问题。希望本文能为你提供有关Andriod端直播技术的深入理解和实践指导。
58 0
|
2月前
|
ARouter Android开发
Android不同module布局文件重名被覆盖
Android不同module布局文件重名被覆盖
174 0
|
3月前
|
Android开发
Android学习 —— 测试init.rc中的条件触发的处理顺序
Android学习 —— 测试init.rc中的条件触发的处理顺序
|
4月前
|
编解码 Android开发
【Android Studio】使用UI工具绘制,ConstraintLayout 限制性布局,快速上手
本文介绍了Android Studio中使用ConstraintLayout布局的方法,通过创建布局文件、设置控件约束等步骤,快速上手UI设计,并提供了一个TV Launcher界面布局的绘制示例。
74 1
|
4月前
|
搜索推荐 Android开发
学习AOSP安卓系统源代码,需要什么样的电脑?不同配置的电脑,其编译时间有多大差距?
本文分享了不同价位电脑配置对于编译AOSP安卓系统源代码的影响,提供了从6000元到更高价位的电脑配置实例,并比较了它们的编译时间,以供学习AOSP源代码时电脑配置选择的参考。
310 0
学习AOSP安卓系统源代码,需要什么样的电脑?不同配置的电脑,其编译时间有多大差距?
|
5月前
|
Android开发 Kotlin
kotlin开发安卓app,如何让布局自适应系统传统导航和全面屏导航
使用`navigationBarsPadding()`修饰符实现界面自适应,自动处理底部导航栏的内边距,再加上`.padding(bottom = 10.dp)`设定内容与屏幕底部的距离,以完成全面的布局适配。示例代码采用Kotlin。
142 15
|
4月前
|
XML 数据可视化 API
Android经典实战之约束布局ConstraintLayout的实用技巧和经验
ConstraintLayout是Android中一款强大的布局管理器,它通过视图间的约束轻松创建复杂灵活的界面。相较于传统布局,它提供更高灵活性与性能。基本用法涉及XML定义约束,如视图与父布局对齐。此外,它支持百分比尺寸、偏移量控制等高级功能,并配有ConstraintSet和编辑器辅助设计。合理运用可显著提高布局效率及性能。
274 0