如何设置ViewGroup的最大宽度?我正在使用一个Theme.Dialog
活动,但是当调整大小到更大的屏幕时,它看起来不太好,而且还有点轻便,我不想让它占据整个屏幕。
我尝试了这个建议,但没有成功。 同时,一些视图中也没有像android:maxWidth
属性一样的属性。
有没有办法限制根LinearLayout的宽度,使其仅为(例如)640 dip?我愿意改用另一个ViewGroup。
有什么建议吗?
如何设置ViewGroup的最大宽度?我正在使用一个Theme.Dialog
活动,但是当调整大小到更大的屏幕时,它看起来不太好,而且还有点轻便,我不想让它占据整个屏幕。
我尝试了这个建议,但没有成功。 同时,一些视图中也没有像android:maxWidth
属性一样的属性。
有没有办法限制根LinearLayout的宽度,使其仅为(例如)640 dip?我愿意改用另一个ViewGroup。
有什么建议吗?
其中一种选项是我所做的,即扩展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_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:bounded_width="900dp">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</com.youpackage.BoundedLinearLayout>
还有attr.xml文件条目
<declare-styleable name="BoundedView">
<attr name="bounded_width" format="dimension" />
<attr name="bounded_height" format="dimension" />
</declare-styleable>
编辑:这是我现在使用的实际代码。虽然还不完整,但在大多数情况下可以工作。
这是对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属性的链接:
http://kevindion.com/2011/01/custom-xml-attributes-for-android-widgets/
感谢这个问题和答案,你的回答对我帮助很大,同时我也希望它能够帮助其他人。
MaxWidthLinearLayout
的布局参数中指定了确切的大小,则内容仍将使用原始宽度...您必须指定MATH_PARENT
并将确切的大小管理放在onMeasure(..)
中。有点傻但可行。 - Gianluca P.在Chase的原始答案基础上进行改进(+1),我会做出一些更改(如下所述)。
I would have the max width set via a custom attribute (xml below the code)
I would call super.measure()
first and then do the Math.min(*)
comparison. Using the original answers code we may encounter problems when the incoming size set in the MeasureSpec
is either LayoutParams.WRAP_CONTENT
or LayoutParams.FILL_PARENT
. As these valid constants have values of -2 and -1 respectivly, the original Math.min(*)
becomes useless as it will preserve these vales over the max size, and say the measured WRAP_CONTENT
is bigger than our max size this check would not catch it. I imagine the OP was thinking of exact dims only (for which it works great)
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>
现在,android.support.constraint.ConstraintLayout
让它更容易。只需将您的视图(任何类型)包装在 ConstraintLayout 中,并将以下属性设置为视图:
android:layout_width="0dp"
app:layout_constraintWidth_default="spread"
app:layout_constraintWidth_max="640dp"
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_width="wrap_content"
android:layout_height="match_parent"
android:maxWidth="350dp"
/>
…
最大高度可以像宽度一样处理;这里为了简洁起见而省略。
这种模式可以应用于任何ViewGroup子类(例如LinearLayout)。
这里有一个简单的答案,
宽度/高度似乎总是需要一起设置。在我的视图中这个方法可行。
<Button
android:text="Center"
android:layout_width="100dp"
android:layout_height="fill_parent"
android:id="@+id/selectionCenterButton"
android:minWidth="50dp"
android:minHeight="50dp"
android:maxWidth="100dp"
android:maxHeight="50dp"
android:layout_weight="1" />
xmlns:app_name="http://schemas.android.com/apk/res-auto"
以解决该问题。 - David Passmore