【问题标题】:Keep child view inside layout in ConstraintLayout将子视图保留在 ConstraintLayout 中的布局内
【发布时间】:2019-04-28 22:40:39
【问题描述】:

我一直在尝试使用 ConstraintLayout 实现一个显示进度数据的栏。问题是当指南太左或太右时,我的 TextView 超出了布局范围。

我尝试将 TextView 的约束从连接到“@id/guideline”更改为“父级”,并添加 Horizo​​ntalBias,但随后 TextView 将变得不准确(稍微移动到右侧/左侧取决于黄色条的长度)

这是当前结果的图像:

这是布局代码:

<android.support.constraint.ConstraintLayout
    android:id="@+id/layoutConstraint"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/white"
    android:paddingLeft="16dp"
    android:paddingTop="100dp"
    android:paddingRight="16dp"
    android:paddingBottom="16dp">

    <android.support.constraint.Guideline
        android:id="@+id/guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent=".01" />

    <TextView
        android:id="@+id/textProgress"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingBottom="12dp"
        android:textColor="@color/black"
        android:textSize="12sp"
        app:layout_constraintEnd_toEndOf="@id/guideline"
        app:layout_constraintStart_toStartOf="@id/guideline"
        app:layout_constraintTop_toTopOf="parent"
        tools:text="current value" />

    <View
        android:id="@+id/layoutProgress"
        android:layout_width="0dp"
        android:layout_height="8dp"
        android:background="@drawable/background_rounded_corner_light_grey"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/textProgress" />

    <View
        android:id="@+id/currentProgress"
        android:layout_width="0dp"
        android:layout_height="8dp"
        android:background="@drawable/background_rounded_corner_yellow"
        app:layout_constraintEnd_toStartOf="@id/guideline"
        app:layout_constraintStart_toStartOf="@id/layoutProgress"
        app:layout_constraintTop_toBottomOf="@id/textProgress" />
</android.support.constraint.ConstraintLayout>

【问题讨论】:

  • 为什么要使用 ProgressBar 的视图插入?
  • 在我的案例中,需要创建自定义的 UI,不仅需要添加文本,还需要添加指向黄色栏左侧的小箭头图标
  • 所以您需要 TextView 与 gudeline 一起移动吗?是这样吗?
  • 是的,没错,就像图片中间的那个
  • 所以最后它不应该超出父母的权利吗?

标签: android android-constraintlayout


【解决方案1】:

您似乎希望将文本“当前值”保持在进度条末尾的中心;但是,如果此位置导致文本在左侧或右侧被截断,则文本应与 ConstraintLayout 的一侧对齐,以使其保持完全可见。

您的 TextView 以您以编程方式定位在 0% 和 100% 之间的百分比准则为中心(我假设。)

我建议您将指南更改为基于像素(dp 或 px)的指南,并将您的 TextView 定位在新指南的中心。不是将基准位置从零更改为 100%,而是计算了一个新范围:

范围的下限 = TextView 宽度的 1/2 加上任何边距。

范围上限 = ConstraintLayout 的宽度 - TextView 的 1/2 宽度减去任何边距。

边距将保持在范围的低端,而进度下降到低端的左侧。随着进度越过低端,指南将向右移动进度条的当前位置 - 低端。随着进度继续达到 100%,该指南将停止在高端。

如果您想坚持使用百分比准则,请按上述方法计算低端和高端。然后,您可以根据容器的宽度计算低百分比和高百分比。

这是一个简短的演示,它使用一个简单的块来进行进度:

MainActivity.java

public class MainActivity extends AppCompatActivity {

    private ConstraintLayout mLayout;
    private View mProgress;
    private int mProgressPosition;
    private int mGuidelineMin;
    private int mGuidelineMax;
    private Guideline mGuideline;
    private int mIncrement;
    private Handler mHandler = new Handler();
    private int mMargin;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mLayout = findViewById(R.id.layout);
        mGuideline = findViewById(R.id.guideline);
        mProgress = findViewById(R.id.progress);
        mMargin = (int) TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP, 16,
            getResources().getDisplayMetrics()
        );

        mLayout.post(new Runnable() {
            private int mLoopCount = 100;

            @Override
            public void run() {
                int textWidth = findViewById(R.id.textView).getWidth();
                mGuidelineMin = textWidth / 2 + mMargin;
                mGuidelineMax = mLayout.getWidth() - textWidth / 2 - mMargin;
                mGuideline.setGuidelineBegin(mGuidelineMin);
                mIncrement = (mLayout.getWidth() - mProgress.getWidth()) / mLoopCount;
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mProgressPosition += mIncrement;
                        mProgress.setTranslationX(mProgressPosition);
                        int guidelinePosition =
                            Math.max(mGuidelineMin, mProgressPosition + mProgress.getWidth() / 2);
                        if (guidelinePosition > mGuidelineMax) {
                            guidelinePosition = mGuidelineMax;
                        }
                        mGuideline.setGuidelineBegin(guidelinePosition);
                        if (--mLoopCount > 0) {
                            mHandler.postDelayed(this, 100);
                        }
                    }
                }, 100);
            }
        });
    }
}

activity_main.xml

<androidx.constraintlayout.widget.ConstraintLayout 
    android:id="@+id/layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <View
        android:id="@+id/progress"
        android:layout_width="15dp"
        android:layout_height="15dp"
        android:background="@android:color/holo_red_light"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.17" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Current value"
        android:textSize="20sp"

        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/guideline"
        app:layout_constraintStart_toStartOf="@+id/guideline"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.07999998" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_begin="140dp" />
</androidx.constraintlayout.widget.ConstraintLayout>

【讨论】:

    【解决方案2】:

    尝试更改这个..

    app:layout_constraintGuide_percent="0.7"
    

    删除这个..

        app:layout_constraintEnd_toEndOf="@id/guideline"
        app:layout_constraintStart_toStartOf="@id/guideline"
    

    并使用了这个..

                    app:layout_constraintLeft_toLeftOf="@+id/guideline"
    

    【讨论】:

    • 是的,我在指南视图中使用过它
    • 不太可悲,它修复了从左侧裁剪 TextView 时的问题,但当从右侧裁剪 TextView 时,它会变得更糟。我还需要将 TextView 与黄色栏的右侧居中(在这种情况下,TextView 将始终位于黄色栏的右侧)
    【解决方案3】:
    <android.support.constraint.ConstraintLayout
        android:id="@+id/layoutConstraint"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/white">
    
        <android.support.constraint.Guideline
            android:id="@+id/guideline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_percent=".01" />
    
        <TextView
            android:id="@+id/textProgress"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingBottom="12dp"
            android:textColor="@color/black"
            android:textSize="12sp"
            app:layout_constraintEnd_toEndOf="@+id/currentProgress"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="@id/currentProgress"
            tools:text="40" />
    
        <View
            android:id="@+id/layoutProgress"
            android:layout_width="0dp"
            android:layout_height="8dp"
            android:background="@color/grey_2"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/textProgress" />
    
        <View
            android:id="@+id/currentProgress"
            android:layout_width="0dp"
            android:layout_height="8dp"
            android:background="@color/accent"
            app:layout_constraintEnd_toStartOf="@id/guideline"
            app:layout_constraintStart_toStartOf="@id/layoutProgress"
            app:layout_constraintTop_toBottomOf="@id/textProgress" />
    </android.support.constraint.ConstraintLayout>
    

    【讨论】:

    • 对不起先生,还是不太正确,还是从左边截断了
    • 我已经测试过了,让我和你分享一个截图..告诉我你想要这个吗?
    • 对不起,先生,如果我将指导百分比设置为非常低的值,实际上 textview 仍会被截断,假设在您的屏幕截图中有效,因为指导百分比值不够低,我还需要用条居中文本,在您的解决方案中它不是居中,而是“向左”,我找到了一个技巧,并将更新此线程
    【解决方案4】:

    因此,将 TextView 保留在 ConstraintLayout 的开始和结束约束内,将其设置为 layout_width0dp 而不是 wrap_content

    【讨论】:

      猜你喜欢
      • 2015-09-30
      • 2018-07-22
      • 1970-01-01
      • 2012-08-23
      • 2021-09-15
      • 1970-01-01
      • 2012-02-24
      • 2021-07-28
      • 2012-04-08
      相关资源
      最近更新 更多