ViewPager does not wrap height to its content - android

ViewPager does not wrap its height to its content. For my layout I need to set the height dynamically because it is nested in other layouts.
Therefore I created a ScrollView as content of the ViewPager and check its height in onCreate method of the Fragment, but the ScrollView has always the same size.
How can I wrap height of the ViewPager to fit to its content?
final ScrollView sv = (ScrollView) v.findViewById(R.id.sv);
ViewTreeObserver vto = sv.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int height = sv.getMeasuredHeight();
//always same height independent of content height
//need to resize ViewPager
ViewGroup.LayoutParams params = (ViewGroup.LayoutParams) mPager.getLayoutParams();
params.height = height;
mPager.setLayoutParams(params);
}
});

Tried a lot of things, finally got it.
-initially set the ViewPager to a big height to fit all possible content and not to make its height reduced
-had to nest 2 LinearLayout to get the correct height.
hth

Related

Get Height and Width of a child layout in contraintlayout

I have a constraint layout in which there is a child layout (frame_layout). The width and height are set as 0dp with match_constraint. How can we get the height and width of this frame_layout once the layout is loaded on the screen ? Using layoutparams gives 0dp. getWidth or getHeight again gives 0dp.
final FrameLayout layout = (FrameLayout) findViewById(R.id.YOUR_VIEW_ID);
ViewTreeObserver vto = layout.getViewTreeObserver();
vto.addOnGlobalLayoutListener (new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
layout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
int width = layout.getMeasuredWidth();
int height = layout.getMeasuredHeight();
}
});

How do you set the height of a view programmatically?

I have 2 views - a container view, and a gauge view. I want to programmatically change the height of the gauge view. The problem is that when I get the height of the container view - it always comes back as 2.0 - even though the height is full-screen!
int fullHeight = containerView.getLayoutParams().height;
Number height = fullHeight * (thisTank.getTankTotalVolume().doubleValue()/thisTank.getTankMaxVolume().doubleValue());
Number width = gaugeView.getWidth();
//gaugeView.setLayoutParams(new LinearLayout.LayoutParams(width.intValue(), height.intValue()));
gaugeView.getLayoutParams().height = height.intValue() * fullHeight;
gaugeView.requestLayout();
Actually, if you set the view's height to WRAP_CONTENT or MATCH_PARENT in XML, the containerView.getLayoutParams().height should be equals to 2, its a default value...!
You have to two options,
First, you can defined a fix value in the XML file
Second, and recommended, you can use a tree observer for this purpose. Please see the below code...!
final View layout = (View)findViewById(R.id.YOUR_VIEW_ID);
ViewTreeObserver vto = layout.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
this.layout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
int width = layout.getMeasuredWidth();
int height = layout.getMeasuredHeight();
}
});

How to determine the final size of view before expand?

I have a LinearLayout containing a TextView. The initial height of LinearLayout is set to 20px where the content of TextView overflows its bounds. I want to animate LinearLayout to expand to wrap content (its Children height). How can I determine the final size of LinearLayout before expanding?
Currently I set Height of View to wrap_content for a moment and after measuring the final height reset the height to 20 again! obviously this cause an unwanted blink before animation and should be replaced by a better solution.
//I hate these two lines
view.getLayoutParams().height=ViewGroup.LayoutParams.WRAP_CONTENT;
view.requestLayout();
//End of hate!
view.post(new Runnable() {
#Override
public void run() {
int targetHeight = view.getMeasuredHeight();
view.getLayoutParams().height=20;
view.requestLayout();
}
});
There is a .measure() method for this:
view.measure(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
int targetHeight = view.getMeasuredHeight();

How to check whether ScrollView is scrollable

I was wondering, how to check whether the current ScrollView is scrollable? It seems that, there isn't public method called canScroll or isScrollable in ScrollView.
Scrollable : You can move the ViewGroup inside the ScrollView up and down, and the scroll bar will be visible when you move it up and down. So, if there is only little rows in the ScrollView, and they can fit inside single screen, ScrollView is not scrollable then.
You can do some little math to calculate the views raw height and the height of the content. If the difference of this heights is < 0 the view is scrollable.
To calculate the raw height you can use View.getMeasuredHeight().
Because ScrollView is a ViewGroup and has max one child, get the height of that child with ViewGroup.getChildAt(0).getHeight();
Use a ViewTreeObserver to get the heights, because it will be called at the moment the layout / view is changing the visibility, otherwise the heights could be 0.
ScrollView scrollView = (ScrollView)findViewById(R.id...);
ViewTreeObserver observer = scrollView.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int viewHeight = scrollView.getMeasuredHeight();
int contentHeight = scrollView.getChildAt(0).getHeight();
if(viewHeight - contentHeight < 0) {
// scrollable
}
}
});
scrollView.viewTreeObserver
.addOnGlobalLayoutListener {
val isScrollable = scrollView.canScrollVertically(1)
}
I think I might be missing something, but shouldn't it be as simple as checking if
scrollView.getHeight() >= parentView.getMeasuredHeight()
you might actually need: scrollView.getChildAt(0).getHeight() and/or parentView.getHeight() instead, but the idea is the same.

Android: get width of Layout programatically having fill_parent in its xml

I have the a LinearLayout with width set in xml as fill_parent , now i need its width at runtime programatically. So i did this:
LinearLayout layoutGet=(LinearLayout) findViewById(R.id.GameField1);
LayoutParams layParamsGet= layoutGet.getLayoutParams();
int width=layParamsGet.width;
But width value on debugging was found to be -1, anybody with idea why can't i get the exact width at runtime for LinearLayout with fill_parent set in layout xml.
I got a simple approach working.
myLayout = (RelativeLayout) findViewById(R.id.my_layout);
myLayout.post(new Runnable()
{
#Override
public void run()
{
Log.i("TEST", "Layout width : "+ myLayout.getWidth());
}
});
Jens Vossnack's approach mentioned below works fine. However, I found that the onGlobalLayout() method of GlobalLayoutListener is called repeatedly, which may not be appropriate in certain cases.
You can try to listen to the globalLayout event, and get the width in there. You probably get the -1 because you are trying to get the width before the views are layed-out.
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
//Do it here
LinearLayout layoutGet=(LinearLayout) findViewById(R.id.GameField1);
LayoutParams layParamsGet= layoutGet.getLayoutParams();
int width=layParamsGet.width;
removeOnGlobalLayoutListener(layoutGet, this); // Assuming layoutGet is the View which you got the ViewTreeObserver from
}
});
#SuppressLint("NewApi")
public static void removeOnGlobalLayoutListener(View v, ViewTreeObserver.OnGlobalLayoutListener listener){
if (Build.VERSION.SDK_INT < 16) v.getViewTreeObserver().removeGlobalOnLayoutListener(listener);
else v.getViewTreeObserver().removeOnGlobalLayoutListener(listener);
}
(vto is the view you want to get the width of)
If you look at the value for FILL_PARENT (you should be using MATCH_PARENT since FILL_PARENT is now deprecated) you will notice the value for it is -1. LayoutParams are simply attributes for how your view should look. Once the view is inflated and looks the way the params specify, the view does not go back and change those Params to reflect the actual values of the view (width/height/etc).
If you wanted to get the actual width of your view you would have to call getWidth() on your view once the layout has been inflated and displayed. Calling getWidth() before your layout has been displayed will result in 0.
LinearLayout layoutGet=(LinearLayout) findViewById(R.id.GameField1);
int width = layoutGet.getWidth();
First of all, you should use match_parent instead of fill_parent (deprecated).
When you do int width=layParamsGet.width;, you take the right result which is -1 corresponding at fill_parent.
If you wan't to get the real width, you need to wait onMesure() call and use
LinearLayout layoutGet=(LinearLayout) findViewById(R.id.GameField1);
int width = layoutGet. getMeasuredHeight();
layoutGet.getWidth() should work out

Categories

Resources