Making all Buttons in a vertical LinearLayout the same width - android

I am trying to make all the buttons in one horizontal LinearLayout the same width, based on one button which contains the longest text.
What i tried is to go through all the buttons in the layout and setting there size like this.
LinearLayout layout = (LinearLayout) findViewById(R.id.buttonLayout);
for(int i = 0;i < layout.getChildCount();i++){
View v = layout.getChildAt(i);
if(v instanceof Button){
if(!(v.getId() == R.id.widestButton)){
((Button) v).setWidth(findViewById(R.id.widestButton).getWidth());
}
}
}
This does set all the buttons size, however, the size being set is not the size of the widestButton, its about 40% of it.
How do i make this work?

I found the answer myself, could have probably found it by googling.
Problem is, i was calling this code on the Activitys onCreate.
At this moment, the sizes of the Buttons are not calculated yet.
So i found the ViewTreeObserver, which is able to add a listener to be called when the Layout is done loading. The code i am using now is:
final LinearLayout layout = (LinearLayout) findViewById(R.id.buttonLayout);
ViewTreeObserver vto = layout.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
layout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
for(int i = 0;i < layout.getChildCount();i++){
View v = layout.getChildAt(i);
if(v instanceof Button){
if(!(v.getId() == R.id.widestButton)){
((Button) v).setWidth(findViewById(R.id.widestButton).getWidth());
}
}
}
}
});
Which works perfectly fine.

Related

How can I make appear RecyclerView with an animation?

In my app if I press a button (the green one on the screenshot) I set my RecyclerView from height 0 to 600 and even if I re-press the same button it disappear by setting it height to 0.
But actually it's ugly to see because it's appear instantly so I would like to add an animation to it like it's growing up slowly or bouncing, I don't know, something that would make it nicer. Is there a way to make something like this?
Here is my code where I make appear or disappear the RecyclerView:
menu.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ViewGroup.LayoutParams params = mRecyclerViewBOT.getLayoutParams();
if(params.height == 0) {
params.height = 600;
mRecyclerViewBOT.setLayoutParams(params);
}else {
params.height = 0;
mRecyclerViewBOT.setLayoutParams(params);
}
}
});
You probably want:
LayoutTransition layoutTransition = new LayoutTransition();
layoutTransition.enableTransitionType(LayoutTransition.CHANGING);
parentView.setLayoutTransition(layoutTransition);
where parentView is the view containing your recyclerView

Get Element Positions after adding to layout in Android

I'm trying to get the postions of an ImageView after i added it to a relative Layout.
I'm adding ImageViews randomly within the relative layout by clicking on a button. So far this works very good. But why does getLeft, getRight, getTop, getBottom return 0? The Thing is, that the values are all available on the next buttonclick. So when ImageView 1 has everything 0 on the creation, it has the information if i click the button again.
So to make it clear:
Buttonclick-1 -> ImageView-1 added (outputs 0 on getLeft,Top,Right,Bottom)
Buttonclick-2 -> ImageView-2 added (ImageView-1 outputs coordinates, but ImageView-2 outputs 0)
I'm sure this has to do with the drawing of the ImageView. Surely it is not ready drawn on the view when i iterate over the children and ask for the actual positions.
Here is my code so far:
final ConstraintLayout cl = (ConstraintLayout) findViewById(R.id.constraintLayout);
final ScrollView sc=(ScrollView) findViewById(R.id.scrollView);
final Button btnButton = (Button) findViewById(R.id.buttontest);
final LinearLayout ll = (LinearLayout) findViewById(R.id.linearLayout);
final RelativeLayout rl = (RelativeLayout) findViewById(R.id.rLayout);
btnButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ImageView im= new ImageView(UserAreaActivity.this);
im.setImageResource(R.mipmap.ic_launcher);
im.setScaleType(ImageView.ScaleType.FIT_XY);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(150, 150);
Random r = new Random();
Random r2 = new Random();
int x = r.nextInt(rl.getWidth());
int y = r2.nextInt(rl.getHeight());
if(x+(layoutParams.width) >= rl.getWidth()){
x=x-layoutParams.width;
}
if(y+(layoutParams.height) >= rl.getHeight()){
y=y-layoutParams.height;
}
layoutParams.leftMargin=x;
layoutParams.topMargin=y;
im.setLayoutParams(layoutParams);
TextView tv = new TextView(UserAreaActivity.this);
tv.setText("my text");
rl.addView(im);
ll.addView(tv);
System.out.println("ID "+im.getId());
System.out.println("Left "+im.getLeft());
System.out.println("Right "+im.getRight());
System.out.println("Top "+im.getTop());
System.out.println("Bottom "+im.getBottom());
for (int i = 0; i < rl.getChildCount(); i++) {
View subView = rl.getChildAt(i);
if (subView instanceof ImageView) {
ImageView imageView = (ImageView) subView;
System.out.println("ID "+i);
System.out.println("Left "+imageView.getLeft());
System.out.println("Right "+imageView.getRight());
System.out.println("Top "+imageView.getTop());
System.out.println("Bottom "+imageView.getBottom());
}
}
}
});
When you call rl.addView(im); you are kicking off a process that will eventually involve a "layout pass" for your RelativeLayout and your ImageView. It is only after this layout pass completes that you will be able to get valid coordinates for your ImageView.
Unfortunately, there's no one-liner for "give me the coordinates after the layout pass". All the best options are asynchronous (i.e. you register some code to run once the ImageView has been laid out). I recommend ViewTreeObserver.OnGlobalLayoutListener.
Something like this:
im.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
System.out.println("ID "+im.getId());
System.out.println("Left "+im.getLeft());
System.out.println("Right "+im.getRight());
System.out.println("Top "+im.getTop());
System.out.println("Bottom "+im.getBottom());
im.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});

How to check programatically if all the Views fit inside the screen

I have a layout which is something like this:
LinearLayout (linearLayout)
'--TextView (textView1)
'--ImageView (imageView)
'--TextView (textView2)
textView1 changes its text sometimes and it can be long, so it leaves part of textView2 out of the screen. I want to prevent that, so I want to remove imageView from the layout whenever this happens. imageView may or may not be visible at the time when this is computed (maybe it was removed before when textView1 was edited previously).
This is what I have coded:
void changeText(String veryLongString){
textView1.setText(veryLongString);
int [] loc = new int [2];
textView2.getLocationOnScreen(loc);
int bottom = textView2.getMeasuredHeight() + loc[1];
if (imageView.getVisibility() == View.GONE)
bottom += imageView.getHeight();
if (bottom > linearLayout.getMeasuredHeight()){
imageView.setVisibility(View.GONE);
} else {
imageView.setVisibility(View.VISIBLE);
}
}
But for some reason this doesn't work as expected, because it seems as if changes in the position and height of the Views don't take place immediately. When I call getMeasuredHeight() and getLocationOnScreen() I get the values BEFORE the changes I have just made. The result that I get is that if I set a very large text imageView is not removed, but if I then set a short text, it is removed.
If there any other way to face this problem?
Even though I think that this is not the right approach (you can do all kinds of stuff in your XML so you don't have to meddle with Java code), here is a quick example of what you can do from Java (for example, in your onStart() method)
ViewGroup group = (ViewGroup) findViewById(R.id.myLayout);
int groupHeight = group.getHeight();
for (int i = 0; i < group.getChildCount(); i++) {
groupHeight -= group.getChildAt(i).getHeight();
if (groupHeight < 0) {
// they don't fit in the layout
myImageView.setVisibility(View.GONE);
}
}

Android, find childviews of parent view

I have problem finding childviews of parent view in android, i do the following
i have a relative layout with 2 textviews and 1 edit text view(for example call this whole view as c1)
i add the above view c1 to a linear layout using linearlyt.addView(c1)
i add multiple such child views to parent view
After adding many such child views to linearlyt, i start filling out the edit text of each child view, the question is How can i get the content/text set in Textview of child view whose edit text is being filled out.TIA
Try this..
public void findEditText(View parentview) {
if (!(parentview instanceof EditText)) {
System.out.println(((EditText)parentview).getText());
}
// If a layout container, iterate over children and seed recursion.
if (parentview instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) parentview).getChildCount(); i++) {
View innerView = ((ViewGroup) parentview).getChildAt(i);
findEditText(innerView);
}
}
}
The first answer is good. If you need something more specific to your case given the constant structure of your rows...:
for (int i = 0; i < yourLinearLayout.getChildCount(); i++) {
RelativeLayout relativeLayout = (RelativeLayout) yourLinearLayout.getChildAt(i);
TextView textView1 = relativeLayout.getChildAt(0);
TextView textView2 = relativeLayout.getChildAt(1);
EditText editText = relativeLayout.getChildAt(2);
...
}

how to set textview dynamically according to numbers of strings

I am getting list of phone companies from web service and i have to set it to textview but the problem is i am not getting alignment as above image.How to achieve it.
From what I understand, you want to add text views one beside the other, but when they overflow (go out of the screen) the next text view should be placed in the next line.
Doing this is not trivial. Implementing something like this (optimally and correctly) requires understanding of how android draws views (onMeasure and onLayout). However if you do not care about efficiency that much (mainly because you are going to do it only for a small portion of the view) then here is my quick hack:
mContainer = (RelativeLayout) findViewById(R.id.container);
// first layout all the text views in a relative layout without any params set.
// this will let the system draw them independent of one another and calculate the
// width of each text view for us.
for (int i = 0; i < 10; i++) {
TextView tv = new TextView(getApplicationContext());
tv.setText("Text View " + i);
tv.setId(i+1);
tv.setPadding(10, 10, 20, 10);
mContainer.addView(tv);
}
// post a runnable on the layout which will do the layout again, but this time
// using the width of the individual text views, it will place them in correct position.
mContainer.post(new Runnable() {
#Override
public void run() {
int totalWidth = mContainer.getWidth();
// loop through each text view, and set its layout params
for (int i = 0; i < 10; i++) {
View child = mContainer.getChildAt(i);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
// this text view can fit in the same row so lets place it relative to the previous one.
if(child.getWidth() < totalWidth) {
if(i > 0) { // i == 0 is in correct position
params.addRule(RelativeLayout.RIGHT_OF, mContainer.getChildAt(i-1).getId());
params.addRule(RelativeLayout.ALIGN_BOTTOM, mContainer.getChildAt(i-1).getId());
}
}
else {
// place it in the next row.
totalWidth = mContainer.getWidth();
params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
params.addRule(RelativeLayout.BELOW, mContainer.getChildAt(i-1).getId());
}
child.setLayoutParams(params);
totalWidth = totalWidth - child.getWidth();
}
mContainer.requestLayout();
}
});
Basically, I let the system do the layout and measurement for me in the first round(s) of drawing. Then using the widths of each text view now available, I reset the layout params based on the wrapping logic and do the layout again.
Try it with text of different size, it will auto adjust. I would say this solution is pretty hacky but it works. If you are not satisfied with it take a look at this.
use
android:textAlignment="textStart"

Categories

Resources