返回顶部
首页 > 资讯 > 精选 >为什么自定义view的wrap_content会失效
  • 854
分享到

为什么自定义view的wrap_content会失效

自定义viewwrap_content 2023-10-29 14:10:57 854人浏览 安东尼
摘要

一、问题描述 在使用自定义View时,View宽 / 高的wrap_content属性不起自身应有的作用,而且是起到与match_parent相同作用。 wrap_content与match_parent区别: wrap_content:视

一、问题描述

在使用自定义View时,View宽 / 高的wrap_content属性不起自身应有的作用,而且是起到与match_parent相同作用。

wrap_content与match_parent区别:

wrap_content:视图的宽/高被设定成刚好适应视图内容的最小尺寸

match_parent:视图的宽/高被设置为充满整个父布局

(在Android api 8之前叫作fill_parent)

其实这里有两个问题:

问题1:wrap_content属性不起自身应有的作用

问题2:wrap_content起到与match_parent相同的作用

二、问题分析

问题出现在View的宽 / 高设置,那我们直接来看自定义View绘制中名列前茅步对View宽 / 高设置的过程:measure过程中的onMeasure()方法

onMeasure()

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  

//参数说明:View的宽 / 高测量规格

//setMeasuredDimension()  用于获得View宽/高的测量值

//这两个参数是通过getDefaultSize()获得的

setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),  

           getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));  

}

继续往下看getDefaultSize()

getDefaultSize()

作用:根据View宽/高的测量规格计算View的宽/高值

源码分析如下:

public static int getDefaultSize(int size, int measureSpec) {  

//参数说明:

// 名列前茅个参数size:提供的默认大小

// 第二个参数:宽/高的测量规格(含模式 & 测量大小)

 //设置默认大小

    int result = size;

    //获取宽/高测量规格的模式 & 测量大小

    int specMode = MeasureSpec.getMode(measureSpec);  

    int specSize = MeasureSpec.getSize(measureSpec);  

    switch (specMode) {  

        // 模式为UNSPECIFIED时,使用提供的默认大小

        // 即名列前茅个参数:size

        case MeasureSpec.UNSPECIFIED:  

            result = size;  

            break;  

        // 模式为AT_MOST,EXACTLY时,使用View测量后的宽/高值

        // 即measureSpec中的specSize

        case MeasureSpec.AT_MOST:  

        case MeasureSpec.EXACTLY:  

            result = specSize;  

            break;  

    }  

 //返回View的宽/高值

    return result;  

}

从上面发现:

在getDefaultSize()的默认实现中,当View的测量模式是AT_MOST或EXACTLY时,View的大小都会被设置成子View MeasureSpec的specSize。

因为AT_MOST对应wrap_content;EXACTLY对应match_parent,所以,默认情况下,wrap_content和match_parent是具有相同的效果的。

解决了问题2:wrap_content起到与match_parent相同的作用

由于在getDefaultSize()的默认实现中,当View被设置成wrap_content和match_parent时,View的大小都会被设置成子View MeasureSpec的specSize。

所以,这个问题的关键在于子View MeasureSpec的specSize的值是多少

我们知道,子View的MeasureSpec值是根据子View的布局参数(LayoutParams)和父容器的MeasureSpec值计算得来,具体计算逻辑封装在getChildMeasureSpec()里。

接下来,看生成子View MeasureSpec的方法:getChildMeasureSpec()的源码分析:

getChildMeasureSpec()

//作用:

/ 根据父视图的MeasureSpec & 布局参数LayoutParams,计算单个子View的MeasureSpec

//即子view的确切大小由两方面共同决定:父view的MeasureSpec 和 子view的LayoutParams属性

public static int getChildMeasureSpec(int spec, int padding, int childDimension) {  

 //参数说明

 * @param spec 父view的详细测量值(MeasureSpec)

 * @param padding view当前尺寸的的内边距和外边距(padding,margin)

 * @param childDimension 子视图的布局参数(宽/高)

    //父view的测量模式

    int specMode = MeasureSpec.getMode(spec);     

    //父view的大小

    int specSize = MeasureSpec.getSize(spec);     

    //通过父view计算出的子view = 父大小-边距(父要求的大小,但子view不一定用这个值)   

    int size = Math.max(0, specSize – padding);  

    //子view想要的实际大小和模式(需要计算)  

    int resultSize = 0;  

    int resultMode = 0;  

    //通过父view的MeasureSpec和子view的LayoutParams确定子view的大小  

    // 当父view的模式为EXACITY时,父view强加给子view确切的值

   //一般是父view设置为match_parent或者固定值的ViewGroup

    switch (specMode) {  

    case MeasureSpec.EXACTLY:  

        // 当子view的LayoutParams>0,即有确切的值  

        if (childDimension >= 0) {  

            //子view大小为子自身所赋的值,模式大小为EXACTLY  

            resultSize = childDimension;  

            resultMode = MeasureSpec.EXACTLY;  

        // 当子view的LayoutParams为MATCH_PARENT时(-1)  

        } else if (childDimension == LayoutParams.MATCH_PARENT) {  

            //子view大小为父view大小,模式为EXACTLY  

            resultSize = size;  

            resultMode = MeasureSpec.EXACTLY;  

        // 当子view的LayoutParams为WRAP_CONTENT时(-2)      

        } else if (childDimension == LayoutParams.WRAP_CONTENT) {  

            //子view决定自己的大小,但最大不能超过父view,模式为AT_MOST  

            resultSize = size;  

            resultMode = MeasureSpec.AT_MOST;  

        }  

        break;  

    // 当父view的模式为AT_MOST时,父view强加给子view一个最大的值。(一般是父view设置为wrap_content)  

    case MeasureSpec.AT_MOST:  

        // 道理同上  

        if (childDimension >= 0) {  

            resultSize = childDimension;  

            resultMode = MeasureSpec.EXACTLY;  

        } else if (childDimension == LayoutParams.MATCH_PARENT) {  

            resultSize = size;  

            resultMode = MeasureSpec.AT_MOST;  

        } else if (childDimension == LayoutParams.WRAP_CONTENT) {  

            resultSize = size;  

            resultMode = MeasureSpec.AT_MOST;  

        }  

        break;  

    // 当父view的模式为UNSPECIFIED时,父容器不对view有任何限制,要多大给多大

    // 多见于ListView、GridView  

    case MeasureSpec.UNSPECIFIED:  

        if (childDimension >= 0) {  

            // 子view大小为子自身所赋的值  

            resultSize = childDimension;  

            resultMode = MeasureSpec.EXACTLY;  

        } else if (childDimension == LayoutParams.MATCH_PARENT) {  

            // 因为父view为UNSPECIFIED,所以MATCH_PARENT的话子类大小为0  

            resultSize = 0;  

            resultMode = MeasureSpec.UNSPECIFIED;  

        } else if (childDimension == LayoutParams.WRAP_CONTENT) {  

            // 因为父view为UNSPECIFIED,所以WRAP_CONTENT的话子类大小为0  

            resultSize = 0;  

            resultMode = MeasureSpec.UNSPECIFIED;  

        }  

        break;  

    }  

    return MeasureSpec.makeMeasureSpec(resultSize, resultMode);  

关于getChildMeasureSpec()里对于子View的测量模式和大小的判断逻辑有点复杂;

三、解决方案

当自定义View的布局参数设置成wrap_content时时,指定一个默认大小(宽 / 高)。

具体是在复写onMeasure()里进行设置

 @Override

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        // 获取宽-测量规则的模式和大小

        Int widthMode = MeasureSpec.getMode(widthMeasureSpec);

        int widthSize = MeasureSpec.getSize(widthMeasureSpec);

        // 获取高-测量规则的模式和大小

        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        // 设置wrap_content的默认宽 / 高值

        // 默认宽/高的设定并无固定依据,根据需要灵活设置

        // 类似TextView,ImageView等针对wrap_content均在onMeasure()对设置默认宽 / 高值有特殊处理,具体读者可以自行查看

        int mWidth = 400;

        int mHeight = 400;

      // 当布局参数设置为wrap_content时,设置默认值

        if (getLayoutParams().width == ViewGroup.LayoutParams.WRAP_CONTENT && getLayoutParams().height == ViewGroup.LayoutParams.WRAP_CONTENT) {

            setMeasuredDimension(mWidth, mHeight);

        // 宽 / 高任意一个布局参数为= wrap_content时,都设置默认值

        } else if (getLayoutParams().width == ViewGroup.LayoutParams.WRAP_CONTENT) {

            setMeasuredDimension(mWidth, heightSize);

        } else if (getLayoutParams().height == ViewGroup.LayoutParams.WRAP_CONTENT) {

            setMeasuredDimension(widthSize, mHeight);

        }

这样,当你的自定义View的宽 / 高设置成wrap_content属性时就会生效了。

--结束END--

本文标题: 为什么自定义view的wrap_content会失效

本文链接: https://lsjlt.com/news/521188.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 为什么自定义view的wrap_content会失效
    一、问题描述 在使用自定义View时,View宽 / 高的wrap_content属性不起自身应有的作用,而且是起到与match_parent相同作用。 wrap_content与match_parent区别: wrap_content:视...
    99+
    2023-10-29
    自定义 view wrap_content
  • android自定义view的步骤是什么
    自定义Android View的步骤如下:1. 创建一个新的Java类,继承自View或其子类,例如TextView、Button等...
    99+
    2023-08-15
    android view
  • android自定义view流程是什么
    Android自定义View的流程如下:1. 创建一个继承自View的子类,命名为CustomView。2. 在CustomView...
    99+
    2023-09-12
    android
  • mysql索引为什么会失效
    这篇文章主要介绍了mysql索引为什么会失效,具有一定借鉴价值,需要的朋友可以参考下。希望大家阅读完这篇文章后大有收获。下面让小编带着大家一起了解一下。mysql索引失效的几种情况:1、条件中有or,即使其...
    99+
    2024-04-02
  • android 自定义圆角button效果的实例代码(自定义view Demo)
    概述 在平时开发过程中经常会碰到需要使用圆角button的情况,一般也会包括很多其他小功能,比如要在里面添加img,设置不同的圆角大小等。 针对这样的场景,直接使用创建多个s...
    99+
    2022-06-06
    button 自定义 view demo 自定义view Android
  • css中为什么z-index会失效
    这篇文章给大家分享的是有关css中为什么z-index会失效的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。   1、父标签position属性为relative;   2、问...
    99+
    2024-04-02
  • Android自定义复杂view的方法是什么
    要自定义复杂的View,可以按照以下步骤进行:1. 创建一个新的类,继承自View或者ViewGroup的子类,例如LinearLa...
    99+
    2023-09-27
    Android
  • mysql中COALESCE函数为什么会失效
    mysql 中 coalesce 函数失效的原因是:参数全是 null参数类型不兼容传递 null 表达式次要错误 MySQL 中 COALESCE 函数失效的原因 COALESCE ...
    99+
    2024-05-01
    mysql
  • mysql中COALESCE函数为什么会失效
    mysql 中 coalesce 函数失效的原因是:参数全是 null参数类型不兼容传递 null 表达式次要错误 MySQL 中 COALESCE 函数失效的原因 COALESCE ...
    99+
    2024-05-01
    mysql
  • Android中怎么自定义View实现标签流效果
    本篇内容主要讲解“Android中怎么自定义View实现标签流效果”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Android中怎么自定义View实现标签流效果”吧!一、概述Android自定义...
    99+
    2023-06-29
  • Android中怎么通过自定义view实现TopBar效果
    这篇文章给大家介绍Android中怎么通过自定义view实现TopBar效果,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。布局文件<xml version="1.0" en...
    99+
    2023-05-30
    android view topbar
  • Android怎么自定义View实现圆弧进度效果
    这篇文章主要介绍“Android怎么自定义View实现圆弧进度效果”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Android怎么自定义View实现圆弧进度效果”文章能帮助大家解决问题。技术实现Ar...
    99+
    2023-07-06
  • SpringBoot自定义/error路径失效的解决
    目录SpringBoot自定义/error路径失效背景配置信息解决思路SpringBoot的/error的自定义处理它的具体定义如下他有三个方法SpringBoot自定义/error...
    99+
    2024-04-02
  • Android自定义View实现飘动的叶子效果(三)
    上一篇对自定义View及一些方法有所了解,下面做一个简单的叶子飘动的例子 主要技术点 1、添加背景图片canvas.drawBitmap() 2、Matrix动画类 3、Ma...
    99+
    2022-06-06
    view Android
  • Android自定义View实现简单的圆形Progress效果
    先给大家展示下效果图,如果感觉不错,请参考实现思路: 我们要实现一个自定义的再一个圆形中绘制一个弧形的自定义View,思路是这样的:   先要创建一个类ProgressVie...
    99+
    2022-06-06
    view progress Android
  • 为什么我的自定义错误类型会导致特定模式的错误?
    有志者,事竟成!如果你在学习Golang,那么本文《为什么我的自定义错误类型会导致特定模式的错误?》,就很适合你!文章讲解的知识点主要包括,若是你对本文感兴趣,或者是想搞懂其中某个知识点,就请你继续...
    99+
    2024-04-05
  • Android自定义view实现阻尼效果的加载动画
    效果: 需要知识: 1. 二次贝塞尔曲线 2. 动画知识 3. 基础自定义view知识 先来解释下什么叫阻尼运动 阻尼振动是指,由于振动系统受到摩擦和介质阻力或其他能耗而使振...
    99+
    2022-06-06
    view 动画 Android
  • Android自定义View实现数字雨效果的全过程
    目录效果图实现步骤总结效果图 在安卓中多种类型的动画,有帧动画、补间动画、属性动画,除此之外,使用自定义的View结合数学公式,就可以绘制出复杂的界面或者动画。这篇文章记录的是仿照黑...
    99+
    2024-04-02
  • android自定义ListView实现底部View自动隐藏和消失的功能
    有这样一个ListView,要求在屏幕底部有一个筛选排序的浮动框: 1、手指下拉隐藏,上滑显示 ; 2、如果没做任何操作,2S之后,要自动显示; 3、滑动到最底部,始终显示。 ...
    99+
    2022-06-06
    listview Android
  • Android中怎么自定义view实现圆环进度条效果
    这篇文章主要讲解了“Android中怎么自定义view实现圆环进度条效果”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Android中怎么自定义view实现圆环进度条效果”吧!核心代码自定义...
    99+
    2023-06-29
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作