Android - 如果没有空间,则按下按钮

时间:2014-07-25 06:50:02

标签: android android-layout android-linearlayout android-relativelayout

我需要在一行中显示两个按钮,但如果第一个按钮占据全宽(如果没有空间),则必须向下移动第二个按钮(不重叠/展平)。

我尝试了以下代码:

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

        <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Buttonttttttttttttttttttttsdfssdfsdfsdf"
                android:id="@+id/button"/>

        <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="New Button"
                android:id="@+id/button2"/>
    </LinearLayout>
</LinearLayout>

但有以下问题: enter image description here

你能帮忙,怎么解决这个问题?也许使用RelativeLayout?

1 个答案:

答案 0 :(得分:2)

我和你的查询类似。这是我最终使用的解决方案。

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

public class WritingLayout extends ViewGroup
{
    private int[] rowHeights;

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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int maxInternalWidth = MeasureSpec.getSize(widthMeasureSpec) - getHorizontalPadding();
        int maxInternalHeight = MeasureSpec.getSize(heightMeasureSpec) - getVerticalPadding();
        List<RowMeasurement> rows = new ArrayList<RowMeasurement>();
        RowMeasurement currentRow = null;
        for (View child : getLayoutChildren())
        {
            LayoutParams childLayoutParams = (LayoutParams)child.getLayoutParams();
            int childWidthSpec = createChildMeasureSpec(childLayoutParams.width, maxInternalWidth, widthMode);
            int childHeightSpec = createChildMeasureSpec(childLayoutParams.height, maxInternalHeight, heightMode);
            child.measure(childWidthSpec, childHeightSpec);
            int childWidth = child.getMeasuredWidth();
            int childHeight = child.getMeasuredHeight();
            if ((currentRow == null) || currentRow.isWouldExceedMax(childWidth))
            {
                currentRow = new RowMeasurement(maxInternalWidth, widthMode);
                rows.add(currentRow);
            }
            currentRow.addChildDimensions(childWidth, childHeight);
        }
        int longestRowWidth = 0;
        int totalRowHeight = 0;
        int rowCount = rows.size();
        this.rowHeights = new int[rowCount];
        for (int rowIndex = 0; rowIndex < rowCount; rowIndex++)
        {
            RowMeasurement row = rows.get(rowIndex);
            int rowHeight = row.getHeight();
            this.rowHeights[rowIndex] = rowHeight;
            totalRowHeight = totalRowHeight + rowHeight;
            longestRowWidth = Math.max(longestRowWidth, row.getWidth());
        }
        setMeasuredDimension((widthMode == MeasureSpec.EXACTLY) ? MeasureSpec.getSize(widthMeasureSpec) : (longestRowWidth + getHorizontalPadding()), (heightMode == MeasureSpec.EXACTLY) ? MeasureSpec.getSize(heightMeasureSpec) : (totalRowHeight + getVerticalPadding()));
    }

    private int createChildMeasureSpec(int childLayoutParam, int max, int parentMode)
    {
        int spec;
        if (childLayoutParam == ViewGroup.LayoutParams.FILL_PARENT)
            spec = MeasureSpec.makeMeasureSpec(max, MeasureSpec.EXACTLY);
        else if (childLayoutParam == ViewGroup.LayoutParams.WRAP_CONTENT)
            spec = MeasureSpec.makeMeasureSpec(max, ((parentMode == MeasureSpec.UNSPECIFIED) ? MeasureSpec.UNSPECIFIED : MeasureSpec.AT_MOST));
        else
            spec = MeasureSpec.makeMeasureSpec(childLayoutParam, MeasureSpec.EXACTLY);
        return spec;
    }

    @Override
    protected LayoutParams generateDefaultLayoutParams()
    {
        return new LayoutParams();
    }

    @Override
    protected boolean checkLayoutParams(ViewGroup.LayoutParams layoutParams)
    {
        return (layoutParams instanceof LayoutParams);
    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs)
    {
        return new LayoutParams(getContext(), attrs);
    }

    @Override
    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p)
    {
        return new LayoutParams(p);
    }


    @Override
    protected void onLayout(boolean changed, int leftPosition, int topPosition, int rightPosition, int bottomPosition)
    {

        int widthOffset = getMeasuredWidth() - getPaddingRight();
        int x = getPaddingLeft();
        int y = getPaddingTop();
        int rowIndex = 0;
        for (View child : getLayoutChildren())
        {
            int childWidth = child.getMeasuredWidth();
            int childHeight = child.getMeasuredHeight();
            LayoutParams layoutParams = (LayoutParams)child.getLayoutParams();
            if ((x + childWidth) > widthOffset)
            {
                x = getPaddingLeft()+rightPosition-childWidth;
                y = y + this.rowHeights[rowIndex];
                rowIndex = rowIndex + 1;
            }
            int _y;
            if (layoutParams.centerVertical)
                _y = y + ((this.rowHeights[rowIndex] - childHeight) / 2);
            else
                _y = y;
            child.layout(x, _y, x + childWidth, _y + childHeight);
            x = x + childWidth;
        }
    }

    private Collection<View> getLayoutChildren()
    {
        int count = getChildCount();
        Collection<View> children = new ArrayList<View>(count);
        for (int index = 0; index < count; index++)
        {
            View child = getChildAt(index);
            if (child.getVisibility() != View.GONE)
                children.add(child);
        }
        return children;
    }

    private int getVerticalPadding()
    {
        return getPaddingTop() + getPaddingBottom();
    }

    private int getHorizontalPadding()
    {
        return getPaddingLeft() + getPaddingRight();
    }

    public static class LayoutParams extends MarginLayoutParams
    {
        boolean centerVertical;

        public LayoutParams()
        {
            this(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        }

        public LayoutParams(int width, int height)
        {
            super(width, height);
            setCenterVertical(false);
        }

        public LayoutParams(Context context, AttributeSet attrs)
        {
            super(context, attrs);
            TypedArray attributes = context.obtainStyledAttributes(attrs, new int[] { android.R.attr.layout_centerVertical });
            setCenterVertical(attributes.getBoolean(0, false));
            attributes.recycle();
        }

        public LayoutParams(ViewGroup.LayoutParams source)
        {
            super(source);
        }

        public LayoutParams(MarginLayoutParams source)
        {
            super(source);
        }

        public LayoutParams(LayoutParams source)
        {
            this(source.width, source.height);
        }

        public void setCenterVertical(boolean centerVertical)
        {
            this.centerVertical = centerVertical;
        }
    }

    private static class RowMeasurement
    {
        private int maxWidth;
        private int widthMode;
        private int width;
        private int height;

        RowMeasurement(int maxWidth, int widthMode)
        {
            this.maxWidth = maxWidth;
            this.widthMode = widthMode;
        }

        int getWidth()
        {
            return this.width;
        }

        int getHeight()
        {
            return this.height;
        }

        boolean isWouldExceedMax(int childWidth)
        {
            return ((this.widthMode != MeasureSpec.UNSPECIFIED) && (getNewWidth(childWidth) > this.maxWidth));
        }

        void addChildDimensions(int childWidth, int childHeight)
        {
            this.width = getNewWidth(childWidth);
            this.height = Math.max(this.height, childHeight);
        }

        private int getNewWidth(int childWidth)
        {
            return ((this.width == 0) ? childWidth : (this.width + childWidth));
        }
    }
}

使用此WritingLayout而不是您现在使用的布局。