You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android可动态添加双列视图对的可复用控件开发需求

需求:开发可复用的双列配对Android控件

需要实现一个可复用的Android控件,用于展示双列视图对,支持动态添加任意数量的视图对,核心要求如下:

  • 第一列视图左对齐,第二列视图右对齐,示例效果:
    Text1    1
    Text2   14
    Text3  423
    
  • 列宽不固定,整列宽度随列内最长文本自适应调整,示例:
    Text1  123456
    Text2      12
    Text3    1234
    Text4       1 
    
    或
    Text1                 123
    Text2Text2             12
    Text3Text3Text3Text3  123
    Text4                   1
    
  • 空间不足时的适配规则:
    • 优先保证第二列显示优先级,第一列文本可换行
    • 第一列需设置最小宽度占比,避免被过度压缩
    • 第二列文本过长时也支持换行
    • 某列文本为多行时,另一列视图需与其垂直居中对齐

已尝试方案及问题

尝试过以下三种方式均未达到预期效果:

  1. 使用GridLayout
  2. 在ConstraintLayout中嵌套两个垂直LinearLayout
  3. 直接使用ConstraintLayout动态添加视图和约束

尝试的布局代码

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.constraint.ConstraintLayout
        android:id="@+id/constraintLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"/>
</FrameLayout>

尝试的C#代码

public class MainActivity : AppCompatActivity
{
    private ConstraintLayout _constraintLayout;
    private Dictionary<object, Tuple<View, View>> _objectWithViews;

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        SetContentView(Resource.Layout.activity_main);

        _constraintLayout = FindViewById<ConstraintLayout>(Resource.Id.constraintLayout);
        _objectWithViews = new Dictionary<object, Tuple<View, View>>();

        var items = new List<Tuple<string, string>>
        {
            Tuple.Create("Text1", "10"),
            Tuple.Create("Text2Text2Text2Text2Text2", "123122124123535"),
            Tuple.Create("Text3Text3Text3", "230"),
            Tuple.Create("Text4Text4Text4Text4", "10"),
            Tuple.Create("Text5Text5", "123450")
        };

        foreach (var item in items)
        {
            View titleView = GetTextView(item.Item1);
            View valueView = GetTextView(item.Item2);

            titleView.SetBackgroundColor(Color.Beige);
            valueView.SetBackgroundColor(Color.Red);

            AddViews(titleView, valueView);
            _objectWithViews.Add(item, Tuple.Create(titleView, valueView));
        }
    }

    private void AddViews(View view1, View view2)
    {
        var constraintSet = new ConstraintSet();

        constraintSet.Clone(_constraintLayout);

        view1.Id = View.GenerateViewId();
        view2.Id = View.GenerateViewId();

        _constraintLayout.AddView(view1);
        _constraintLayout.AddView(view2);

        constraintSet.ConstrainWidth(view1.Id, ConstraintSet.MatchConstraint);
        constraintSet.ConstrainHeight(view1.Id, ConstraintSet.WrapContent);

        constraintSet.ConstrainWidth(view2.Id, ConstraintSet.WrapContent);
        constraintSet.ConstrainHeight(view2.Id, ConstraintSet.WrapContent);

        // 尝试设置第二列最大宽度避免挤压第一列,但无效
        /*constraintSet.ConstrainMaxWidth(view2.Id, ConstraintSet.MatchConstraintWrap);
        constraintSet.ConstrainPercentWidth(view2.Id, 0.6f);*/

        constraintSet.Connect(view1.Id, ConstraintSet.Left, ConstraintSet.ParentId, ConstraintSet.Left);
        constraintSet.Connect(view2.Id, ConstraintSet.Right, ConstraintSet.ParentId, ConstraintSet.Right);
        constraintSet.Connect(view1.Id, ConstraintSet.Right, view2.Id, ConstraintSet.Left);
        constraintSet.Connect(view2.Id, ConstraintSet.Left, view1.Id, ConstraintSet.Right);

        constraintSet.CreateHorizontalChain(ConstraintSet.ParentId, ConstraintSet.Left, ConstraintSet.ParentId,
            ConstraintSet.Right, new[] { view1.Id, view2.Id }, null, ConstraintSet.ChainPacked);

        if (!_objectWithViews.Any())
        {
            constraintSet.Connect(view1.Id, ConstraintSet.Top, ConstraintSet.ParentId, ConstraintSet.Top);
            constraintSet.Connect(view2.Id, ConstraintSet.Top, ConstraintSet.ParentId, ConstraintSet.Top);
        }
        else
        {
            var previousViews = _objectWithViews.Last().Value;

            constraintSet.Connect(view1.Id, ConstraintSet.Top, previousViews.Item1.Id, ConstraintSet.Bottom);
            constraintSet.Connect(view2.Id, ConstraintSet.Top, view1.Id, ConstraintSet.Top);
            constraintSet.Connect(view2.Id, ConstraintSet.Bottom, view1.Id, ConstraintSet.Bottom);
        }

        constraintSet.ApplyTo(_constraintLayout);
    }

    private TextView GetTextView(string text)
    {
        var titleView = new TextView(this)
        {
            Text = text,
        };

        titleView.SetSingleLine(false);
        titleView.SetMaxLines(5);

        return titleView;
    }
}

当前效果

当前实现未达到预期:第一列文本被过度压缩,长文本换行后第二列视图未与第一列垂直居中;列宽未随最长文本自适应调整,第二列长文本也未按规则换行。


内容的提问来源于stack exchange,提问作者matekome

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 12:15:41