package com.github.jjobes.slidedaytimepicker;
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.NumberPicker;
import android.widget.TimePicker;
/**
* A custom {@link android.support.v4.view.ViewPager} implementation that corrects
* the height of the ViewPager and also dispatches touch events to either the ViewPager
* or the day or time picker depending on the direction of the swipe.
*
* @author jjobes
*
*/
public class CustomViewPager extends ViewPager
{
private NumberPicker mDayPicker;
private TimePicker mTimePicker;
private float x1, y1, x2, y2;
private float mTouchSlop;
public CustomViewPager(Context context)
{
super(context);
init(context);
}
public CustomViewPager(Context context, AttributeSet attrs)
{
super(context, attrs);
init(context);
}
private void init(Context context)
{
mTouchSlop = ViewConfiguration.get(context).getScaledPagingTouchSlop();
}
/**
* Setting wrap_content on a ViewPager's layout_height in XML
* doesn't seem to be recognized and the ViewPager will fill the
* height of the screen regardless. We'll force the ViewPager to
* have the same height as its immediate child.
*/
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (getChildCount() > 0)
{
View childView = getChildAt(0);
if (childView != null)
{
childView.measure(widthMeasureSpec, heightMeasureSpec);
int h = childView.getMeasuredHeight();
setMeasuredDimension(getMeasuredWidth(), h);
getLayoutParams().height = h;
}
}
mDayPicker = (NumberPicker) findViewById(R.id.dayPicker);
mTimePicker = (TimePicker) findViewById(R.id.timePicker);
}
/**
* When the user swipes their finger horizontally, dispatch
* those touch events to the ViewPager. When they swipe
* vertically, dispatch those touch events to the day or
* time picker (depending on which page we're currently on).
*
* @param event
*/
@Override
public boolean dispatchTouchEvent(MotionEvent event)
{
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
x1 = event.getX();
y1 = event.getY();
break;
case MotionEvent.ACTION_MOVE:
x2 = event.getX();
y2 = event.getY();
if (isScrollingHorizontal(x1, y1, x2, y2))
{
// When the user is scrolling the ViewPager horizontally,
// block the pickers from scrolling vertically.
return super.dispatchTouchEvent(event);
}
break;
}
// As long as the ViewPager isn't scrolling horizontally,
// dispatch the event to the NumberPicker or TimePicker,
// depending on which page the ViewPager is currently on.
switch (getCurrentItem())
{
case 0:
if (mDayPicker != null)
mDayPicker.dispatchTouchEvent(event);
break;
case 1:
if (mTimePicker != null)
mTimePicker.dispatchTouchEvent(event);
break;
}
// need this for the ViewPager to scroll horizontally at all
return super.onTouchEvent(event);
}
/**
* Determine whether the distance between the user's ACTION_DOWN
* event (x1, y1) and the current ACTION_MOVE event (x2, y2) should
* be interpreted as a horizontal swipe.
*
* @param x1
* @param y1
* @param x2
* @param y2
* @return
*/
private boolean isScrollingHorizontal(float x1, float y1, float x2, float y2)
{
float deltaX = x2 - x1;
float deltaY = y2 - y1;
if (Math.abs(deltaX) > mTouchSlop &&
Math.abs(deltaX) > Math.abs(deltaY))
{
return true;
}
return false;
}
}