I need to get the visible height of header in listivew .How to get the height of First item in Listview(Header) or any View.
I Tried method given Below but these are giving me the original height of item not visible height.
view.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#SuppressLint("NewApi")
#SuppressWarnings("deprecation")
#Override
public void onGlobalLayout() {
//now we can retrieve the width and height
int width = view.getWidth();
int height = view.getHeight();
//...
//do whatever you want with them
//...
//this is an important step not to keep receiving callbacks:
//we should remove this listener
//I use the function to remove it based on the api level!
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN)
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
else
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
and
view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
int widht = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
and this too
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics); height =
metrics.heightPixels; width = metrics.widthPixels;
But not getting any result.
Thanks in advance
You can try this. Let your layout file is as follows:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/rl_container"
android:layout_height="match_parent"
android:layout_width="match_parent">
<ListView
android:id="#+id/sample_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
In your activity java file:
ListView mListView = (ListView) findViewById(R.id.sample_list_view);
mListView.setAdapter(mAdapter);
// add header view.
// Let "mHeaderView" is a header view inflated from some layout file
mListView.addHeaderView(mHeaderView);
// let your listview's parent view (in layout file) is a relative layout
// with id = "rl_container" as shown in above XML layout file
RelativeLayout rlContainer = (RelativeLayout)findViewById(R.id.rl_container);
// To find visible height of the first item (header in this case)
// mListView.getChildAt(i) return view of the ith child from top.
// header is considered to be as 0th child.
// not sure about multiple headers. but it should be same.
View childView = mListView.getChildAt(0);
// visible height is bottom cordinate of the child view - top cordinate of the list view's parent container.
// here I am considering list view as the top child of its parent container.
// code can be modified accordingly to consider margins from top.
int visibleHeight = childView.getBottom() - rlContainer.getTop();
if(visibleHeight < 0) {
//then item is not visible
}
It is working for me as I am using it in my project. comments and suggestions are welcomed.
Related
I am trying to get the list view heigh at run time to fit the item to height of screen.
Here is my code: in my getView()
int totalHeight = activity.getListView().getHeight();
int rowHeight = totalHeight / getCount(); // Divide by number of items.
activity.getListView().setScrollContainer(false);
activity.getListView().setVerticalScrollBarEnabled(false);
convertView.setMinimumHeight(rowHeight);
In my activity i have programatically created List View with both width and height as MATCH_PARENT.
But i tried to debug and saw that only for the first item the list view height is 0 but for rest of the items its giving me proper height.
Why so
? how to fix this ?
It's most probably due to that the view has not been created yet. In this situation the height would be 0.
You can get the height of the view using something like:
final ListView listView = activity.getListView();
ViewTreeObserver vto = listView.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int totalHeight = listView.getHeight();
int rowHeight = totalHeight / getCount(); // Divide by number of items.
listView.setScrollContainer(false);
listView.setVerticalScrollBarEnabled(false);
convertView.setMinimumHeight(rowHeight);
ViewTreeObserver obs = listView.getViewTreeObserver();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
obs.removeOnGlobalLayoutListener(this);
} else {
obs.removeGlobalOnLayoutListener(this);
}
}
});
The reason for checking the Build.VERSION is that in the SDK prior to Jelly Bean the name of the method was different (OnGlobalLayout vs GlobalOnLayout)
It is happening because when the getView for the first item was called the height of the listview is not determined.
you need to use ViewTreeObserver to give you an event for layout change and in that you can get the height.
I inflate a layout containing an ImageView and a RelativeLayout. The layout has its width set to match_parent and its height set to wrap_content. The height is determined by the ImageView, but the image set to the ImageView is loaded dynamically from the internet.
Since I know the image ratio, I'd like to set the size of the ImageView before it's displayed to avoid a jump in the UI due to the change in the layout height when the image is set.
To set the size I need the layout width, to compute the ImageView height.
I tried
int width = header.getMeasuredWidth();
but since the layout is not drawn yet it returns 0
I also tried to use measure before, as suggested here
header.measure(0, 0);
int width = header.getMeasuredWidth();
but measure returns a NullPointerException
How can I do that?
list_header.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="#+id/pic"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<RelativeLayout
android:id="#+id/header_text_container"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:background="#789987">
</RelativeLayout>
</RelativeLayout>
MyListFragment.java
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mListView = (ListView) getView().findViewById(R.id.listview);
View header = getActivity().getLayoutInflater().inflate(R.layout.list_header, null);
int width = header.getMeasuredWidth(); // 0 because not drawn yet
ImageView pic = (ImageView) header.findViewById(R.id.pic);
pic.setLayoutParams(new LayoutParams(width, (int) (width/imgRatio)));
pic.invalidate();
header.invalidate();
/* ... */
}
You could try with a ViewTreeObserver.
Your Fragment/Activity should implement OnGlobalLayoutListener, in OnActivityCreate declare handler
ViewGroup container = (ViewGroup) findViewById(R.id.header_text_container)
ViewTreeObserver vto = container.getViewTreeObserver();
vto.addOnGlobalLayoutListener(this);
and put your width logic in listener when size are available
#Override
public void onGlobalLayout() {
// Remember to remove handler
container.getViewTreeObserver().removeGlobalOnLayoutListener(this);
View header = getActivity().getLayoutInflater().inflate(R.layout.list_header, null);
int width = header.getMeasuredWidth(); // 0 because not drawn yet
...
}
you can get the size in Activity's onWindowFocusChanged(boolean hasFocus) method.
You can get the width and height of a view in onGlobalLayout, wich is a method to Callback method wich is invoked when the global layout state or the visibility of views within the view tree changes (thus as soon as the view is drawn and the size is known).
ViewTreeObserver vto = header.getViewTreeObserver();
if(vto!=null){
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
header.getWidth();
header.getHeight();
}
});
}
i have a list view defined in the xml, now i am setting the content view setContentView(R.layout.topic_layout); , i have 5 items in it,currently its filling only half the height of the list view but i want it to completely fill the height so that i dont have any space at the bottom.
i have searched for it but couldnt find any solution, please help me to acheive this :
and also i am setting the adapter like this:
adapter = new MyAdapter(this);
if (adapter != null) {
setListAdapter(adapter);
}
If you have a fixed number of items and want them to stretch all the way to the end of the screen, ListView is not the best choice for you. Use a LinearLayout which takes up all the space and add all the items to it. This is assuming you want the items to take up all the space every time.
Using LinearLayout, you can spread the items out evenly without doing any calculations yourself.
LinearLayout linearLayout = new LinearLayout(getSupportActivity());
linearLayout.setOrientation(android.widget.LinearLayout.VERTICAL);
RelativeLayout.LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
for (int i = 0; i < 5; i++) {
View individualView = new View(getSupportActivity());
// Create your custom view here and add it to the linear layout
// Leave the height as 0, LinearLayout will calculate the height properly.
params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0);
additionalOption.setLayoutParams(params);
// As a we are adding it to the linear layout, they will all have a weight of 1, which will make them spread out evenly.
linearLayout.addView(additionalOption);
}
mainView.addView(linearLayout);
EDIT: If you have already implemented it with ListView and is troublesome to change it, you can do the following.
Make sure the list view width and height are set to match_parent in the xml. Then in getView() of the adapter where you create your custom view, do the following
// Get the height of the ListView
int totalHeight = listView.getHeight();
int rowHeight = totalHeight/getCount(); // Divide by number of items.
// Create custom view with the height calculated above.
Be careful about the totalHeight being 0. If you create the ListView in onCreate() and set the adapter in onCreate() as well, the ListView will most likely not have the width or height calculated yet. Try setting the adapter in onResume() instead. By this point, the dimensions of the ListView would have been calculated and laid out on the screen.
Hope this helps.
I totally agree with #Aswin, using LinearLayout with layout_weight property would be your solution. But if you insist to use listView, i can offer you a workout which is not so recommended.
You can get your screenHeight when activity created by using these codes:
Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
DisplayMetrics dm = new DisplayMetrics();
display.getMetrics(dm);
int height = dm.heightPixels;
int listItemHeight = height / YOUR_ITEM_COUNT;
Then you can use this listItemHeight in your listAdapter, by setting inflated view's height on getView method.
This is what I use to do:
Set your xml listview height to match_parent instead of wrap_content, in order to fill all the available space.
Set the minimum height of each item in the listview to match the listview height divided by the number of elements.
Activity Layout:
(...)
<ListView
android:id="#+id/myListView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
(...)
ArrayAdapter for the Listview:
private class MyAdapter extends ArrayAdapter<MyObject> {
(...)
#Override
public View getView(int position, View convertView, ViewGroup parent) {
MyObject myobject = getItem(position);
ObjectHolder oh;
if (convertView == null) {
LayoutInflater mInflater = (LayoutInflater) myContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(R.layout.myitemlayout, parent, false);
// This is the important line:
convertView.setMinimumHeight(parent.getHeight()/getCount());
(...)
return convertView;
}
}
I added a linear layout in horizontal scroll view and in layout add some text views. Is it possible to get visible children in this layout.
This code get all child but i want to get visible (currently displaying) children only:
final HorizontalScrollView scroll = (HorizontalScrollView)findViewById(R.id.horizontalScrollView1);
LinearLayout linearLayout = ((LinearLayout)scroll.findViewById(R.id.linearLayout1));
int chilrenNum = linearLayout.getChildCount();
Well , after a bit of searching on SO I found this answer to listen to scroll events. Implement Scroll Event Listener in Android.
The idea is to override onScrollChanged in your ScrollView and keep track of the visible part of your scrollview in your activity.
Doing that you can easily get the visible views by a code that looks like this:
int currentPosition = lastXPosition; // lastXPosition gets updated from scroll event
int layoutWidth = linearLayout.getWidth();
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int childWidth = layoutWidth/linearLayout.getChildCount();
int firstVisibleXPos = currentPosition - width/2; // currentPosition will be in the middle of the screen
int lastVisibleXPos = currentPosition + width/2;
int indexOfFirstVisible = firstVisibleXPos/childWidth;
int indexOfLastVisible = lastVisibleXPos/ childWidth;
All the above code assumes fixed child view sizes . if you are using variable child size you will need to get their width first and keep track of it then calculate the visiblity based on index and position in parent view.
In my application i have a list view and i am inflating a web view into the list view. I am able to load data and images into the list view item. The problem is the list items are not of same height due to different contents. I want to make all list items having same height
How to calculate the height of the list item that has the maximum data and set that height to rest of the list items in the list.
How would i do that.. i have no clue on that.. Say if the 10th item has the maximum height i want to apply that height to the rest. help me implement this please and thank you for your support
<?xml version="1.0" encoding="utf-8"?>
<WebView
android:id="#+id/wv1"
android:layout_width="fill_parent" android:paddingRight="20dp"
android:layout_height="wrap_content" />
Have an array of flags, say
boolean[] flags=new boolean[szieOfList];
fill this array to false;
Have a variable max height in your activity or adapter, say max, initialize it with 0 in onCreate method, now in getView method where you are inflating xml, write the following code:
LayoutInflater layoutInflater = (LayoutInflater) getActivity()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view= (WebView) layoutInflater
.inflate(R.layout.web_view, null);
if(flag[position])
{
LayoutParams params = view.getLayoutParams();
params.height = max;
view.setLayoutParams(params);
}
ViewTreeObserver observer = view.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
//in here, place the code that requires you to know the dimensions.
flag[position]=true;
int height= view.getHeight();
if(max<height)
{
max=height;
notifyDataSetInvalidated();
}
else
{
LayoutParams params = view.getLayoutParams();
params.height = max;
view.setLayoutParams(params);
}
//this will be called as the layout is finished, prior to displaying.
}
}