Android仿人人客户端(v5(5)

在MotionEvent.ACTION_MOVE代码块中,发现条件是满足的,返回true。表示和MotionEvent.ACTION_DOWN的一样,在后续的回调方法内Action move将不再处理。最后看当手指抬起,处理的代码如下:


  case MotionEvent.ACTION_UP:

            Log.i(TAG, "dispatchTouchEvent():  ACTION_UP");

            

            if (isClick && mPanelInvisible && mAllowScroll) {

                isClick = false;

                mPanelInvisible = false;

                

                int scrollX = getChildAt(1).getScrollX();

                mScroller.startScroll(scrollX, 0, -scrollX, 0, ANIMATION_DURATION_TIME);

                invalidate();

                

                return true;

            }

            

            break;

上面的代码片段含义:当用户手指在屏幕上按下,当前ViewGroup中没有子View正在滚动,左侧面板处于可见,手指按下的坐标X值是在手柄(B视图的当前可见部分)的宽度范围内,则down事件到此处理结束。在move代码块里同样判断用户当前手指按下的坐标X值是在手柄宽度范围内的,则move事件也到此结束。在手指抬起后,up事件里判断在down是事件里设置的标识,发现条件都满足,响应用户在手柄上的单击事件请求。也就是说父View把用户的请求已响应了,不用传递到子View。子View也不知道发生过这件事。(大概意思就是这样)

触控区域太大的问题,每次都判断用户手指按下的坐标x值,是否在手柄宽度范围内(不管左侧面板是否可见)。灵敏度的问题,其实就是响应滚动子View的临界值的大小问题,值越小灵敏都越高。

ScrollerContainer类,修改后的代码如下:


package com.everyone.android.widget;



import android.content.Context;

import android.util.Log;

import android.util.TypedValue;

import android.view.MotionEvent;

import android.view.VelocityTracker;

import android.view.ViewConfiguration;

import android.widget.RelativeLayout;

import android.widget.Scroller;



/**

 * 功能描述:手指在屏幕上左右滑动时,该类的实例负责让其子View根据用户的手势左右偏移(滚动)

 * 

 * @author android_ls

 */

public class ScrollerContainer extends RelativeLayout {



    private static final String TAG = "ScrollerContainer";



    private Scroller mScroller;



    private VelocityTracker mVelocityTracker;



    /**

     * 手柄(手把)的宽度

     */

    private int mHandlebarWidth;



    /**

     * 在偏移过程中,动画持续的时间

     */

    private static final int ANIMATION_DURATION_TIME = 300;

    

    /**

     * 记录当前的滑动结束后的状态,左侧面板是否可见

     * true  向右滑动(左侧面板处于可见)

     * false 向左滑动(左侧面板处于不可见)

     */

    private boolean mPanelInvisible;

    

    /**

     * 是否已滑动结束

     */

    private boolean mFinished;

    

    /**

     * 是否允许滚动

     * 满足的条件:

     *     左侧面板可见,当前手指按下的坐标x值 ,是在手柄宽度范围内;

     *     左侧面板不可见,当前手指按下的坐标x值 < 手柄宽度

     */

    private boolean mAllowScroll;

    

    /**

     * 是否满足响应单击事件的条件

     * 满足的条件:左侧面板可见,当前手指按下的坐标x值 ,是在手柄宽度范围内

     */

    private boolean isClick;

    

    public ScrollerContainer(Context context) {

        super(context);



        mScroller = new Scroller(context);

        mHandlebarWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 70, getResources().getDisplayMetrics());

    }

    

    @Override

    public boolean dispatchTouchEvent(MotionEvent ev) {

        Log.e(TAG, "dispatchTouchEvent()");

        

        switch (ev.getAction()) {

        case MotionEvent.ACTION_DOWN:

            Log.i(TAG, "dispatchTouchEvent():  ACTION_DOWN");

            

            mFinished = mScroller.isFinished();

            if(mFinished){

                int x = (int) ev.getX();

                int width = getWidth();

                

                if(mPanelInvisible)// 左侧面板可见

                {

                    if(x > (width - mHandlebarWidth)){ // 当前手指按下的坐标x值 ,是在手柄宽度范围内

                        isClick = true;

                        mAllowScroll = true;

                        return true;

                    } else {

                        isClick = false;

                        mAllowScroll = false;

                    }

                } else { // 左侧面板不可见

                    if(x < mHandlebarWidth ){ // 当前手指按下的坐标x值 < 手柄宽度 (也就是说在手柄宽度范围内,是可以相应用户的向右滑动手势)

                        mAllowScroll = true;

                    }else{

                        mAllowScroll = false;

                    }

                }

                

            } else {

                // 当前正在滚动子View,其它的事不响应

                return false;

            }

            

            break;



        case MotionEvent.ACTION_MOVE:

            Log.i(TAG, "dispatchTouchEvent():  ACTION_MOVE");

            int margin = getWidth() - (int) ev.getX();

            if (margin < mHandlebarWidth && mAllowScroll) {

                

                Log.e(TAG, "dispatchTouchEvent ACTION_MOVE margin = " + margin + "\t mHandlebarWidth = " + mHandlebarWidth);

                return true;

            }

            

            break;

        case MotionEvent.ACTION_UP:

            Log.i(TAG, "dispatchTouchEvent():  ACTION_UP");

            

            if (isClick && mPanelInvisible && mAllowScroll) {

                isClick = false;

                mPanelInvisible = false;

                

                int scrollX = getChildAt(1).getScrollX();

                mScroller.startScroll(scrollX, 0, -scrollX, 0, ANIMATION_DURATION_TIME);

                invalidate();

                

                return true;

            }

            

            break;

        case MotionEvent.ACTION_CANCEL:

            Log.i(TAG, "dispatchTouchEvent():  ACTION_CANCEL");

            break;

        default:

            break;

        }

        

        return super.dispatchTouchEvent(ev);

    }

    

    @Override

    public boolean onInterceptTouchEvent(MotionEvent ev) {

        Log.e(TAG, "onInterceptTouchEvent()");

        

        switch (ev.getAction()) {

        case MotionEvent.ACTION_DOWN:

            Log.i(TAG, "onInterceptTouchEvent():  ACTION_DOWN");

            mFinished = mScroller.isFinished();

            if(!mFinished){

                return false;

            }

            

            break;

        case MotionEvent.ACTION_MOVE:

            Log.i(TAG, "onInterceptTouchEvent():  ACTION_MOVE");

            

            mVelocityTracker = VelocityTracker.obtain();

            mVelocityTracker.addMovement(ev);

            

            // 一秒时间内移动了多少个像素

            mVelocityTracker.computeCurrentVelocity(1000, ViewConfiguration.getMaximumFlingVelocity());

            float velocityValue = Math.abs(mVelocityTracker.getXVelocity()) ;

            Log.d(TAG, "onInterceptTouchEvent():  mVelocityValue = " + velocityValue);

            

            if (velocityValue > 300 && mAllowScroll) {

                return true;

            }

            

            break;

        case MotionEvent.ACTION_UP:

            Log.i(TAG, "onInterceptTouchEvent():  ACTION_UP");

            

            if (mVelocityTracker != null) {

                mVelocityTracker.recycle();

                mVelocityTracker = null;

            }

            

            break;

        case MotionEvent.ACTION_CANCEL:

            Log.i(TAG, "onInterceptTouchEvent():  ACTION_CANCEL");

            break;

        default:

            break;

        }

        

        return super.onInterceptTouchEvent(ev);

    }



    @Override

    public boolean onTouchEvent(MotionEvent event) {

        Log.e(TAG, "onTouchEvent()");



        float x = event.getX();

        

        switch (event.getAction()) {

        case MotionEvent.ACTION_DOWN:

            Log.i(TAG, "onTouchEvent():  ACTION_DOWN");

            mFinished = mScroller.isFinished();

            if(!mFinished){

                return false;

            }

            break;



        case MotionEvent.ACTION_MOVE:

            Log.i(TAG, "onTouchEvent():  ACTION_MOVE");

            getChildAt(1).scrollTo(-(int)x, 0);

            break;



        case MotionEvent.ACTION_UP:

            Log.i(TAG, "onTouchEvent():  ACTION_UP");

            

            if(!mAllowScroll){

                break;

            }

            

           float width = getWidth();

           // 响应滚动子View的临界值,若觉得响应过于灵敏,可以将只改大些。

           // 比如:criticalWidth = width / 3或criticalWidth = width / 2,看情况而定,呵呵。

           float criticalWidth = width / 5;

           

           Log.i(TAG, "onTouchEvent():  ACTION_UP x = " + x + "\t criticalWidth = " + criticalWidth);

           

           int scrollX = getChildAt(1).getScrollX();

           

           if ( x < criticalWidth) {

               Log.i(TAG, "onTouchEvent():  ACTION_UP 向左滑动");

               

                mPanelInvisible = false;

               

                mScroller.startScroll(scrollX, 0, -scrollX, 0, ANIMATION_DURATION_TIME);

                invalidate();

            } else if ( x > criticalWidth){

                Log.i(TAG, "onTouchEvent():  ACTION_UP 向右滑动");

              

                mPanelInvisible = true;

                

                int toX = (int)(width - Math.abs(scrollX) - mHandlebarWidth);

                mScroller.startScroll(scrollX, 0, -toX, 0, ANIMATION_DURATION_TIME);

                invalidate();

            }

            

            break;

        case MotionEvent.ACTION_CANCEL:

            Log.i(TAG, "onTouchEvent():  ACTION_CANCEL");

            break;

        default:

            break;

        }

        

        return super.onTouchEvent(event);

    }



    @Override

    public void computeScroll() {

        // super.computeScroll();

        

        if(mScroller.computeScrollOffset()){

            this.getChildAt(1).scrollTo(mScroller.getCurrX(), mScroller.getCurrY());

            this.postInvalidate();

        }

    }



    /**

     * 向右滑动View,让左侧操作面饭可见

     */

    public void slideToRight() {

        mFinished = mScroller.isFinished();

        if(mFinished && !mPanelInvisible){

            mPanelInvisible = true;

            

            float width = getWidth();

            int scrollX = getChildAt(1).getScrollX();


#### Android开发除了flutter还有什么是必须掌握的吗?

相信大多数从事Android开发的朋友们越来越发现,找工作越来越难了,面试的要求越来越高了

除了基础扎实的java知识,数据结构算法,设计模式还要求会底层源码,NDK技术,性能调优,还有会些小程序和跨平台,比如说flutter,以思维脑图的方式展示在下图;

![](https://img-blog.csdnimg.cn/img_convert/c5f768c69d36f8b7720521a96ced063b.webp?x-oss-process=image/format,png)





**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化学习资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618156601)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**


            mPanelInvisible = true;

            

            float width = getWidth();

            int scrollX = getChildAt(1).getScrollX();


#### Android开发除了flutter还有什么是必须掌握的吗?

相信大多数从事Android开发的朋友们越来越发现,找工作越来越难了,面试的要求越来越高了

除了基础扎实的java知识,数据结构算法,设计模式还要求会底层源码,NDK技术,性能调优,还有会些小程序和跨平台,比如说flutter,以思维脑图的方式展示在下图;

[外链图片转存中...(img-e7xOi3DL-1714361091081)]





**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化学习资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618156601)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值