Android ViewPager不支持wrap_content的原因

2024-03-19 08:20

本文主要是介绍Android ViewPager不支持wrap_content的原因,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • Android ViewPager不支持wrap_content的原因
    • 问题
    • 源码分析
    • 解决

Android ViewPager不支持wrap_content的原因

问题

<androidx.viewpager.widget.ViewPagerandroid:id="@+id/wrap_view_pager"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="#666666" />

将 ViewPager 的高度设置为 wrap_content,但是实现显示的效果却是填充了整个父容器。

源码分析

// ViewPager#onMeasure()
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {setMeasuredDimension(getDefaultSize(0, widthMeasureSpec),getDefaultSize(0, heightMeasureSpec));
}
// View#getDefaultSize()
public static int getDefaultSize(int size, int measureSpec) {int result = size;int specMode = MeasureSpec.getMode(measureSpec);int specSize = MeasureSpec.getSize(measureSpec);switch (specMode) {case MeasureSpec.UNSPECIFIED:result = size;break;case MeasureSpec.AT_MOST:case MeasureSpec.EXACTLY:result = specSize;break;}return result;
}

在这里插入图片描述

源码分析:

  • 前提:View的MeasureSpec是由MeasureMode和MeasureSize构成,子View的MeasureSpec是由父View的MeasureSpec和子View的LayoutParams计算来的。
  • 在 ViewPager 中,onMeasure() 直接调用 setMeasuredDimension() 设置宽高,并没有根据子View来计算测量。
  • 接着调用 getDefaultSize() 方法,第一个参数传入0,第二个参数传入ViewPager的measureSpec,根据上图父View的MeasureMode和子View的LayoutParams对照关系,由此可得:
    • ViewPager的MeasureMode为EXACTLY时,specSize为具体值或父View的剩余空间。
    • ViewPager的MeasureMode为AT_MOST时,specSize为父View的剩余空间。

因此当ViewPager设置为wrap_content时,ViewPager为父容器的高度。

解决

重写 onMeasure() 方法,先主动测量子View的大小,将测量后的结果设置给ViewPager。

class WrapContentViewPager @JvmOverloads constructor(context: Context,attrs: AttributeSet? = null
) : ViewPager(context, attrs) {override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {for (i in 0 until childCount) {val child = getChildAt(i)measureChild(child,widthMeasureSpec,MeasureSpec.makeMeasureSpec(child.layoutParams.height, MeasureSpec.UNSPECIFIED))}val heightSize = MeasureSpec.getSize(heightMeasureSpec)val heightMode = MeasureSpec.getMode(heightMeasureSpec)var height = 0when (heightMode) {MeasureSpec.EXACTLY -> {height = heightSize}else -> {for (i in 0 until childCount) {val child = getChildAt(i)height = Math.max(height, child.measuredHeight)}}}super.onMeasure(widthMeasureSpec,MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY))}
}

这篇关于Android ViewPager不支持wrap_content的原因的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/825371

相关文章

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui

部署Vue项目到服务器后404错误的原因及解决方案

《部署Vue项目到服务器后404错误的原因及解决方案》文章介绍了Vue项目部署步骤以及404错误的解决方案,部署步骤包括构建项目、上传文件、配置Web服务器、重启Nginx和访问域名,404错误通常是... 目录一、vue项目部署步骤二、404错误原因及解决方案错误场景原因分析解决方案一、Vue项目部署步骤

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

定价129元!支持双频 Wi-Fi 5的华为AX1路由器发布

《定价129元!支持双频Wi-Fi5的华为AX1路由器发布》华为上周推出了其最新的入门级Wi-Fi5路由器——华为路由AX1,建议零售价129元,这款路由器配置如何?详细请看下文介... 华为 Wi-Fi 5 路由 AX1 已正式开售,新品支持双频 1200 兆、配有四个千兆网口、提供可视化智能诊断功能,建

pip install jupyterlab失败的原因问题及探索

《pipinstalljupyterlab失败的原因问题及探索》在学习Yolo模型时,尝试安装JupyterLab但遇到错误,错误提示缺少Rust和Cargo编译环境,因为pywinpty包需要它... 目录背景问题解决方案总结背景最近在学习Yolo模型,然后其中要下载jupyter(有点LSVmu像一个

Android里面的Service种类以及启动方式

《Android里面的Service种类以及启动方式》Android中的Service分为前台服务和后台服务,前台服务需要亮身份牌并显示通知,后台服务则有启动方式选择,包括startService和b... 目录一句话总结:一、Service 的两种类型:1. 前台服务(必须亮身份牌)2. 后台服务(偷偷干

SpringBoot中的404错误:原因、影响及解决策略

《SpringBoot中的404错误:原因、影响及解决策略》本文详细介绍了SpringBoot中404错误的出现原因、影响以及处理策略,404错误常见于URL路径错误、控制器配置问题、静态资源配置错误... 目录Spring Boot中的404错误:原因、影响及处理策略404错误的出现原因1. URL路径错

在Rust中要用Struct和Enum组织数据的原因解析

《在Rust中要用Struct和Enum组织数据的原因解析》在Rust中,Struct和Enum是组织数据的核心工具,Struct用于将相关字段封装为单一实体,便于管理和扩展,Enum用于明确定义所有... 目录为什么在Rust中要用Struct和Enum组织数据?一、使用struct组织数据:将相关字段绑

Android kotlin语言实现删除文件的解决方案

《Androidkotlin语言实现删除文件的解决方案》:本文主要介绍Androidkotlin语言实现删除文件的解决方案,在项目开发过程中,尤其是需要跨平台协作的项目,那么删除用户指定的文件的... 目录一、前言二、适用环境三、模板内容1.权限申请2.Activity中的模板一、前言在项目开发过程中,尤

Linux内存泄露的原因排查和解决方案(内存管理方法)

《Linux内存泄露的原因排查和解决方案(内存管理方法)》文章主要介绍了运维团队在Linux处理LB服务内存暴涨、内存报警问题的过程,从发现问题、排查原因到制定解决方案,并从中学习了Linux内存管理... 目录一、问题二、排查过程三、解决方案四、内存管理方法1)linux内存寻址2)Linux分页机制3)