Last active
May 19, 2018 13:05
-
-
Save adneal/7287925 to your computer and use it in GitHub Desktop.
A way to swipe between the children of a ViewPager using the ActionBar. Similar the Google Chrome app for Android.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<com.your_package_name.ProgressTracker xmlns:android="http://schemas.android.com/apk/res/android" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:enabled="false" | |
android:orientation="horizontal" | |
android:paddingEnd="8dp" > | |
<ImageView | |
android:id="@+id/up" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_gravity="center_vertical|start" | |
android:contentDescription="@null" | |
android:visibility="gone" /> | |
<LinearLayout | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_gravity="center_vertical|start" | |
android:orientation="vertical" > | |
<TextView | |
android:id="@+id/action_bar_title" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:ellipsize="end" | |
android:singleLine="true" | |
android:text="@string/app_name" | |
android:textIsSelectable="false" | |
android:textSize="18sp" /> | |
<TextView | |
android:id="@+id/action_bar_subtitle" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_marginTop="-3dp" | |
android:ellipsize="end" | |
android:singleLine="true" | |
android:textIsSelectable="false" | |
android:textSize="14sp" | |
android:visibility="gone" /> | |
</LinearLayout> | |
</com.your_package_name.ProgressTracker> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* A {@link LinearLayout} that tracks a user's finger movement | |
* | |
* @author Andrew Neal (andrew@seeingpixels.org) | |
*/ | |
public class ProgressTracker extends LinearLayout { | |
/** The callback invoked depicting the current finger movement */ | |
private OnProgressChangeListner mCallback; | |
/** Used to track the velocity of the finger movement */ | |
private VelocityTracker mVelocityTracker; | |
/** The current progress */ | |
private float mProgress; | |
/** | |
* Constructor for <code>ProgressTracker</code> | |
* | |
* @param context The {@link Context} to use | |
* @param attrs The attributes of the XML tag that is inflating the view | |
*/ | |
public ProgressTracker(Context context, AttributeSet attrs) { | |
super(context, attrs); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
@Override | |
public boolean onTouchEvent(MotionEvent event) { | |
final int index = event.getActionIndex(); | |
final int pointerId = event.getPointerId(index); | |
switch (event.getAction()) { | |
case MotionEvent.ACTION_DOWN: | |
// Initialize the VelocityTracker | |
if (mVelocityTracker == null) { | |
mVelocityTracker = VelocityTracker.obtain(); | |
} else { | |
mVelocityTracker.clear(); | |
} | |
// Track the movement | |
mVelocityTracker.addMovement(event); | |
// Invoke the callback | |
if (mCallback != null) { | |
mCallback.onStartTrackingTouch(); | |
} | |
break; | |
case MotionEvent.ACTION_MOVE: | |
// Track the movement and capture the velocity | |
mVelocityTracker.addMovement(event); | |
mVelocityTracker.computeCurrentVelocity(1000); | |
// Calculate the progress and invoke the callback | |
if (mCallback != null) { | |
mProgress = mVelocityTracker.getXVelocity(pointerId); | |
mCallback.onProgressChanged((int) mProgress); | |
} | |
break; | |
case MotionEvent.ACTION_UP: | |
case MotionEvent.ACTION_CANCEL: | |
// Clean up | |
mVelocityTracker.clear(); | |
mProgress = 0; | |
// Invoke the callback | |
if (mCallback != null) { | |
mCallback.onStopTrackingTouch(); | |
} | |
break; | |
default: | |
break; | |
} | |
return true; | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
@Override | |
protected void onDetachedFromWindow() { | |
// Release any resources | |
if (mVelocityTracker != null) { | |
mVelocityTracker.recycle(); | |
mVelocityTracker = null; | |
} | |
mCallback = null; | |
super.onDetachedFromWindow(); | |
} | |
/** | |
* Initializes the progress callback | |
* | |
* @param callback The {@link OnProgressChangeListner} to use | |
*/ | |
public void setOnProgressChangeListner(OnProgressChangeListner callback) { | |
mCallback = callback; | |
} | |
/** | |
* An interface for monitoring the progress of the user's finger across the | |
* <code>ProgressTracker</code> {@link View} | |
*/ | |
public interface OnProgressChangeListner { | |
/** | |
* Indicates that {@link MotionEvent#ACTION_MOVE} has been called and | |
* therefore the attached {@link ViewPager} should call | |
* {@link ViewPager#fakeDragBy(float)} | |
* | |
* @param progress The current progress | |
*/ | |
void onProgressChanged(int progress); | |
/** | |
* Indicates that {@link MotionEvent#ACTION_DOWN} has been called and | |
* therefore the attached {@link ViewPager} should call | |
* {@link ViewPager#beginFakeDrag()} | |
*/ | |
void onStartTrackingTouch(); | |
/** | |
* Indicates that {@link MotionEvent#ACTION_UP} or | |
* {@link MotionEvent#ACTION_CANCEL} has been called and therefore the | |
* attached {@link ViewPager} should call | |
* {@link ViewPager#endFakeDrag()} | |
*/ | |
void onStopTrackingTouch(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Inflate the custom ActionBar layout | |
final LayoutInflater inflater = LayoutInflater.from(this); | |
final View progress = inflater.inflate(R.layout.action_bar, null); | |
((ProgressTracker) progress).setOnProgressChangeListner(new OnProgressChangeListner() { | |
@Override | |
public void onProgressChanged(int progress) { | |
if (pager.isFakeDragging()) { | |
pager.fakeDragBy(progress / 100); | |
} | |
} | |
@Override | |
public void onStartTrackingTouch() { | |
if (!pager.isFakeDragging()) { | |
pager.beginFakeDrag(); | |
} | |
} | |
@Override | |
public void onStopTrackingTouch() { | |
if (pager.isFakeDragging()) { | |
pager.endFakeDrag(); | |
} | |
} | |
}); | |
// Apply the custom view the ActionBar | |
final ActionBar actionBar = getActionBar(); | |
actionBar.setDisplayShowCustomEnabled(true); | |
actionBar.setDisplayShowTitleEnabled(false); | |
final LayoutParams params = new LayoutParams( | |
android.view.ViewGroup.LayoutParams.MATCH_PARENT, | |
android.view.ViewGroup.LayoutParams.MATCH_PARENT); | |
actionBar.setCustomView(progress, params); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment