How to get height in pixels of LinearLayout with layout_weight - java

this is my first post. I am learning to code in java for android apps.
I am using a LinearLayout "variable named: ll" with a predefined layout_weight (which I want to change whenever I want in the future) and height and width set to MATCH_PARENT. I want to get the height of this LinearLayout in pixels. I fill this using java (ll.addView(variableForAnObject);).
I am trying to get its height using ll.getLayoutParams().height; but I am getting -1. Because I believe this is the constant for MATCH_PARENT. Setting the height to 0dp makes the ll invisible and gives height as 0.
Please tell me if there's a way to get its height. I think I can do this by getting screen height using DisplayMetrics and making nearly impossible calculations (for me, at least) but this will be too complex.

try with ll.getHeight() should work
if not, it's because android has not yet calculed its bounds, then:
//inside of onCreate method should work
ll.post(new Runnable() {
#Override
public void run() {
//maybe also works height = ll.getLayoutParams().height;
height = ll.getHeight();
}
});

It is -1 because its dimensions have not yet been set, whenever you set layout it takes some time to compute the actual values including height, width etc.
Use OnLayoutListener to listen when it has finished with the layout.
layout.onLayoutChange (View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
//Extract values here
height = view.getHeight();
width = view.getWidth()
}
See this for more about the OnLayoutListener

Define your LinearLayout in your class and use getHeight() and getWidth(). Example:
LinearLayout yourLayout = (LinearLayout) findViewById (R.id.yourLL);
double height = yourLayout.getHeight();
double width = yourLayout.getWidth();
Hope it helps! :)

Give the id field in your layout xml file:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:id="#+id/<ID>>
Use this id to get reference in java class and find height and width:
LinearLayout linearLayout= (LinearLayout) findViewById (R.id.<ID>);
double height = linearLayout.getHeight();
double width = linearLayout.getWidth();

Related

Set AppBarLayout size Programmatically on Android

My AppBarLayout hold a Toolbar and TabLayout. When view is anchored, height is set to 0 setLayoutParams(0). On another state, the view is collapsed, I need to restore appbar height. I tried setLayoutParams(heightDp) where
float heightDp = getResources().getDisplayMetrics().heightPixels / 6;
but the height is not accurate.
private void setLayoutParams(int paramsHeight) {
CoordinatorLayout.LayoutParams lsp = (CoordinatorLayout.LayoutParams) mAppBarLayout.getLayoutParams();
lsp.height = paramsHeight;
mAppBarLayout.setLayoutParams(lsp);
}
How can I determine exact AppBar height programatically.
You should get it from default resources with TypedArray:
int mActionBarSize;
TypedArray attrs= getContext().getTheme().obtainStyledAttributes(new int[] { android.R.attr.actionBarSize });
mActionBarSize = (int) attrs.getDimension(0, 0);
You must recycle TypedArray
attrs.recycle();
This way you will get the value according to your screen.

How get height of the a view with gone visibility and height defined as wrap_content in xml?

I have a ListView with visibility=gone and height=wrap_content, and i need its height to can make an animation of expand.
I already tried it:
view.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
int height = view.getMeasuredHeight();
and
v.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
int height = view.getMeasuredHeight();
and
v.measure(View.MeasureSpec.makeMeasureSpec(ViewGroup.LayoutParams.MATCH_PARENT, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(ViewGroup.LayoutParams.WRAP_CONTENT, View.MeasureSpec.UNSPECIFIED));
int height = view.getMeasuredHeight();
But it returned me a lesser value.
I am trying to do this after onResume.
The only way that i found was setting the width of the my view from width of a visible header view, then the below code returned me the right value.
int widthSpec = MeasureSpec.makeMeasureSpec(headerView.getWidth(), MeasureSpec.EXACTLY);
int heightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
v.measure(widthSpec, heightSpec);
int height = v.getMeasuredHeight();
view.post(new Runnable() {
#Override
public void run() {
view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
int height = view.getMeasuredHeight();
}
});
This worked for me. The method "post" makes sure the view is already added to the screen.
There is only one efficient way to do that if you want to animate height of a view whose visibility is gone
First add this in xml of hidden view
android:animateLayoutChanges="true"
then thats how you can set it to animate
yourView.layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
Android will animate any layout change on that specific view
When an object is gone, it no longer is part of the layout. Maybe you mean to set your object to invisible, in which case you'll probably get a sensical value
This works for me
view.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
int height = view.getMeasuredHeight();

How do you use a custom view in a HorizontalScrollView?

I've got a custom view (called CustomStrechView) which extends an ImageView. The point of this view is so that I can get an image to fill the view without losing the aspect ratio.
Now the CustomStrechView works fine when I use it in most applications, but when I try to apply it within my HorizontalScrollView, the images all seem to disappear. I'm not sure why this happens. I've tried removing the <HorizontalScrollView /> and when I do the images show back up, so I feel there is some property that needs to be set, but I can't seem to find it.
Can anyone point out what I’m doing wrong or a better way to get a custom view to work in a HorizontalScrollView?
Edit:
After playing around with this for a bit, I've determined that I can get the custom view to show the image only if I hardcode the width dimension, ie:
<com.example.dragdropshapes.CustomStrechView
android:layout_width="200dp"
Leaving the height as fill_parent is fine...
Code:
Here's how my custom view is being used in the xml file:
<!-- Removing this makes the images show up -->
<HorizontalScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true"
android:layout_marginTop="50dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:showDividers="middle"
android:orientation="horizontal">
<!-- Changing this to a normal ImageView makes the image show up -->
<com.example.dragdropshapes.CustomStrechView
android:id="#+id/pickshapes"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:clickable="true"
android:onClick="pickShapes"
android:background="#drawable/border"
android:src="#drawable/ic_launcher"
/>
<!-- There are 5 other custom ImageViews here -->
</LinearLayout>
</HorizontalScrollView>
Here's the major part of the custom view code:
public class CustomStrechView extends ImageView{
private final Drawable srcPic;
private final String TAG = "strechyTag";
private boolean changeSize = false;
private int Xpx;
private int Ypx;
public CustomStrechView(Context context) {
super(context);
srcPic = this.getDrawable();
}
//... other constructors, not really important...
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
Log.d(TAG, "in the onMeasure!!\n");
int width, height;
width = MeasureSpec.getSize(widthMeasureSpec);
height = width * srcPic.getIntrinsicHeight() / srcPic.getIntrinsicWidth();
setMeasuredDimension(width, height);
}
}
Through some debugging I was able to at least partially solve this myself. Turns out that the width acquired from the MeasureSpec.getSize(widthMeasureSpec); call was 0. Thus the calculation ended in width and height being 0 and the setMeasuredDimension call would then make the image invisible.
Now I'm saying I have this partially solved, because I still don't understand why I was getting that value of 0. I think it's because in a HorizontalScrollView the width isn't determined (it depends on the content within) thus whatever MeasureSpec.getSize(widthMeasureSpec); is actually doing is talking to the parent, and the parent in a normal Linear or RelativeLayout has a defined width where as in a HorizontalScrollView it does not... but that's just speculation at this point.
So I made a fix for it, if the width is 0 we run the calculation via the height instead. The height needed two cases to cover it to avoid divide by 0 errors (the else if and the else collectively).
Here's my current solution with the same xml file I noted in the Question.
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
if(width > 0)
height = width * srcPic.getIntrinsicHeight() / srcPic.getIntrinsicWidth();
else if(srcPic.getIntrinsicWidth() < srcPic.getIntrinsicHeight())
width = height / (srcPic.getIntrinsicHeight() / srcPic.getIntrinsicWidth());
else
width = height / (srcPic.getIntrinsicWidth() / srcPic.getIntrinsicHeight());
setMeasuredDimension(width, height);
}

Android: Making the width and the height of a custom view equal

I am using a custom view (CoordinateGridView) in XML like this:
<com.android.catvehicle.CoordinateGridView
android:id="#+id/coordinateGrid"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
I am trying to get the width of the CoordinateGridView to fill the entire width of the screen. The height should then match the width -- therefore, the custom view should always be drawn as a square.
How do I do this?
Override the onMeasure function in CoordinateGridView:
public void onMeasure(int widthSpec, int heightSpec) {
super.onMeasure(widthSpec, heightSpec);
int size = Math.min(getMeasuredWidth(), getMeasuredHeight());
setMeasuredDimension(size, size);
}
See https://github.com/chiuki/android-square-view for a full example.

How to specify width of custom view?

I'm having trouble trying to set a specific size for the width of my custom view. I know I can just hard-code a value in the layout_width field in the XML file but I'm trying not to result to hard-coding values. I need my View to be half the size of the screen. So, within the class I find half the screen size:
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
try{
Point size = new Point();
display.getSize(size);
screenWidth = size.x;
}catch(NoSuchMethodError e){
screenWidth = display.getWidth();
}
Then, I call:
measure(width|MeasureSpec.EXACTLY, LayoutParams.WRAP_CONTENT|MeasureSpec.EXACTLY);
//Where width is equal to half the screen width
but this does not seem to be working for my case. So, to sum it all up, how do you properly specify a particular size for a custom View? Any help will be useful and appreciated! Thanks!
Override the onMeasure() method in your Custom View:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = getResources().getDisplayMetrics().widthPixels >> 1;
widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
Basically, override the width MeasureSpec to be exactly half the width of the screen, then pass that through to the superclass.
I believe that you might not be able to accurately get the width of the screen at this point because you need to wait till the entire hierarchy (up until the most root view) is laid out. You may need to do something like:
ViewTreeObserver.OnGlobalLayoutListener layoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int width = getWidth();
int height = getHeight();
//set layoutparams with those values.
}
};
getViewTreeObserver().addOnGlobalLayoutListener(layoutListener);
You can confirm the correctness of this by seeing if the values you're getting when you try getting the display width inside of onMeasure differ from the values you get when the onGlobalLayout callback is invoked.

Categories

Resources