Android:如何使文本视图向左浮动?

Android:如何使文本视图向左浮动?,android,xml,layout,Android,Xml,Layout,我想让文本视图向左浮动(就像css浮动一样)。我有这么多文本视图的原因是我希望我的应用程序中的每个单词都可以点击。所以我想要这个结果: 目前,我有以下xml代码: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" and

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

目前,我有以下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>

但结果是这样的:


我是android开发新手,非常感谢。:)

您真正需要的是包装整个视图的行布局。不幸的是,Android没有。你真幸运,我真的

它是一个自定义类,但只要完全限定它,并在res/values下包含以下attrs.xml文件,就可以在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;
        }
    }
}
package com.example.widget;
导入java.util.ArrayList;
导入java.util.Collections;
导入java.util.Iterator;
导入java.util.List;
导入android.content.Context;
导入android.content.res.TypedArray;
导入android.util.AttributeSet;
导入android.view.view;
导入android.view.ViewGroup;
导入com.example.widget.R;
公共类RowLayout扩展了ViewGroup{
公共静态最终整数默认水平间距=5;
公共静态最终整数默认值垂直间距=5;
私有最终整数水平间距;
专用垂直间距;
private List currentRows=Collections.emptyList();
公共行布局(上下文、属性集属性){
超级(上下文,attrs);
TypedArray styledAttributes=上下文。获取styledAttributes(attrs,R.styleable.RowLayout);
horizontalSpacing=styledAttributes.getDimensionPixelSize(R.styleable.RowLayout\u android\u horizontalSpacing,
默认值(水平间距);
verticalSpacing=styledAttributes.getDimensionPixelSize(R.styleable.RowLayout\u android\u verticalSpacing,
默认值(垂直间距);
styledAttributes.recycle();
}
@凌驾
测量时的保护空隙(内部宽度测量等级、内部高度测量等级){
最终int-widthMode=MeasureSpec.getMode(widthmasurespec);
最终int heightMode=MeasureSpec.getMode(heightMeasureSpec);
final int maxInternalWidth=MeasureSpec.getSize(widthMeasureSpec)-getHorizontalPadding();
final int maxInternalHeight=MeasureSpec.getSize(heightMeasureSpec)-getVerticalPadding();
列表行=新建ArrayList();
RowMeasurement currentRow=新的RowMeasurement(maxInternalWidth,widthMode);
行。添加(currentRow);
对于(查看子项:getLayoutChildren()){
LayoutParams childLayoutParams=child.getLayoutParams();
int childWidthSpec=createChildMeasureSpec(childLayoutParams.width、maxInternalWidth、widthMode);
int childHeightSpec=createChildMeasureSpec(childLayoutParams.height、maxInternalHeight、heightMode);
测量(childWidthSpec、childHeightSpec);
int childWidth=child.getMeasuredWidth();
int childHeight=child.getMeasuredHeight();
if(currentRow.WouldeExceedMax(childWidth)){
currentRow=新行测量(maxInternalWidth,widthMode);
行。添加(currentRow);
}
currentRow.addChildDimensions(childWidth、childHeight);
}
int longestRowWidth=0;
int totalRowHeight=0;
对于(int index=0;indexwidthOffset){
x=getPaddingLeft();
y+=当前行高+垂直间距;
if(roweiterator.hasNext()){
currentRow=rowIterator.next();
}
}
布局(x,y,x+子宽度,y+子高度);
x+=子宽度+水平间距;
}
}
私有列表getLayoutChildren(){
List children=new ArrayList();
对于(int index=0;index<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>
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;
}
}