Android可动态添加双列视图对的可复用控件开发需求
需求:开发可复用的双列配对Android控件
需要实现一个可复用的Android控件,用于展示双列视图对,支持动态添加任意数量的视图对,核心要求如下:
- 第一列视图左对齐,第二列视图右对齐,示例效果:
Text1 1 Text2 14 Text3 423 - 列宽不固定,整列宽度随列内最长文本自适应调整,示例:
或Text1 123456 Text2 12 Text3 1234 Text4 1Text1 123 Text2Text2 12 Text3Text3Text3Text3 123 Text4 1 - 空间不足时的适配规则:
- 优先保证第二列显示优先级,第一列文本可换行
- 第一列需设置最小宽度占比,避免被过度压缩
- 第二列文本过长时也支持换行
- 某列文本为多行时,另一列视图需与其垂直居中对齐
已尝试方案及问题
尝试过以下三种方式均未达到预期效果:
- 使用GridLayout
- 在ConstraintLayout中嵌套两个垂直LinearLayout
- 直接使用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
相关产品推荐
相关产品推荐

