2011-05-03 95 views
55

如何设置ViewGroup的最大宽度?我使用的是一个Theme.Dialog活动,但是,当调整到更大的屏幕时,这看起来不太好,它也有点轻巧,我不希望它占据整个屏幕。在ViewGroup上设置最大宽度

我试过this suggestion无济于事。此外,没有android:maxWidth财产像一些意见。

有没有办法限制根LinearLayout,以便它只是(例如)640下降?我愿意为此更改为另一个ViewGroup。

有什么建议吗?

回答

86

我做的一个选择是扩展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> 

编辑:这是实际的代码我使用现在。这仍然不完整,但在大多数情况下工作。

+0

不想继承,但它在我的经验 – zsniperx 2011-06-08 20:24:13

+2

这工作就像一个魅力的工作! – dmon 2011-06-08 23:09:08

+0

你是救命吧 – HelmiB 2012-01-26 13:18:07

28

在Chase(+1)的原始答案的基础上构建,我将进行一些更改(如下所述)。

  1. 我将具有最大宽度通过的自定义属性(XML代码下面)设置

  2. 我称之为super.measure()第一和然后执行Math.min(*)比较。在MeasureSpec中设置的传入尺寸为LayoutParams.WRAP_CONTENTLayoutParams.FILL_PARENT时,使用原始答案代码我们可能会遇到问题。由于这些有效常量的值分别为-2-1,原始Math.min(*)变得无用,因为它将保持这些值超过最大值,并且说测量的WRAP_CONTENT比我们的最大值大,这个检查不会捕获它。我想象中的OP,只是考虑确切DIMS(为它的伟大工程)的

    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 ATTR

<!-- MaxWidthLinearLayout --> 
    <declare-styleable name="MaxWidthLinearLayout"> 
     <attr name="maxWidth" format="dimension" /> 
    </declare-styleable> 
+0

感谢你的反应,我不再需要这个了,但我确定其他人也可能需要它,如果我觉得我需要修改我的代码,我一定会检查一下! – zsniperx 2011-12-24 00:17:13

+1

if for others/me在几年的时间里,当我忘记我做了什么:) – Dori 2012-01-20 10:44:56

+3

此代码不能按预期工作。在调整宽度的同时,包含的元素仍然以原始宽度工作。因此内容被截断。 Jonypoins回答作品。 – 2014-04-08 07:11:10

27

下面是大道的回答更好的代码。

在方法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/

感谢这个问题和答案。你的答案对我有很大的帮助,我希望它在将来也能帮助其他人。

+1

您的回答是最完整的,谢谢;-) – 2013-09-20 10:02:31

+1

这个答案比较好。 (也是为什么Dori错过了一个微不足道的错误?) – Zyoo 2014-01-06 07:50:16

+0

如果在MaxWidthLinearLayout的布局参数中指定了一个确切的大小,内容仍然使用原始宽度......您必须指定'MATH_PARENT'并将确切的大小'onMeasure(..)'里面的管理。愚蠢但工作。 – 2014-05-21 15:46:21

-3

下面是一个简单的答案,

宽度/高度似乎总是要一起设置。这在我看来是有效的。

<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" /> 

该按钮的父级设置为包装内容,因此缩小,但最多可达400宽(4个按钮)。

+0

这只适用于TextView及其后代。 – Henry 2012-12-20 07:32:01

+3

按钮不是ViewGroup。 ViewGroups没有max *属性。 Button是TextView的子类,它具有这些属性。整个问题是关于如何处理没有max *属性的视图。 – dm78 2013-08-08 21:51:23

3

将外部布局或Viewgroup图层添加到当前布局文件。此布局的高度和宽度将是最大高度/宽度。 现在你的内部布局可以设置为包装内容,并受到外部布局的限制。 E.g:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical"> 

    <!-- OuterLayout to set Max Height and Width -- Add this ViewGroup to your layout File --> 
    <LinearLayout 
     android:id="@+id/outerLayout" 
     android:layout_width="650dp" 
     android:layout_height="650dp" 
     android:orientation="vertical" > 

     <LinearLayout 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:orientation="vertical" > 
     </LinearLayout> 
    </LinearLayout> 
</LinearLayout> 
+1

这是迄今为止最直接最有效的解决方案,同时也注意到,为了保持一切居中,将父母的重力和第一个孩子的布局设置为中心。 – 2017-01-24 03:39:05

+1

所以我现在意识到这个问题的一个问题是它迫使视图占用'Xdp'空间,至少它更像'min'和'max' widt/heighth。仅适用于最大宽度。接受的解决方案将给你预期的结果:) – AmeyaB 2017-01-24 22:29:57

+1

实际上,我将它与我实现的方法结合使用,该方法将通过使用基于1的坐标系来为外部容器的偏移量添加边距,以便实际获得真正的设备独立定位只需传递一个从0.0到1.0的值,这实际上也消除了使用密度像素的需要。它非常强大,对我而言,你的解决方案肯定更好。 – 2017-01-25 20:37:00

6

现在android.support.constraint.ConstraintLayout使得它更容易。只是ConstraintLayout包装您的视图(任何类型),并设置以下属性的观点:

android:layout_width="0dp" 
app:layout_constraintWidth_default="spread" 
app:layout_constraintWidth_max="640dp" 

http://tools.android.com/recent/constraintlayoutbeta5isnowavailable