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
Related
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);
}
}
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));
}
}
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));
}
}
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));
}
}
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;
}
}
}