如何使用layout_weight获得相同大小的宽度和高度[方形]?

时间:2014-08-05 15:41:15

标签: android android-layout-weight

我有以下代码:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="1" >
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="Test 1"
        android:textSize="24sp" />
</LinearLayout>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="1" >
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="Test 2"
        android:textSize="24sp" />
</LinearLayout>

结果:

enter image description here

如何将View的高度与其宽度相等(由layout_weight产生)?

5 个答案:

答案 0 :(得分:7)

您必须覆盖onMeasure方法设置与高度相同的高度。请看这个问题:Simple way to do dynamic but square layout

这是我提出的完整解决方案:

SquareLinearLayout.java:

public class SquareLinearLayout extends LinearLayout {
public SquareLinearLayout(Context context) {
    super(context);
}

public SquareLinearLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public SquareLinearLayout(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    int width = MeasureSpec.getSize(widthMeasureSpec);
    int height = MeasureSpec.getSize(heightMeasureSpec);
    int widthDesc = MeasureSpec.getMode(widthMeasureSpec);
    int heightDesc = MeasureSpec.getMode(heightMeasureSpec);
    int size = 0;
    if (widthDesc == MeasureSpec.UNSPECIFIED
            && heightDesc == MeasureSpec.UNSPECIFIED) {
        size = getContext().getResources().getDimensionPixelSize(R.dimen.default_size); // Use your own default size, for example 125dp
    } else if ((widthDesc == MeasureSpec.UNSPECIFIED || heightDesc == MeasureSpec.UNSPECIFIED)
            && !(widthDesc == MeasureSpec.UNSPECIFIED && heightDesc == MeasureSpec.UNSPECIFIED)) {
        //Only one of the dimensions has been specified so we choose the dimension that has a value (in the case of unspecified, the value assigned is 0)
        size = width > height ? width : height;
    } else {
        //In all other cases both dimensions have been specified so we choose the smaller of the two
        size = width > height ? height : width;
    }
    setMeasuredDimension(size, size);
 }
}

activity_my.xml:

<ListView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:listitem="@layout/item"
tools:context=".MyActivity">

</ListView>

item.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="match_parent"
    android:layout_height="match_parent">

        <com.appsrise.squarelinearlayout.SquareLinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@android:color/holo_blue_bright">
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:text="Test 1"
                android:textSize="24sp" />
        </com.appsrise.squarelinearlayout.SquareLinearLayout>

        <com.appsrise.squarelinearlayout.SquareLinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@android:color/holo_green_light">
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:text="Test 2"
                android:textSize="24sp" />
        </com.appsrise.squarelinearlayout.SquareLinearLayout>

</LinearLayout>

MyActivity.java:

public class MyActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_my);

    ListView listView = (ListView) findViewById(R.id.listview);
    listView.setAdapter(new BaseAdapter() {

        private LayoutInflater mInflater = LayoutInflater.from(MyActivity.this);

        @Override
        public int getCount() {
            return 100;
        }

        @Override
        public Object getItem(int position) {
            return null;
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (convertView == null)
                convertView = mInflater.inflate(R.layout.item, parent, false);
            return convertView;
        }
    });
 }
}

答案 1 :(得分:6)

更简单的解决方案是在调用onMeasure时将宽度测量规范传递到高度规范中(或者如果您希望高度确定方形大小,则将其传递给高度规范)。

import android.content.Context;
import android.util.AttributeSet;
import android.widget.LinearLayout;

public class SquareLinearLayout extends LinearLayout{
    public SquareLinearLayout(Context context) {
        super(context);
    }

    public SquareLinearLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public SquareLinearLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, widthMeasureSpec);
        // or super.onMeasure(heightMeasureSpec, heightMeasureSpec);
    }
}

答案 2 :(得分:1)

Xamarin版

[Register("SquareFrameLayout")]
public class SquareFrameLayout : LinearLayout
{
    public SquareFrameLayout(Context context) : base(context)
    {
    }

    public SquareFrameLayout(Context context, IAttributeSet attrs) : base(context, attrs)
    {
    }

    public SquareFrameLayout(Context context, IAttributeSet attrs, int defStyle) : base(context, attrs, defStyle)
    {
    }

    protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        base.OnMeasure(widthMeasureSpec, heightMeasureSpec);

        var width = MeasureSpec.GetSize(widthMeasureSpec);
        var height = MeasureSpec.GetSize(heightMeasureSpec);
        var widthDesc = MeasureSpec.GetMode(widthMeasureSpec);
        var heightDesc = MeasureSpec.GetMode(heightMeasureSpec);

        if (widthDesc == MeasureSpecMode.Unspecified && heightDesc == MeasureSpecMode.Unspecified)
        {
            //size = Context.Resources.GetDimensionPixelSize(Resource.Dimension.default_size); // Use your own default size, for example 125dp
            height = width = 0;
        }
        else if(heightDesc != MeasureSpecMode.Unspecified && widthDesc == MeasureSpecMode.Unspecified)
        {
            width = height;
        }
        else if (widthDesc != MeasureSpecMode.Unspecified && heightDesc == MeasureSpecMode.Unspecified)
        {
            height = width;
        }
        else
        {
            //In all other cases both dimensions have been specified so we choose the smaller of the two
            var size = width > height ? height : width;
            width = height = size;
        }

        SetMeasuredDimension(width, height);
    }

[Register("SquareLinearLayout")]
public class SquareLinearLayout : LinearLayout
{
    public SquareLinearLayout(Context context) : base(context)
    {
    }

    public SquareLinearLayout(Context context, IAttributeSet attrs) : base(context, attrs)
    {
    }

    public SquareLinearLayout(Context context, IAttributeSet attrs, int defStyle) : base(context, attrs, defStyle)
    {
    }

    protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        base.OnMeasure(widthMeasureSpec, heightMeasureSpec);

        var width = MeasureSpec.GetSize(widthMeasureSpec);
        var height = MeasureSpec.GetSize(heightMeasureSpec);
        var widthDesc = MeasureSpec.GetMode(widthMeasureSpec);
        var heightDesc = MeasureSpec.GetMode(heightMeasureSpec);

        if (widthDesc == MeasureSpecMode.Unspecified && heightDesc == MeasureSpecMode.Unspecified)
        {
            //size = Context.Resources.GetDimensionPixelSize(Resource.Dimension.default_size); // Use your own default size, for example 125dp
            height = width = 0;
        }
        else if(heightDesc != MeasureSpecMode.Unspecified && widthDesc == MeasureSpecMode.Unspecified)
        {
            width = height;
        }
        else if (widthDesc != MeasureSpecMode.Unspecified && heightDesc == MeasureSpecMode.Unspecified)
        {
            height = width;
        }
        else
        {
            //In all other cases both dimensions have been specified so we choose the smaller of the two
            var size = width > height ? height : width;
            width = height = size;
        }

        SetMeasuredDimension(width, height);
    }
}

答案 3 :(得分:0)

你也可以这样做,如果你只需要一个TextView需要是正方形:

ViewTreeObserver vto = textview.getViewTreeObserver();
            vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    textview.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                    int width = textview.getMeasuredWidth();
                    int height = textview.getMeasuredHeight();
                    ViewGroup.LayoutParams params = textview.getLayoutParams();
                    if (width > height)
                        params.height = width;
                    else
                        params.width = height;
                    textview.setLayoutParams(params);

                }
            });

答案 4 :(得分:-1)

您可以将LinearLayout划分为两个相等的LinearLayout,就像这样..

<LinearLayout android:orientation="horizontal" android:layout_height="fill_parent" android:layout_width="fill_parent">
  <LinearLayout android:layout_weight="1" android:layout_height="fill_parent" android:layout_width="fill_parent">

      <TextView
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:gravity="center"
             android:text="Test 1"
             android:textSize="24sp" />

  </LinearLayout>
  <LinearLayout android:layout_weight="1" android:layout_height="fill_parent" android:layout_width="fill_parent">

       <TextView
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:gravity="center"
             android:text="Test 1"
             android:textSize="24sp" />

  </LinearLayout>
</LinearLayout>

这会将LinearLayout划分为两个相等的LinearLayouts,其中每个LinearLayouts都会包含TextView s