[Android]Button超出布局显示及点击&view超出父view无法响应点击事件

摘要

  • 关于Android子view超出父view点击事件失效问题
  • 例如button超出父布局之外的点击事件无效

首先看一下结构图

[Android]Button超出布局显示及点击&view超出父view无法响应点击事件_第1张图片

我根布局用的LinearLayout;
然后嵌套了一个一定高度的LinearLayout;为上图顶部宽度撑满父元素的矩形框;称之为“线布2”;
线布2 里又水平布局了两个线性布局;
左边的线性布局不管; 右边的线性布局里嵌套了4个button按钮;

现在的问题是:

  1. 超出 线布2 的3个button按钮无法显示;
  2. 超出 线布2 的3个button按钮无法响应点击事件;

对于问题一:

我们想要显示溢出的3个button按钮,在 线布2 里的右布局中;
所以我们让这个右布局能溢出显示就好了;

相关代码

android:clipChildren="false"
android:clipToPadding="false"

官方对于第一行的解释:

Defines whether a child is limited to draw inside of its bounds or not.
翻译:定义一个子视图是否局限于它的范围内。
所以我们设置为false,让子视图不局限与自己;

官方对于第二行的解释:

Defines whether the ViewGroup will clip its drawing surface so as to exclude the padding area.
翻译:定义ViewGroup是否将剪辑其绘图表面以排除填充区域。
由于笔者是Android新手,对此表示不太理解,也没有去研究它
(刚入手Android开发一周,只为做一个作品参加学校比赛,不过这作品也是我用心良苦的设计,欢迎大家点击下方链接体验^ _ ^);

  • 对此我们解决了第一个问题,不过笔者实验了一番,发现把上述两行代码加在 线布2 的xml里,并没有显示 线布2 里溢出的右布局,也就是说那几个button按钮还是看不见;
  • 我搜索问题时,说是上述两行代码是作用于 孙子视图 与 儿子视图;在此不解释孙子与儿子视图;
  • 而我的 线布2 的父布局正是根布局,也就是说我需要在根布局中使用这两个参数,才可以使 线布2 里的右布局溢出于 线布2 显示;
    实验成功;

笔者项目中,该问题用了一下午才解决,其实主要是首次开发,布局文件过于混乱,所以致使上述参数不生效,(但是我在所有布局标签加上也不生效,这点很纳闷)无奈之下,我把主要的布局文件分离开来,再使用include引入;
模块化确实方便,嘻嘻;

对于问题二:

  • 让溢出的button按钮可点击
  • 这个问题花费了我半天时间,一直搜找解决方案,遗憾的是,相关问题少,解决方案无用;
  • 所以我尝试自己解决此问题,可谓是另辟蹊跷;

先介绍我搜索的解决方案,在此归纳成两条:

1. 使用android:focusable="true"参数

android:focusable="true"
其解释为:是否可聚焦,也是是否可点击
——
我把此参数在所有控件及布局中放了个遍,也无法触发溢出的按钮
——
我也搜找到相关的参数,同样无法点击。
——
我以为是下边的布局覆盖掉了溢出的按钮
——
然后我使用相对布局作为根布局,让有button的布局最后绘制,但结果是lose
——
我摸了摸秃头,发现事态不对劲,遂重建test布局,测试了一番;
——
发现没有其他布局的时候,也点击不了;
——
事情发展到这一步,我想我已经看破红尘…哦不是看破Layout了、手动滑稽
——
杰伦–结论:
所有溢出父布局的控件,无法响应事件,但通过参数可以显示;

其实这个结论是我自己臆想的,但是我实在是找不到方法;

  • 这个世界的真理和公理,都是观物者们眼中的事物;//突然哲学

2. 拒绝使用布局进行嵌套

  • 这个方案就是取消 线布2 布局,这样就没有布局去限制 线布2 中的button了;
  • 但是,热爱模块化的我怎么会让button组脱离组织呢;(其实我差点就屈服于这个方案了)
    这种方案就不做详细解释;让我们直接进入下一环:另辟蹊跷

另辟蹊跷:

  • 我想着如果能在整个Activity窗口捕捉点击事件,就好办了;

public boolean onTouchEvent(MotionEvent event);
果然,程序员的直觉
——
只需要在Activity代码区重写此方法就好了;
不过他只返回布尔值,其值含义为是否触摸了屏幕;
聪明的我怎能让他只干这件事;
遂:

@Override
public boolean onTouchEvent(MotionEvent event) {
    //首先定义一个数组用来接收按钮的坐标xy值
    int[] xy = new int[2];
    
    //获取按钮的top/left xy值
    //button变量我在onCreat()函数中已经获取了控件,具体按实际情况写
    button.getLocationOnScreen(xy);

	//再定义一个数组用来计算控件的bottom/right xy值
    int[] xy_end = new int[2];
    xy_end[0] = buttom.getWidth() + xy[0];
    xy_end[1] = buttom.getHeight() + xy[1];
	//现在我们已经得到了按钮的左上坐标和右下坐标
	//两个点可以确定一个矩形嘛

	//event里包含了点击的信息;
	//我们判断点击的坐标是否在按钮坐标内,实际就是判断点击的xy值是否在上述矩形中;
    if (event.getX() >= xy[0] && event.getX() <= xy_end[0]
        && event.getY() >= xy[1] && event.getY() <= xy_end[1]) {
        //如果是,那么就执行里边的代码,在这里我们可以callOnClick()按钮

		//这里的代码说明
		//实际体验了一番,发现轻点一下和长按均可以激活按钮;
		//但是,我的按钮拥有animate()事件,所以连续点击会在动画未完成时再次点击按钮,
		//所以我做了个判断,让动画未完成时不再执行点击,机制如我
		//实际中,读者完全不用这两行代码
		//让我看看有哪些读者看都不看直接复制代码--手动滑稽
		//虽说站在巨人肩膀上,但是也要搞懂其原理才不会摔下来。
        if (isMoreShow == false && xy[0] >= button.getHeight())
            return false;

		//我们callOnClick了按钮,也就是模拟点击了按钮;
        button.callOnClick();
        return false;
    }

    return super.onTouchEvent(event);
}
  • 就这短短几行代码,搞了我半天的心态,严格说还有一个晚上;

不足:

  • 不足之处还是有的
  1. 如果按钮过多,就需要写入更多的判断,这非常的不优雅;可是总比无法点击要好;
  2. 如果按钮有自定义点击背景(按下背景),将不显示,身为强迫症的我怎么能忍;

展示:

[Android]Button超出布局显示及点击&view超出父view无法响应点击事件_第2张图片

结语

  • 软件地址下载地址
  • 个人GitHub地址Fc-404

你可能感兴趣的:(Android,安卓,android,移动开发,java)