I have a ListView which contains an ArrayAdapter which contains items for each hour of the day, and I need it to place the item which contains the current hour in the center of the visible region of the ListView.
I've tried setSelection, but it will place the item on the top instead of the center.
Is there any method to do it without calculating layout heights and such?
Right now I'm using this method, because I know the items are 40dip tall, but they won't always be 40dip tall.
private void centerListView() {
final Calendar c = Calendar.getInstance();
final int hour = c.get(Calendar.HOUR_OF_DAY);
final int listViewProgrammerPixels = listViewProgrammer.getHeight();
final int itemPixels = (int) (40 * getResources().getDisplayMetrics().density + 0.5f);
final int pixelsFromTop = (listViewProgrammerPixels - itemPixels) / 2;
listViewProgrammer.setSelectionFromTop(hour, pixelsFromTop);
}
I have done this using this logic first you have to get height of ListView and the height of View in adapter getView method then write this code in your click event .
int offset = ((listViewheight / 2) - (viewHeight / 2));
mListView.smoothScrollToPositionFromTop(position,Math.abs(offset));
Hope this will work for you.
Use this property item_layout.setGravity(Gravity.CENTER);
Related
I want to implement the google photos application timeline feature in the recycler view in which we can show the year of images as a label while scrolling as shown in below image.
Can anyone help in this or implemented something like this.
I have solved this problem by simply adding a new Linear-layout on top of the recyclerview with a child textview in the layout and then by calculating the height ratio(as per the count of images per year) with respect to the total height available.Also considering the minimum height of textview to 100 if the ratio is too small.
private float getEffectiveHeight(float totalHeight, float count, float totalCount) {
if (count * (totalHeight / totalCount) < 100)
return 100;
else
return count * (totalHeight / totalCount);
}
I have a listView in my screen. This listView fills 2/3 of my screen (so its height varies on different devices). I have - lets say 50 items in my array list - but I need to put X number of items in it which is visible to the user (e.g on small screen 3, on normal screen 5, on tablet 8).
So the way I'm doing is getting the height of listView in PX, then get its DP size and since I know the height of each row is 60dp then divide height of listViwe in DP format to height of row (which 60dp). So it returns number of items that will be visible to the user and I pass this number to getCount() method of my adapter to populate this amount of items.
This is my code, I have an observer that will be assigned some where in onCreate() method like this this.mListView.getViewTreeObserver().addOnGlobalLayoutListener(mListViewGlobalListener);
ViewTreeObserver.OnGlobalLayoutListener mListViewGlobalListener = new ViewTreeObserver.OnGlobalLayoutListener()
{
#Override
public void onGlobalLayout()
{
removeListViewListener();
if (mListView == null || mAdapter == null)
{
return;
}
int heightInPx = mListView.getHeight();
int heightInDp = pixelsToDp(heightInPx, getResources().getDisplayMetrics());
int maxDisplayDriver = heightInDp / 60;
mAdapter.setMaxDisplayDrivers(maxDisplayDriver);
Logger.error("TEST", "heightInPx:" + heightInPx + ", heightInDp:" + heightInDp + ", maxDisplayDriver:" + maxDisplayDriver);
}
};
public static int pixelsToDp(int px, DisplayMetrics metrics)
{
return (int) (px / metrics.density);
}
Now when I run the app I have following log: E/TEST: heightInPx:96, heightInDp:32, maxDisplayDriver:0
I believe the height is wrong because I can put at least 4 items in my screen that will be 240dp, while the log shows something else.
You can get the height of listview this way because a listview can have n number of childs and getHeight() returns the actual height not the height of currently visible portion. So for listview and other similar view it doesn't return height as even system doesn't know because all childitems are not yet rendered.
So as suggested by other geeks as well, you need to calculate the height of item + margin+padding (if any) and then multiply it by number of child(how do you know this? read ahead).
Now number of child would be different in different screen size. So you need to put a counter inside getView to check how many times its getting called onCreate to get to know the number of childitem
I am trying to build my own grid view functions - extending on the GridView.
The only thing I cannot solve is how to get the current scroll position of the GridView.
getScrollY() does always return 0, and the onScrollListener's parameters are just a range of visible child views, not the actual scroll position.
This does not seem very difficult, but I just can't find a solution in the web.
Anybody here who have an idea?
I did not find any good solution,
but this one is at least able to maintain the scroll position kind of pixel-perfectly:
int offset = (int)(<your vertical spacing in dp> * getResources().getDisplayMetrics().density);
int index = mGrid.getFirstVisiblePosition();
final View first = container.getChildAt(0);
if (null != first) {
offset -= first.getTop();
}
// Destroy the position through rotation or whatever here!
mGrid.setSelection(index);
mGrid.scrollBy(0, offset);
By that you can not get an absolute scroll position, but a visible item + displacement pair.
NOTES:
This is meant for API 8+.
You can get with mGrid.getVerticalSpacing() in API 16+.
You can use mGrid.smoothScrollToPositionFromTop(index, offset) in API 11+ instead of the last two lines.
Hope that helps and gives you an idea.
On Gingerbread, GridView getScrollY() works in some situations, and in some doesn't. Here is an alternative based on the first answer. The row height and the number of columns have to be known (and all rows must have equal height):
public int getGridScrollY()
{
int pos, itemY = 0;
View view;
pos = getFirstVisiblePosition();
view = getChildAt(0);
if(view != null)
itemY = view.getTop();
return YFromPos(pos) - itemY;
}
private int YFromPos(int pos)
{
int row = pos / m_numColumns;
if(pos - row * m_numColumns > 0)
++row;
return row * m_rowHeight;
}
The first answer also gives a good clue on how to pixel-scroll a GridView. Here is a generalized solution, which will scroll a GridView equivalent to scrollTo(0, scrollY):
public void scrollGridToY(int scrollY)
{
int row, off, oldOff, oldY, item;
// calc old offset:
oldY = getScrollY(); // getGridScrollY() will not work here
row = oldY / m_rowHeight;
oldOff = oldY - row * m_rowHeight;
// calc new offset and item:
row = scrollY / m_rowHeight;
off = scrollY - row * m_rowHeight;
item = row * m_numColumns;
setSelection(item);
scrollBy(0, off - oldOff);
}
The functions are implemented inside a subclassed GridView, but they can be easily recoded as external.
I want to create a Gridview just like a GooglePlay. The only difference in our case is the size of width & height should be the based on the popularity.
For example, If I have a array list of categories along with number of popularity. The order of category is fixed, so it will appear on the grid in same order, the only thing is going to change its width and height.
So, If my grid has 2 columns, then blocks should be adjusted automatically.
I have seen the demo of stagerred view but unable to replicate as per my requirement. So If any one has any suggestion will be appreciated.
Thanks
If you want to adjust the width of your block automatically you have to get Display Size.
This code Works for me.
public static void calculateSize(Activity ac) {
DisplayMetrics dMetrics = new DisplayMetrics();
ac.getWindowManager().getDefaultDisplay().getMetrics(dMetrics);
float density = dMetrics.density;
int w = Math.round(dMetrics.widthPixels / density);
int h = Math.round(dMetrics.heightPixels / density);
YourBlock.WIDTH = Math.round((w - (YourBlock.PADDING * (YourBlock.COLUMN + 1))) / YourBlock.COLUMN);
YourBlock.HEIGHT = Math.round(YourBlock.WIDTH * YourBlock.RATIO);
}
In this case:
public static final int YouBlock.COLUMN = 2;
public static float YourBlock.RATIO = 2.0f/3;
public static int YouBlock.PADDING = 4;
Example:
Each item will automacticaly adjusts width with each device (each size)
I am trying to build my own grid view functions - extending on the GridView.
The only thing I cannot solve is how to get the current scroll position of the GridView.
getScrollY() does always return 0, and the onScrollListener's parameters are just a range of visible child views, not the actual scroll position.
This does not seem very difficult, but I just can't find a solution in the web.
Anybody here who have an idea?
I did not find any good solution,
but this one is at least able to maintain the scroll position kind of pixel-perfectly:
int offset = (int)(<your vertical spacing in dp> * getResources().getDisplayMetrics().density);
int index = mGrid.getFirstVisiblePosition();
final View first = container.getChildAt(0);
if (null != first) {
offset -= first.getTop();
}
// Destroy the position through rotation or whatever here!
mGrid.setSelection(index);
mGrid.scrollBy(0, offset);
By that you can not get an absolute scroll position, but a visible item + displacement pair.
NOTES:
This is meant for API 8+.
You can get with mGrid.getVerticalSpacing() in API 16+.
You can use mGrid.smoothScrollToPositionFromTop(index, offset) in API 11+ instead of the last two lines.
Hope that helps and gives you an idea.
On Gingerbread, GridView getScrollY() works in some situations, and in some doesn't. Here is an alternative based on the first answer. The row height and the number of columns have to be known (and all rows must have equal height):
public int getGridScrollY()
{
int pos, itemY = 0;
View view;
pos = getFirstVisiblePosition();
view = getChildAt(0);
if(view != null)
itemY = view.getTop();
return YFromPos(pos) - itemY;
}
private int YFromPos(int pos)
{
int row = pos / m_numColumns;
if(pos - row * m_numColumns > 0)
++row;
return row * m_rowHeight;
}
The first answer also gives a good clue on how to pixel-scroll a GridView. Here is a generalized solution, which will scroll a GridView equivalent to scrollTo(0, scrollY):
public void scrollGridToY(int scrollY)
{
int row, off, oldOff, oldY, item;
// calc old offset:
oldY = getScrollY(); // getGridScrollY() will not work here
row = oldY / m_rowHeight;
oldOff = oldY - row * m_rowHeight;
// calc new offset and item:
row = scrollY / m_rowHeight;
off = scrollY - row * m_rowHeight;
item = row * m_numColumns;
setSelection(item);
scrollBy(0, off - oldOff);
}
The functions are implemented inside a subclassed GridView, but they can be easily recoded as external.