首先,说一下这个控件实现的功能。
1.EditText中的内容可上下滚动,通过截取ScrollView的触摸事件
2.当EditText中内容滚动到了底部,继续上滑则外面的ScrollView向上滚动
3.当EditText中内容滚动到顶部,继续下滑则外面的ScrollView向下滚动
4.当EditText中无内容,手指在EditText中滑动可以控制ScrollView的滚动
实现上述几个功能之后,基本就可以在项目中使用了。
其实,这个知识点在网上已经有很多种实现了,之前在开发中为了赶时间我也是在网上找了段代码直接用的,结果发现有问题,上述的2,3两点功能未实现,于是自己就优化了一下。
从网络来的当然就得回归到网络,所以就在此分享一下。
实现思路:
1.你得知道TextView中有一个onScrollChanged()方法,这个就是用来查看控件中文字滚动状态的。而EditText继承于TextView。
有了这个方法,我们就可以知道EditText中的文字滚动的距离。
2.在onMeasure()方法中,获取EditText可以滚动的最大距离H_scroll。一个是内容的高度H_content,一个是控件的高度H_view, (H_content - H_view = H_scroll)
这一点有些抽象,大家自己体会体会吧。
3.每次手指按下都重置控件,重新判断是否可以滚动。需复写dispatchTouchEvent()。
4.判断谁来执行滚动。即判断是EditText的内容滚动,还是ScrollView中的内容滚动。而要实现这一点很简单:
getParent().requestDisallowInterceptTouchEvent(true); --------- 拦截父控件的触摸事件,EditText内容滚动
getParent().requestDisallowInterceptTouchEvent(false); --------- 不拦截,父控件中的内容可滚动说完了一二三四,就直接上代码了。大家可以copy下来,直接运行试一下,欢迎提bug和讨论。 收工。package com.shifangdingfu.view.widget; import android.content.Context; import android.text.Layout; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.widget.EditText; /** * Created by Javine on 2016/8/26 0026. * 支持EditText中内容上下滑动,解决与ScrollView滑动冲突的问题 */ public class ScrollEditText extends EditText { private final int MOVE_SLOP = 20; //移动距离临界 //滑动距离的最大边界 private int mOffsetHeight; //是否到顶或者到底的标志 private boolean mBottomFlag = false; private boolean isCanScroll = false;//标记内容是否触发了滚动 private float lastY = 0; public ScrollEditText(Context context) { this(context,null); } public ScrollEditText(Context context, AttributeSet attrs) { super(context,attrs); } public ScrollEditText(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int paddingTop; int paddingBottom; int mHeight; int mLayoutHeight; //获得内容面板 Layout mLayout = getLayout(); mLayoutHeight = mLayout.getHeight(); paddingTop = getTotalPaddingTop(); paddingBottom = getTotalPaddingBottom(); //获得控件的实际高度 mHeight = getHeight(); //计算滑动距离的边界(H_content - H_view = H_scroll) mOffsetHeight = mLayoutHeight + paddingTop + paddingBottom - mHeight; } @Override public boolean dispatchTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN){ //手指按下事件,重置状态 mBottomFlag = false; isCanScroll = false; lastY=0; } return super.dispatchTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { boolean result = super.onTouchEvent(event); //如果是需要拦截,则再拦截,这个方法会在onScrollChanged方法之后再调用一次 if (!mBottomFlag) getParent().requestDisallowInterceptTouchEvent(true); if (event.getAction() == MotionEvent.ACTION_MOVE){ if (lastY == 0){ lastY = event.getRawY(); } //条件:手指move了一段距离,但是onScrollChanged函数未调用,说明文字无法滚动了,则将触摸处理权交还给ParentView if (Math.abs(lastY - event.getRawY()) > MOVE_SLOP){ if (!isCanScroll){ getParent().requestDisallowInterceptTouchEvent(false); } } //Log.d("Javine","ActionMove: "+ lastY + "," + event.getRawY()); } return result; } @Override protected void onScrollChanged(int horiz, int vert, int oldHoriz, int oldVert) { super.onScrollChanged(horiz, vert, oldHoriz, oldVert); isCanScroll = true; //Log.d("Javine","onScrolled "+vert); if (vert == mOffsetHeight || vert == 0) { //这里将处理权交还给父控件 getParent().requestDisallowInterceptTouchEvent(false); mBottomFlag = true; } } }
本文介绍了如何创建一个自定义的ScrollEditText,该控件能实现EditText内容滚动并与外层ScrollView联动。功能包括:EditText内容滚动、滚动到底部时继续上滑使ScrollView滚动、无内容时控制ScrollView滚动。作者针对网上找到的代码存在的问题进行了优化,通过监听TextView的onScrollChanged()方法和计算最大滚动距离等实现这些功能。
212

被折叠的 条评论
为什么被折叠?



