howto get the size of a linearlayout - android

I try to get the size of a linearlayout. I get always iactualHeight=0 in the following code:
li=(LinearLayout)findViewById(R.id.textviewerbuttonlayout);
li.requestLayout();
int iactualHeight=li.getLayoutParams().height;
My Layout is defined as follow:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:background="#FFFFFF"
android:id="#+id/textviewerlayout"
android:orientation="vertical">
<WebView
android:id="#+id/mywebview"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="22" />
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/textviewerbuttonlayout"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:background="#FFFFFF"
android:orientation="horizontal" >
.... BUTTONS .....
</LinearLayout>
</LinearLayout>
Somebody any idea ?

you will not get value unitl onCreate finishes.so add these in onResume() or in onStart()
int height= li.getHeight();
int width = li.getWidth();
the other option is to use globallayoutlistener(if you want to get height in onCreate) so you will get notified when li(your layout) is added.
ViewTreeObserver observer= li.getViewTreeObserver();
observer.addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
Log.d("Log", "Height: " + li.getHeight());
Log.d("Log", "Width: " + li.getWidth());
}
});

The problem is you are requesting the height too early. Take a look at how android draws views.
The easiest way to get the guaranteed height is to use addOnLayoutChangedListener:
View myView = findViewById(R.id.my_view);
myView.addOnLayoutChangedListener(new OnLayoutChangeListener() {
#Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight,
int oldBottom) {
// its possible that the layout is not complete in which case
// we will get all zero values for the positions, so ignore the event
if (left == 0 && top == 0 && right == 0 && bottom == 0) {
return;
}
int height = top - bottom;
}
});

Related

Slide Menu Layout returns null reference for left and content view

I am trying to get the reference of SlideMenuLayout left and content view , but when I called getSlideLeftView() it returns null !
here is the code:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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=".RootActivity">
<com.jkb.slidemenu.SlideMenuLayout
android:id="#+id/mainSlideMenu"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
app:slideMode="left">
<include layout="#layout/left_menu_layout" />
<include layout="#layout/content_layout" />
</com.jkb.slidemenu.SlideMenuLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Root Activity :
public class RootActivity extends AppCompatActivity {
private SlideMenuLayout leftMenu;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_root);
leftMenu = (SlideMenuLayout) findViewById(R.id.mainSlideMenu);
View left = leftMenu.getSlideLeftView(); // returns null !!!
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, DashboardFragment.newInstance())
.commitNow();
}
}
}
From the SlideMenuLayout source code, I see that left slide menu view, right slide menu view, content view only initialized inside onMeasure() method, so you need to change your code to:
leftMenu.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
#Override
public void onLayoutChange(View v, int left, int top, int right, int bottom,
int oldLeft, int oldTop, int oldRight, int oldBottom) {
leftMenu.removeOnLayoutChangeListener(this);
// Initialize left, right, content view here
View leftView = leftMenu.getSlideLeftView();
}
});

ScrollView and complex subviews that contains scrolling feauture

I've got a problem with one of my views on android, which has quite complex structure.
Basically, what I wan't to achieve is something like this:
Having scrolled view, that has inside some views with wrap content, but last of those views, has gridview. The problem is that without setting exact height of the grid view (and with wrap content)... scroll doesn't allow to scroll to the end of this grid. I don't want to use scroll inside this GridView, I used this widget to simplify data population and use build-in controls and adapters.
My XML:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:id="#+id/scrollview_root"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
// some relevant subviews
</LinearLayout>
// here problem starts
<GridView
android:id="#+id/grid_products"
android:layout_width="match_parent"
android:minHeight="50dp"
android:layout_height="wrap_content" />
// here problem ends
</LinearLayout>
</ScrollView>
I tried to provide custom scrollView with overwritten onMesure, also tried in onResume invalidateScroll and use computeScroll method.
Here is some code for overwritten onMesure:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
int expandSpec = MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK,MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) getLayoutParams();
params.height = getMeasuredHeight()+10000;
setLayoutParams(params);
invalidate();
requestLayout();
}
But with no luck ... still I have to provide exact value for layout_height, otherwise its not visible and not reachable via scrolling.
I experimented a lot and for now have no idea, what I can check next and to do to make it works.
Thanks in advance for any help,
Regards David
UPDATE WITH WORKING SOLUTION
This works for me https://stackoverflow.com/a/8483078/566817 with custom GridView class, that has this method inside:
public int measureRealHeight(Context context)
{
final int columnsCount = 3;
final int screenWidth = ((Activity)context).getWindowManager().getDefaultDisplay().getWidth();
final double screenDensity = getResources().getDisplayMetrics().density;
final int columnWidth = (int) (screenWidth / columnsCount + screenDensity + 0.5f);
final int verticalSpacing = (int) context.getResources().getDimension(R.dimen.grid_spacing_vertical);
final int rowsCount = getAdapter().getCount() / columnsCount + (getAdapter().getCount() % columnsCount == 0 ? 0 : 1);
return columnWidth * rowsCount + verticalSpacing * (rowsCount - 1);
}
Also need to update LayoutParams in my Fragment in onResume method:
#Override
public void onResume()
{
super.onResume();
int realHeight = gridViewProducts.measureRealHeight(getActivity());
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) gridViewProducts.getLayoutParams();
lp.height = realHeight;
gridViewProducts.setLayoutParams(lp);
gridViewProducts.requestLayout();
}
My grid in XML
<xxx.CustomGridView
android:id="#+id/grid_products"
android:isScrollContainer="false"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:numColumns="3" />
I spend much time on this so far, and have no better solution so far unfortunately (I know its not perfect solution).
I hope it will help someone :)

getLocationOnScreen of a child of GridLayout

I'm attempting to get the x/y of an imageview within a GridLayout but my log keeps showing X & Y: 0 0 any ideas?
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/root" >
...
<GridLayout
android:id="#+id/gridLayout1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:columnCount="3"
android:rowCount="5" >
...
<ImageView
android:id="#+id/fivetwo"
android:layout_width="75dp"
android:layout_height="75dp"
android:contentDescription="#string/gameboard"
android:gravity="center"
android:src="#drawable/tile"
android:layout_columnSpan="1"
android:layout_rowSpan="1" />
heres the java:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_level);
....
ImageView temp = (ImageView) findViewById(R.id.fivetwo);
int originalPos[] = new int[2];
temp.getLocationOnScreen( originalPos );
Log.i(TAG, "X & Y: " + originalPos[0] + " " + originalPos[1]);
...
Remember:getX() and getY()return 0 if components are not drawn yet (in onCreate(){} ).
To find out the position of a view as soon as it is ready:
Add a tree observer to the layout. This should return the correct position.
onCreate is called before the layout of the child views are done. So the width and height is not calculated yet. To get the height and width. Put this on the onCreate method
final ImageView temp = (ImageView) findViewById(R.id.fivetwo);
ViewTreeObserver vto = temp.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
temp.getViewTreeObserver().removeGlobalOnLayoutListener(this);
int x = temp.getX();
int y = temp.getY();
Log.v(TAG, String.format("X:%d Y:%d",x,y);
}
});
You need to wait for the callback when the layout has placed the children views. The code you are using returns 0 because the position is returned before the layout is placed. Use this code:
temp.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
getViewTreeObserver().removeGlobalOnLayoutListener(this);
int[] locations = new int[2];
temp.getLocationOnScreen(locations);
int x = locations[0];
int y = locations[1];
}
});

Android Impossibile fill Layout height with custom view

I created a custom View, and I put this on a LinearLayout.
Problem is that I cannot fill completely the height of the layout, the size of the custom View is always squared, width = height.
Here is my layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:layout_weight="0">
<it.inav.graphics.MapView
android:id="#+id/map"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"/>
</LinearLayout>
The only way it seems to work is using a RelativeLayout and "strecth" the view using both
android:layout_alignParentBottom="true"
android:layout_alignParentTop="true"
but still, if I try to get the size height, it returns the same length of before.
The problem was in the definition of the View, and not in the XML.
I have done copy-paste of this piece of code:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int measuredWidth = measure(widthMeasureSpec);
int measuredHeight = measure(heightMeasureSpec);
int d = Math.min(measuredWidth, measuredHeight);
setMeasuredDimension(d, d);
}
And, naturally, it sets the size of the View as a square with the length of the minor.
This is the correct code:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int measuredWidth = measure(widthMeasureSpec);
int measuredHeight = measure(heightMeasureSpec);
setMeasuredDimension(measuredWidth, measuredHeight);
}

How to change android slidingdrawer handle button position

In default handle button in android SlidingDrawer in the centre of the drawer. Is it possible to change that position to left or right..? If it possible how can I do that, android:gravity="left" is not work in the button.
Put your handle in a RelativeLayout, and set android:layout_alignParentRight="true" on the handle.
For example like this:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello" />
<SlidingDrawer android:id="#+id/drawer"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:handle="#+id/handle"
android:content="#+id/content">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/handle">
<ImageView android:src="#drawable/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true" />
</RelativeLayout>
<LinearLayout
android:gravity="center"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#aaaa00" android:id="#+id/content">
<ImageView android:src="#drawable/icon"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center">
</ImageView>
</LinearLayout>
</SlidingDrawer>
</FrameLayout>
The problem I had with HenrikS answer was that in my case I had some views behind the relative layout and when I tried to click them I realized that the relative layout was intercepting those clicks because the width was set to fill_parent.
To workaround this I modified the layout of the handler view (the ImageView) in my case to the left, hope it is helpful.
public class CustomSlidingDrawer extends SlidingDrawer {
public CustomSlidingDrawer(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CustomSlidingDrawer(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
final int height = b - t;
ImageView handle = (ImageView) getHandle();
int childLeft = 0;
int childWidth = handle.getWidth();
int topOffset = 0;
int bottomOffest = 0;
int childHeight = handle.getHeight();
int childTop = this.isOpened()?topOffset:height - childHeight + bottomOffest;
handle.layout(childLeft, childTop , childLeft + childWidth, childTop+childHeight);
}
}
The idea is simple: set the handle's padding to the correct value depending on the alignment you want.
In the example below, I derive a class from SlidingDrawer and override onLayout as follows. My sliding drawer is at the bottom of the screen, and I want the handle to be left-aligned rather than center-aligned.
public class ToolDrawer extends SlidingDrawer {
private int m_handleWidth = 0; // original handle width
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
if (x <= m_handleWidth) {
return super.onTouchEvent(event);
}
return false;
}
protected void onLayout (boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (changed) {
ImageView iv = (ImageView) getHandle();
iv.setPadding(0, 0, getWidth() - iv.getWidth(), 0);
if (m_handleWidth == 0) {
m_handleWidth = iv.getWidth();
}
}
}
}
It's as simple as that.
I tried android:paddingBottom="300dp" for the ImageView and it works fine, also with left, right and top.
But you have to set the padding from the middle-position, so bottom="300dp" means the handle move up 300 from the middle
A simpler solution for left-aligned handle:
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
final View handle = getHandle();
handle.layout(0, handle.getTop(), handle.getWidth(), handle.getBottom());
}
I have researched this problem for 2 days and I realized that you need to use another library. Because, when you use RelativeLayout or LinearLayout, you're just get fill_parent screen and of course it will be affected by touching ( although you don't touch on icon ).
So, I use SlidingTray from Sileria library ( ver 3.5 ) http://aniqroid.sileria.com/doc/api/
Then like this
I found the solution for garibay
You just need to set android:clickable="true" on content layout of sliding drawer.

Categories

Resources