android:layout_weight的真实含义

本文深入探讨了Android中LinearLayout布局的layout_weight属性的工作原理。通过对比不同配置下的TextView表现,揭示了权重分配与view宽度设置之间的关系,并给出了官方推荐的最佳实践。

转自http://blog.youkuaiyun.com/yanzi1225627/article/details/24667299

首先声明只有在Linearlayout中,该属性才有效。之所以android:layout_weight会引起争议,是因为在设置该属性的同时,设置android:layout_width为wrap_content和match_parent会造成两种截然相反的效果。如下所示:

[html]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. <LinearLayout  
  2.        android:layout_width="match_parent"  
  3.        android:layout_height="wrap_content"  
  4.        android:orientation="horizontal" >  
  5.   
  6.        <TextView  
  7.            android:layout_width="match_parent"  
  8.            android:layout_height="wrap_content"  
  9.            android:layout_weight="1"  
  10.            android:background="@android:color/black"  
  11.            android:text="111"  
  12.            android:textSize="20sp" />  
  13.   
  14.        <TextView  
  15.            android:layout_width="match_parent"  
  16.            android:layout_height="wrap_content"  
  17.            android:layout_weight="2"  
  18.            android:background="@android:color/holo_green_light"  
  19.            android:text="222"  
  20.            android:textSize="20sp" />  

上面的布局将两个TextView的宽度均设为match_parent,一个权重为1,一个权重为2.得到效果如下:


可以看到权重为1的反而占了三分之二!

再看如下布局:

[html]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. <LinearLayout  
  2.     android:layout_width="match_parent"  
  3.     android:layout_height="wrap_content"  
  4.     android:orientation="horizontal" >  
  5.   
  6.     <TextView  
  7.         android:layout_width="wrap_content"  
  8.         android:layout_height="wrap_content"  
  9.         android:layout_weight="1"  
  10.         android:background="@android:color/black"  
  11.         android:text="111"  
  12.         android:textSize="20sp" />  
  13.   
  14.     <TextView  
  15.         android:layout_width="wrap_content"  
  16.         android:layout_height="wrap_content"  
  17.         android:layout_weight="2"  
  18.         android:background="@android:color/holo_green_light"  
  19.         android:text="222"  
  20.         android:textSize="20sp" />  
  21. </LinearLayout>  

即宽度为wrap_content,得到视图如下:


左边 TextView占比三分之一,又正常了。

android:layout_weight的真实含义是:一旦View设置了该属性(假设有效的情况下),那么该 View的宽度等于原有宽度(android:layout_width)加上剩余空间的占比!

设屏幕宽度为L,在两个view的宽度都为match_parent的情况下,原有宽度为L,两个的View的宽度都为L,那么剩余宽度为L-(L+L) = -L, 左边的View占比三分之一,所以总宽度是L+(-L)*1/3 = (2/3)L.事实上默认的View的weight这个值为0,一旦设置了这个值,那么所在view在绘制的时候执行onMeasure两次的原因就在这。

Google官方推荐,当使用weight属性时,将width设为0dip即可,效果跟设成wrap_content是一样的。这样weight就可以理解为占比了!

<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/dialog_layout" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginBottom="@dimen/dimen_84dp" android:orientation="vertical"> <com.google.android.material.appbar.COUIDividerAppBarLayout android:id="@+id/appbar" style="@style/CommonAppBarStyle" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/color_transparent" android:clickable="true" android:focusable="true" android:paddingLeft="@dimen/dimen_0dp" android:paddingRight="@dimen/dimen_0dp" app:elevation="@dimen/toolbar_elevation"> <com.coui.appcompat.toolbar.COUIToolbar android:id="@+id/toolbar" style="@style/COUIToolBarInAppBarLayoutStyle" android:layout_width="match_parent" android:background="@null" app:supportTitleTextAppearance="@style/textAppearanceSecondTitle" app:titleCenter="false" /> <com.coui.appcompat.tablayout.COUITabLayout android:id="@+id/tab_layout" android:background="@color/color_transparent" style="@style/COUISmallTabLayoutStyle" /> </com.google.android.material.appbar.COUIDividerAppBarLayout> <RelativeLayout android:id="@+id/content_layout" android:layout_width="match_parent" android:layout_height="match_parent"> <com.filemanager.common.view.ViewPagerWrapperForPC android:id="@+id/view_pager_wrapper" android:layout_width="match_parent" android:layout_height="match_parent"> <com.filemanager.common.view.viewpager.RTLViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@+id/appbar" android:clipChildren="false" android:clipToPadding="false" android:orientation="horizontal" /> </com.filemanager.common.view.ViewPagerWrapperForPC> </RelativeLayout> </LinearLayout> <FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:background="?attr/couiColorBackgroundElevatedWithCard" android:minHeight="@dimen/operation_btn_background_height"> <View android:id="@+id/button_divider" android:layout_width="match_parent" android:layout_height="@dimen/divider_background_height" android:layout_gravity="top" android:alpha="0" android:background="?attr/couiColorDivider" android:forceDarkAllowed="false" /> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <LinearLayout android:id="@+id/select_root_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginStart="@dimen/dimen_16dp" android:orientation="vertical"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:clickable="false" android:orientation="horizontal"> <TextView android:id="@+id/select_title_content" android:layout_width="match_parent" android:layout_height="match_parent" android:lineHeight="22dp" android:text="@string/not_selected_file" android:textAppearance="@style/couiTextHeadlineXS" android:textColor="?attr/couiColorLabelPrimary" android:textSize="16sp" android:visibility="visible" /> <ImageView android:id="@+id/select_arraw_up" android:layout_width="18dp" android:layout_height="18dp" android:src="@drawable/arrow_up" android:layout_marginLeft="@dimen/dimen_6dp" android:visibility="gone" android:layout_gravity="center"/> </LinearLayout> <TextView android:id="@+id/select_body_content" android:layout_width="wrap_content" android:layout_height="wrap_content" android:lineHeight="20dp" android:textSize="14sp" android:textAppearance="?attr/couiTextBodyXS" android:textColor="?attr/couiColorLabelSecondary" android:visibility="gone" android:text="@string/selected_size"/> </LinearLayout> <View android:layout_width="0dp" android:layout_height="0dp" android:layout_weight="1"/> <com.coui.appcompat.button.COUIButton android:id="@+id/btn_add_file" style="@style/Widget.COUI.Button.Large" android:layout_width="@dimen/dimen_96dp" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginEnd="@dimen/dimen_16dp" android:text="@string/label_add_recent_file" /> </LinearLayout> </FrameLayout> </FrameLayout>这是这个页面
07-29
package com.example.skeletonscreen import android.graphics.Color import android.os.Bundle import android.os.Handler import android.os.Looper import android.view.View import android.view.ViewGroup import android.widget.LinearLayout import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat import com.facebook.shimmer.ShimmerFrameLayout import com.ethanhua.skeleton.Skeleton class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val mainView = findViewById<ConstraintLayout>(R.id.main) val skeletonScreen= Skeleton.bind(mainView) .show() // shimmerLayout = findViewById(R.id.shimmerLayout) // listContainer = findViewById(R.id.container_list) // // // 动态生成 5 个骨架条目 // generateListSkeletonItems(5) // 模拟数据加载 Handler(Looper.getMainLooper()).postDelayed({ // shimmerLayout.stopShimmer() // shimmerLayout.visibility = View.GONE // // // 替换为真实布局 skeletonScreen.hide() // val realContent = layoutInflater.inflate(R.layout.activity_main, null) // val rootView = findViewById<ViewGroup>(android.R.id.content) // rootView.addView(realContent) }, 2000) } }<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <!-- activity_profile_skeleton.xml --> <!-- activity_profile.xml --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp"> <ImageView android:id="@+id/ivAvatar" android:layout_width="80dp" android:layout_height="80dp" android:src="@drawable/timer" /> <TextView android:id="@+id/tvName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="用户名" android:textSize="20sp" android:textStyle="bold" android:layout_marginTop="16dp"/> <TextView android:id="@+id/tvBio" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="用户简介内容..." android:layout_marginTop="8dp"/> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="#CCCCCC" android:layout_marginTop="16dp"/> <TextView android:id="@+id/tvPostsTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="动态" android:textSize="18sp" android:layout_marginTop="16dp"/> <ListView android:id="@+id/lvPosts" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:layout_marginTop="8dp"/> </LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout>这是我的代码哪里出了问题
最新发布
09-04
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值