Pages

Friday, August 5, 2011

Creating Custom Horizontal Scroll View With Snap or paging

I have faced various issues to develop a horizontal scroll view with paging effect. I googled it a lot but not able to find anything satisfactory. Some search results help me, using those i have created my own custom horizontal scrollview class which can give similar effect as effect on Tablet Home page.

I will be discussing it step by step so that you can use it where required and it becomes easy for you to understand.

Step 1) Layout file -  Simple layout file for demo


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_height="match_parent"
android:layout_width="match_parent" android:id="@+id/layer">
</LinearLayout>

Step 2) CustomHorizontalScrollView - Class file which extends HorizontalScrollView and give snapping or paging effect.


public class CustomHorizontalScrollView extends HorizontalScrollView implements
OnTouchListener, OnGestureListener {

        private static final int SWIPE_MIN_DISTANCE = 300;

private static final int SWIPE_THRESHOLD_VELOCITY = 300;
private static final int SWIPE_PAGE_ON_FACTOR = 10;


private GestureDetector gestureDetector;
private int scrollTo = 0;
private int maxItem = 0;
private int activeItem = 0;
private float prevScrollX = 0;
private boolean start = true;
private int itemWidth = 0;
private float currentScrollX;
private boolean flingDisable = true;

public CustomHorizontalScrollView(Context context) {
super(context);
setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT));
}

public CustomHorizontalScrollView(Context context, int maxItem,
int itemWidth) {
this(context);
this.maxItem = maxItem;
this.itemWidth = itemWidth;
gestureDetector = new GestureDetector(this);
this.setOnTouchListener(this);
}

@Override
public boolean onTouch(View v, MotionEvent event) {
if (gestureDetector.onTouchEvent(event)) {
return true;
}
Boolean returnValue = gestureDetector.onTouchEvent(event);

int x = (int) event.getRawX();

switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
if (start) {
this.prevScrollX = x;
start = false;
}
break;
case MotionEvent.ACTION_UP:
start = true;
this.currentScrollX = x;
int minFactor = itemWidth
/ ConfigurationParams.SWIPE_PAGE_ON_FACTOR;

if ((this.prevScrollX - this.currentScrollX) > minFactor) {
if (activeItem < maxItem - 1)
activeItem = activeItem + 1;

} else if ((this.currentScrollX - this.prevScrollX) > minFactor) {
if (activeItem > 0)
activeItem = activeItem - 1;
}
System.out.println("horizontal : " + activeItem);
scrollTo = activeItem * itemWidth;
this.smoothScrollTo(scrollTo, 0);
returnValue = true;
break;
}
return returnValue;
}

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
if (flingDisable)
return false;
boolean returnValue = false;
float ptx1 = 0, ptx2 = 0;
if (e1 == null || e2 == null)
return false;
ptx1 = e1.getX();
ptx2 = e2.getX();
// right to left

if (ptx1 - ptx2 > ConfigurationParams.SWIPE_MIN_DISTANCE
&& Math.abs(velocityX) > ConfigurationParams.SWIPE_THRESHOLD_VELOCITY) {
if (activeItem < maxItem - 1)
activeItem = activeItem + 1;

returnValue = true;

} else if (ptx2 - ptx1 > ConfigurationParams.SWIPE_MIN_DISTANCE
&& Math.abs(velocityX) > ConfigurationParams.SWIPE_THRESHOLD_VELOCITY) {
if (activeItem > 0)
activeItem = activeItem - 1;

returnValue = true;
}
scrollTo = activeItem * itemWidth;
this.smoothScrollTo(0, scrollTo);
return returnValue;
}

@Override
public boolean onDown(MotionEvent e) {
return false;
}

@Override
public void onLongPress(MotionEvent e) {
}

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
return false;
}

@Override
public void onShowPress(MotionEvent e) {
}

@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
}



Step 3) TestHorizontalActivity- This class will be used as test class


public class TestHorizontalActivity extends Activity {

private LinearLayout linearLayout;
private CustomHorizontalScrollView horizontalScrollView;

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

int width = activity.getWindowManager().getDefaultDisplay().getWidth();
int height = activity.getWindowManager().getDefaultDisplay().getHeight();
horizontalScrollView = new CustomHorizontalScrollView(this, 3,
width);
setContentView(R.layout.horizontal);
linearLayout = (LinearLayout) findViewById(R.id.layer);
linearLayout.addView(horizontalScrollView);

LinearLayout container = new LinearLayout(this);
container.setLayoutParams(new LayoutParams(width, height));
// container.setHeight(height);

TextView textView = new TextView(this);
textView.setWidth(width);
textView.setHeight(height);
textView.setGravity(Gravity.CENTER);
textView.setText("First  Screen");
textView.setBackgroundColor(Color.CYAN);
container.addView(textView);

textView = new TextView(this);
textView.setWidth(width);
textView.setHeight(height);
textView.setGravity(Gravity.CENTER);
textView.setText("Second  Screen");
textView.setBackgroundColor(Color.GREEN);
container.addView(textView);

textView = new TextView(this);
textView.setWidth(width);
textView.setHeight(height);
textView.setGravity(Gravity.CENTER);
textView.setText("Third  Screen");
textView.setBackgroundColor(Color.RED);
container.addView(textView);

horizontalScrollView.addView(container);
}

}


This is it, these 3 simple steps and you are ready to run a paging effect in your android application.

In next blog i will discuss how we can use combination of both horizontal scrolling and vertical scrolling.


I hope this post will be helpful. 

Please share your comments and and you can also contact me @ info@iotasol.com or visit our site www.iotasol.com , www.iotadomains.com.

3 comments:

  1. ConfigurationParams cannot be resolved to a variable i am getting this error. i am new to android how to resolve this

    ReplyDelete
    Replies
    1. Try one or all of this options:

      -Try to clean de project, in eclipse 'Project'/'Clean...'
      -Try to deleted de folder 'gen' and clean de project again ...
      -Open de SDK manager and update all the package of the API in use.

      Delete
    2. Just delete all "ConfigurationParams." since the variables is already defined in the same class of CustomHorizontalView.class

      Delete