Wednesday 23 April 2014

Android - How To Implement Horizontal Scroll ListView

This post about how to implment horizontal scroll view

Sample Screen Shot-


activity_horizontal_scroll_view.xml


<RelativeLayout 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" >

    <com.shwetamaaks.horizontalscrollactivity.CenterLockHorizontalScroll
        android:id="@+id/scrollView"
        android:layout_width="match_parent"
        android:layout_height="100dip"
        android:layout_alignParentBottom="true" >

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal" >
        </LinearLayout>
    </com.shwetamaaks.horizontalscrollactivity.CenterLockHorizontalScroll>

    <LinearLayout
        android:id="@+id/bottomLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@id/scrollView"
        android:orientation="horizontal"
        android:weightSum="2" >

        <Button
            android:id="@+id/btnPrev"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Prev" />

        <Button
            android:id="@+id/btnNext"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Next" />
    </LinearLayout>

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@id/bottomLayout"
        android:layout_alignParentTop="true"
        android:layout_centerInParent="true"
        android:textColor="#FF0000"
        />

</RelativeLayout>


news_list_item.xml



<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@drawable/app_back"
    android:paddingTop="15dip"
    android:paddingBottom="15dip" >

    
    <LinearLayout 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        
        >
        
        
         <TextView
        android:id="@+id/txtNewsSource"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Title" />
         
         
         
    </LinearLayout>
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Detail news" />

</LinearLayout>

CenterLockHorizontalScroll.java


package com.shwetamaaks.horizontalscrollactivity;

import java.util.ArrayList;

import android.app.Activity;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;


public class CenterLockHorizontalScroll extends HorizontalScrollView {

 private static final int SWIPE_MIN_DISTANCE = 5;
 private static final int SWIPE_THRESHOLD_VELOCITY = 300;
 private int mActiveFeature = 0;
 private ArrayList mItems = null;

 private GestureDetector mGestureDetector;

 private boolean mScrollable = true;

 Context context;

 int prevIndex = 0;

 public CenterLockHorizontalScroll(Context context, AttributeSet attrs) {
  super(context, attrs);
  this.context = context;
  this.setSmoothScrollingEnabled(true);

 }

 public void setAdapter(Context context, CustomListAdapter mAdapter) {

  try {
   fillViewWithAdapter(mAdapter);
  } catch (ZeroChildException e) {

   e.printStackTrace();
  }
 }

 public void setScrollingEnabled(boolean enabled) {
  mScrollable = enabled;
 }

 public boolean isScrollable() {
  return mScrollable;
 }
//
 @Override
 public boolean onTouchEvent(MotionEvent ev) {

  Log.e("on touch for centewehjt", "xfvxc");
  switch (ev.getAction()) {
  case MotionEvent.ACTION_DOWN:
   // if we can scroll pass the event to the superclass
   if (mScrollable)
    return super.onTouchEvent(ev);
   // only continue to handle the touch event if scrolling enabled
   return mScrollable; // mScrollable is always false at this point

  case MotionEvent.ACTION_MOVE:

   // if we can scroll pass the event to the superclass
   if (mScrollable)
    return super.onTouchEvent(ev);
   // only continue to handle the touch event if scrolling enabled
   return mScrollable; // mScrollable is always false at this point

  default:
   return super.onTouchEvent(ev);
  }
 }
 
 


 @Override
 public boolean onInterceptTouchEvent(MotionEvent ev) {
  // Don't do anything with intercepted touch events if
  // we are not scrollable
  if (!mScrollable)
   return false;
  else
   return super.onInterceptTouchEvent(ev);
 }

 private void fillViewWithAdapter(CustomListAdapter mAdapter)
   throws ZeroChildException {
  if (getChildCount() == 0) {
   throw new ZeroChildException(
     "CenterLockHorizontalScrollView must have one child");
  }
  if (getChildCount() == 0 || mAdapter == null)
   return;

  ViewGroup parent = (ViewGroup) getChildAt(0);

  parent.removeAllViews();

  for (int i = 0; i < mAdapter.getCount(); i++) {
   parent.addView(mAdapter.getView(i, null, parent));
  }
 }

 public void setCenter(int index) {

  ViewGroup parent = (ViewGroup) getChildAt(0);

  View preView = parent.getChildAt(prevIndex);
  android.widget.LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
    LinearLayout.LayoutParams.WRAP_CONTENT,
    LinearLayout.LayoutParams.WRAP_CONTENT);
  lp.setMargins(5, 5, 5, 5);
  preView.setLayoutParams(lp);

  View view = parent.getChildAt(index);
  int screenWidth = ((Activity) context).getWindowManager()
    .getDefaultDisplay().getWidth();

  int scrollX = (view.getLeft() - (screenWidth / 2))
    + (view.getWidth() / 2);
  this.smoothScrollTo(scrollX, 0);
  prevIndex = index;
 }

 class MyGestureDetector extends SimpleOnGestureListener {
  @Override
  public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
    float velocityY) {
   try {
    // right to left
    if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE
      && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
     int featureWidth = getMeasuredWidth();
     mActiveFeature = (mActiveFeature < (5 - 1)) ? mActiveFeature + 1
       : 5 - 1;
     smoothScrollTo(mActiveFeature * featureWidth, 0);
     return true;
    }
    // left to right
    else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
      && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
     int featureWidth = getMeasuredWidth();
     mActiveFeature = (mActiveFeature > 0) ? mActiveFeature - 1
       : 0;
     smoothScrollTo(mActiveFeature * featureWidth, 0);
     return true;
    }
   } catch (Exception e) {
    Log.e("Fling", "There was an error processing the Fling event:"
      + e.getMessage());
   }
   return false;
  }
 }

}

CustomListAdapter.java


package com.shwetamaaks.horizontalscrollactivity;

import java.util.ArrayList;

import com.example.horizontalscrollactivity.R;



import android.content.Context;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.TextView;


public class CustomListAdapter extends ArrayAdapter<String> {
 Context context;
 private ArrayList<String> list;
 int layoutId;
 Holder holder;
 public View view;
 public int currPosition = 0;

 public CustomListAdapter(Context context, int textViewResourceId,
   ArrayList<String> list) {
  super(context, android.R.layout.simple_list_item_1, list);
  this.context = context;
  this.list = list;
  layoutId = textViewResourceId;

 }

 @Override
 public int getCount() {
  return list.size();
 }

 @Override
 public String getItem(int position) {
  return list.get(position);
 }

 @Override
 public View getView(final int position, View convertView, ViewGroup parent) {
  LinearLayout layout;

  if (convertView == null) {

   layout = (LinearLayout) View.inflate(context, layoutId, null);

   holder = new Holder();

   holder.title = (TextView) layout.findViewById(R.id.txtNewsSource);
   layout.setTag(holder);

  } else {
   layout = (LinearLayout) convertView;
   view = layout;
   holder = (Holder) layout.getTag();
  }
  String newsSource = getItem(position);
  holder.title.setText(newsSource);
  Log.v("Test", "lo frm newsadpater");

  return layout;
 }

 private class Holder {
  public TextView title;

 }
 public int getCurrentPosition(){
  return currPosition;
 }
}

MainActivity.java


package com.shwetamaaks.horizontalscrollactivity;

import java.util.ArrayList;

import com.example.horizontalscrollactivity.R;

import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.annotation.TargetApi;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import android.os.Build;

public class MainActivity extends Activity {
 CenterLockHorizontalScroll centerLockHorizontalScrollview;
 CustomListAdapter customListAdapter;
 private GestureListener mGestureDetector;
 private static final int SWIPE_MIN_DISTANCE = 5;
 private static final int SWIPE_THRESHOLD_VELOCITY = 300;

 OnSwipeDetectListener onSwipeTouchListener;

 Button btnPrev, btnNext;
 GestureDetector gestureDetector;
 int currIndex = 0;
 private TextView text;
 ArrayList<String> list = new ArrayList<String>() {

  {
   add("Manchester city");
   add("Manchester United");
   add("Chelsea");
   add("Liverpool");
   add("TottenHam");
   add("Everton");
   add("WestHam");
   add("Arsenal");
   add("West Broom");
   add("New Castle");
   add("Norich City");
   add("Swansea city");
   add("stroke city");

  }
 };

 @TargetApi(Build.VERSION_CODES.HONEYCOMB)
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_horizontal_scroll_view);

  gestureDetector = new GestureDetector(new GestureListener());

  mGestureDetector = new GestureListener();
  btnNext = (Button) findViewById(R.id.btnNext);
  btnPrev = (Button) findViewById(R.id.btnPrev);
  text = (TextView) findViewById(R.id.text);
  centerLockHorizontalScrollview = (CenterLockHorizontalScroll) findViewById(R.id.scrollView);
  customListAdapter = new CustomListAdapter(this,
    R.layout.news_list_item, list);
  centerLockHorizontalScrollview.setAdapter(this, customListAdapter);
  btnNext.setOnClickListener(onClickListener);
  btnPrev.setOnClickListener(onClickListener);

  centerLockHorizontalScrollview.setScrollingEnabled(false);

  onSwipeTouchListener = new OnSwipeDetectListener(this) {

   public void onSwipeTop() {
    Toast.makeText(MainActivity.this, "top", Toast.LENGTH_SHORT)
      .show();
   }

   public void onSwipeRight() {
    Toast.makeText(MainActivity.this, "right", Toast.LENGTH_SHORT)
      .show();
    if (currIndex != 0) {
     currIndex--;
     centerLockHorizontalScrollview.setCenter(currIndex);
     text.setText(list.get(currIndex == 0 ? 0 : currIndex - 1));
    }
   }

   public void onSwipeLeft() {
    Toast.makeText(MainActivity.this, "left", Toast.LENGTH_SHORT)
      .show();

    if (currIndex < list.size()) {
     centerLockHorizontalScrollview.setCenter(currIndex);
     currIndex++;
     text.setText(list.get(currIndex - 1));
    }

   }

   public void onSwipeBottom() {
    Toast.makeText(MainActivity.this, "bottom", Toast.LENGTH_SHORT)
      .show();
   }

  };

  centerLockHorizontalScrollview
    .setOnTouchListener(new OnTouchListener() {

     @Override
     public boolean onTouch(View v, MotionEvent event) {
      // TODO Auto-generated method stub
      if (gestureDetector.onTouchEvent(event)) {
       return false;

      }

      return true;
     }
    });

  // centerLockHorizontalScrollview.setOnTouchListener(onSwipeTouchListener);

  // centerLockHorizontalScrollview.setOnTouchListener(new
  // OnSwipeDetectListener(this){
  //
  // public void onSwipeTop() {
  // Toast.makeText(HorizontalScrollViewActivity.this, "top",
  // Toast.LENGTH_SHORT).show();
  // }
  // public void onSwipeRight() {
  // Toast.makeText(HorizontalScrollViewActivity.this, "right",
  // Toast.LENGTH_SHORT).show();
  // }
  // public void onSwipeLeft() {
  // Toast.makeText(HorizontalScrollViewActivity.this, "left",
  // Toast.LENGTH_SHORT).show();
  // }
  // public void onSwipeBottom() {
  // Toast.makeText(HorizontalScrollViewActivity.this, "bottom",
  // Toast.LENGTH_SHORT).show();
  // }
  //
  // public boolean onTouch(View v, MotionEvent event) {
  // return true;
  // }
  //
  // });

 }

 private final class GestureListener extends SimpleOnGestureListener {
  private static final int SWIPE_THRESHOLD = 300;
  private static final int SWIPE_VELOCITY_THRESHOLD = 300;

  @Override
  public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
    float velocityY) {
   // TODO Auto-generated method stub
   boolean result = false;
   try {
    float diffY = e2.getY() - e1.getY();
    float diffX = e2.getX() - e1.getX();
    if (Math.abs(diffX) > Math.abs(diffY)) {
     if (Math.abs(diffX) > SWIPE_THRESHOLD
       && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
      if (diffX > 0) {

       Log.e("right", "------------------");
       // onSwipeRight();
      } else {
       Log.e("Left", "------------------");
      }
     }
    } else {
     if (Math.abs(diffY) > SWIPE_THRESHOLD
       && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
      if (diffY > 0) {
       // onSwipeBottom();
      } else {
       // onSwipeTop();
      }
     }
    }
   } catch (Exception exception) {
    exception.printStackTrace();
   }
   return result;
  }

 }

 OnClickListener onClickListener = new OnClickListener() {

  @Override
  public void onClick(View v) {
   if (v.getId() == R.id.btnPrev) {
    if (currIndex != 0) {
     currIndex--;
     centerLockHorizontalScrollview.setCenter(currIndex);
     text.setText(list.get(currIndex == 0 ? 0 : currIndex - 1));
    }
   } else if (v.getId() == R.id.btnNext) {

    if (currIndex < list.size()) {
     centerLockHorizontalScrollview.setCenter(currIndex);
     currIndex++;
     text.setText(list.get(currIndex - 1));
    }
   }

  }
 };

 public boolean dispatchTouchEvent(MotionEvent ev) {

  onSwipeTouchListener.getGestureDetector().onTouchEvent(ev);
  return super.dispatchTouchEvent(ev);
 };
}

OnSwipeDetectListener.java


package com.shwetamaaks.horizontalscrollactivity;

import android.content.Context;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.View.OnTouchListener;


public class OnSwipeDetectListener implements OnTouchListener {

 private GestureDetector gestureDetector;
 

 
    private boolean mScrollable = true;
    
 
 public GestureDetector getGestureDetector(){
     return  gestureDetector;
 }

 public OnSwipeDetectListener(Context con) {
  // TODO Auto-generated constructor stub
  gestureDetector = new GestureDetector(con, new GestureListener());
 }


    public void setScrollingEnabled(boolean enabled) {
        mScrollable = enabled;
    }

    public boolean isScrollable() {
        return mScrollable;
    }

    
 
 private final class GestureListener extends SimpleOnGestureListener {
  private static final int SWIPE_THRESHOLD = 100;
  private static final int SWIPE_VELOCITY_THRESHOLD = 100;

  @Override
  public boolean onDown(MotionEvent e) {
   // TODO Auto-generated method stub
   Log.e("on down on swipe gesture listener", "-->");
    switch (e.getAction()) {
             case MotionEvent.ACTION_DOWN:
                 // if we can scroll pass the event to the superclass
                 if (mScrollable) 
                  //return super.onTouchEvent(e);
                 // only continue to handle the touch event if scrolling enabled
                 return mScrollable; // mScrollable is always false at this point
             default:
                 return true;
         }
   
  }
  
  @Override
  public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
    float velocityY) {
   // TODO Auto-generated method stub
   boolean result = false;
            try {
                float diffY = e2.getY() - e1.getY();
                float diffX = e2.getX() - e1.getX();
                if (Math.abs(diffX) > Math.abs(diffY)) {
                    if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                        if (diffX > 0) {
                            onSwipeRight();
                        } else {
                            onSwipeLeft();
                        }
                    }
                } else {
                    if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                        if (diffY > 0) {
                            onSwipeBottom();
                        } else {
                            onSwipeTop();
                        }
                    }
                }
            } catch (Exception exception) {
                exception.printStackTrace();
            }
            return result;
  }

 }
 
  public void onSwipeRight() {
     }

     public void onSwipeLeft() {
     }

     public void onSwipeTop() {
     }

     public void onSwipeBottom() {
     }

 @Override
 public boolean onTouch(View v, MotionEvent event) {
  // TODO Auto-generated method stub
  return false;
 }
 
 

}

ZeroChildException.java


package com.shwetamaaks.horizontalscrollactivity;

public class ZeroChildException extends Exception {

 private static final long serialVersionUID = 1L;

 public ZeroChildException() {

 }

 public ZeroChildException(String errorMessage) {
  super(errorMessage);
 }

}


Enjoy Coding!!!!!!

All The Best...!!!!!!:)





1 comment: