I want to create a reusable control to present list of two-views pairs. I want to be able to addd different number of such pairs programatically. Views in first column should be aligned to start and views in second column should be aligned to end. For example let's assume we want to present pairs label and value so we want something like this:
Text1 1 Text2 14 Text3 423
but there is one important thing. These columns width shouldn't be fixed. If at least one text is longer, the whole column should be wider. So for example:
Text1 123456 Text2 12 Text3 1234 Text4 1
or
Text1 123 Text2Text2 12 Text3Text3Text3Text3 123 Text4 1
Of course there is a maximum space for this control so if there is no enough space second column should has higher priority and texts in first column should be broken into more lines. First column shouldn't be totally squeeze so should has some minimum width (percentage) and if text in second column is still too long then text in second column should be broken into more lines too. If some text is multiline then text in other column should be centered verticaly to this text.
I've tried to do this using GridLayout or using two vertical LinearLayout inside ConstraintLayout or using only ConstraintLayout and adding views and constraints to it. Nothing works as I expected.
<?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>
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);
// This way i tried to set max second column width to not totally squeeze first column but it also doesn't work
/*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;
}
}
Result
