Best practice in programmatically creating UI - android

lately i always got to a point where i want to create my UI dynamically.
I found a way to do so but i dont really like it.
For example i wanted to create a GoogleCalender like Dayview and ended up doing like so: (don't read the code in detail just see that it's bad)
constraintSet = new ConstraintSet();
View nextHolder = new View(this);
View nextMarker = new View(this);
TextView nextTime = new TextView(this);
holders[i] = nextHolder;
times[i] = nextTime;
markers[i] = nextMarker;
int calcHour = hour + i;
if (calcHour < 10) {
nextTime.setText("0" + Integer.toString(calcHour) + ":00");
} else {
nextTime.setText(Integer.toString(calcHour) + ":00");
}
nextTime.setTextColor(0xFF000000);
nextMarker.setBackgroundColor(ResourcesCompat.getColor(getResources(), R.color.grey, null));
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
holders[i].setId(Utils.generateViewId());
markers[i].setId(Utils.generateViewId());
times[i].setId(Utils.generateViewId());
} else {
holders[i].setId(View.generateViewId());
markers[i].setId(View.generateViewId());
times[i].setId(View.generateViewId());
}
int nextHolderID = holders[i].getId();
int nextMarkerID = markers[i].getId();
int nextTimeID = nextTime.getId();
constraintLayout.addView(holders[i]);
constraintLayout.addView(markers[i]);
constraintLayout.addView(times[i]);
constraintSet.clone(constraintLayout);
//Constraint the Time-Stamp-Holders
constraintSet.constrainHeight(nextHolderID, Utils.convertDpToPixel(40, context));
constraintSet.constrainWidth(nextHolderID, ConstraintSet.MATCH_CONSTRAINT);
constraintSet.connect(nextHolderID, ConstraintSet.START, ConstraintSet.PARENT_ID,
ConstraintSet.START);
constraintSet.connect(nextHolderID, ConstraintSet.END, ConstraintSet.PARENT_ID,
ConstraintSet.END);
if (i == 1) {
constraintSet.connect(nextHolderID, ConstraintSet.TOP, startHolder.getId(),
ConstraintSet.BOTTOM, Utils.convertDpToPixel(8, context));
} else {
constraintSet.connect(nextHolderID, ConstraintSet.TOP, holders[i - 1].getId(),
ConstraintSet.BOTTOM, Utils.convertDpToPixel(8, context));
}
//Constraint the Time TextViews
constraintSet.constrainHeight(nextTimeID, ConstraintSet.WRAP_CONTENT);
constraintSet.constrainWidth(nextTimeID, ConstraintSet.WRAP_CONTENT);
constraintSet.connect(nextTimeID, ConstraintSet.BOTTOM, nextHolderID,
ConstraintSet.BOTTOM, Utils.convertDpToPixel(8, context));
constraintSet.connect(nextTimeID, ConstraintSet.TOP, nextHolderID,
ConstraintSet.TOP, Utils.convertDpToPixel(8, context));
constraintSet.connect(nextTimeID, ConstraintSet.START, nextHolderID,
ConstraintSet.START, Utils.convertDpToPixel(16, context));
//Constraint the timeline Views
constraintSet.constrainHeight(nextMarkerID, ConstraintSet.MATCH_CONSTRAINT);
constraintSet.constrainWidth(nextMarkerID, ConstraintSet.MATCH_CONSTRAINT);
constraintSet.connect(nextMarkerID, ConstraintSet.BOTTOM, nextTimeID,
ConstraintSet.BOTTOM, Utils.convertDpToPixel(8, context));
constraintSet.connect(nextMarkerID, ConstraintSet.TOP, nextTimeID,
ConstraintSet.TOP, Utils.convertDpToPixel(8, context));
constraintSet.connect(nextMarkerID, ConstraintSet.START, nextTimeID,
ConstraintSet.END, Utils.convertDpToPixel(16, context));
constraintSet.connect(nextMarkerID, ConstraintSet.END, nextHolderID,
ConstraintSet.END, Utils.convertDpToPixel(16, context));
constraintSet.applyTo(constraintLayout);
It's ugly and not performant.
So what i want to create now is a match history:
I would have a view that holds a match with 2 textViews for each teamname and 1 textView for the score. Those arrows should show how they would be placed in a constraint layout.
My guess how it should be done would be to create a layout.xml for the MatchView and in that xml i have a placeholder for the other textViews which i than can change programmatically. This layout.xml would be then used by my MatchView class and an object of my MatchView class is one MatchView.
For example:
MatchView matchView = new MatchView("Team1", "Team2", "score")
And the MatchView class would look like this:
public class MatchView {
MatchView.setLayout(match_view.xml);
TextView team1 = findViewById(team1TXT);
TextView team2 ...
//For the first view
MatchView(String team1, String team2, String score){
team1.setText(team1);
//...
constrain.toParent();
}
//For every following view
MatchView(String team1, String team2, String score, MatchView parentMatchView){
team1.setText(team1);
//...
constrain.toView(parentMatchView);
}
}
Is this the way how it's done? Are there more convenient ways?
If i guessed write do you have me a tutorial where they show how you really do it?
I searched for many days but i don't find what im really looking for.
I hope I'm not asking something too stupid.
Thanks in advance and greetings
Bolle

Related

How do I add views dynamically through Kotlin code

So I need to add views to my constraint layout for each item in a list.
The code I have right now is:
for (i in 0..hikes.size - 1) {
var parentLayout = findViewById<ConstraintLayout>(R.id.RoutesOverview)
var constraintSet = ConstraintSet()
var view = View(this)
view.id = i
var params = ConstraintLayout.LayoutParams (
LayoutParams.MATCH_PARENT,
700
)
params.setMargins(48, 48, 48, 0)
view.setBackgroundColor(Color.parseColor("#81c27a"))
view.layoutParams = params
RoutesOverview.addView(view)
constraintSet.clone(parentLayout)
constraintSet.connect(view.id, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM)
constraintSet.connect(view.id, ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END)
constraintSet.connect(view.id, ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START)
constraintSet.connect(view.id, ConstraintSet.TOP, prev.id, ConstraintSet.TOP)
constraintSet.applyTo(parentLayout)
prev = view
}
The RoutesOverview object is just the constraintLayout from my xml.
In the first iteration the prev object contains a view who is always there.
When trying this code, I see that the left and right margin gets set correctly, but the top doesn't nor get the second, third... view placed correctly.
The purpose of the views is actually just to use as a background for other textviews to get displayed on, I don't know if there's a better way to do this.

How to use ConstraintSet to set what like app:layout_constraintBottom_toBottomOf?

Now,here is my question.
how can I use ConstraintSet's connect to set attr like 'app:layout_constraintBottom_toBottomOf="parent"'
Try this
TextView textView = new TextView(this);
textView.setId(R.id.text_id);
ConstraintSet set = new ConstraintSet();
set.clone(constraintLayout);
set.connect(textView.getId(), ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM, 0);
constraintLayout.addView(textView);
set.applyTo(constraintLayout);

Adding constraints to views programmatically using ConstraintSet does not give expected result in Android?

I have a custom ConstraintLayout, and there's a TextView inside of it. I'm doing everything programmatically WITHOUT XML at all, here's the code:
public class CustomView extends ConstraintLayout {
private TextView textView;
public CustomView(Context context) {
super(context);
textView = new TextView(context);
textView.setId(View.generateViewId());
textView.setText("...");
// Adding border to the view in order to visualize the frame
GradientDrawable border = new GradientDrawable();
border.setColor(Color.TRANSPARENT);
border.setStroke(1, Color.BLACK);
textView.setBackground(border);
addView(textView);
// Apply constraints to textView. Left = right = top = bottom = 120
ConstraintSet set = new ConstraintSet();
set.clone(this);
set.connect(textView.getId(), ConstraintSet.LEFT, ConstraintSet.PARENT_ID, ConstraintSet.LEFT, 120);
set.connect(textView.getId(), ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP, 120);
set.connect(textView.getId(), ConstraintSet.RIGHT, ConstraintSet.PARENT_ID, ConstraintSet.RIGHT, 120);
set.connect(textView.getId(), ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM, 120);
set.applyTo(this);
}
}
When I run the above code, I'm getting some wrong results:
If the text in textView is short:
If the text in textView is long:
If I understand correct that your wrong result - you don't see the margins?
I think this because defaults layout_width layout_height of your textview - wrap_content. Defaults must be 0dp.
Try like:
LayoutParams lp = new LayoutParams(0, 0);
textView.setLayoutParams(lp);

Can't see my programmatically added textviews in ConstraintLayout

I've added 2 textviews in ConstrainLayout in code, but i can't see them.
The screen is empty.
Please can anybody help me to figure out this?
Thanks a lot!
public class ActivitySixth extends AppCompatActivity {
private TextView tv1;
private TextView tv3;
private ConstraintLayout mConstraintLayout;
private static final int ID_CONS_LAY = 160;
private static final int ID_TV1 = 160;
private static final int ID_TV3 = 160;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sixth);
mConstraintLayout = findViewById(R.id.parent_Constraint);
ConstraintSet set = new ConstraintSet();
set.clone(mConstraintLayout);
tv1 = new TextView(this);
tv3 = new TextView(this);
tv1.setText("TextView number ONE");
tv3.setText("TextView number THREE");
tv1.setId(ID_TV1);
tv3.setId(ID_TV3);
mConstraintLayout.addView(tv1);
mConstraintLayout.addView(tv3);
set.connect(tv1.getId(), ConstraintSet.LEFT, R.id.parent_Constraint, ConstraintSet.LEFT, 0);
set.connect(tv3.getId(), ConstraintSet.RIGHT, R.id.parent_Constraint, ConstraintSet.RIGHT, 0);
set.applyTo(mConstraintLayout);
}
}
First, the IDs should be different, second, you need to add constraints to the TextViews' width/height:
set.connect(tv1.getId(), ConstraintSet.LEFT, R.id.parent_Constraint, ConstraintSet.LEFT, 0);
set.constrainWidth(tv1.getId(), WRAP_CONTENT);
set.constrainHeight(tv1.getId(), WRAP_CONTENT);
set.connect(tv3.getId(), ConstraintSet.RIGHT, R.id.parent_Constraint, ConstraintSet.RIGHT, 0);
set.constrainWidth(tv3.getId(), WRAP_CONTENT);
set.constrainHeight(tv3.getId(), WRAP_CONTENT);
set.applyTo(mConstraintLayout);
By the way, to avoid conflicts, you can define ids using resources xml.
create ids.xml inside your res\values folder
define ids:
<resources>
<item type="id" name="textView1" />
</resources>
use the defined id:
R.id.textView1
Hello Please follow below code
ConstraintLayout layout = (ConstraintLayout) findViewById(R.id.mainConstraint);
ConstraintSet set = new ConstraintSet();
ImageView view = new ImageView(this);
layout.addView(view, 0);
set.clone(layout);
set.connect(view.getId(), ConstraintSet.TOP, layout.getId(), ConstraintSet.TOP, 60);
set.applyTo(layout);
TextView contactUs = new TextView(this);
contactUs.setText(R.string.contactus);
contactUs.setTextSize(25);
contactUs.setId(R.id.contactUs);
ConstraintLayout.LayoutParams clpcontactUs = new ConstraintLayout.LayoutParams(
ConstraintLayout.LayoutParams.WRAP_CONTENT, ConstraintLayout.LayoutParams.WRAP_CONTENT);
contactUs.setLayoutParams(clpcontactUs);
constraintLayout.addView(contactUs);
ConstraintSet set = new ConstraintSet();
set.clone(mConstraintLayout);
set.connect(tv1.getId(), ConstraintSet.LEFT, R.id.parent_Constraint, ConstraintSet.LEFT, 0);
set.connect(tv3.getId(), ConstraintSet.RIGHT, R.id.parent_Constraint, ConstraintSet.RIGHT, 0);
set.applyTo(mConstraintLayout);
try something like this..
ref. http://www.zoftino.com/adding-views-&-constraints-to-android-constraint-layout-programmatically

Applying margins programmatically in a Constraint Layout

I cannot get margins to work correctly when using a ConstraintSet
ConstraintSet constraintSet = new ConstraintSet();
ConstraintLayout constraintLayout = (ConstraintLayout) LayoutInflater.from(this).inflate(R.layout.activity_main, null);
constraintSet.clone(constraintLayout);
// START WORKS
//constraintSet.connect(R.id.text, ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START, 50);
// LEFT DOES NOT
constraintSet.connect(R.id.text, ConstraintSet.LEFT, ConstraintSet.PARENT_ID, ConstraintSet.LEFT, 50);
constraintSet.connect(R.id.text, ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END, 50);
constraintSet.connect(R.id.text, ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP, 50);
constraintSet.connect(R.id.text, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM, 50);
constraintSet.applyTo(constraintLayout);
There's a small sample app there if anyone wants to reproduce: https://github.com/martinbonnin/TestConstraintLayout/tree/master
Anyone knows what I'm missing ?
I am not sure what you are trying to do. What is your expected result.
But...
You are using END and LEFT which is a little strange.
normally you would use START&END or LEFT&RIGHT

Categories

Resources