美文网首页
带切换确认的RadioGroup

带切换确认的RadioGroup

作者: 榕城歌者 | 来源:发表于2019-05-16 18:50 被阅读0次

    作者在编写一个文章编辑页面,效果图如下:


    微信图片_20190516175329.png

    在完成Beta版本之后,被要求增加一个小需求,要求在切换页面的时候,必须对原来页面的内容进行判断,如果页面没有内容,那么直接切换过去;假如原页面含有内容,需要弹出一个对话框,让用户二次确认。效果如下:


    微信图片_20190516175345.png

    由于UI上有对两个Title下划线指示器长短的要求,所以采用了ViewPager+RadioGroup来实现这个页面。
    关于如何自定义实现指示器长度,作者采用的是RadioGroup,通过修改背景来实现。
    背景实现可以参考另一篇文章:
    Shape为View定制下划线
    也通过其它方式去修改Title下划线指示器的文章:
    Android 自定义ViewPager下划线指示器Indicator长度
    本篇文章的重点不是在此,便不再细说。
    为了能切换的时候,弹出确认框。作者给每一个RadioButton增加点击监听:

     opinionRadioButton.setOnClickListener {
                if(页面是否有输入内容){
                    弹出切换确认对话框
                }else{
                    直接切换过去
                }
            }
    

    运行之后,发现页面毫无波澜。代码没有执行OnClickListener里面的onClick方法。事件被消费掉了,没有下发到RadioButton的OnClickListener。
    所以,问题的核心就是截取点击事件,不能让RadioButton或者RadioGroup消费掉,我们要自己决定是否消费掉这个事件。
    了解事件分发的原理,我们都知道,事件分发都是从上层交给下层进行的。也就是容器类ViewGroup首先会将事件分发给下面的子View,如果子View不处理,ViewGroup才去处理。
    而截取事件,就是要打断事件下发的流程。按照业务逻辑,那就是页面内容决定了是否拦截。
    这样看起来,思路就简单多了。在RadioGroup判断是否拦截事件,如果需要拦截,那么自身消费掉。
    需要自定义一个RadioGroup,重写onInterceptTouchEvent方法,控制RadioGroup是否消费事件。

    public class InterceptRadioGroup extends RadioGroup {
    
        private InterceptListener externalListener;
    
        public InterceptRadioGroup(Context context) {
            super(context);
        }
    
        public InterceptRadioGroup(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            if (externalListener != null) {
                if (externalListener.onExternalIntercept(ev)) {
                    return true;
                }
                return super.onInterceptTouchEvent(ev);
            }
            return super.onInterceptTouchEvent(ev);
        }
    
        public View findViewByXY(float x, float y) {
            View v = null;
            for (int i = 0; i < getChildCount(); i++) {
                View child = getChildAt(i);
                Rect rect = new Rect(child.getLeft(), child.getTop(), child.getRight(), child.getBottom());
                if (!rect.contains((int) x, (int) y)) {
                    continue;
                }
                v = child;
                break;
            }
    
            return v;
        }
    
    
        public void setExternalListener(InterceptListener externalListener) {
            this.externalListener = externalListener;
        }
    
        public interface InterceptListener {
            boolean onExternalIntercept(MotionEvent ev);
        }
    }
    

    定义一个InterceptListener接口,里面只有一个回调方法onExternalIntercept,返回true则表示消费掉这个事件。onInterceptTouchEvent的核心就是调用这个方法来决定是否继续下发事件,以此打断RadiaoGroup的切换。
    具体实现:

    typeRadioGroup.setExternalListener(object : InterceptRadioGroup.InterceptListener {
                override fun onExternalIntercept(ev: MotionEvent?): Boolean {
                    //如果页面没有内容不拦截,isNOtInterceptEvent()是true,onExternalIntercept返回false
                    if (isNOtInterceptEvent()) {
                        return false;
                    }
                    var result = false
                    ev?.let {
                        //判断点击到哪个Button
                        val view = typeRadioGroup.findViewByXY(ev.x, ev.y)
                        if (view is RadioButton) {
                            val button = view as RadioButton
                            //过滤重复点击
                            if (button.isChecked) {
                                result = false
                            } else {
                                //弹出确认框,onExternalIntercept返回true,不让事件继续下发
                                val switchDialog = BaseRemindDialog.Build(this@EditArticleActivity)
                                        .setTitle(getString(R.string.dialog_title_tip))
                                        .setContent(getString(R.string.text_ensure_switch_edit))
                                        .setLeftBtn(getString(R.string.text_cancel))
                                        .setRightBtn(getString(R.string.text_confirm))
                                        .setRightColor(ContextCompat.getColor(this@EditArticleActivity, R.color.text_color_black))
                                        .setListent(object : BaseRemindDialog.OnClickListent {
                                            override fun onLeftClick() {
    
                                            }
    
                                            override fun onRightClick() {
                                                //事件已经被消费了,需要手动去修改RadioButton的选中状态
                                                typeRadioGroup.check(view.id)
                                            }
    
                                        }).build()
                                switchDialog.show()
                            }
                            result = true
                        } else {
                            result = false
                        }
                    }
                    return result
                }
    
            })
    

    相关文章

      网友评论

          本文标题:带切换确认的RadioGroup

          本文链接:https://www.haomeiwen.com/subject/bpcwaqtx.html