Android: layout animation like Inshorts news app - android

swipe up and down effect like those news apps inshorts,hike news,murmur.
whole layout smoothly up/down.
check app on this link inshorts and murmur.
i tried this code...
public class VerticalViewPager extends ViewPager {
public VerticalViewPager(Context context) {
super(context);
init();
}
public VerticalViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
// The majority of the magic happens here
setPageTransformer(true, new VerticalPageTransformer());
// The easiest way to get rid of the overscroll drawing that happens on the left and right
setOverScrollMode(OVER_SCROLL_NEVER);
}
private class VerticalPageTransformer implements PageTransformer {
#SuppressLint("NewApi")
#Override
public void transformPage(View view, float position) {
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);
} else if (position <= 1) { // [-1,1]
view.setAlpha(1);
// Counteract the default slide transition
view.setTranslationX(view.getWidth() * -position);
//set Y position to swipe in from top
float yPosition = position * view.getHeight();
view.setTranslationY(yPosition);
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0);
}
}
}
/**
* Swaps the X and Y coordinates of your touch event.
*/
private MotionEvent swapXY(MotionEvent ev) {
float width = getWidth();
float height = getHeight();
float newX = (ev.getY() / height) * width;
float newY = (ev.getX() / width) * height;
ev.setLocation(newX, newY);
return ev;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev){
boolean intercepted = super.onInterceptTouchEvent(swapXY(ev));
swapXY(ev); // return touch coordinates to original reference frame for any child views
return intercepted;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
return super.onTouchEvent(swapXY(ev));
}
}
In MainActivity.java
VerticalViewPager Pager2;
PagerAdapter adapter;
String[] articleTitle;
String[] articleName;
String[] articleDiscription;
OnCreate()
Pager2=(VerticalViewPager)findViewById(R.id.pager);
// Pass results to ViewPagerAdapter Class
adapter = new ViewPagerAdapter(getActivity(), articleTitle, articleName, articleDiscription, btnBack,articleImage);
// Binds the Adapter to the ViewPager
Pager2.setAdapter(adapter);
activity_main.xml
<com.example.flipnews.VerticalViewPager
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/pager"
/>
In my code simple up-down swipe done,like this link.
but i want to create better animation effect like above mentioned apps.
or phone inbuilt photo gallery effect.
Thanks in advance.

I found solution after many research i hope its helpful for others.
Tip: set view pager background color black for better swipe effect.
private static class VerticalPageTransformer implements PageTransformer {
private static float MIN_SCALE = 0.75f;
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);
} else if (position <= 0) { // [-1,0]
// Use the default slide transition when moving to the left page
view.setAlpha(1);
//view.setTranslationX(1);
view.setScaleX(1);
view.setScaleY(1);
float yPosition = position * view.getHeight();
view.setTranslationY(yPosition);
view.setTranslationX(-1 * view.getWidth() * position);
} else if (position <= 1) { // (0,1]
// Fade the page out.
view.setAlpha(1 - position);
view.setTranslationX(-1 * view.getWidth() * position);
// Scale the page down (between MIN_SCALE and 1)
float scaleFactor = MIN_SCALE
+ (1 - MIN_SCALE) * (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0);
}
}
}
private MotionEvent swapXY(MotionEvent ev) {
float width = getWidth();
float height = getHeight();
float newX = (ev.getY() / height) * width;
float newY = (ev.getX() / width) * height;
ev.setLocation(newX, newY);
return ev;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev){
boolean intercepted = super.onInterceptTouchEvent(swapXY(ev));
swapXY(ev); // return touch coordinates to original reference frame for any child views
return intercepted;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
return super.onTouchEvent(swapXY(ev));
}
}

Related

Viewpager is not sliding properly in OnePlus 5T device

I'm in my android app I need a viewpager which slide vertically (up
down manner). For this I have made a custom viewpager & in which I'm
using the traditional viewpager & applied PageTransfirmer to make it
swipe vertically not horizontly. Everything is working fine in other
devices except One Plus 5t (andriod version 9)
My code is below:
public class VerticalViewPager extends ViewPager {
private float initialXValue;
private float initialYValue;
private float minXDifference = 200;
private float minYDifference = 100;
public static SwapListener swapListener;
public static String SwipeLeft = "left";
public static String SwipeRight = "right";
public static boolean swipeTriggered = false;
public static boolean verticalSwipeTriggered = false;
private FixedSpeedScroller mScroller = null;
private boolean enabled;
public VerticalViewPager(Context context) {
super(context);
init();
}
public VerticalViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
// The majority of the magic happens here
setPageTransformer(true, new VerticalPageTransformer());
// The easiest way to get rid of the overscroll drawing that
happens on
the left and right
setOverScrollMode(OVER_SCROLL_NEVER);
try {
Class<?> viewpager = ViewPager.class;
Field scroller = viewpager.getDeclaredField("mScroller");
scroller.setAccessible(true);
mScroller = new FixedSpeedScroller(getContext(),
new DecelerateInterpolator());
scroller.set(this, mScroller);
} catch (Exception ignored) {
}
}
/*
* Set the factor by which the duration will change
*/
public void setScrollDuration(int duration) {
mScroller.setScrollDuration(duration);
}
private class FixedSpeedScroller extends Scroller {
private int mDuration = 1000;
public FixedSpeedScroller(Context context) {super(context);}
public FixedSpeedScroller(Context context, Interpolator interpolator) {
super(context, interpolator);
}
public FixedSpeedScroller(Context context, Interpolator interpolator,
boolean flywheel) {super(context, interpolator, flywheel);}
#Override
public void startScroll(int startX, int startY, int dx, int dy, int
duration) {
// Ignore received duration, use fixed one instead
super.startScroll(startX, startY, dx, dy, mDuration);
}
#Override
public void startScroll(int startX, int startY, int dx, int dy) {
// Ignore received duration, use fixed one instead
super.startScroll(startX, startY, dx, dy, mDuration);
}
public void setScrollDuration(int duration) {mDuration = duration;}
}
private class VerticalPageTransformer implements
ViewPager.PageTransformer {
#Override
public void transformPage(View view, float position) {
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);
}
else if (position <= 1) {
view.setAlpha(1);
// Counteract the default slide transition
view.setTranslationX(view.getWidth() * -position);
//set Y position to swipe in from top
float yPosition = position * view.getHeight();
view.setTranslationY(yPosition);
}
else {
// This page is way off-screen to the right.
view.setAlpha(0);
}
}
}
/**
* Swaps the X and Y coordinates of your touch event.
*/
private MotionEvent swapXY(MotionEvent ev) {
float width = getWidth();
float height = getHeight();
float newX = (ev.getY() / height) * width;
float newY = (ev.getX() / width) * height;
ev.setLocation(newX, newY);
return ev;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev){
boolean intercepted = super.onInterceptTouchEvent(swapXY(ev));
swapXY(ev); // return touch coordinates to original reference frame
for any child views
//IsSwipeAllowed(ev);
return intercepted;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
IsSwipeAllowed(ev);
return super.onTouchEvent(swapXY(ev));
}
private void IsSwipeAllowed(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN) {
initialXValue = event.getX();
initialYValue = event.getY();
}
if(event.getAction()==MotionEvent.ACTION_MOVE) {
try {
float diffX = Math.abs(event.getX() - initialXValue);
float diffy = Math.abs(event.getY() - initialYValue);
if (diffX > diffy && diffX > minXDifference) {
// swipe horizotal
if (!swipeTriggered && event.getX() > initialXValue) {
swapListener.listenSwapEvent(SwipeRight);
swipeTriggered = true;
}
else if (event.getX() < initialXValue) {
if (!HomeScreen.projectName.equals("ABMCPL") &&
CustomViewPager.IsSwipeAllowed(event) && !swipeTriggered) {
swapListener.listenSwapEvent(SwipeLeft); // to webview page
swipeTriggered = true;
}
}
}
else if (diffX < diffy && diffy > minYDifference) {
if (!verticalSwipeTriggered && event.getY() > initialYValue) {
viewPager.setCurrentItem(LandingPage.viewPager.getCurrentItem() - 1);
verticalSwipeTriggered = true;
}
else if (!verticalSwipeTriggered && event.getY() < initialYValue){
verticalSwipeTriggered = true;
}
}
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
public interface SwapListener {
void listenSwapEvent (String direction);
}
}

how to make vertical animation like feedly android app

i am using vertical viewpager but it is not smooth like feedly android app.I dont know what component is used by feedly.
Any help will be appreciated.
public class VerticalViewPager extends ViewPager {
public VerticalViewPager(Context context) {
super(context);
init();
}
public VerticalViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
// The majority of the magic happens here
setPageTransformer(true, new VerticalPageTransformer());
// The easiest way to get rid of the overscroll drawing that happens on the left and right
setOverScrollMode(OVER_SCROLL_NEVER);
}
private class VerticalPageTransformer implements ViewPager.PageTransformer {
private static final float MIN_SCALE = .75f;
#Override
public void transformPage(View view, float position) {
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);
} else if (position <= 0) { // [-1,0]
// Use the default slide transition when moving to the left page
view.setAlpha(1);
// Counteract the default slide transition
view.setTranslationX(view.getWidth() * -position);
//set Y position to swipe in from top
float yPosition = position * view.getHeight();
view.setTranslationY(yPosition);
view.setScaleX(1);
view.setScaleY(1);
} else if (position <= 1) { // [0,1]
view.setAlpha(1);
// Counteract the default slide transition
view.setTranslationX(view.getWidth() * -position);
// Scale the page down (between MIN_SCALE and 1)
float scaleFactor = MIN_SCALE
+ (1 - MIN_SCALE) * (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0);
}
}
}
/*private class VerticalPageTransformer implements ViewPager.PageTransformer {
#Override
public void transformPage(View view, float position) {
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);
} else if (position <= 1) { // [-1,1]
view.setAlpha(1);
// Counteract the default slide transition
view.setTranslationX(view.getWidth() * -position);
//set Y position to swipe in from top
float yPosition = position * view.getHeight();
view.setTranslationY(yPosition);
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0);
}
}
}*/
/**
* Swaps the X and Y coordinates of your touch event.
*/
private MotionEvent swapXY(MotionEvent ev) {
float width = getWidth();
float height = getHeight();
float newX = (ev.getY() / height) * width;
float newY = (ev.getX() / width) * height;
ev.setLocation(newX, newY);
return ev;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev){
boolean intercepted = super.onInterceptTouchEvent(swapXY(ev));
swapXY(ev); // return touch coordinates to original reference frame for any child views
return intercepted;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
//return super.onTouchEvent(swapXY(ev));
final boolean toHandle = super.onTouchEvent(swapXY(ev));
// Return MotionEvent to normal
swapXY(ev);
return toHandle;
}
#Override
public boolean canScrollVertically(int direction) {
return true;
}
#Override
public boolean canScrollHorizontally(int direction) {
return false;
}
}
I think you have to go with this link , i think in your xml two scroll function is calling and that's why it gives issue .
https://stackoverflow.com/questions/14326317/view-pager-not-smooth-when-embedded-within-scrollview

How to scroll back to vertical Viewpager while having a Horizontal Viewpager as its child?

i have a vertical viewpager with Fragment A, and Fragment B. Fragment B has a horizontal viewpager with 3 pages, but there i have a problem: when i am at page 2 or 3 inside Fragment B, i can't scroll vertically to return to fragment A, i can do it only from page 1. i don't know where the problem is, as the 3 pages are almost the same.
Here's my VerticalPager code:
public class VerticalPager extends ViewPager {
public VerticalPager(Context context) {
super(context);
init();
}
public VerticalPager(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
// The majority of the magic happens here
setPageTransformer(true, new VerticalPageTransformer());
// The easiest way to get rid of the overscroll drawing that happens on the left and right
setOverScrollMode(OVER_SCROLL_NEVER);
}
private class VerticalPageTransformer implements ViewPager.PageTransformer {
#Override
public void transformPage(View view, float position) {
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);
} else if (position <= 1) { // [-1,1]
view.setAlpha(1);
// Counteract the default slide transition
view.setTranslationX(view.getWidth() * -position);
//set Y position to swipe in from top
float yPosition = position * view.getHeight();
view.setTranslationY(yPosition);
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0);
}
}
}
/**
* Swaps the X and Y coordinates of your touch event.
*/
private MotionEvent swapXY(MotionEvent ev) {
float width = getWidth();
float height = getHeight();
float newX = (ev.getY() / height) * width;
float newY = (ev.getX() / width) * height;
ev.setLocation(newX, newY);
return ev;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev){
boolean intercepted = super.onInterceptTouchEvent(swapXY(ev));
swapXY(ev); // return touch coordinates to original reference frame for any child views
return intercepted;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
return super.onTouchEvent(swapXY(ev));
}
}

How to smoothen the swiping in viewpager

In my application I'm using view pager for vertical scroll for swiping the pages. Vertical scrolling working fine. An issues is While swiping the pages,it is not swiping smoothly , it is stucking while swiping.Can Anyone give me solution for my issue. Thanks in advance.
public class VerticalViewPager extends ViewPager {
public VerticalViewPager(Context context) {
super(context);
init();
}
public VerticalViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
// The majority of the magic happens here
setPageTransformer(true, new VerticalPageTransformer());
// The easiest way to get rid of the overscroll drawing that happens on the left and right
setOverScrollMode(OVER_SCROLL_NEVER);
}
private static class VerticalPageTransformer implements PageTransformer {
private static float MIN_SCALE = 0.95f;
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);
} else if (position <= 0) { // [-1,0]
view.setAlpha(1);
//view.setTranslationX(1);
view.setScaleX(1);
view.setScaleY(1);
float yPosition = position * view.getHeight();
view.setTranslationY(yPosition);
view.setTranslationX(-1 * view.getWidth() * position);
} else if (position <= 1) { // (0,1]
// Fade the page out.
view.setAlpha(1 - position);
view.setTranslationX(-1 * view.getWidth() * position);
// Scale the page down (between MIN_SCALE and 1)
float scaleFactor = MIN_SCALE
+ (1 - MIN_SCALE) * (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
} else {
view.setAlpha(0);
}
}
}
private MotionEvent swapXY(MotionEvent ev) {
float width = getWidth();
float height = getHeight();
float newX = (ev.getY() / height) * width;
float newY = (ev.getX() / width) * height;
ev.setLocation(newX, newY);
return ev;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev){
boolean intercepted = super.onInterceptTouchEvent(swapXY(ev));
swapXY(ev);
return intercepted;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
return super.onTouchEvent(swapXY(ev));
}
}

How to make a View height bigger than screen in a Custom Layout class (for sliding up panel purpose)

SOLVED
In order to solve my problem I just had to programatically set my custom view height in the onFinishInflate(). The code snippet belows solved the problem:
/**
* Inflates the two views being animated
*/
#Override
protected void onFinishInflate() {
Display display = ((Activity) mContext).getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
mView = findViewById(R.id.viewHeader);
mView.setLayoutParams(new LayoutParams(width, height));
mDraggableView = findViewById(R.id.mpc_current_track_album_art);
mExtendedPlayer = findViewById(R.id.emp_inner_wrapper);
mPlaylist = (ListView)findViewById(R.id.emp_playlist);
}
I'm using this tutorial to implement a Sliding Up panel behaviour: FLAVIEN LAURENT. I'm not using any of the existing libraries 'cause I want two specific features:
The bottom from the view that I'll pull up is a MP Control Panel and the play button is a FAB. I need to make the top of the layout transparent, so only the FAB will appear;
When I pull up the Control Panel, I want to hide it behind the screen's top margin;
My problem is: as I slide it up beyound the screen top's border, the exact size of the panel is left transparent at the bottom of the View expanded. How can I make it goes until the end of the screen?
http://postimg.org/image/oegwuj32b/
Here is the problem! Transparent part that shows the bottom view after sliding up the panel
My Custom Layout class is like that:
package br.com.materialdesigntest.commons.util.layouts;
import android.content.Context;
import android.support.v4.view.MotionEventCompat;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RelativeLayout;
import br.com.materialdesigntest.R;
import br.com.materialdesigntest.commons.util.ImageFileUtil;
public class DraggableViewGroup extends RelativeLayout {
private Integer CONTROL_PANEL_SIZE;
private final ViewDragHelper mDragHelper;
private View mView;
private View mDraggableView;
private View mExtendedPlayer;
private View mPlayButton;
private View mExtendedPlayerHolder;
private float mInitialMotionX;
private float mInitialMotionY;
private int mDragRange;
private int mTop;
private float mDragOffset;
private Context mContext;
private Boolean started = Boolean.FALSE;
// CONSTRUCTORS_________________________________________________________________________________
public DraggableViewGroup(Context context) {
this(context, null);
mContext = context;
}
public DraggableViewGroup(Context context, AttributeSet attrs) {
this(context, attrs, 0);
mContext = context;
}
public DraggableViewGroup(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
CONTROL_PANEL_SIZE = (int) ImageFileUtil.convertDpToPixel(97, context);
mDragHelper = ViewDragHelper.create(this, 1f, new DragHelperCallback());
mContext = context;
}
// CALLBACKS____________________________________________________________________________________
/**
* Inflates the two views being animated
*/
#Override
protected void onFinishInflate() {
mView = findViewById(R.id.viewHeader);
mDraggableView = findViewById(R.id.current_cover_art);
mExtendedPlayer = findViewById(R.id.ep_extended_player);
mPlayButton = findViewById(R.id.options_fab_button);
}
/**
* Called by a parent to request that a child update its values for mScrollX and mScrollY if necessary.
*/
#Override
public void computeScroll() {
// Move the captured settling view by the appropriate amount for the current time.
// If continueSettling returns true, the caller should call it again on the next frame to continue.
// true if state callbacks should be deferred via posted message. Set this to true if you are
// calling this method from computeScroll() or similar methods invoked as part of layout or drawing.
if (mDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(this);
}
}
/**
* If a vertical movement happened or if headerView was touched, intercepts the event, passing it
* to onTouchEvent method
*
* #param ev
* #return
*/
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
final int action = MotionEventCompat.getActionMasked(ev);
// First user touch, ViewGroups doesn't care for that
if ((action != MotionEvent.ACTION_DOWN)) {
mDragHelper.cancel();
return super.onInterceptTouchEvent(ev);
}
// User leaving the screen
if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
mDragHelper.cancel();
return false;
}
final float x = ev.getX();
final float y = ev.getY();
boolean interceptTap = false;
switch (action) {
case MotionEvent.ACTION_DOWN: {
mInitialMotionX = x;
mInitialMotionY = y;
// Determine if the supplied view is under the given point in the parent view's coordinate system.
interceptTap = mDragHelper.isViewUnder(mDraggableView, (int) x, (int) y)
|| mDragHelper.isViewUnder(mExtendedPlayer, (int) x, (int) y);
break;
}
case MotionEvent.ACTION_MOVE: {
final float adx = Math.abs(x - mInitialMotionX);
final float ady = Math.abs(y - mInitialMotionY);
// Threshold that determines if a gesture happened
final int slop = mDragHelper.getTouchSlop();
// A movement has happened in the X position: don't care for it
if (ady > slop && adx > ady) {
mDragHelper.cancel();
return false;
}
}
}
Boolean answer = mDragHelper.shouldInterceptTouchEvent(ev) || interceptTap;
if (!mDragHelper.isViewUnder(mPlayButton, (int) x, (int) y)) {
answer = Boolean.FALSE;
}
// Returns the decision to intercept or not the event. As implemented, it should intercept only
// id headerView was touched or a vertical movement has happened
return answer;
}
/**
* Records the initial points where the movement started. Checks if the movements triggers the
* threashold. IF YES AND HEADERVIEW IS BEING HIT THEN CHECKS MOVEMENT IS DIFERENT OF TAPPING THEN
* MAXIMIZES DESCVIEW, OTHERWISE MINIMIZES IT
*
* #param ev
* #return
*/
#Override
public boolean onTouchEvent(MotionEvent ev) {
// Process a touch event received by the parent view. This method will dispatch callback
// events as needed before returning. The parent view's onTouchEvent implementation should call this.
mDragHelper.processTouchEvent(ev);
final int action = ev.getAction();
final float x = ev.getX();
final float y = ev.getY();
switch (action & MotionEventCompat.ACTION_MASK) {
// Gets the point where the movement started from (user first touched the screen)
case MotionEvent.ACTION_DOWN: {
mInitialMotionX = x;
mInitialMotionY = y;
break;
}
// When user leaves the screens, checks if it was a tap or movement. If the first has happened
// then maximizes the descView, otherwise minimize it
case MotionEvent.ACTION_UP: {
final float dx = x - mInitialMotionX;
final float dy = y - mInitialMotionY;
final int slop = mDragHelper.getTouchSlop();
// uses points distance mathematics formula to determinar if the movement triggers the
// threshold. IF NOT (it means it was just a tap), minimizes it, otherwise maximize it
if (dx * dx + dy * dy < slop * slop) {
if (mDragOffset == 0) {
minimize();
} else {
maximize();
}
}
break;
}
}
Boolean answer = isViewHit(mDraggableView, (int) x, (int) y)
|| isViewHit(mExtendedPlayer, (int) x, (int) y);
// Decides to continue receiving the events if headerView is under user finger and headerView or descView where hit by a gesture
return answer;
}
/**
* Measure the view and its content to determine the measured width and the measured height.
*
* #param widthMeasureSpec
* #param heightMeasureSpec
*/
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
measureChildren(widthMeasureSpec, heightMeasureSpec);
int maxWidth = MeasureSpec.getSize(widthMeasureSpec);
int maxHeight = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, 0),
resolveSizeAndState(maxHeight, heightMeasureSpec, 0));
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
mDragRange = getHeight() - CONTROL_PANEL_SIZE;
if (!started) {
started = Boolean.TRUE;
mTop = getHeight() - CONTROL_PANEL_SIZE;
}
System.out.println("b == " + b);
mView.layout(
l,
mTop,
r,
b);
}
// UTIL METHOODS________________________________________________________________________________
public void maximize() {
final int topBound = getPaddingTop() - CONTROL_PANEL_SIZE;
int y = (int) (topBound);
// Animate the given view to the given left and top
if (mDragHelper.smoothSlideViewTo(mView, mView.getLeft(), y)) {
ViewCompat.postInvalidateOnAnimation(this);
}
}
public void minimize() {
final int topBound = getPaddingTop();
int y = (int) (topBound + 1 * mDragRange);
// Animate the given view to the given left and top
if (mDragHelper.smoothSlideViewTo(mView, mView.getLeft(), y)) {
ViewCompat.postInvalidateOnAnimation(this);
}
}
/**
* Checks if the given view was subject of a tapping gesture
*
* #param view
* #param x
* #param y
* #return
*/
private boolean isViewHit(View view, int x, int y) {
int[] viewLocation = new int[2];
view.getLocationOnScreen(viewLocation);
int[] parentLocation = new int[2];
this.getLocationOnScreen(parentLocation);
int screenX = parentLocation[0] + x;
int screenY = parentLocation[1] + y;
return screenX >= viewLocation[0] && screenX < viewLocation[0] + view.getWidth() &&
screenY >= viewLocation[1] && screenY < viewLocation[1] + view.getHeight();
}
// NESTED CLASSES/INTERFACES____________________________________________________________________
private class DragHelperCallback extends ViewDragHelper.Callback {
/**
* Sets which view will be draggable
*
* #param child
* #param pointerId
* #return
*/
#Override
public boolean tryCaptureView(View child, int pointerId) {
return child == mView;
}
/**
* Listener that watches for headerView positions changes, dimmes the descView based on
* headerView top position
*
* #param changedView
* #param left
* #param top
* #param dx
* #param dy
*/
#Override
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
mTop = top;
mDragOffset = (float) top / mDragRange;
requestLayout();
}
/**
* Returns the range that a child view can move (up or down)
* In this class, it will return the Y range possible to move inside the whole layout
* that wrappers the two present views
*
* #param child
* #return
*/
#Override
public int getViewVerticalDragRange(View child) {
return mDragRange;
}
/**
* When user releases the finger from headerView. If he left the screen below half of it
* this method tells the app to minimize descView, otherwise maximize it
*
* #param releasedChild
* #param xvel
* #param yvel
*/
#Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
if (yvel < 0) {
maximize();
} else {
minimize();
}
}
/**
* Determines the vertical bounds to which the views will be allowed to move
*
* #param child
* #param top
* #param dy
* #return
*/
#Override
public int clampViewPositionVertical(View child, int top, int dy) {
final int topBound = getPaddingTop() - CONTROL_PANEL_SIZE;
final int bottomBound = getHeight() - mView.getPaddingBottom();
final int newTop = Math.min(Math.max(top, topBound), bottomBound);
return newTop;
}
#Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
final int leftBound = getPaddingLeft();
final int rightBound = getWidth() - mView.getWidth();
final int newLeft = Math.min(Math.max(left, leftBound), rightBound);
return newLeft;
}
}
}

Categories

Resources