Android:如何将文本视图浮动到左侧?

时间:2011-03-29 02:54:28

标签: android xml layout

我想让textviews浮动到左边(就像css浮动一样)。我有这么多文本视图的原因是我希望我的应用程序中的每个单词都是可点击的。所以我想要这个结果: enter image description here

目前,我有以下xml代码:

<?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="horizontal" android:baselineAligned="false">
    <TextView android:text="@string/nicholasStr" android:layout_width="wrap_content" android:textSize="18sp" android:textStyle="bold" android:layout_height="wrap_content" android:id="@+id/nicholas" ></TextView>
    <TextView android:text="@string/wasStr" android:layout_width="wrap_content" android:textSize="18sp" android:textStyle="bold" android:id="@+id/was" android:layout_height="wrap_content" ></TextView>
    <TextView android:layout_width="wrap_content" android:textSize="18sp" android:textStyle="bold" android:id="@+id/dots" android:layout_height="wrap_content" android:text="@string/dots"></TextView>
    <TextView android:layout_width="wrap_content" android:textSize="18sp" android:textStyle="bold" android:layout_height="wrap_content" android:text="@string/older" android:id="@+id/older"></TextView>
    <TextView android:layout_width="wrap_content" android:textSize="18sp" android:textStyle="bold" android:layout_height="wrap_content" android:text="@string/older" android:id="@+id/older"></TextView>
    <TextView android:layout_width="wrap_content" android:textSize="18sp" android:textStyle="bold" android:layout_height="wrap_content" android:text="@string/older" android:id="@+id/older"></TextView>
    <TextView android:text="@string/older" android:layout_width="wrap_content" android:textSize="18sp" android:textStyle="bold" android:layout_height="wrap_content" android:id="@+id/older"></TextView>
</LinearLayout>

但结果是这样的:

enter image description here

我是android dev的新手,非常感谢提前。 :)

3 个答案:

答案 0 :(得分:20)

您真正需要的是一个包装整个视图的行布局。不幸的是,Android没有。幸运的是,我做到了! ;)

这是一个自定义类,但只要您完全符合它,就可以在xml中使用它,并在res / values下包含以下attrs.xml文件

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="RowLayout">
        <attr name="android:verticalSpacing" />
        <attr name="android:horizontalSpacing" />
    </declare-styleable>
</resources>

以下是来源:

package com.example.widget;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
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;

import com.example.widget.R;

public class RowLayout extends ViewGroup {
    public static final int DEFAULT_HORIZONTAL_SPACING = 5;
    public static final int DEFAULT_VERTICAL_SPACING = 5;
    private final int horizontalSpacing;
    private final int verticalSpacing;
    private List<RowMeasurement> currentRows = Collections.emptyList();

    public RowLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray styledAttributes = context.obtainStyledAttributes(attrs, R.styleable.RowLayout);
        horizontalSpacing = styledAttributes.getDimensionPixelSize(R.styleable.RowLayout_android_horizontalSpacing,
                DEFAULT_HORIZONTAL_SPACING);
        verticalSpacing = styledAttributes.getDimensionPixelSize(R.styleable.RowLayout_android_verticalSpacing,
                DEFAULT_VERTICAL_SPACING);
        styledAttributes.recycle();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        final int maxInternalWidth = MeasureSpec.getSize(widthMeasureSpec) - getHorizontalPadding();
        final int maxInternalHeight = MeasureSpec.getSize(heightMeasureSpec) - getVerticalPadding();
        List<RowMeasurement> rows = new ArrayList<RowMeasurement>();
        RowMeasurement currentRow = new RowMeasurement(maxInternalWidth, widthMode);
        rows.add(currentRow);
        for (View child : getLayoutChildren()) {
            LayoutParams childLayoutParams = 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.wouldExceedMax(childWidth)) {
                currentRow = new RowMeasurement(maxInternalWidth, widthMode);
                rows.add(currentRow);
            }
            currentRow.addChildDimensions(childWidth, childHeight);
        }

        int longestRowWidth = 0;
        int totalRowHeight = 0;
        for (int index = 0; index < rows.size(); index++) {
            RowMeasurement row = rows.get(index);
            totalRowHeight += row.getHeight();
            if (index < rows.size() - 1) {
                totalRowHeight += verticalSpacing;
            }
            longestRowWidth = Math.max(longestRowWidth, row.getWidth());
        }
        setMeasuredDimension(widthMode == MeasureSpec.EXACTLY ? MeasureSpec.getSize(widthMeasureSpec) : longestRowWidth
                + getHorizontalPadding(), heightMode == MeasureSpec.EXACTLY ? MeasureSpec.getSize(heightMeasureSpec)
                : totalRowHeight + getVerticalPadding());
        currentRows = Collections.unmodifiableList(rows);
    }

    private int createChildMeasureSpec(int childLayoutParam, int max, int parentMode) {
        int spec;
        if (childLayoutParam == LayoutParams.FILL_PARENT) {
            spec = MeasureSpec.makeMeasureSpec(max, MeasureSpec.EXACTLY);
        } else if (childLayoutParam == 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 void onLayout(boolean changed, int leftPosition, int topPosition, int rightPosition, int bottomPosition) {
        final int widthOffset = getMeasuredWidth() - getPaddingRight();
        int x = getPaddingLeft();
        int y = getPaddingTop();

        Iterator<RowMeasurement> rowIterator = currentRows.iterator();
        RowMeasurement currentRow = rowIterator.next();
        for (View child : getLayoutChildren()) {
            final int childWidth = child.getMeasuredWidth();
            final int childHeight = child.getMeasuredHeight();
            if (x + childWidth > widthOffset) {
                x = getPaddingLeft();
                y += currentRow.height + verticalSpacing;
                if (rowIterator.hasNext()) {
                    currentRow = rowIterator.next();
                }
            }
            child.layout(x, y, x + childWidth, y + childHeight);
            x += childWidth + horizontalSpacing;
        }
    }

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

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

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

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

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

        public int getHeight() {
            return height;
        }

        public int getWidth() {
            return width;
        }

        public boolean wouldExceedMax(int childWidth) {
            return widthMode == MeasureSpec.UNSPECIFIED ? false : getNewWidth(childWidth) > maxWidth;
        }

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

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

答案 1 :(得分:0)

您可以使用orientation = vertical的相对布局轻松完成。

例如:在 activity_main.xml文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >

<Button
    android:id="@+id/btnButton1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Button 1"/>

<Button
    android:id="@+id/btnButton2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Button 2"
    android:layout_toRightOf="@+id/btnButton1"/>

<TextView
     android:id="@+id/textView1"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_below="@+id/btnButton3"
     android:layout_marginTop="94dp"
     android:text="User :"
     android:textAppearance="?android:attr/textAppearanceLarge" />
  .......

</RelativeLayout>

答案 2 :(得分:0)

我找到了一个非常简单的解决方案来创建一个包含多行选项的菜单:

public class OptionMenu extends LinearLayout {
private int widthConsumed = 0;
private LinearLayout currentRow;

interface OptionRunnable {
    void onOptionSelected(int option);
}

public OptionMenu(Context context) {
    super(context);
    setOrientation(VERTICAL);
}

public void setOptions(List<Integer> options, OptionRunnable runnable) {
    getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
        @Override
        public boolean onPreDraw() {
            getViewTreeObserver().removeOnPreDrawListener(this);

            Stream.of(options).forEach(option -> {
                TextView text = (TextView) LayoutInflater.from(getContext()).inflate(R.layout.incl_textviewer_option_button, OptionMenu.this, false);
                text.setText(option);
                text.setTag(option);
                text.setOnClickListener(v -> runnable.onOptionSelected((Integer) v.getTag()));

                text.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
                getCurrentRow(text.getMeasuredWidth()).addView(text);
            });
            return true;
        }
    });
}

private LinearLayout getCurrentRow(int width) {
    if(currentRow == null) {
        currentRow = new LinearLayout(getContext());
        currentRow.setOrientation(HORIZONTAL);
        addView(currentRow);
    }

    widthConsumed += width;

    if(widthConsumed < getWidth())
        return currentRow;

    LinearLayout newRow = new LinearLayout(getContext());
    newRow.setOrientation(HORIZONTAL);
    currentRow = newRow;
    widthConsumed = width;
    addView(newRow);

    return newRow;
}
}