【问题标题】:Android: How can I make text views float to the left?Android:如何让文本视图向左浮动?
【发布时间】:2011-03-29 02:54:28
【问题描述】:

我想让 textviews 向左浮动(如 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:orientation = "vertical"
  • 尝试RelativeLayout 并查看这篇文章 [link] developer.android.com/resources/articles/…
  • 如果你用java而不是xml动态地制作它们。你可以检查最后一个的右边缘,看看它离屏幕边缘有多远,这样你就知道什么时候需要跳到下一行了。
  • 谢谢你们的回复。 @Tim:你有示例代码吗?

标签: android xml layout


【解决方案1】:

您真正需要的是包含整个视图的行布局。不幸的是,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;
        }
    }
}

【讨论】:

  • 很高兴让像我这样的新手知道他们需要以下行: xmlns:app="schemas.android.com/apk/res-auto" 在根布局中。即 schemas.android.com/apk/res/android" xmlns:app="schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content">
  • 很好的答案。奇迹般有效。如果你能把它放到 Github 上,那就太棒了,也许还有一个小文档。让我知道是否可以提供帮助:)
【解决方案2】:

您可以使用方向 = 垂直的相对布局轻松做到这一点。

例如: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>

【讨论】:

    【解决方案3】:

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

    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;
    }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-20
      • 2017-12-06
      • 1970-01-01
      • 2015-01-14
      • 1970-01-01
      • 1970-01-01
      • 2014-04-24
      相关资源
      最近更新 更多