【问题标题】:How to set constraint layout minimum width to the width of another view from xml如何从xml将约束布局最小宽度设置为另一个视图的宽度
【发布时间】:2018-12-02 00:14:36
【问题描述】:

在群组消息集的消息行中,最小(文本和时间)布局宽度是用户名视图的宽度。见下图(见时间对齐)

//Pseudo code
textLayout = text + time 
usernameLayout = senderName

if(usernameLayout == gone){
    textLayout width == wrap_content
}else{
  textLayout minimum width == usernameLayout width  
}

输出是这样的

我想要的结果如下

布局代码

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/message_row_parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start|bottom"
android:baselineAligned="false"
android:paddingStart="@dimen/padding_8dp"
android:paddingEnd="40dp">


<android.support.constraint.ConstraintLayout
    android:id="@+id/message_box"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/chat_incoming_bg">

    <TextView
        android:id="@+id/tvUserName"
        style="@style/TextStyle.Chat.Item.Name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="4dp"
        android:layout_marginEnd="8dp"
        android:ellipsize="end"
        android:fontFamily="sans-serif-medium"
        android:maxLines="1"
        android:paddingEnd="@dimen/padding_8dp"
        android:text="Jarvis Pixel9 New testName "
        android:textColor="@color/red800"
        android:visibility="visible"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <android.support.constraint.ConstraintLayout
        android:id="@+id/chat_text_layout"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_gravity="start"
        android:gravity="start"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tvUserName">


        <com.vanniktech.emoji.EmojiTextView
            android:id="@+id/message_body"
            style="@style/Base.TextAppearance.AppCompat.Body1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingLeft="@dimen/padding_8dp"
            android:paddingTop="@dimen/padding_4dp"
            android:paddingRight="@dimen/padding_8dp"
            android:paddingBottom="@dimen/padding_8dp"
            android:text="Hijkhkfjhds"
            android:textColorLink="@color/link_color"
            android:textSize="?attr/TextSizeBody"
            app:emojiSize="28sp"
            tools:ignore="MissingConstraints"
            tools:layout_editor_absoluteY="0dp" />

        <LinearLayout
            android:id="@+id/ll_msg_info"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="end|bottom"
            android:gravity="end|bottom"
            android:minWidth="60dp"
            android:orientation="horizontal"
            android:paddingEnd="@dimen/padding_8dp"
            android:paddingBottom="@dimen/padding_4dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="1.0"
            app:layout_constraintStart_toEndOf="@+id/message_body"
            tools:ignore="RtlSymmetry">

            <TextView
                android:id="@+id/message_time"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical"
                android:gravity="center_vertical"
                android:text="12:50 PM"
                android:textColor="@color/black54"
                android:textSize="?attr/TextSizeInfo" />

            <ImageView
                android:id="@+id/img_failed_status"
                android:layout_width="16dp"
                android:layout_height="16dp"
                android:layout_gravity="center_vertical"
                android:layout_marginStart="4dp"
                android:gravity="center_vertical"
                android:src="@drawable/ic_cancel_24dp"
                android:visibility="gone" />
        </LinearLayout>

    </android.support.constraint.ConstraintLayout>

    </android.support.constraint.ConstraintLayout>

    </android.support.constraint.ConstraintLayout>

如果我设置 chat_text_layout 宽度 0dp 和 tvUserName 并带有一些文本,则它们可以正常工作,但如果 tvUserName = gone 则不能正常工作。

【问题讨论】:

  • 我希望我的回答已经解决了您的疑问,如果您需要进一步的帮助,您可以提出。 :)

标签: android android-layout android-constraintlayout


【解决方案1】:

经过大量试验和错误后,此解决方案正在运行

感谢Sinan Erginstackoverflow 的回答。

XML 布局

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/message_row_parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start|bottom"
android:baselineAligned="false"
android:paddingStart="@dimen/padding_8dp"
android:paddingEnd="40dp">

<android.support.constraint.ConstraintLayout
    android:id="@+id/message_box"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginEnd="8dp"
    android:background="@drawable/chat_incoming_bg"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="0.0"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent">
    <!--User Name -->
    <android.support.constraint.ConstraintLayout
        android:id="@+id/user_layout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="gone"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <TextView
            android:id="@+id/tvContactName"
            style="@style/TextStyle.Chat.Item.Name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginTop="4dp"
            android:layout_marginEnd="8dp"
            android:ellipsize="end"
            android:fontFamily="sans-serif-medium"
            android:paddingEnd="@dimen/padding_8dp"
            android:textColor="@color/red800"
            android:visibility="visible"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/tvServerName"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />


        <TextView
            android:id="@+id/tvServerName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginTop="4dp"
            android:layout_marginEnd="4dp"
            android:ellipsize="end"
            android:maxEms="7"
            android:maxLength="20"
            android:maxLines="1"
            android:scrollHorizontally="true"
            android:singleLine="true"
            android:textSize="12sp"
            android:visibility="visible"
            app:layout_constraintBaseline_toBaselineOf="@+id/tvContactName"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="1.0"
            app:layout_constraintStart_toEndOf="@+id/tvContactName"
            app:layout_constraintTop_toTopOf="parent" />

    </android.support.constraint.ConstraintLayout>
    <!--Message Layout-->
    <com.shain.views.ChatTextLayout
        android:id="@+id/qt_chat_text_layout"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/user_layout"
        app:layout_constraintVertical_bias="0.50"
        app:layout_constraintWidth_min="wrap"
        app:viewPartMain="@+id/message_body"
        app:viewPartSlave="@+id/ll_msg_info">


        <com.vanniktech.emoji.EmojiTextView
            android:id="@+id/message_body"
            style="@style/Base.TextAppearance.AppCompat.Body1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:focusableInTouchMode="false"
            android:paddingLeft="@dimen/padding_8dp"
            android:paddingTop="@dimen/padding_4dp"
            android:paddingBottom="@dimen/padding_4dp"
            android:paddingRight="@dimen/padding_8dp"
            android:textColorLink="@color/link_color"
            android:textSize="?attr/TextSizeBody"
            app:emojiSize="28sp"
            tools:ignore="MissingConstraints" />

        <LinearLayout
            android:id="@+id/ll_msg_info"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="end|bottom"
            android:gravity="end|bottom"
            android:minWidth="60dp"
            android:orientation="horizontal"
            android:paddingEnd="@dimen/padding_8dp"
            android:paddingBottom="@dimen/padding_4dp"
            tools:ignore="RtlSymmetry">

            <TextView
                android:id="@+id/message_time"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical"
                android:gravity="center_vertical"
                android:textColor="@color/black54"
                android:textSize="?attr/TextSizeInfo" />

            <ImageView
                android:id="@+id/img_failed_status"
                android:layout_width="16dp"
                android:layout_height="16dp"
                android:layout_gravity="bottom"
                android:layout_marginStart="4dp"
                android:gravity="center_vertical"
                android:src="@drawable/ic_cancel_24dp"
                android:visibility="gone" />
        </LinearLayout>

    </com.shain.views.ChatTextLayout>

</android.support.constraint.ConstraintLayout>

Java 自定义视图代码

public class ChatTextLayout extends ConstraintLayout {

private int widthSize;
private int heightSize;

private TextView viewPartMain;
private View viewPartSlave;
private TypedArray a;

private LayoutParams viewPartMainLayoutParams;
private int viewPartMainWidth;
private int viewPartMainHeight;

private LayoutParams viewPartSlaveLayoutParams;
private int viewPartSlaveWidth;
private int viewPartSlaveHeight;

private boolean withGroupHeader = false;

public ChatTextLayout(Context context) {
    super(context);
}

public ChatTextLayout(Context context, AttributeSet attrs) {
    super(context, attrs);

    a = context.obtainStyledAttributes(attrs, R.styleable.MessageTextStyle, 0, 0);
}

public void setWithGroupHeader(boolean withGroupHeader) {
    this.withGroupHeader = withGroupHeader;
}

@Override
protected void onAttachedToWindow() {
    super.onAttachedToWindow();

    try {
        viewPartMain = this.findViewById(a.getResourceId(R.styleable.MessageTextStyle_viewPartMain, -1));
        viewPartSlave = this.findViewById(a.getResourceId(R.styleable.MessageTextStyle_viewPartSlave, -1));
    } catch (Exception e) {
        e.printStackTrace();
    }
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    widthSize = MeasureSpec.getSize(widthMeasureSpec);
    heightSize = MeasureSpec.getSize(heightMeasureSpec);

    if (viewPartMain == null || viewPartSlave == null || widthSize <= 0) {
        return;
    }

    int availableWidth = widthSize - getPaddingLeft() - getPaddingRight();
    int availableHeight = heightSize - getPaddingTop() - getPaddingBottom();

    viewPartMainLayoutParams = (LayoutParams) viewPartMain.getLayoutParams();
    viewPartMainWidth = viewPartMain.getMeasuredWidth() + viewPartMainLayoutParams.leftMargin + viewPartMainLayoutParams.rightMargin;
    viewPartMainHeight = viewPartMain.getMeasuredHeight() + viewPartMainLayoutParams.topMargin + viewPartMainLayoutParams.bottomMargin;

    viewPartSlaveLayoutParams = (LayoutParams) viewPartSlave.getLayoutParams();
    viewPartSlaveWidth = viewPartSlave.getMeasuredWidth() + viewPartSlaveLayoutParams.leftMargin + viewPartSlaveLayoutParams.rightMargin;
    viewPartSlaveHeight = viewPartSlave.getMeasuredHeight() + viewPartSlaveLayoutParams.topMargin + viewPartSlaveLayoutParams.bottomMargin;

    int viewPartMainLineCount = viewPartMain.getLineCount();
    float viewPartMainLastLineWidth = viewPartMainLineCount > 0 ? viewPartMain.getLayout().getLineWidth(viewPartMainLineCount - 1) : 0;

    widthSize = getPaddingLeft() + getPaddingRight();
    heightSize = getPaddingTop() + getPaddingBottom();

    if (viewPartMainLineCount > 1 && !(viewPartMainLastLineWidth + viewPartSlaveWidth > viewPartMain.getMeasuredWidth())) {
        widthSize += viewPartMainWidth;
        heightSize += viewPartMainHeight;
    } else if (viewPartMainLineCount > 1 && (viewPartMainLastLineWidth + viewPartSlaveWidth > availableWidth)) {
        widthSize += viewPartMainWidth;
        heightSize += viewPartMainHeight + viewPartSlaveHeight;
    } else if (viewPartMainLineCount == 1 && (viewPartMainWidth + viewPartSlaveWidth > availableWidth)) {
        widthSize += viewPartMain.getMeasuredWidth();
        heightSize += viewPartMainHeight + viewPartSlaveHeight;
    } else {
        heightSize += viewPartMainHeight;
        widthSize += viewPartMainWidth + viewPartSlaveWidth;
    }

    this.setMeasuredDimension(widthSize, heightSize);
    super.onMeasure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY));

}

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);

    if (viewPartMain == null || viewPartSlave == null) {
        return;
    }
    if (withGroupHeader) {
        viewPartMain.layout(
                getPaddingLeft(),
                getPaddingTop() - Utils.dp(4f),
                viewPartMain.getWidth() + getPaddingLeft(),
                viewPartMain.getHeight() + getPaddingTop());

        viewPartSlave.layout(
                right - left - viewPartSlaveWidth - getPaddingRight(),
                bottom - top - getPaddingBottom() - viewPartSlaveHeight,
                right - left - getPaddingRight(),
                bottom - top - getPaddingBottom());
    } else {
        viewPartMain.layout(
                getPaddingLeft(),
                getPaddingTop(),
                viewPartMain.getWidth() + getPaddingLeft(),
                viewPartMain.getHeight() + getPaddingTop());

        viewPartSlave.layout(
                right - left - viewPartSlaveWidth - getPaddingRight(),
                bottom - top - getPaddingBottom() - viewPartSlaveHeight,
                right - left - getPaddingRight(),
                bottom - top - getPaddingBottom());
    }
  }
}

attrs.xml

 <declare-styleable name="MessageTextStyle">
    <attr name="viewPartMain" format="reference"></attr>
    <attr name="viewPartSlave" format="reference"></attr>
</declare-styleable>

【讨论】:

  • 你能分享这个的github链接吗?
  • Github 上没有,但是如果您有任何疑问,我会帮助您。
  • 你能把这个上传到github上吗?
【解决方案2】:

ll_msg_info 中删除以下行,因为视图只能使用两个约束。因为您设置了 right/endbottom 约束,您的布局将使用它。

app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toEndOf="@+id/message_body"

【讨论】:

    【解决方案3】:

    我认为,下面的代码将满足您的用例。

    XML 代码(用于布局):

    <?xml version="1.0" encoding="utf-8"?>
    
    <android.support.constraint.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/chat">
    
        <TextView
            android:id="@+id/tvName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:maxWidth="300dp"
            android:text="This Is A Very Long Name As You See"
            android:paddingStart="20dp"
            android:paddingEnd="4dp"
            android:textSize="16sp"
            android:textColor="@android:color/holo_red_dark"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
        <TextView
            android:id="@+id/tvComment"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:maxWidth="300dp"
            android:text="This is some comment."
            android:paddingStart="20dp"
            android:paddingEnd="4dp"
            android:textSize="18sp"
            android:textColor="@android:color/black"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/tvName" />
    
        <TextView
            android:id="@+id/tvTime"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="12:50"
            android:textSize="14sp"
            android:paddingEnd="5dp"
            android:paddingBottom="3dp"
            app:layout_constraintTop_toBottomOf="@+id/tvComment"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHorizontal_bias="1.0" />
    </android.support.constraint.ConstraintLayout>
    

    XML 代码(用于名为“聊天”的可绘制对象):

    <?xml version="1.0" encoding="utf-8"?>
    
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        <item>
            <rotate
                android:fromDegrees="-45"
                android:pivotX="0%"
                android:pivotY="0%"
                android:toDegrees="0" >
                <shape android:shape="rectangle" >
                    <solid android:color="@android:color/holo_green_light" />
                </shape>
            </rotate>
        </item>
    
        <item android:left="16dp">
            <shape android:shape="rectangle" >
                <solid android:color="@android:color/holo_green_light" />
                <corners android:radius="6dp" />
            </shape>
        </item>
    </layer-list>
    

    截图(以上代码):

    对于屏幕尺寸 - 5.0 英寸(1080 x 1920 像素)[设备:像素]

    您也可以针对不同的屏幕尺寸运行它,对我来说绝对没问题。

    希望对你有帮助。

    【讨论】:

    • 嗨,我检查了它仍然不是很完美。它有更多的空白,气泡看起来很大。我正在开发类似 Whatsapp 的东西,其中时间布局会根据文本大小进行调整。
    • 以上问题我已经用新应用解决了:layout_constraintWidth_min="wrap" in constraint layout 1.1.3
    • 但在较大的文本时间和文本布局重叠
    • 在上面提到的代码中,textView 的时间会根据文本的长度进行调整,即名称文本和评论文本,如果你仔细注意到的话。
    • 可以像我现在管理的那样管理气泡大小。 :)
    猜你喜欢
    • 2020-03-20
    • 2022-01-21
    • 2020-01-18
    • 1970-01-01
    • 1970-01-01
    • 2019-06-03
    • 1970-01-01
    • 1970-01-01
    • 2017-04-19
    相关资源
    最近更新 更多