android优先显示右边的布局,空间不足时挤压左边控件,并且右侧一直紧挨左侧布局

从需求出发

image.png
  • 显示用户名和用户 ID
  • 整体宽度不能固定,要跟随内容变化
  • 空间不够的话优先显示ID,截取用户名过长部分显示为“...”
    抽象起来就是多个元素横向排列,在空间不足的小屏手机上,保证显示右边的元素,挤压左边的。

注:需求图和描述来自网友博文。

实现

实现方式一(很简单)
<LinearLayout
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:gravity="center_vertical"
      android:orientation="horizontal">
      <TextView
            android:id="@+id/tv_shop_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            style="@style/text_medium_color3_size12"
            android:textColor="@color/black_33"
            android:singleLine="true"
            android:ellipsize="end"
            android:textSize="16sp"/>
       <LinearLayout
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:orientation="horizontal"
                  android:layout_marginStart="7dp"
                  android:gravity="center_vertical">
                  <ImageView
                        android:id="@+id/iv_shop_class"
                        android:layout_width="@dimen/store_grade_w"
                        android:layout_height="@dimen/store_grade_h"/>
                  <TextView
                       android:id="@+id/tv_shop_class"
                       android:layout_width="wrap_content"
                       android:layout_height="wrap_content"
                       android:layout_marginStart="4.5dp"
                       android:textSize="10sp"/>
      </LinearLayout>
</LinearLayout>

很简单,给空间不足时需要挤压的TextView设置layout_width="wrap_content",layout_weight="1"即可。

实现方式二:EllipsizeLayout

源码:

public class EllipsizeLayout extends LinearLayout{
    public EllipsizeLayout(Context context) {
        this(context, null);
    }

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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (getOrientation() == HORIZONTAL
                && (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY)) {
            int totalLength = 0;
            boolean outOfSpec = false;
            TextView ellipView = null;
            final int count = getChildCount();

            for (int ii = 0; ii < count && !outOfSpec; ++ii) {
                final View child = getChildAt(ii);
                if (child != null && child.getVisibility() != GONE) {
                    if (child instanceof TextView) {
                        final TextView tv = (TextView) child;
                        if (tv.getEllipsize() != null) {
                            if (ellipView == null) {
                                ellipView = tv;
                                // clear maxWidth on mEllipView before measure
                                ellipView.setMaxWidth(Integer.MAX_VALUE);
                            } else {
                                // TODO: support multiple android:ellipsize
                                outOfSpec = true;
                            }
                        }
                    }
                    final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child
                            .getLayoutParams();
                    outOfSpec |= (lp.weight > 0f);
                    measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
                    totalLength += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
                }
            }
            outOfSpec |= (ellipView == null) || (totalLength == 0);
            final int parentWidth = MeasureSpec.getSize(widthMeasureSpec);

            if (!outOfSpec && totalLength > parentWidth) {
                int maxWidth = ellipView.getMeasuredWidth() - (totalLength - parentWidth);
                // TODO: Respect android:minWidth (easy with @TargetApi(16))
                int minWidth = 0;
                if (maxWidth < minWidth) {
                    maxWidth = minWidth;
                }
                ellipView.setMaxWidth(maxWidth);
            }
        }

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

使用方式:

<com.floruit.cxy.view.EllipsizeLayout
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:gravity="center_vertical"
      android:orientation="horizontal">
      <TextView
            android:id="@+id/tv_shop_name"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:singleLine="true"
            android:ellipsize="end"
            android:layout_height="wrap_content"
            style="@style/text_medium_color3_size12"
            android:textColor="@color/black_33"
            android:textSize="16sp"
            android:text="fkdjfklsdkdjflskdjfls"/>
     <LinearLayout
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:orientation="horizontal"
                 android:layout_marginStart="7dp"
                 android:gravity="center_vertical">
                 <ImageView
                       android:id="@+id/iv_shop_class"
                       android:layout_width="@dimen/store_grade_w"
                       android:layout_height="@dimen/store_grade_h"/>
                 <TextView
                       android:id="@+id/tv_shop_class"
                       android:layout_width="wrap_content"
                       android:layout_height="wrap_content"
                       android:layout_marginStart="4.5dp"
                       android:text="aaaaaaaaa"
                       android:textSize="10sp"/>
      </LinearLayout>
</com.floruit.cxy.view.EllipsizeLayout>

给空间不足时需要挤压的TextView设置layout_width="0dp",layout_weight="1"即可。

实现效果如图所示:


推荐阅读更多精彩内容