I have TextView+webview as ListItem of ListView. When I change orientation. I am reloading all files as well setting adapter again and I am calling following code to select item from list programtically so I can get onItemClick call same ways as user would have clicked.
if(position!=-1 && getAdapter()!=null){
requestFocusFromTouch();
performItemClick(
getAdapter().getView(position,
null, null), position,
getAdapter().getItemId(position));
}
Now when I change orientation of screen, the selected item's webview is not scrolling till the end. It seems that it is not changing its scrolled position when we change orientation (Even though we reset adapter).
I tried requestlayout(), forcelayout(), invalidate(),reload() method of webview but none of them seems to be working.
You probably have your WebViews heights set to wrap_contents. This means that their heights are 0 when the list is loaded and they expand to a > 0 height at some point. One way to solve your issue would be to wait for all of the webviews to call onSizeChanged before scrolling, another option would be to re-position the list every time the lists contents change size.
Related
I am trying to scroll and request focus to an off screen element from a recycler view. I have a list of 15 languages. When app starts the user can select one language from the recycler. Then if the app starts again the recycler scrolls and request focusto that item.
But imagine the user selects the last language from the list which is not showed in the recycler when the app starts. How to scroll and therefore reqeust focus to that element which is not currently showed in the recycler?
I expected to do something like recycler.scrollToPosition(14) and then scrollToPosition(14) , but the index is outof bunds... I guess thats because the element is not created yet. Any idea?
I had similar scenario and below code worked for me:
(rv_your_recycler_view.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(position, offset)
Just set offset to 0 and position to 14, this will get you last item.
P.S. If it doesn't work check if your recyclerview's bottom constraint tied up to parent's bottom.
app:layout_constraintBottom_toBottomOf="parent"
If you try to scroll and set the focus at the same time then it may fail. While the scrolling will proceed, the request for the focus will fail if the item is not yet present in the RecyclerView. (As you state.)
The solution is to separate the two activities. Scroll to the position as you do now, but set the focus when the item is bound to the view holder in the adapter. This will require you to keep track of which item has the focus so that it can be referenced in the adapter.
I would like to be able to determine the height of a listview prior to adding items. The listview is defined as layout_height=0dp and layout_weight=5 (or some other value, its not fill_parent or wrap_content). When I call lv.getHeight prior to adding items, the height returns 0. I've tried using lv.requestLayout() and lv.getMeasuredHeight in the onResume method of my fragment.
Things I've tried so far:
Querying the listview height in an onGlobalLayout handler. This gets me the correct height, but the listadapter's getView has already been called to populate the list. If I wait to bind the adapter until after onGlobalLayout, then when I use adapter.notifyDataSetChanged() to update the view, I'm stuck in a loop of onGlobalLayout handler calls.
From the docs, onResume appears to be called after the layout is complete, so I would expect that the listview.getHeight or listview.getMeasuredHeight would return valid values at this time, but all I get is 0.
Why I want this. I need to know how many items will fit in the listview prior to adding them. I want to add a number (count-1) of "blank items" at the top of the list so that it is possible for the user to scroll the top item in the list to the bottom so it is visually next to another control below the list.
Finally found this.
View's getWidth() and getHeight() returns 0
But it appears to be counter to the documentation of onResume
I have a situation involving animation of listview's item appearances.
I have a few views in a ScollView , the last of which is the listview. I have attached an appearence animation of the row (a fade in animation).
The problem I have is that when the screen is loaded , the getView() of listview already executes for the initial items , even though the listview is not currently in view.
Hence when a user scroll downs , he sees the list plainly.
I am unsure how to go about this situation . Is there any callback that can be invoked when a row from a listview becomes visible on screen ? .
Yes there is a callback (OnScrollChangeListener), first visible index and last visible index etc. You can achieve what you are trying to using combination of these.
But you need to try that yourself first. No one can simply write a code for you.
You can learn about listview here
I've got a GridView with a custom Adapter, displaying thumbnails of pictures to the user. I can select and deselect pictures (I use setAlpha(0.25) on the views to notify the user of the change), and that's all well and fine.
Now what I want to do next, is have a button on top of the gridview that clears the whole selection, i.e. call setAlpha(1.0) on all views that were changed. So far I can reset my elements in the adapter, and I can setAlpha to 1, but the view doesn't update unless I scroll it out of the display, and then get back to it, or notify the adapter of changes, which redraws all my views, which does not look too pretty if only one element was selected.
I already dynamically set and reset individual elements through the GridView's onClickListener, but can't do this for more. I even tried calling performClick on all selected items through my button, but again it only displays the changes after the views have been out of the screen and are shown again.
Here's how I simulate the clicks:
for (int i = 0; i < mAdapter.getCount(); i++) {
PictureForSelection tempPic = (PictureForSelection) mAdapter.getItem(i);
if (tempPic.isPicSelected()) {
//tempPic.setIfSelected(false);
gridview.performItemClick(mAdapter.getView(i, null, null), i, i);
}
}
EDIT:
Conclusion - don't simulate clicks like this :)
So now I skip click simulation and use this:
gridview.getChildAt(i).setAlpha((float) 1.0);
In general it does exactly what I wanted it to do, except for one case:
If I have for example 3 pictures selected, one is off screen, one is partly shown, and one is fully shown, the ones shown (even partially) don't update their views.
If all the selected pictures are displayed it works flawlessly, but if some are out of the display, the rest do not update until the adapter's getView() gets called by Android. Still, thanks #mmlooloo for getting me so far.
If anyone knows a way around this, please do share :)
After setting your alpha you can call imageview.invalidate(); this causes your imageview to redraw itself.
if notifyDataSetChanged() is not working you can try like this.
i'm not sure whether this works,
1.onclick of the button you set the gridView.setAdapter(null);
2. Then set a new CustomAdapter object to gridview with default values.
I have a Gallery view created with a SimpleAdapter that extends BaseAdapter. It contains more items than what it can fit in the screen.
So I'm using Gallery.getFirstVisiblePosition() and Gallery.getLastVisiblePosition() to get the first and last visible position. But these functions doesn't always return the correct values especially after setting the selected position by calling mGallery.setSelection() followed by a SimpleAdapter.notifyDataChanged() call. Most of the time it getFirstVisiblePosition() returns 0 even if the first element is not visible.
Also note that the no. of visible items in Gallery is different in portrait and landscape mode. The value returned by getFirstVisiblePosition() look correct in landscape but is returned wrong in portrait mode.
Anyone has any thoughts/ideas?
Thanks!
The first visible position will be updated only after a layout. You cannot call notifyDatasetChanged() and right away get the first visible position, you must wait for the next layout pass.