I´m trying to create an app inspired in the google play app.
I have my
RelativeLayout
- RelativeLayout: * Header(this is the one that will be hidden when scrolling).
- RelativeLayout
* ListView
When I scroll down I want the header to be pushed up the screen and then my listview will occupy the whole screen and when I scroll up the header will return to its original position.
I am currently using this code, but it flickers when I´m somewhere at the top of the list.
// Hide top relative layout
list.setOnScrollListener(new AbsListView.OnScrollListener() {
int mPosition=0;
int mOffset=0;
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
int position = list.getFirstVisiblePosition();
View v = list.getChildAt(0);
int offset = (v == null) ? 0 : v.getTop();
if (mPosition < position || (mPosition == position && mOffset < offset)){
// Scrolled up
overridePendingTransition(R.anim.slide_up, R.anim.slide_down);
headerLayout.setVisibility(View.GONE);
} else {
// Scrolled down
headerLayout.setVisibility(View.VISIBLE);
}
}
});
Can anyone please help me? It will be appreciate. I don't know if I'm using the right layouts.
Thanks in advanced!
Related
I am trying to implement sort of collpasing toolbar - but without the toolbar(instead of the toolbar it would be a dropdown element, which is essentially a RelativeLayout that has LinearLayout right beneath (the expanded items in the dropdown) that is hovering over the whole layout once the dropdown is pressed.
I thought about implementing a collapsing toolbar and putting the drop down inside the toolbar, but that probably won't be a good idea since a drop down is not a static component like an imageview for example.
I also use ActionBar in my app, so migrating to Toolbar will most likely be very time-consuming, not to mention all the technical issues that come with it.
Aside from that, I thought about detecting a movement/scrolling direction in the listview, and then hide/show the drop down, but it is very buggy when I simply hold my finger on the list view ( it goes mad and switches from up to down and vice versa very very quickly and doesn't stop until I lift the finger).
Are there any other options to implement this sort of behavior?
I'm very curious about what others propose, because I fight with that some time ago. Finnaly I'm detecting movement/scrolling direction in the listview, and then hide/show the header (as you mention). I did it like this (and I don't have bugs):
listView.setOnScrollListener(OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
final int currentFirstVisibleItem = view.getFirstVisiblePosition();
if (currentFirstVisibleItem > mLastFirstVisibleItem) header.setVisibility(View.GONE);
else if (currentFirstVisibleItem < mLastFirstVisibleItem) header.setVisibility(View.VISIBLE);
mLastFirstVisibleItem = currentFirstVisibleItem;
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
});
I the end I made header to show/hide with animation.
ListView has a default scrollListener. You can use it to know if it's scrolling or not. then hide the dropDown!
listView.setOnScrollListener(new AbsListView.OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView absListView, int i) {
//detect stop. have a counter then view the dropDown
}
#Override
public void onScroll(AbsListView absListView, int i, int i1, int i2) {
//Hide dropDown
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if(mLastFirstVisibleItem<firstVisibleItem)
{
Log.i("SCROLLING DOWN","TRUE");
}
if(mLastFirstVisibleItem>firstVisibleItem)
{
Log.i("SCROLLING UP","TRUE");
}
mLastFirstVisibleItem=firstVisibleItem;
}
}
});
I'm developing a chat application and I'm trying to load 10 messages at a time, and when the user scrolls up it loads 10 more. therefore I used stackFromBottom=true to load the messages from the bottom :
<ListView
android:id="#+id/messagesList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:transcriptMode="normal"
android:stackFromBottom="true">
And I have a scroll listener to know when the user reached the top (firstVisibleItem == 0 , i.e the first message) so I can load more messages:
messagesList.setOnScrollListener(new AbsListView.OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView absListView, int i) {
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (firstVisibleItem ==0 && !loading && !startApp) {
loading = true;
skip += 10;
fetchMessages = new FetchMessages(); //load more items
fetchMessages.execute(true);
}
}
});
The issue is when you scroll up and reach the top, 10 more messages load but the Listview automatically scrolls to the bottom. I want to stay in the exact same position when new items are added to the Listview, just like any regular chat application.
This is the add messages method:
#Override
protected void onPostExecute(String json) {
if(json!=null){
...
//After Parse JSON ...
chatMessageAdapter.list.add(0,chatMessage); //add the message to the top of the list
chatMessageAdapter.notifyDataSetChanged(); //listview scrolls to the bottom afterwards
}
loading = false;
startApp = false;
}
I tried many of the suggestions in other threads but none of them actually worked. I hope someone could help here.
Many thanks.
what did work for me was that:
// save index and top position
int index = mList.getFirstVisiblePosition();
View v = mList.getChildAt(0);
int top = (v == null) ? 0 : v.getTop();
// notify dataset changed or re-assign adapter here
// restore the position of listview
mList.setSelectionFromTop(index, top);
Do note you have to remove android:transcriptMode="normal" from your xml, otherwise it wouldn't work.
There was some method for loading more data when scroll to the bottom.but I need a method for load data by scrolling to the top of the list in android.
like whats up and another chat application.
can you help me?
Below logic will work for loading more data when you scroll to the top of the listview.
listview.setOnScrollListener(new AbsListView.OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
currentScrollState = scrollState;
if (currentVisibleItemCount > 0 && currentScrollState == SCROLL_STATE_IDLE) {
if (currentFirstVisibleItem == 0) {
// getMessages(); //write what you want to do when you scroll up to the end of listview.
}
}
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,int totalItemCount) {
currentFirstVisibleItem = firstVisibleItem;
currentVisibleItemCount = visibleItemCount;
currentTotalItemCount = totalItemCount;
}
});
Hope this helps.
Well telegram have the same list view and the source code is available here https://github.com/DrKLO/Telegram
Or you may want to detect the scrolling of your list view check this answer
Detecting the scrolling direction in the adapter (up/down)
hope this will help.
If Pull To Refresh is what you are looking for, please refer to this link:
https://android-arsenal.com/details/1/1909
I am building an application like techcrunch.
I am fetching data from server in JSON format and displaying the data in list view like article title,author name and image.
I have applied pagination means when user scroll more articles load in a list view. My pagination works fine but there is an issue in the scroll function as the fresh or new data loads the scroll dose not aligns with the data.
To clarify more in simple words my scroll-er goes at the top of the page when i am actually scrolling down
this is my code :
listView.setOnScrollListener(new AbsListView.OnScrollListener()
{
#Override
public void onScrollStateChanged(AbsListView absListView, int i)
{
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
{
int lastItem = firstVisibleItem + visibleItemCount;
if(lastItem == totalItemCount){
if (mPreLast != lastItem)
{
mPreLast = lastItem;
onStart();
}
}
}
});`
You can use:
listView.setSelectionFromTop(newPosition, 0);
With this method you can set the position to a ListView, using the first parameter as the new position on the list, and the second parameter can be used to set the distance from the top
i have gridview with two column
user can scroll vertically to see gridview items
the problem is when user scrolling is finished
the first visible row is not completely seen .i want to set top of first visible row to top of gridview so first row is comletely visible
can anyone help me?
Update:
the first item is
and the second item is
but after scroll we see
you can try this
grid.setOnScrollListener(new OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView arg0, int scrollState) {
//this is the state when scroll finish
if(scrollState==SCROLL_STATE_IDLE)
//the first visible item is the first (even partially) visbile item
//setSelection will scroll the grid to the beginning of such item
grid.setSelection(firstVisibleItem);
}
#Override
public void onScroll(AbsListView arg0, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
});
I use RecyclerView, and i hope it's good for you!
mLayoutManager = new GridLayoutManager(getActivity(), 2);
mListRV= (RecyclerView).findViewById(R.id.list_rv);
mListRV.setLayoutManager(mLayoutManager);
mListRV.setOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
View v = mLayoutManager.getChildAt(0);
int offsetTop = v.getTop();
int offsetBottom = v.getBottom();
int height = (offsetBottom - offsetTop);
if(offsetTop >= -height/2) {
mListRV.smoothScrollBy(0, offsetTop);
} else {
mListRV.smoothScrollBy(0, height + offsetTop);
}
}
}
});
With this code, when you finish scroll, if the first visible item only show a part in recyclerView. It will auto scroll to show full item. You can use:
mLayoutManager.scrollToPositionWithOffset(position, offset);
But it is so fast, the user can be confused. And you will not need use customLayoutManager to edit scroll's properties.
Hope that helps for you!