在 ViewGroup 上设置最大宽度
Posted
技术标签:
【中文标题】在 ViewGroup 上设置最大宽度【英文标题】:Setting a maximum width on a ViewGroup 【发布时间】:2011-08-18 01:36:21 【问题描述】:如何设置 ViewGroup 的最大宽度?我正在使用Theme.Dialog
活动,但是,当调整到更大的屏幕时,它看起来不太好,它也有点轻巧,我不希望它占据整个屏幕。
我试过this suggestion 无济于事。此外,没有像某些视图那样的android:maxWidth
属性。
有没有办法限制根 LinearLayout 使其仅(例如)640 dip?我愿意为此更改为另一个 ViewGroup。
有什么建议吗?
【问题讨论】:
【参考方案1】:这是一个纯 Kotlin 解决方案,另外还有一个好处是可以使用 android:maxWidth
。
BoundedFrameLayout.kt
package example.com
import android.content.Context
import android.util.AttributeSet
import android.widget.FrameLayout
import androidx.core.content.withStyledAttributes
import com.sas.android.common.R
class BoundedFrameLayout @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr)
private var maxWidth = -1
init
if (attrs != null)
context.withStyledAttributes(attrs, R.styleable.BoundedView)
maxWidth = getDimensionPixelSize(
R.styleable.BoundedView_android_maxWidth, maxWidth
)
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int)
var widthSpec = widthMeasureSpec
if (maxWidth >= 0)
val widthSize = MeasureSpec.getSize(widthMeasureSpec)
if (widthSize > maxWidth)
val widthMode = MeasureSpec.getMode(widthMeasureSpec)
widthSpec = MeasureSpec.makeMeasureSpec(maxWidth, widthMode)
super.onMeasure(widthSpec, heightMeasureSpec)
attrs.xml
<resources>
<declare-styleable name="BoundedView">
<attr name="android:maxWidth" />
</declare-styleable>
</resources>
然后在你的布局 XML 中:
…
<com.example.BoundedFrameLayout
android:layout_
android:layout_
android:maxWidth="350dp"
/>
…
最大高度可以和宽度一样处理;为简洁起见,此处省略。
此模式可用于任何 ViewGroup 子类(例如 LinearLayout)。
【讨论】:
【参考方案2】:现在android.support.constraint.ConstraintLayout
更容易了。只需使用 ConstraintLayout 包装您的视图(任何类型),并为视图设置以下属性:
android:layout_
app:layout_constraintWidth_default="spread"
app:layout_constraintWidth_max="640dp"
http://tools.android.com/recent/constraintlayoutbeta5isnowavailable
【讨论】:
【参考方案3】:这是一个简单的答案,
宽度/高度似乎总是必须一起设置。这在我看来是有效的。
<Button
android:text="Center"
android:layout_
android:layout_
android:id="@+id/selectionCenterButton"
android:minWidth="50dp"
android:minHeight="50dp"
android:maxWidth="100dp"
android:maxHeight="50dp"
android:layout_weight="1" />
按钮的父级设置为包裹内容,因此会缩小,但最大宽度为 400(4 个按钮)。
【讨论】:
按钮不是 ViewGroup。 ViewGroups 没有 max* 属性。 Button 是 TextView 的子类,它确实具有这些属性。整个问题是关于如何处理没有 max* 属性的视图。【参考方案4】:我所做的一个选择是扩展 LinearLayout 并覆盖 onMeasure 函数。例如:
public class BoundedLinearLayout extends LinearLayout
private final int mBoundedWidth;
private final int mBoundedHeight;
public BoundedLinearLayout(Context context)
super(context);
mBoundedWidth = 0;
mBoundedHeight = 0;
public BoundedLinearLayout(Context context, AttributeSet attrs)
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.BoundedView);
mBoundedWidth = a.getDimensionPixelSize(R.styleable.BoundedView_bounded_width, 0);
mBoundedHeight = a.getDimensionPixelSize(R.styleable.BoundedView_bounded_height, 0);
a.recycle();
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
// Adjust width as necessary
int measuredWidth = MeasureSpec.getSize(widthMeasureSpec);
if(mBoundedWidth > 0 && mBoundedWidth < measuredWidth)
int measureMode = MeasureSpec.getMode(widthMeasureSpec);
widthMeasureSpec = MeasureSpec.makeMeasureSpec(mBoundedWidth, measureMode);
// Adjust height as necessary
int measuredHeight = MeasureSpec.getSize(heightMeasureSpec);
if(mBoundedHeight > 0 && mBoundedHeight < measuredHeight)
int measureMode = MeasureSpec.getMode(heightMeasureSpec);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(mBoundedHeight, measureMode);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
然后你的 XML 将使用自定义类:
<com.yourpackage.BoundedLinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_
android:layout_
android:orientation="vertical"
app:bounded_>
<TextView
android:layout_
android:layout_
/>
</com.youpackage.BoundedLinearLayout>
还有 attr.xml 文件入口
<declare-styleable name="BoundedView">
<attr name="bounded_width" format="dimension" />
<attr name="bounded_height" format="dimension" />
</declare-styleable>
编辑:这是我现在使用的实际代码。这仍然不完整,但在大多数情况下都有效。
【讨论】:
令人难以置信的是,Google 没有开箱即用地包含maxWidth
,而是我们必须继承 :-(
你是绝对正确的。他们正在有效地众包平台:]
添加 app_name:bounded_ 时出现错误
@AHmédNet 将 xmlns:app_name="http://schemas.android.com/apk/res-auto"
添加到布局的顶部元素以解决该问题【参考方案5】:
这是 Dori 答案的更好代码。
在方法onMeasure
中,如果在方法中先调用super.onMeasure(widthMeasureSpec, heightMeasureSpec);
,那么布局中所有对象的宽度都不会改变。因为它们在您设置布局(父)宽度之前已初始化。
public class MaxWidthLinearLayout extends LinearLayout
private final int mMaxWidth;
public MaxWidthLinearLayout(Context context)
super(context);
mMaxWidth = 0;
public MaxWidthLinearLayout(Context context, AttributeSet attrs)
super(context, attrs);
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.MaxWidthLinearLayout);
mMaxWidth = a.getDimensionPixelSize(R.styleable.MaxWidthLinearLayout_maxWidth, Integer.MAX_VALUE);
a.recycle();
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
int measuredWidth = MeasureSpec.getSize(widthMeasureSpec);
if (mMaxWidth > 0 && mMaxWidth < measuredWidth)
int measureMode = MeasureSpec.getMode(widthMeasureSpec);
widthMeasureSpec = MeasureSpec.makeMeasureSpec(mMaxWidth, measureMode);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
这里是xml attr的使用链接:http://kevindion.com/2011/01/custom-xml-attributes-for-android-widgets/
感谢您提出这个问题和答案。您的回答对我有很大帮助,希望以后也能对其他人有所帮助。
【讨论】:
这个答案更好。 (还有为什么 Dori 错过了一个小错误?) 如果在MaxWidthLinearLayout
的布局参数中指定了精确大小,则内容仍使用原始宽度...您必须指定 MATH_PARENT
并将精确大小管理放入onMeasure(..)
。愚蠢但工作。【参考方案6】:
在 Chase (+1) 的原始答案的基础上,我会进行一些更改(如下所述)。
我将通过自定义属性设置最大宽度(代码下方的 xml)
我会先调用super.measure()
,然后再进行Math.min(*)
比较。当MeasureSpec
中设置的传入大小为LayoutParams.WRAP_CONTENT
或LayoutParams.FILL_PARENT
时,使用原始答案代码可能会遇到问题。由于这些有效常量的值分别为 -2 和 -1,原来的 Math.min(*)
变得无用,因为它将保留这些值超过最大大小,并说测量WRAP_CONTENT
大于我们的最大尺寸,此检查无法捕捉到它。我想 OP 只考虑精确的暗淡(效果很好)
public class MaxWidthLinearLayout extends LinearLayout
private int mMaxWidth = Integer.MAX_VALUE;
public MaxWidthLinearLayout(Context context)
super(context);
public MaxWidthLinearLayout(Context context, AttributeSet attrs)
super(context, attrs);
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.MaxWidthLinearLayout);
mMaxWidth = a.getDimensionPixelSize(R.styleable.MaxWidthLinearLayout_maxWidth, Integer.MAX_VALUE);
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//get measured height
if(getMeasuredWidth() > mMaxWidth)
setMeasuredDimension(mMaxWidth, getMeasuredHeight());
和xml属性
<!-- MaxWidthLinearLayout -->
<declare-styleable name="MaxWidthLinearLayout">
<attr name="maxWidth" format="dimension" />
</declare-styleable>
【讨论】:
感谢您的回复。我不再需要这个了,但我相信其他人也可能需要它。如果我觉得我需要修改我的代码,我一定会检查一下! 如果在我忘记我所做的事情的几年内是为了其他人/我:) 此代码无法按预期工作。调整宽度时,包含的元素仍使用原始宽度。因此,内容只是被截断。 Jonypoins 的答案很有效。以上是关于在 ViewGroup 上设置最大宽度的主要内容,如果未能解决你的问题,请参考以下文章