Show/Hide layouts when scroll ListView in Android

   Detecting scrolling in ListView is fairly common in Android application development. To day, in this tip, I will share a simple solution to detect scroll reached to top/bottom of ListView and showing "header" and "footer" layout at this time. Another, when user scrolling, these layouts were disappeared.
   In order to do this, you must use setOnScrollListener() method of ListView and in onScrollListener() method, you provide some actions when scroll, reached to top/bottom.
Source code for this method can be like this:
public OnScrollListener onScrollListener() {
  return new OnScrollListener() {

   @Override
   public void onScrollStateChanged(AbsListView view, int scrollState) {
   }

   @Override
   public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
     int totalItemCount) {
    if (firstVisibleItem == 0) {
     // check if we reached the top or bottom of the list
     View v = listView.getChildAt(0);
     int offset = (v == null) ? 0 : v.getTop();
     if (offset == 0) {
      // reached the top: visible header and footer
      Log.i(TAG, "top reached");
      setViewStatus(footer, header, View.VISIBLE);
     }
    } else if (totalItemCount - visibleItemCount == firstVisibleItem) {
     View v = listView.getChildAt(totalItemCount - 1);
     int offset = (v == null) ? 0 : v.getTop();
     if (offset == 0) {
      // reached the bottom: visible header and footer
      Log.i(TAG, "bottom reached!");
      setViewStatus(footer, header, View.VISIBLE);
     }
    } else if (totalItemCount - visibleItemCount > firstVisibleItem){
     // on scrolling
     setViewStatus(footer, header, View.GONE);
     Log.i(TAG, "on scroll");
    }
   }
  };
 }
    In your activity, making some important methods (set data for ListView, set some "demo" event listener for buttons in "header/footer" layout, show/hide these items,...):

Full ReadingActivity.java code:
package com.blogspot.hongthaiit.mangareader;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class ReadingActivity extends Activity {

 private ListView listView;
 private ListViewAdapter adapter;
 private View btnLike, btnShare, btnNext, btnPrev, btnComment;
 private TextView chapterName;
 private ViewGroup header, footer;
 private final static String TAG = ReadingActivity.class.getSimpleName();

 private final static String[] imageArray = { "http://i.imgur.com/bRzOCig.jpg",
   "http://i.imgur.com/ykPVmnp.jpg", "http://i.imgur.com/RbKOKnG.jpg",
   "http://i.imgur.com/REjrtGp.jpg", "http://i.imgur.com/PT9QjQ9.jpg",
   "http://i.imgur.com/dg5NY1D.jpg", "http://i.imgur.com/Imlqk8j.jpg",
   "http://i.imgur.com/U2IPvXy.jpg", "http://i.imgur.com/0MNYYuG.jpg",
   "http://i.imgur.com/VZhAPel.jpg", "http://i.imgur.com/35jBerW.jpg",
   "http://i.imgur.com/0jHZEfn.jpg", "http://i.imgur.com/81HvMfA.jpg",
   "http://i.imgur.com/nobvCRi.jpg", "http://i.imgur.com/wdT3ZVw.jpg",
   "http://i.imgur.com/DV9MDja.jpg", "http://i.imgur.com/PN2TQnS.jpg" };

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_reading);
  listView = (ListView) findViewById(R.id.list_view);
  locateListViewHeaderAndFooter();
  setListViewAdapter();
  
  //set on scrolling listener for ListView
  listView.setOnScrollListener(onScrollListener());
 }

 // adding header and footer for listview
 private void locateListViewHeaderAndFooter() {
  // declaring elements
  btnLike = findViewById(R.id.btn_like);
  btnComment = findViewById(R.id.btn_comment);
  btnNext =  findViewById(R.id.btn_next);
  btnPrev = findViewById(R.id.btn_prev);
  btnShare = findViewById(R.id.btn_share);
  chapterName = (TextView) findViewById(R.id.chapter_name);
  header = (ViewGroup) findViewById(R.id.layout_header);
  footer = (ViewGroup) findViewById(R.id.layout_footer);
  chapterName.setText("One Piece chap 650");

  // set "demo" events for buttons
  btnLike.setOnClickListener(onButtonClick("You liked it"));
  btnComment.setOnClickListener(onButtonClick("Please enter your comment..."));
  btnNext.setOnClickListener(onButtonClick("Go to Next chap ter"));
  btnPrev.setOnClickListener(onButtonClick("Go to Previous chap ter"));
  btnShare.setOnClickListener(onButtonClick("Thanks for sharing..."));


 }
 
 private void setListViewAdapter() {
  adapter = new ListViewAdapter(this, R.layout.item_listview, imageArray);
  listView.setAdapter(adapter);
 }

 public OnScrollListener onScrollListener() {
  return new OnScrollListener() {

   @Override
   public void onScrollStateChanged(AbsListView view, int scrollState) {
   }

   @Override
   public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
     int totalItemCount) {
    if (firstVisibleItem == 0) {
     // check if we reached the top or bottom of the list
     View v = listView.getChildAt(0);
     int offset = (v == null) ? 0 : v.getTop();
     if (offset == 0) {
      // reached the top: visible header and footer
      Log.i(TAG, "top reached");
      setViewStatus(footer, header, View.VISIBLE);
     }
    } else if (totalItemCount - visibleItemCount == firstVisibleItem) {
     View v = listView.getChildAt(totalItemCount - 1);
     int offset = (v == null) ? 0 : v.getTop();
     if (offset == 0) {
      // reached the bottom: visible header and footer
      Log.i(TAG, "bottom reached!");
      setViewStatus(footer, header, View.VISIBLE);
     }
    } else if (totalItemCount - visibleItemCount > firstVisibleItem){
     // on scrolling
     setViewStatus(footer, header, View.GONE);
     Log.i(TAG, "on scroll");
    }
   }
  };
 }

 // handle buttons events
 private OnClickListener onButtonClick(final String buttonEventName) {
  return new OnClickListener() {

   @Override
   public void onClick(View v) {
    Toast.makeText(ReadingActivity.this, buttonEventName, Toast.LENGTH_SHORT).show();
   }
  };
 }

 private void setViewStatus(ViewGroup vg1, ViewGroup vg2, int status) {
  vg1.setVisibility(status);
  vg2.setVisibility(status);
 }
}
    Creating a customize adapter for ListView:
ListViewAdapter.java
package com.blogspot.hongthaiit.mangareader;

import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;

import com.squareup.picasso.Picasso;

public class ListViewAdapter extends ArrayAdapter {

 private Activity activity;

 public ListViewAdapter(Activity activity, int resource, String[] objects) {
  super(activity, resource, objects);
  this.activity = activity;
 }

 @Override
 public View getView(int position, View convertView, ViewGroup parent) {
  ViewHolder holder;
  LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
  // If holder not exist then locate all view from UI file.
  if (convertView == null) {
   // inflate UI from XML file
   convertView = inflater.inflate(R.layout.item_listview, parent, false);
   // get all UI view
   holder = new ViewHolder(convertView);
   // set tag for holder
   convertView.setTag(holder);
  } else {
   // if holder created, get tag from view
   holder = (ViewHolder) convertView.getTag();
  }
  
  //load image from url by Picasso library
  Picasso.with(activity).load(getItem(position)).into(holder.page);
  
  return convertView;
 }

 private class ViewHolder {
  private ImageView page;

  public ViewHolder(View v) {
   page = (ImageView) v.findViewById(R.id.image);
  }
 }
}
    Over here, programmatically codes completed. Declaring necessary layouts in xml files:
  • layout_header.xml: the view above ListView:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:id="@+id/layout_footer"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:background="#91000000"
   android:orientation="horizontal"
   android:padding="5dp" >
 
    <ImageView
       android:id="@+id/btn_prev"
       android:layout_width="0dp"
       android:layout_height="wrap_content"
       android:layout_weight="0.2"
       android:contentDescription="@string/app_name"
       android:src="@drawable/previous" />
 
    <TextView
       android:id="@+id/chapter_name"
       android:layout_width="0dp"
       android:textStyle="bold"
       android:layout_gravity="center"
       android:gravity="center"
       android:layout_height="wrap_content"
       android:layout_weight="0.6"
       android:textColor="@android:color/white" />
 
    <ImageView
       android:id="@+id/btn_next"
       android:layout_width="0dp"
       android:layout_height="wrap_content"
       android:layout_weight="0.2"
       android:contentDescription="@string/app_name"
       android:src="@drawable/next" />
 
</LinearLayout>
  • layout_footer.xml: the view below ListView:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:id="@+id/layout_header"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:background="#91000000"
   android:orientation="horizontal"
   android:padding="5dp" >
 
    <ImageView
       android:id="@+id/btn_like"
       android:layout_width="0dp"
       android:layout_height="wrap_content"
       android:layout_weight="0.33"
       android:contentDescription="@string/app_name"
       android:src="@drawable/like" />
 
    <ImageView
       android:id="@+id/btn_comment"
       android:layout_width="0dp"
       android:layout_height="wrap_content"
       android:layout_weight="0.33"
       android:contentDescription="@string/app_name"
       android:src="@drawable/comment" />
 
    <ImageView
       android:id="@+id/btn_share"
       android:layout_width="0dp"
       android:layout_height="wrap_content"
       android:layout_weight="0.33"
       android:contentDescription="@string/app_name"
       android:src="@drawable/share" />
 
</LinearLayout>
  • activity_reading.xml: activity layout, we'll include 2 above items here:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:id="@+id/container"
   android:layout_width="match_parent"
   android:layout_height="match_parent" >
 
    <ListView
       android:id="@+id/list_view"
       android:layout_width="match_parent"
       android:layout_height="wrap_content" >
    </ListView>
 
    <include
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_alignParentTop="true"
       layout="@layout/layout_header" />
 
    <include
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_alignParentBottom="true"
       layout="@layout/layout_footer" />
 
</RelativeLayout>
  • item_listview.xml: each ListView item layout - only include an ImageView:
item_listview.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"
   android:orientation="horizontal"
   android:padding="5dp" >
 
    <ImageView
       android:id="@+id/image"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:contentDescription="@string/action_settings"
       android:scaleType="fitXY" />
 
</LinearLayout>
    Running program, our result will be liked this:
pic name pic name pic name

    NOTE:

In this post, I use Picasso library to load images from urls:
- See my PREVIOUS POST to learn how to use it.
- Visit Picasso Home Page to deep understanding it.

(sorry for ads)

Share


Previous post
« Prev Post
Next post
Next Post »