How to measure the width of view in android - android

I am having two text views in Linear layout having horizontal orientation. Width of text views are wrap_content. If the sum of width of two text views is less than the screen width it is fine. If the sum of width exceeds the screen width then i need to change the orientation from horizontal to vertical.
I tried using getWidth() in onCreate of the activity but it returned 0. I can try creating a custom view with onSizeChanged() function but i am using two text views so i am not sure that when onSizeChanged() in one text view will not make sure that the other textview is fully drawn to get the width. Any suggestions is really helpful for me.
<LinearLayout android:id="#+id/status_container"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="horizontal">
<TextView android:id="#+id/view1"
android:layout_height="wrap_content"
android:layout_width="wrap_content"/>
<TextView android:id="#+id/view2"
android:layout_height="wrap_content"
android:layout_width="wrap_content"/>
</LinearLayout>
// In OnCreate() function
TextView view1 = (TextView) findViewById(R.id.view1);
TextView view2 = (TextView) findViewById(R.id.view2);
view1.setText("Good Morning,");
view2.setText("I am Ron");
int view1_width = view1.getWidth();
int view2_width = view2.getWidth();
if ((view1_width + view2_width) > screen_width) {
// Change the Linear Layout orientation to Vertical
}
Here view1_width and view2_width are returning 0. I want to check if the view1_width + view2_width is greater than the screen width then i need to change the orientation into vertical, or else Horizontal orientation is fine.
-Ron

Add this to your activity's onCreate
ViewTreeObserver vto = layout.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
//You should be able to get the width and height over here.
layout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});

Related

Android buttons equal width

I need to have 2 buttons which wrap content but always stay same equal in width.
I want BUTTON 1 stretch to the width of BUTTON 2. Or if BUTTON 1 Would be wider I would need BUTTON 2 to stretch to the width of BUTTON 1
How can I achieve this? I tried using LinearLayout with weights, but it only works if linear layout width matched parent, which makes buttons unnecessary wide.
To make both the button identical you have to calculate width of both the button like this
ViewTreeObserver vto1 = button1.getViewTreeObserver();
vto1.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
width = button1.getWidth();
height = button1.getHeight();
}
});
ViewTreeObserver vto2 = button2.getViewTreeObserver();
vto2 .addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
width = button2.getWidth();
height = button2.getHeight();
}
});
then compare both the button height and set the larger one to both the buttons.
Try this!!! This may help...
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="2">
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Button 1"/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Button 2"/>
</LinearLayout>
This will give the output as,
Use Linear Layout Weight Attribute
First Enclose Both Buttons In Linear Layout And give them horizontal orientation.
Then Give Them Equal Weights
android:layout_weight="1"
Try This Result
While Ajay's answer is right, but it requires you to remove the listener once you are done with it.
ViewTreeObserver vto2 = button2.getViewTreeObserver();
vto2 .addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
width = button2.getWidth();
height = button2.getHeight();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
myView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
else {
myView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
}
});
I'm answering an old question, but there exist a one line solution.
Add android:layout_width="0dip" to both (i.e. all) buttons definitions in .xml file.
Another (alternative) solution is to add android:layout_width="fill_parent" to both (all) buttons definitions.

ImageView expanding container despite adjustViewBounds

I want to wrap an ImageView inside a LinearLayout so that I can center a group of views. However, the original image needs to be scaled down to fit in the ImageView, and the original size expands the LinearLayout, despite my use of adjustViewBounds="true" and an enclosing FrameLayout as suggested by previous questions on SO.
The desired layout should look like this,
but the observed layout looks like this,
as produced by the XML below:
<android.support.percent.PercentRelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="project.MainActivity">
<LinearLayout
android:layout_width="wrap_content"
app:layout_heightPercent="32%"
android:orientation="horizontal"
android:background="#b44343"
android:layout_centerHorizontal="true"
android:layout_alignParentTop="true">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Sample Text"/>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#5555ae">
<ImageView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#2c8c4c"
android:src="#drawable/spades_icon"
android:adjustViewBounds="true"
android:scaleType="centerInside"/>
</FrameLayout>
</LinearLayout>
</android.support.percent.PercentRelativeLayout>
I can't use the other suggestion of setting android:maxHeight="100dp" because I need the height to be relative to that of the screen.
I see that you have added android:adjustViewBounds="true".
You can combine that with android:maxWidth="60dp"
So your imageView should look like this.
<ImageView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#2c8c4c"
android:src="#drawable/spades_icon"
android:adjustViewBounds="true"
android:maxWidth="60dp"
android:scaleType="centerInside"/>
You can change the max width to any number you want.
Things you can do:
1) Set a specific width / height to the FrameLayout enclosing the ImageView and set android:scaleType to centerInside, fitCenter, or fitXY for the ImageViwe.
2) Programatically, in your activity, after onCreate, in onResume for example, you can get the LayoutParams and change the width and height of the ImageView doing you own scaleing. I take this aproach when I scale against the screen widht or height at run time.
EDIT 1
Example of second alternative:
public class TestActivity extends AppCompatActivity {
ImageView imgView;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.testactivity_layout);
imgView = (ImageView) findViewById(R.id.imgview);
}
#Override
protected void onResume() {
super.onResume();
ViewGroup.LayoutParams params = imgView.getLayoutParams();
params.width = 100;
}
}
Notes:
The width is expressed in pixel.
To get the display metrics:
How to get screen display metrics in application class
To establish a relative width for the ImageView, get the width of the display and calculate the desireed % as the width of the image.
Based on this answer to another question, a solution that removes the whitespace in the LinearLayout while preserving the height and aspect ratio of the image is:
#Override
public void onWindowFocusChanged(boolean hasFocus) {
LinearLayout layout = (LinearLayout) findViewById(R.id.mLinearLayout);
ImageView imageView = (ImageView) findViewById(R.id.mImageView);
TextView textView = (TextView) findViewById(R.id.mTextView);
layout.getLayoutParams().width = textView.getWidth()+imageView.getWidth();
layout.requestLayout();
}
EDIT:
Based on #Juan's answer and these instructions, the following code also achieves the desired result:
#Override
protected void onResume() {
DisplayMetrics displayMetrics = new DisplayMetrics();
this.getWindowManager()
.getDefaultDisplay()
.getMetrics(displayMetrics);
ViewGroup.LayoutParams params = imgView.getLayoutParams();
params.height = (int)Math.floor(displayMetrics.heightPixels * 0.32);
}

Android: TextView inside ScrollView: How to limit height

I have put a TextView inside a ScrollView in Android:
<ScrollView
android:layout_width = "fill_parent"
android:layout_height = "wrap_content">
<TextView
android:layout_width = "wrap_content"
android:layout_height = "wrap_content" />
</ScrollView>
With this configuration, the scrollview grows to wrap the textview-content.
How can I achieve that the scrollview takes only as much space as needed (for few text), but at the same time limit the size to 100dp (for long texts) ?
If I set layout_height to 100dp, a lot of space is wasted when the text is short
If I set layout_height to wrap_content, the scrollview runs the risk to fill the whole screen, but I don't want the whole sreen to only contain this scrollview. It should be 100dp heigh as a maximum.
The solution which was found:
Thank you for alls answers. For all people that have the same issue, here goes the accepted solution:
Create a custom ScrollView class an use this class inside your xml file instead ScrollView. Then override onMeasure() method:
public class ScrollMyVew extends ScrollView {
public static final int maxHeight = 100; // 100dp
// default constructors
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(dpToPx(getResources(),maxHeight), MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
private int dpToPx(Resources res, int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, res.getDisplayMetrics());
}
}
This solution is taken from https://stackoverflow.com/a/23617530/3080611
Try something like this:
<ScrollView
android:id="#+id/myScrollView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:fillViewport="true"/>
<TextView
android:id="#+id/myTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxHeight="your_value_here"/>
</ScrollView>
Dynamically change the size of the TextView if the number of characters exceeds a certain amount.
Ex:
TextView v = (TextView) findViewById(R.id.sometext);
LayoutParams lp = v.getLayoutParams();
lp.height = 50;
v.setLayoutParams(lp);

Dynamically setting relative dimension of a linearlayout

I want to resize my LinearLayout (or a view) to a dimension which is relative to the parent or itself. For example, I want the width to be 1/3 of the parent's width. Or, the height should be same as its own width. I don't want to use any constants , so that it works for all devices.
adding code:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<LinearLayout android:id="#+id/ll_board"
android:gravity="center_horizontal"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</LinearLayout>
...
</LinearLayout>
code:
public class GMActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
LinearLayout board_layout = (LinearLayout)findViewById(R.id.ll_board);
// I wanted to resize board_layout here ..
// getParent().getWidth() returns 0
Log.d("gm", "layout: " + ((LinearLayout) board_layout.getParent()).getWidth());
// ..
}
}
getWidth() is giving 0. Is it too early to call this? If yes, what is the correct place to call this?
Basically my intention is to make the width of the layout a fraction of the screen size width, and, height same as its own width.
Considering layout your LinearLayout and that its parent it's another LinearLayout:
Get the parent's width:
int parentWidth = ((LinearLayout) layout.getParent()).getWidth();
Get the view's width:
int viewWidth = ((LinearLayout) layout).getWidth();
set the
view.setHeight(viewWidth );
view.setWidth(parentWidth / 3);
I found height=width solution (square shaped layout) in LinearLayout in Square Form

How do I calculate the required height of a GridView that is inside of a ScrollView on Android?

I have a GridView inside of a LinearLayout inside of a ScrollView that pages in data from the server. Beneath the GridView is a button to load more data. My GridView will have an ultimate height that is larger than the screen. If I set the height of my GridView to either wrap_content or parent_fill, it sizes itself to the exact available on-screen height and does not scroll at all, cropping out the extra rows. If I explicitly set the layout_height to something large, like 1000dip, scrolling behaves properly, however I cannot predict the final height of my scroll view apriori.
How do I programmatically determine the necessary height of a GridView to get the desired behaviour?
Here is my layout below. As you can see I set the height to 1000dip, but that is bogus, I need that value to get set automatically/programmatically:
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true"
android:layout_weight="1"
>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/grid"
android:layout_width="fill_parent"
android:layout_height="1000dip"
android:columnWidth="70dp"
android:numColumns="auto_fit"
android:verticalSpacing="0dp"
android:horizontalSpacing="0dp"
android:stretchMode="columnWidth"
android:gravity="center"
android:background="#000000"
android:layout_weight="1"
/>
<Button
android:id="#+id/load_more"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Load More Foo"
/>
</LinearLayout>
</ScrollView>
Here is one way to do this, if someone needs it. A bit of a hack but does the trick. You have to set GridView initially big enough for all the views (e.g. 10000dip)
final GridView imageContainer = // your GridView
imageContainer.getViewTreeObserver().addOnGlobalLayoutListener( new OnGlobalLayoutListener()
{
#Override
public void onGlobalLayout()
{
imageContainer.getViewTreeObserver().removeGlobalOnLayoutListener( this );
View lastChild = imageContainer.getChildAt( imageContainer.getChildCount() - 1 );
imageContainer.setLayoutParams( new LinearLayout.LayoutParams( LayoutParams.FILL_PARENT, lastChild.getBottom() ) );
}
});
I know it's an old case, but I had a similar problem where my ScrollView contained multiple LinearLayouts, which in their turn contained a header and a GridView.
Basically I made categorised sections with headers containing images belonging to that category.
The GridView had to have a flexible height.
I found a lot of answers about overriding onMeasure(), but it worked only on some devices, not all. The height would eventually be 1, or 3 or just 0, displaying only a few pixels of the image.
StretchingGridView class
I overrode the drawableStateChanged() method with this code, inspired by #Karitsa's solution:
#Override
public void drawableStateChanged() {
getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
getViewTreeObserver().removeOnGlobalLayoutListener( this );
View lastChild = getChildAt( getChildCount() - 1 );
if (lastChild != null) {
int height = Math.max(lastChild.getBottom(), getColumnWidth());
float child = getAdapter().getCount();
float col = getNumColumns();
int rows = (int) Math.ceil(child / col);
height = rows * getColumnWidth() + (getHorizontalSpacing() * rows-1);
setLayoutParams( new LinearLayout.LayoutParams( LayoutParams.MATCH_PARENT, height ) );
}
}
});
}
Note: My GridView uses square images, so I base the height on their width. I don't think it works well with flexible grid item heights.
Apparently GridViews inside ScrollViews are not kosher in Android-land. Switching to ListView with custom-made rows. That seems to behave better.

Categories

Resources