From 95e9ddf95ae4e465c905f4ab7926d8e7f44e7b82 Mon Sep 17 00:00:00 2001 From: Yarh Date: Tue, 22 Sep 2015 12:16:51 +0300 Subject: [PATCH 1/4] fix minimised view position on orientation change --- .../com/github/pedrovgs/DraggableView.java | 1594 +++++++++-------- sample/AndroidManifest.xml | 111 +- .../sample/activity/DIFragmentActivity.java | 7 + .../sample/activity/MainActivity.java | 7 + .../sample/activity/TvShowsActivity.java | 129 +- .../sample/activity/VideoSampleActivity.java | 53 +- .../activity/YoutubeSampleActivity.java | 277 +-- 7 files changed, 1192 insertions(+), 986 deletions(-) diff --git a/draggablepanel/src/main/java/com/github/pedrovgs/DraggableView.java b/draggablepanel/src/main/java/com/github/pedrovgs/DraggableView.java index 5895a14..e4b1e47 100644 --- a/draggablepanel/src/main/java/com/github/pedrovgs/DraggableView.java +++ b/draggablepanel/src/main/java/com/github/pedrovgs/DraggableView.java @@ -24,9 +24,11 @@ import android.support.v4.view.ViewCompat; import android.support.v4.widget.ViewDragHelper; import android.util.AttributeSet; +import android.util.DisplayMetrics; import android.view.MotionEvent; import android.view.View; import android.widget.RelativeLayout; + import com.github.pedrovgs.transformer.Transformer; import com.github.pedrovgs.transformer.TransformerFactory; import com.nineoldandroids.view.ViewHelper; @@ -36,748 +38,852 @@ * * @author Pedro Vicente Gómez Sánchez */ -public class DraggableView extends RelativeLayout { - - private static final int DEFAULT_SCALE_FACTOR = 2; - private static final int DEFAULT_TOP_VIEW_MARGIN = 30; - private static final int DEFAULT_TOP_VIEW_HEIGHT = -1; - private static final float SLIDE_TOP = 0f; - private static final float SLIDE_BOTTOM = 1f; - private static final float MIN_SLIDE_OFFSET = 0.1f; - private static final boolean DEFAULT_ENABLE_HORIZONTAL_ALPHA_EFFECT = true; - private static final boolean DEFAULT_ENABLE_CLICK_TO_MAXIMIZE = false; - private static final boolean DEFAULT_ENABLE_CLICK_TO_MINIMIZE = false; - private static final boolean DEFAULT_ENABLE_TOUCH_LISTENER = true; - private static final int MIN_SLIDING_DISTANCE_ON_CLICK = 10; - private static final int ONE_HUNDRED = 100; - private static final float SENSITIVITY = 1f; - private static final boolean DEFAULT_TOP_VIEW_RESIZE = false; - private static final int INVALID_POINTER = -1; - - private int activePointerId = INVALID_POINTER; - private float lastTouchActionDownXPosition; - - private View dragView; - private View secondView; - private TypedArray attributes; - - private FragmentManager fragmentManager; - private ViewDragHelper viewDragHelper; - private Transformer transformer; - - private boolean enableHorizontalAlphaEffect; - private boolean topViewResize; - private boolean enableClickToMaximize; - private boolean enableClickToMinimize; - private boolean touchEnabled; - - private DraggableListener listener; - - public DraggableView(Context context) { - super(context); - } - - public DraggableView(Context context, AttributeSet attrs) { - super(context, attrs); - initializeAttributes(attrs); - } - - public DraggableView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - initializeAttributes(attrs); - } - - /** - * Return if user can maximize minimized view on click. - */ - public boolean isClickToMaximizeEnabled() { - return enableClickToMaximize; - } - - /** - * Enable or disable click to maximize view when dragged view is minimized - * If your content have a touch/click listener (like YoutubePlayer), you - * need disable it to active this feature. - * - * @param enableClickToMaximize to enable or disable the click. - */ - public void setClickToMaximizeEnabled(boolean enableClickToMaximize) { - this.enableClickToMaximize = enableClickToMaximize; - } - - /** - * Return if user can minimize maximized view on click. - */ - public boolean isClickToMinimizeEnabled() { - return enableClickToMinimize; - } - - /** - * Enable or disable click to minimize view when dragged view is maximized - * If your content have a touch/click listener (like YoutubePlayer), you - * need disable it to active this feature. - * - * @param enableClickToMinimize to enable or disable the click. - */ - public void setClickToMinimizeEnabled(boolean enableClickToMinimize) { - this.enableClickToMinimize = enableClickToMinimize; - } - - /** - * Return if touch listener is enable or disable - */ - private boolean isTouchEnabled() { - return this.touchEnabled; - } - - /** - * Enable or disable the touch listener - * - * @param touchEnabled to enable or disable the touch event. - */ - public void setTouchEnabled(boolean touchEnabled) { - this.touchEnabled = touchEnabled; - } - - /** - * Slide the view based on scroll of the nav drawer. - * "setEnableTouch" user prevents click to expand while the drawer is moving, it will be - * set to false when the @slideOffset is bigger than MIN_SLIDE_OFFSET. - * When the slideOffset is bigger than 0.1 and dragView isn't close, set the dragView - * to minimized. - * It's only possible to maximize the view when @slideOffset is equals to 0.0, - * in other words, closed. - * - * @param slideOffset Value between 0 and 1, represent the value of slide: - * 0.0 is equal to close drawer and 1.0 equals open drawer. - * @param drawerPosition Represent the position of nav drawer on X axis. - * @param width Width of nav drawer - */ - public void slideHorizontally(float slideOffset, float drawerPosition, int width) { - if (slideOffset > MIN_SLIDE_OFFSET && !isClosed() && isMaximized()) { - minimize(); - } - setTouchEnabled(slideOffset <= MIN_SLIDE_OFFSET); - ViewHelper.setX(this, width - Math.abs(drawerPosition)); - } - - /** - * Configure the horizontal scale factor applied when the view is dragged to the bottom of the - * custom view. - */ - public void setXTopViewScaleFactor(float xScaleFactor) { - transformer.setXScaleFactor(xScaleFactor); - } - - /** - * Configure the vertical scale factor applied when the view is dragged to the bottom of the - * custom view. - */ - public void setYTopViewScaleFactor(float yScaleFactor) { - transformer.setYScaleFactor(yScaleFactor); - } - - /** - * Configure the dragged view margin right applied when the dragged view is minimized. - * - * @param topFragmentMarginRight in pixels. - */ - public void setTopViewMarginRight(int topFragmentMarginRight) { - transformer.setMarginRight(topFragmentMarginRight); - } - - /** - * Configure the dragView margin bottom applied when the dragView is minimized. - */ - public void setTopViewMarginBottom(int topFragmentMarginBottom) { - transformer.setMarginBottom(topFragmentMarginBottom); - } - - /** - * Configure the dragged view height. - * - * @param topFragmentHeight in pixels - */ - public void setTopViewHeight(int topFragmentHeight) { - transformer.setViewHeight(topFragmentHeight); - } - - /** - * Configure the disabling of the alpha effect applied when the dragView is dragged horizontally. - */ - public void setHorizontalAlphaEffectEnabled(boolean enableHorizontalAlphaEffect) { - this.enableHorizontalAlphaEffect = enableHorizontalAlphaEffect; - } - - /** - * Configure the DraggableListener notified when the view is minimized, maximized, closed to the - * right or closed to the left. - */ - public void setDraggableListener(DraggableListener listener) { - this.listener = listener; - } - - /** - * Configure DraggableView to resize top view instead of scale it. - */ - public void setTopViewResize(boolean topViewResize) { - this.topViewResize = topViewResize; - } - - /** - * To ensure the animation is going to work this method has been override to call - * postInvalidateOnAnimation if the view is not settled yet. - */ - @Override public void computeScroll() { - if (!isInEditMode() && viewDragHelper.continueSettling(true)) { - ViewCompat.postInvalidateOnAnimation(this); - } - } - - /** - * Maximize the custom view applying an animation to return the view to the initial position. - */ - public void maximize() { - smoothSlideTo(SLIDE_TOP); - notifyMaximizeToListener(); - } - - /** - * Minimize the custom view applying an animation to put the top fragment on the bottom right - * corner of the screen. - */ - public void minimize() { - smoothSlideTo(SLIDE_BOTTOM); - notifyMinimizeToListener(); - } - - /** - * Close the custom view applying an animation to close the view to the right side of the screen. - */ - public void closeToRight() { - if (viewDragHelper.smoothSlideViewTo(dragView, transformer.getOriginalWidth(), - getHeight() - transformer.getMinHeightPlusMargin())) { - ViewCompat.postInvalidateOnAnimation(this); - notifyCloseToRightListener(); - } - } - - /** - * Close the custom view applying an animation to close the view to the left side of the screen. - */ - public void closeToLeft() { - if (viewDragHelper.smoothSlideViewTo(dragView, -transformer.getOriginalWidth(), - getHeight() - transformer.getMinHeightPlusMargin())) { - ViewCompat.postInvalidateOnAnimation(this); - notifyCloseToLeftListener(); - } - } - - /** - * Checks if the top view is minimized. - * - * @return true if the view is minimized. - */ - public boolean isMinimized() { - return isDragViewAtBottom() && isDragViewAtRight(); - } - - /** - * Checks if the top view is maximized. - * - * @return true if the view is maximized. - */ - public boolean isMaximized() { - return isDragViewAtTop(); - } - - /** - * Checks if the top view closed at the right place. - * - * @return true if the view is closed at right. - */ - public boolean isClosedAtRight() { - return dragView.getLeft() >= getWidth(); - } - - /** - * Checks if the top view is closed at the left place. - * - * @return true if the view is closed at left. - */ - public boolean isClosedAtLeft() { - return dragView.getRight() <= 0; - } - - /** - * Checks if the top view is closed at the right or left place. - * - * @return true if the view is closed. - */ - public boolean isClosed() { - return isClosedAtLeft() || isClosedAtRight(); - } - - /** - * Override method to intercept only touch events over the drag view and to cancel the drag when - * the action associated to the MotionEvent is equals to ACTION_CANCEL or ACTION_UP. - * - * @param ev captured. - * @return true if the view is going to process the touch event or false if not. - */ - @Override public boolean onInterceptTouchEvent(MotionEvent ev) { - if (!isEnabled()) { - return false; - } - switch (MotionEventCompat.getActionMasked(ev) & MotionEventCompat.ACTION_MASK) { - case MotionEvent.ACTION_CANCEL: - case MotionEvent.ACTION_UP: - viewDragHelper.cancel(); - return false; - case MotionEvent.ACTION_DOWN: - int index = MotionEventCompat.getActionIndex(ev); - activePointerId = MotionEventCompat.getPointerId(ev, index); - if (activePointerId == INVALID_POINTER) { - return false; - } - break; - default: - break; - } - boolean interceptTap = viewDragHelper.isViewUnder(dragView, (int) ev.getX(), (int) ev.getY()); - return viewDragHelper.shouldInterceptTouchEvent(ev) || interceptTap; - } - - /** - * Override method to dispatch touch event to the dragged view. - * - * @param ev captured. - * @return true if the touch event is realized over the drag or second view. - */ - @Override public boolean onTouchEvent(MotionEvent ev) { - int actionMasked = MotionEventCompat.getActionMasked(ev); - if ((actionMasked & MotionEventCompat.ACTION_MASK) == MotionEvent.ACTION_DOWN) { - activePointerId = MotionEventCompat.getPointerId(ev, actionMasked); - } - if (activePointerId == INVALID_POINTER) { - return false; - } - viewDragHelper.processTouchEvent(ev); - if (isClosed()) { - return false; - } - boolean isDragViewHit = isViewHit(dragView, (int) ev.getX(), (int) ev.getY()); - boolean isSecondViewHit = isViewHit(secondView, (int) ev.getX(), (int) ev.getY()); - analyzeTouchToMaximizeIfNeeded(ev, isDragViewHit); - if (isMaximized()) { - dragView.dispatchTouchEvent(ev); - } else { - dragView.dispatchTouchEvent(cloneMotionEventWithAction(ev, MotionEvent.ACTION_CANCEL)); - } - return isDragViewHit || isSecondViewHit; - } - - private void analyzeTouchToMaximizeIfNeeded(MotionEvent ev, boolean isDragViewHit) { - switch(ev.getAction()) { - case MotionEvent.ACTION_DOWN: - lastTouchActionDownXPosition = ev.getX(); - break; - case MotionEvent.ACTION_UP: - float clickOffset = ev.getX() - lastTouchActionDownXPosition; - if (shouldMaximizeOnClick(ev, clickOffset, isDragViewHit)) { - if (isMinimized() && isClickToMaximizeEnabled()) { - maximize(); - } else if (isMaximized() && isClickToMinimizeEnabled()) { - minimize(); - } - } - break; - default: - break; - } - } - - public boolean shouldMaximizeOnClick(MotionEvent ev, float deltaX, boolean isDragViewHit) { - return (Math.abs(deltaX) < MIN_SLIDING_DISTANCE_ON_CLICK) - && ev.getAction() != MotionEvent.ACTION_MOVE - && isDragViewHit; - } - - /** - * Clone given motion event and set specified action. This method is useful, when we want to - * cancel event propagation in child views by sending event with {@link - * android.view.MotionEvent#ACTION_CANCEL} - * action. - * - * @param event event to clone - * @param action new action - * @return cloned motion event - */ - private MotionEvent cloneMotionEventWithAction(MotionEvent event, int action) { - return MotionEvent.obtain(event.getDownTime(), event.getEventTime(), action, event.getX(), - event.getY(), event.getMetaState()); - } - - /** - * Override method to configure the dragged view and secondView layout properly. - */ - @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - if (isInEditMode()) - super.onLayout(changed, left, top, right, bottom); - else if (isDragViewAtTop()) { - dragView.layout(left, top, right, transformer.getOriginalHeight()); - secondView.layout(left, transformer.getOriginalHeight(), right, bottom); - ViewHelper.setY(dragView, top); - ViewHelper.setY(secondView, transformer.getOriginalHeight()); - } else { - secondView.layout(left, transformer.getOriginalHeight(), right, bottom); - } - } - - /** - * Override method to map dragged view, secondView to view objects, to configure dragged - * view height and to initialize DragViewHelper. - */ - @Override protected void onFinishInflate() { - super.onFinishInflate(); - if (!isInEditMode()) { - mapGUI(attributes); - initializeTransformer(attributes); - attributes.recycle(); - initializeViewDragHelper(); - } - } - - private void mapGUI(TypedArray attributes) { - int dragViewId = - attributes.getResourceId(R.styleable.draggable_view_top_view_id, R.id.drag_view); - int secondViewId = - attributes.getResourceId(R.styleable.draggable_view_bottom_view_id, R.id.second_view); - dragView = findViewById(dragViewId); - secondView = findViewById(secondViewId); - } - - /** - * Configure the FragmentManager used to attach top and bottom Fragments to the view. The - * FragmentManager is going to be provided only by DraggablePanel view. - */ - void setFragmentManager(FragmentManager fragmentManager) { - this.fragmentManager = fragmentManager; - } - - /** - * Attach one fragment to the dragged view. - * - * @param topFragment to be attached. - */ - void attachTopFragment(Fragment topFragment) { - addFragmentToView(R.id.drag_view, topFragment); - } - - /** - * Attach one fragment to the secondView. - * - * @param bottomFragment to be attached. - */ - void attachBottomFragment(Fragment bottomFragment) { - addFragmentToView(R.id.second_view, bottomFragment); - } - - /** - * Modify dragged view pivot based on the dragged view vertical position to simulate a horizontal - * displacement while the view is dragged. - */ - void changeDragViewPosition() { - transformer.updatePosition(getVerticalDragOffset()); - } - - /** - * Modify secondView position to be always below dragged view. - */ - void changeSecondViewPosition() { - ViewHelper.setY(secondView, dragView.getBottom()); - } - - /** - * Modify dragged view scale based on the dragged view vertical position and the scale factor. - */ - void changeDragViewScale() { - transformer.updateScale(getVerticalDragOffset()); - } - - /** - * Modify the background alpha if has been configured to applying an alpha effect when the view - * is dragged. - */ - void changeBackgroundAlpha() { - Drawable background = getBackground(); - if (background != null) { - int newAlpha = (int) (ONE_HUNDRED * (1 - getVerticalDragOffset())); - background.setAlpha(newAlpha); - } - } - - /** - * Modify the second view alpha based on dragged view vertical position. - */ - void changeSecondViewAlpha() { - ViewHelper.setAlpha(secondView, 1 - getVerticalDragOffset()); - } - - /** - * Modify dragged view alpha based on the horizontal position while the view is being - * horizontally dragged. - */ - void changeDragViewViewAlpha() { - if (enableHorizontalAlphaEffect) { - float alpha = 1 - getHorizontalDragOffset(); - if (alpha == 0) { - alpha = 1; - } - ViewHelper.setAlpha(dragView, alpha); - } - } - - /** - * Restore view alpha to 1 - */ - void restoreAlpha() { - if (enableHorizontalAlphaEffect && ViewHelper.getAlpha(dragView) < 1) { - ViewHelper.setAlpha(dragView, 1); - } - } - - /** - * Check if dragged view is above the middle of the custom view. - * - * @return true if dragged view is above the middle of the custom view or false if is below. - */ - boolean isDragViewAboveTheMiddle() { - return transformer.isAboveTheMiddle(); - } - - /** - * Check if dragged view is next to the left bound. - * - * @return true if dragged view right position is behind the right half of the custom view. - */ - boolean isNextToLeftBound() { - return transformer.isNextToLeftBound(); - } - - /** - * Check if dragged view is next to the right bound. - * - * @return true if dragged view left position is behind the left quarter of the custom view. - */ - boolean isNextToRightBound() { - return transformer.isNextToRightBound(); - } - - /** - * Check if dragged view is at the top of the custom view. - * - * @return true if dragged view top position is equals to zero. - */ - boolean isDragViewAtTop() { - return transformer.isViewAtTop(); - } - - /** - * Check if dragged view is at the right of the custom view. - * - * @return true if dragged view right position is equals to custom view width. - */ - boolean isDragViewAtRight() { - return transformer.isViewAtRight(); - } - - /** - * Check if dragged view is at the bottom of the custom view. - * - * @return true if dragged view bottom position is equals to custom view height. - */ - boolean isDragViewAtBottom() { - return transformer.isViewAtBottom(); - } - - /** - * Calculate if one position is above any view. - * - * @param view to analyze. - * @param x position. - * @param y position. - * @return true if x and y positions are below the view. - */ - 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(); - } - - /** - * Use FragmentManager to attach one fragment to one view using the viewId. - * - * @param viewId used to obtain the view. - * @param fragment to be attached. - */ - private void addFragmentToView(final int viewId, final Fragment fragment) { - fragmentManager.beginTransaction().replace(viewId, fragment).commit(); - } - - /** - * Initialize the viewDragHelper. - */ - private void initializeViewDragHelper() { - viewDragHelper = ViewDragHelper.create(this, SENSITIVITY, new DraggableViewCallback(this, dragView)); - } - - /** - * Initialize Transformer with a scalable or change width/height implementation. - */ - private void initializeTransformer(TypedArray attributes) { - topViewResize = - attributes.getBoolean(R.styleable.draggable_view_top_view_resize, DEFAULT_TOP_VIEW_RESIZE); - TransformerFactory transformerFactory = new TransformerFactory(); - transformer = transformerFactory.getTransformer(topViewResize, dragView, this); - transformer.setViewHeight(attributes.getDimensionPixelSize(R.styleable.draggable_view_top_view_height, - DEFAULT_TOP_VIEW_HEIGHT)); - transformer.setXScaleFactor( - attributes.getFloat(R.styleable.draggable_view_top_view_x_scale_factor, - DEFAULT_SCALE_FACTOR)); - transformer.setYScaleFactor( - attributes.getFloat(R.styleable.draggable_view_top_view_y_scale_factor, - DEFAULT_SCALE_FACTOR)); - transformer.setMarginRight( - attributes.getDimensionPixelSize(R.styleable.draggable_view_top_view_margin_right, - DEFAULT_TOP_VIEW_MARGIN)); - transformer.setMarginBottom( - attributes.getDimensionPixelSize(R.styleable.draggable_view_top_view_margin_bottom, - DEFAULT_TOP_VIEW_MARGIN)); - } - - /** - * Initialize XML attributes. - * - * @param attrs to be analyzed. - */ - private void initializeAttributes(AttributeSet attrs) { - TypedArray attributes = getContext().obtainStyledAttributes(attrs, R.styleable.draggable_view); - this.enableHorizontalAlphaEffect = - attributes.getBoolean(R.styleable.draggable_view_enable_minimized_horizontal_alpha_effect, - DEFAULT_ENABLE_HORIZONTAL_ALPHA_EFFECT); - this.enableClickToMaximize = - attributes.getBoolean(R.styleable.draggable_view_enable_click_to_maximize_view, - DEFAULT_ENABLE_CLICK_TO_MAXIMIZE); - this.enableClickToMinimize = - attributes.getBoolean(R.styleable.draggable_view_enable_click_to_minimize_view, - DEFAULT_ENABLE_CLICK_TO_MINIMIZE); - this.attributes = attributes; - } - - /** - * Realize an smooth slide to an slide offset passed as argument. This method is the base of - * maximize, minimize and close methods. - * - * @param slideOffset to apply - * @return true if the view is slided. - */ - private boolean smoothSlideTo(float slideOffset) { - final int topBound = getPaddingTop(); - int x = (int) (slideOffset * (getWidth() - transformer.getMinWidthPlusMarginRight())); - int y = (int) (topBound + slideOffset * getVerticalDragRange()); - if (viewDragHelper.smoothSlideViewTo(dragView, x, y)) { - ViewCompat.postInvalidateOnAnimation(this); - return true; - } - return false; - } - - /** - * @return configured dragged view margin right configured. - */ - private int getDragViewMarginRight() { - return transformer.getMarginRight(); - } - - /** - * @return configured dragged view margin bottom. - */ - private int getDragViewMarginBottom() { - return transformer.getMarginBottom(); - } - - /** - * Calculate the dragged view left position normalized between 1 and 0. - * - * @return absolute value between the dragged view left position divided by custon view width - */ - private float getHorizontalDragOffset() { - return (float) Math.abs(dragView.getLeft()) / (float) getWidth(); - } - - /** - * Calculate the dragged view top position normalized between 1 and 0. - * - * @return dragged view top divided by vertical drag range. - */ - private float getVerticalDragOffset() { - return dragView.getTop() / getVerticalDragRange(); - } - - /** - * Calculate the vertical drag range between the custom view and dragged view. - * - * @return the difference between the custom view height and the dragged view height. - */ - private float getVerticalDragRange() { - return getHeight() - transformer.getMinHeightPlusMargin(); - } - - /** - * Notify te view is maximized to the DraggableListener - */ - private void notifyMaximizeToListener() { - if (listener != null) { - listener.onMaximized(); - } - } - - /** - * Notify te view is minimized to the DraggableListener - */ - private void notifyMinimizeToListener() { - if (listener != null) { - listener.onMinimized(); - } - } - - /** - * Notify te view is closed to the right to the DraggableListener - */ - private void notifyCloseToRightListener() { - if (listener != null) { - listener.onClosedToRight(); - } - } - - /** - * Notify te view is closed to the left to the DraggableListener - */ - private void notifyCloseToLeftListener() { - if (listener != null) { - listener.onClosedToLeft(); - } - } - - public int getDraggedViewHeightPlusMarginTop() { - return transformer.getMinHeightPlusMargin(); - } +public class DraggableView extends RelativeLayout{ + + private static final int DEFAULT_SCALE_FACTOR = 2; + private static final int DEFAULT_TOP_VIEW_MARGIN = 30; + private static final int DEFAULT_TOP_VIEW_HEIGHT = -1; + private static final float SLIDE_TOP = 0f; + private static final float SLIDE_BOTTOM = 1f; + private static final float MIN_SLIDE_OFFSET = 0.1f; + private static final boolean DEFAULT_ENABLE_HORIZONTAL_ALPHA_EFFECT = true; + private static final boolean DEFAULT_ENABLE_CLICK_TO_MAXIMIZE = false; + private static final boolean DEFAULT_ENABLE_CLICK_TO_MINIMIZE = false; + private static final boolean DEFAULT_ENABLE_TOUCH_LISTENER = true; + private static final int MIN_SLIDING_DISTANCE_ON_CLICK = 10; + private static final int ONE_HUNDRED = 100; + private static final float SENSITIVITY = 1f; + private static final boolean DEFAULT_TOP_VIEW_RESIZE = false; + private static final int INVALID_POINTER = -1; + + private int activePointerId = INVALID_POINTER; + private float lastTouchActionDownXPosition; + + private View dragView; + private View secondView; + private TypedArray attributes; + + private FragmentManager fragmentManager; + private ViewDragHelper viewDragHelper; + private Transformer transformer; + + private boolean enableHorizontalAlphaEffect; + private boolean topViewResize; + private boolean enableClickToMaximize; + private boolean enableClickToMinimize; + private boolean touchEnabled; + + private DraggableListener listener; + + + public DraggableView(Context context){ + super(context); + } + + + public DraggableView(Context context, AttributeSet attrs){ + super(context, attrs); + initializeAttributes(attrs); + } + + + public DraggableView(Context context, AttributeSet attrs, int defStyle){ + super(context, attrs, defStyle); + initializeAttributes(attrs); + } + + + /** + * Return if user can maximize minimized view on click. + */ + public boolean isClickToMaximizeEnabled(){ + return enableClickToMaximize; + } + + + /** + * Enable or disable click to maximize view when dragged view is minimized + * If your content have a touch/click listener (like YoutubePlayer), you + * need disable it to active this feature. + * + * @param enableClickToMaximize to enable or disable the click. + */ + public void setClickToMaximizeEnabled(boolean enableClickToMaximize){ + this.enableClickToMaximize = enableClickToMaximize; + } + + + /** + * Return if user can minimize maximized view on click. + */ + public boolean isClickToMinimizeEnabled(){ + return enableClickToMinimize; + } + + + /** + * Enable or disable click to minimize view when dragged view is maximized + * If your content have a touch/click listener (like YoutubePlayer), you + * need disable it to active this feature. + * + * @param enableClickToMinimize to enable or disable the click. + */ + public void setClickToMinimizeEnabled(boolean enableClickToMinimize){ + this.enableClickToMinimize = enableClickToMinimize; + } + + + /** + * Return if touch listener is enable or disable + */ + private boolean isTouchEnabled(){ + return this.touchEnabled; + } + + + /** + * Enable or disable the touch listener + * + * @param touchEnabled to enable or disable the touch event. + */ + public void setTouchEnabled(boolean touchEnabled){ + this.touchEnabled = touchEnabled; + } + + + /** + * Slide the view based on scroll of the nav drawer. + * "setEnableTouch" user prevents click to expand while the drawer is moving, it will be + * set to false when the @slideOffset is bigger than MIN_SLIDE_OFFSET. + * When the slideOffset is bigger than 0.1 and dragView isn't close, set the dragView + * to minimized. + * It's only possible to maximize the view when @slideOffset is equals to 0.0, + * in other words, closed. + * + * @param slideOffset Value between 0 and 1, represent the value of slide: + * 0.0 is equal to close drawer and 1.0 equals open drawer. + * @param drawerPosition Represent the position of nav drawer on X axis. + * @param width Width of nav drawer + */ + public void slideHorizontally(float slideOffset, float drawerPosition, int width){ + if(slideOffset > MIN_SLIDE_OFFSET && !isClosed() && isMaximized()){ + minimize(); + } + setTouchEnabled(slideOffset <= MIN_SLIDE_OFFSET); + ViewHelper.setX(this, width - Math.abs(drawerPosition)); + } + + + /** + * Configure the horizontal scale factor applied when the view is dragged to the bottom of the + * custom view. + */ + public void setXTopViewScaleFactor(float xScaleFactor){ + transformer.setXScaleFactor(xScaleFactor); + } + + + /** + * Configure the vertical scale factor applied when the view is dragged to the bottom of the + * custom view. + */ + public void setYTopViewScaleFactor(float yScaleFactor){ + transformer.setYScaleFactor(yScaleFactor); + } + + + /** + * Configure the dragged view margin right applied when the dragged view is minimized. + * + * @param topFragmentMarginRight in pixels. + */ + public void setTopViewMarginRight(int topFragmentMarginRight){ + transformer.setMarginRight(topFragmentMarginRight); + } + + + /** + * Configure the dragView margin bottom applied when the dragView is minimized. + */ + public void setTopViewMarginBottom(int topFragmentMarginBottom){ + transformer.setMarginBottom(topFragmentMarginBottom); + } + + + /** + * Configure the dragged view height. + * + * @param topFragmentHeight in pixels + */ + public void setTopViewHeight(int topFragmentHeight){ + transformer.setViewHeight(topFragmentHeight); + } + + + /** + * Configure the disabling of the alpha effect applied when the dragView is dragged horizontally. + */ + public void setHorizontalAlphaEffectEnabled(boolean enableHorizontalAlphaEffect){ + this.enableHorizontalAlphaEffect = enableHorizontalAlphaEffect; + } + + + /** + * Configure the DraggableListener notified when the view is minimized, maximized, closed to the + * right or closed to the left. + */ + public void setDraggableListener(DraggableListener listener){ + this.listener = listener; + } + + + /** + * Configure DraggableView to resize top view instead of scale it. + */ + public void setTopViewResize(boolean topViewResize){ + this.topViewResize = topViewResize; + } + + + /** + * To ensure the animation is going to work this method has been override to call + * postInvalidateOnAnimation if the view is not settled yet. + */ + @Override + public void computeScroll(){ + if(!isInEditMode() && viewDragHelper.continueSettling(true)){ + ViewCompat.postInvalidateOnAnimation(this); + } + } + + + /** + * Maximize the custom view applying an animation to return the view to the initial position. + */ + public void maximize(){ + smoothSlideTo(SLIDE_TOP); + notifyMaximizeToListener(); + } + + + /** + * Minimize the custom view applying an animation to put the top fragment on the bottom right + * corner of the screen. + */ + public void minimize(){ + smoothSlideTo(SLIDE_BOTTOM); + notifyMinimizeToListener(); + } + + + /** + * Close the custom view applying an animation to close the view to the right side of the screen. + */ + public void closeToRight(){ + DisplayMetrics dm = getResources().getDisplayMetrics(); + int maxSize = Math.max(dm.widthPixels, dm.heightPixels); + if(viewDragHelper.smoothSlideViewTo( + dragView, transformer.getOriginalWidth() + maxSize, getHeight() - transformer.getMinHeightPlusMargin() + )){ + ViewCompat.postInvalidateOnAnimation(this); + notifyCloseToRightListener(); + } + } + + + /** + * Close the custom view applying an animation to close the view to the left side of the screen. + */ + public void closeToLeft(){ + DisplayMetrics dm = getResources().getDisplayMetrics(); + int maxSize = Math.max(dm.widthPixels, dm.heightPixels); + if(viewDragHelper.smoothSlideViewTo( + dragView, -(transformer.getOriginalWidth() + maxSize), getHeight() - transformer.getMinHeightPlusMargin() + )){ + ViewCompat.postInvalidateOnAnimation(this); + notifyCloseToLeftListener(); + } + } + // public void closeToLeft(boolean internal){ + // if(viewDragHelper.smoothSlideViewTo( + // dragView, -transformer.getOriginalWidth(), getHeight() - transformer.getMinHeightPlusMargin() + // )){ + // ViewCompat.postInvalidateOnAnimation(this); + // if(notifyCloseToLeftListener(); + // } + // } + // + + + /** + * Checks if the top view is minimized. + * + * @return true if the view is minimized. + */ + public boolean isMinimized(){ + return isDragViewAtBottom() && isDragViewAtRight(); + } + + + /** + * Checks if the top view is maximized. + * + * @return true if the view is maximized. + */ + public boolean isMaximized(){ + return isDragViewAtTop(); + } + + + /** + * Checks if the top view closed at the right place. + * + * @return true if the view is closed at right. + */ + public boolean isClosedAtRight(){ + return dragView.getLeft() >= getWidth(); + } + + + /** + * Checks if the top view is closed at the left place. + * + * @return true if the view is closed at left. + */ + public boolean isClosedAtLeft(){ + return dragView.getRight() <= 0; + } + + + /** + * Checks if the top view is closed at the right or left place. + * + * @return true if the view is closed. + */ + public boolean isClosed(){ + return isClosedAtLeft() || isClosedAtRight(); + } + + + /** + * Override method to intercept only touch events over the drag view and to cancel the drag when + * the action associated to the MotionEvent is equals to ACTION_CANCEL or ACTION_UP. + * + * @param ev captured. + * @return true if the view is going to process the touch event or false if not. + */ + @Override + public boolean onInterceptTouchEvent(MotionEvent ev){ + if(!isEnabled()){ + return false; + } + switch(MotionEventCompat.getActionMasked(ev) & MotionEventCompat.ACTION_MASK){ + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: + viewDragHelper.cancel(); + return false; + case MotionEvent.ACTION_DOWN: + int index = MotionEventCompat.getActionIndex(ev); + activePointerId = MotionEventCompat.getPointerId(ev, index); + if(activePointerId == INVALID_POINTER){ + return false; + } + break; + default: + break; + } + boolean interceptTap = + viewDragHelper.isViewUnder(dragView, (int) ev.getX(), (int) ev.getY()); + return viewDragHelper.shouldInterceptTouchEvent(ev) || interceptTap; + } + + + /** + * Override method to dispatch touch event to the dragged view. + * + * @param ev captured. + * @return true if the touch event is realized over the drag or second view. + */ + @Override + public boolean onTouchEvent(MotionEvent ev){ + int actionMasked = MotionEventCompat.getActionMasked(ev); + if((actionMasked & MotionEventCompat.ACTION_MASK) == MotionEvent.ACTION_DOWN){ + activePointerId = MotionEventCompat.getPointerId(ev, actionMasked); + } + if(activePointerId == INVALID_POINTER){ + return false; + } + viewDragHelper.processTouchEvent(ev); + if(isClosed()){ + return false; + } + boolean isDragViewHit = isViewHit(dragView, (int) ev.getX(), (int) ev.getY()); + boolean isSecondViewHit = isViewHit(secondView, (int) ev.getX(), (int) ev.getY()); + analyzeTouchToMaximizeIfNeeded(ev, isDragViewHit); + if(isMaximized()){ + dragView.dispatchTouchEvent(ev); + } else{ + dragView.dispatchTouchEvent(cloneMotionEventWithAction(ev, MotionEvent.ACTION_CANCEL)); + } + return isDragViewHit || isSecondViewHit; + } + + + private void analyzeTouchToMaximizeIfNeeded(MotionEvent ev, boolean isDragViewHit){ + switch(ev.getAction()){ + case MotionEvent.ACTION_DOWN: + lastTouchActionDownXPosition = ev.getX(); + break; + case MotionEvent.ACTION_UP: + float clickOffset = ev.getX() - lastTouchActionDownXPosition; + if(shouldMaximizeOnClick(ev, clickOffset, isDragViewHit)){ + if(isMinimized() && isClickToMaximizeEnabled()){ + maximize(); + } else if(isMaximized() && isClickToMinimizeEnabled()){ + minimize(); + } + } + break; + default: + break; + } + } + + + public boolean shouldMaximizeOnClick(MotionEvent ev, float deltaX, boolean isDragViewHit){ + return (Math.abs(deltaX) < MIN_SLIDING_DISTANCE_ON_CLICK) && ev.getAction() != MotionEvent.ACTION_MOVE && isDragViewHit; + } + + + /** + * Clone given motion event and set specified action. This method is useful, when we want to + * cancel event propagation in child views by sending event with {@link + * android.view.MotionEvent#ACTION_CANCEL} + * action. + * + * @param event event to clone + * @param action new action + * @return cloned motion event + */ + private MotionEvent cloneMotionEventWithAction(MotionEvent event, int action){ + return MotionEvent.obtain( + event.getDownTime(), event.getEventTime(), action, event.getX(), event.getY(), event.getMetaState() + ); + } + + + /** + * Override method to configure the dragged view and secondView layout properly. + */ + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom){ + if(isInEditMode()){ + super.onLayout(changed, left, top, right, bottom); + } else if(isDragViewAtTop()){ + dragView.layout(left, top, right, transformer.getOriginalHeight()); + secondView.layout(left, transformer.getOriginalHeight(), right, bottom); + ViewHelper.setY(dragView, top); + ViewHelper.setY(secondView, transformer.getOriginalHeight()); + } else{ + // secondView.layout(left, transformer.getOriginalHeight(), right, bottom); + if(isClosedAtLeft()){ + } else if(isClosedAtRight()){ + } else{ + smoothSlideTo(SLIDE_BOTTOM); + } + } + } + + + /** + * Override method to map dragged view, secondView to view objects, to configure dragged + * view height and to initialize DragViewHelper. + */ + @Override + protected void onFinishInflate(){ + super.onFinishInflate(); + if(!isInEditMode()){ + mapGUI(attributes); + initializeTransformer(attributes); + attributes.recycle(); + initializeViewDragHelper(); + } + } + + + private void mapGUI(TypedArray attributes){ + int dragViewId = + attributes.getResourceId(R.styleable.draggable_view_top_view_id, R.id.drag_view); + int secondViewId = + attributes.getResourceId(R.styleable.draggable_view_bottom_view_id, R.id.second_view); + dragView = findViewById(dragViewId); + secondView = findViewById(secondViewId); + } + + + /** + * Configure the FragmentManager used to attach top and bottom Fragments to the view. The + * FragmentManager is going to be provided only by DraggablePanel view. + */ + void setFragmentManager(FragmentManager fragmentManager){ + this.fragmentManager = fragmentManager; + } + + + /** + * Attach one fragment to the dragged view. + * + * @param topFragment to be attached. + */ + void attachTopFragment(Fragment topFragment){ + addFragmentToView(R.id.drag_view, topFragment); + } + + + /** + * Attach one fragment to the secondView. + * + * @param bottomFragment to be attached. + */ + void attachBottomFragment(Fragment bottomFragment){ + addFragmentToView(R.id.second_view, bottomFragment); + } + + + /** + * Modify dragged view pivot based on the dragged view vertical position to simulate a horizontal + * displacement while the view is dragged. + */ + void changeDragViewPosition(){ + transformer.updatePosition(getVerticalDragOffset()); + } + + + /** + * Modify secondView position to be always below dragged view. + */ + void changeSecondViewPosition(){ + ViewHelper.setY(secondView, dragView.getBottom()); + } + + + /** + * Modify dragged view scale based on the dragged view vertical position and the scale factor. + */ + void changeDragViewScale(){ + transformer.updateScale(getVerticalDragOffset()); + } + + + /** + * Modify the background alpha if has been configured to applying an alpha effect when the view + * is dragged. + */ + void changeBackgroundAlpha(){ + Drawable background = getBackground(); + if(background != null){ + int newAlpha = (int) (ONE_HUNDRED * (1 - getVerticalDragOffset())); + background.setAlpha(newAlpha); + } + } + + + /** + * Modify the second view alpha based on dragged view vertical position. + */ + void changeSecondViewAlpha(){ + ViewHelper.setAlpha(secondView, 1 - getVerticalDragOffset()); + } + + + /** + * Modify dragged view alpha based on the horizontal position while the view is being + * horizontally dragged. + */ + void changeDragViewViewAlpha(){ + if(enableHorizontalAlphaEffect){ + float alpha = 1 - getHorizontalDragOffset(); + if(alpha == 0){ + alpha = 1; + } + ViewHelper.setAlpha(dragView, alpha); + } + } + + + /** + * Restore view alpha to 1 + */ + void restoreAlpha(){ + if(enableHorizontalAlphaEffect && ViewHelper.getAlpha(dragView) < 1){ + ViewHelper.setAlpha(dragView, 1); + } + } + + + /** + * Check if dragged view is above the middle of the custom view. + * + * @return true if dragged view is above the middle of the custom view or false if is below. + */ + boolean isDragViewAboveTheMiddle(){ + return transformer.isAboveTheMiddle(); + } + + + /** + * Check if dragged view is next to the left bound. + * + * @return true if dragged view right position is behind the right half of the custom view. + */ + boolean isNextToLeftBound(){ + return transformer.isNextToLeftBound(); + } + + + /** + * Check if dragged view is next to the right bound. + * + * @return true if dragged view left position is behind the left quarter of the custom view. + */ + boolean isNextToRightBound(){ + return transformer.isNextToRightBound(); + } + + + /** + * Check if dragged view is at the top of the custom view. + * + * @return true if dragged view top position is equals to zero. + */ + boolean isDragViewAtTop(){ + return transformer.isViewAtTop(); + } + + + /** + * Check if dragged view is at the right of the custom view. + * + * @return true if dragged view right position is equals to custom view width. + */ + boolean isDragViewAtRight(){ + return transformer.isViewAtRight(); + } + + + /** + * Check if dragged view is at the bottom of the custom view. + * + * @return true if dragged view bottom position is equals to custom view height. + */ + boolean isDragViewAtBottom(){ + return transformer.isViewAtBottom(); + } + + + /** + * Calculate if one position is above any view. + * + * @param view to analyze. + * @param x position. + * @param y position. + * @return true if x and y positions are below the view. + */ + 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(); + } + + + /** + * Use FragmentManager to attach one fragment to one view using the viewId. + * + * @param viewId used to obtain the view. + * @param fragment to be attached. + */ + private void addFragmentToView(final int viewId, final Fragment fragment){ + fragmentManager.beginTransaction().replace(viewId, fragment).commit(); + } + + + /** + * Initialize the viewDragHelper. + */ + private void initializeViewDragHelper(){ + viewDragHelper = + ViewDragHelper.create(this, SENSITIVITY, new DraggableViewCallback(this, dragView)); + } + + + /** + * Initialize Transformer with a scalable or change width/height implementation. + */ + private void initializeTransformer(TypedArray attributes){ + topViewResize = + attributes.getBoolean(R.styleable.draggable_view_top_view_resize, DEFAULT_TOP_VIEW_RESIZE); + TransformerFactory transformerFactory = new TransformerFactory(); + transformer = transformerFactory.getTransformer(topViewResize, dragView, this); + transformer.setViewHeight( + attributes.getDimensionPixelSize( + R.styleable.draggable_view_top_view_height, DEFAULT_TOP_VIEW_HEIGHT + ) + ); + transformer.setXScaleFactor( + attributes.getFloat( + R.styleable.draggable_view_top_view_x_scale_factor, DEFAULT_SCALE_FACTOR + ) + ); + transformer.setYScaleFactor( + attributes.getFloat( + R.styleable.draggable_view_top_view_y_scale_factor, DEFAULT_SCALE_FACTOR + ) + ); + transformer.setMarginRight( + attributes.getDimensionPixelSize( + R.styleable.draggable_view_top_view_margin_right, DEFAULT_TOP_VIEW_MARGIN + ) + ); + transformer.setMarginBottom( + attributes.getDimensionPixelSize( + R.styleable.draggable_view_top_view_margin_bottom, DEFAULT_TOP_VIEW_MARGIN + ) + ); + } + + + /** + * Initialize XML attributes. + * + * @param attrs to be analyzed. + */ + private void initializeAttributes(AttributeSet attrs){ + TypedArray attributes = + getContext().obtainStyledAttributes(attrs, R.styleable.draggable_view); + this.enableHorizontalAlphaEffect = attributes.getBoolean( + R.styleable.draggable_view_enable_minimized_horizontal_alpha_effect, DEFAULT_ENABLE_HORIZONTAL_ALPHA_EFFECT + ); + this.enableClickToMaximize = attributes.getBoolean( + R.styleable.draggable_view_enable_click_to_maximize_view, DEFAULT_ENABLE_CLICK_TO_MAXIMIZE + ); + this.enableClickToMinimize = attributes.getBoolean( + R.styleable.draggable_view_enable_click_to_minimize_view, DEFAULT_ENABLE_CLICK_TO_MINIMIZE + ); + this.attributes = attributes; + } + + + /** + * Realize an smooth slide to an slide offset passed as argument. This method is the base of + * maximize, minimize and close methods. + * + * @param slideOffset to apply + * @return true if the view is slided. + */ + private boolean smoothSlideTo(float slideOffset){ + final int topBound = getPaddingTop(); + int x = (int) (slideOffset * (getWidth() - transformer.getMinWidthPlusMarginRight())); + int y = (int) (topBound + slideOffset * getVerticalDragRange()); + if(viewDragHelper.smoothSlideViewTo(dragView, x, y)){ + ViewCompat.postInvalidateOnAnimation(this); + return true; + } + return false; + } + + + /** + * @return configured dragged view margin right configured. + */ + private int getDragViewMarginRight(){ + return transformer.getMarginRight(); + } + + + /** + * @return configured dragged view margin bottom. + */ + private int getDragViewMarginBottom(){ + return transformer.getMarginBottom(); + } + + + /** + * Calculate the dragged view left position normalized between 1 and 0. + * + * @return absolute value between the dragged view left position divided by custon view width + */ + private float getHorizontalDragOffset(){ + return (float) Math.abs(dragView.getLeft()) / (float) getWidth(); + } + + + /** + * Calculate the dragged view top position normalized between 1 and 0. + * + * @return dragged view top divided by vertical drag range. + */ + private float getVerticalDragOffset(){ + return dragView.getTop() / getVerticalDragRange(); + } + + + /** + * Calculate the vertical drag range between the custom view and dragged view. + * + * @return the difference between the custom view height and the dragged view height. + */ + private float getVerticalDragRange(){ + return getHeight() - transformer.getMinHeightPlusMargin(); + } + + + /** + * Notify te view is maximized to the DraggableListener + */ + private void notifyMaximizeToListener(){ + if(listener != null){ + listener.onMaximized(); + } + } + + + /** + * Notify te view is minimized to the DraggableListener + */ + private void notifyMinimizeToListener(){ + if(listener != null){ + listener.onMinimized(); + } + } + + + /** + * Notify te view is closed to the right to the DraggableListener + */ + private void notifyCloseToRightListener(){ + if(listener != null){ + listener.onClosedToRight(); + } + } + + + /** + * Notify te view is closed to the left to the DraggableListener + */ + private void notifyCloseToLeftListener(){ + if(listener != null){ + listener.onClosedToLeft(); + } + } + + + public int getDraggedViewHeightPlusMarginTop(){ + return transformer.getMinHeightPlusMargin(); + } } diff --git a/sample/AndroidManifest.xml b/sample/AndroidManifest.xml index 960a0f2..9f99368 100755 --- a/sample/AndroidManifest.xml +++ b/sample/AndroidManifest.xml @@ -1,79 +1,84 @@ - + - + - + - - - - + + + + - + - + - + - + - + - + - - - + + + - - - + + + - + - - + + android:label="@string/places_sample_activity_title" /> - + + - - - + + + android:label="@string/youtube_sample_activity_title" /> - - - + - + + + + + diff --git a/sample/src/main/java/com/github/pedrovgs/sample/activity/DIFragmentActivity.java b/sample/src/main/java/com/github/pedrovgs/sample/activity/DIFragmentActivity.java index 7f956a2..43e4363 100644 --- a/sample/src/main/java/com/github/pedrovgs/sample/activity/DIFragmentActivity.java +++ b/sample/src/main/java/com/github/pedrovgs/sample/activity/DIFragmentActivity.java @@ -15,6 +15,7 @@ */ package com.github.pedrovgs.sample.activity; +import android.content.res.Configuration; import android.os.Bundle; import com.actionbarsherlock.app.SherlockFragmentActivity; import com.github.pedrovgs.sample.DraggablePanelApplication; @@ -32,4 +33,10 @@ public class DIFragmentActivity extends SherlockFragmentActivity { super.onCreate(savedInstanceState); ((DraggablePanelApplication) getApplication()).inject(this); } + + + public void onConfigurationChanged(Configuration newConfig){ + super.onConfigurationChanged(newConfig); + + } } diff --git a/sample/src/main/java/com/github/pedrovgs/sample/activity/MainActivity.java b/sample/src/main/java/com/github/pedrovgs/sample/activity/MainActivity.java index 8f7c7db..1fe4e77 100644 --- a/sample/src/main/java/com/github/pedrovgs/sample/activity/MainActivity.java +++ b/sample/src/main/java/com/github/pedrovgs/sample/activity/MainActivity.java @@ -17,6 +17,7 @@ import android.app.Activity; import android.content.Intent; +import android.content.res.Configuration; import android.os.Bundle; import butterknife.ButterKnife; import butterknife.OnClick; @@ -52,4 +53,10 @@ public class MainActivity extends Activity { Intent intent = new Intent(this, VideoSampleActivity.class); startActivity(intent); } + + + public void onConfigurationChanged(Configuration newConfig){ + super.onConfigurationChanged(newConfig); + + } } diff --git a/sample/src/main/java/com/github/pedrovgs/sample/activity/TvShowsActivity.java b/sample/src/main/java/com/github/pedrovgs/sample/activity/TvShowsActivity.java index ebf2dc5..ea3a89d 100644 --- a/sample/src/main/java/com/github/pedrovgs/sample/activity/TvShowsActivity.java +++ b/sample/src/main/java/com/github/pedrovgs/sample/activity/TvShowsActivity.java @@ -15,6 +15,7 @@ */ package com.github.pedrovgs.sample.activity; +import android.content.res.Configuration; import android.os.Bundle; import android.os.Handler; import android.view.View; @@ -88,12 +89,16 @@ public class TvShowsActivity extends DIFragmentActivity { */ private void initializeDraggableView() { Handler handler = new Handler(); - handler.postDelayed(new Runnable() { - @Override public void run() { - draggableView.setVisibility(View.GONE); - draggableView.closeToRight(); - } - }, DELAY_MILLIS); + handler.postDelayed( + new Runnable(){ + + @Override + public void run(){ + draggableView.setVisibility(View.GONE); + draggableView.closeToRight(); + } + }, DELAY_MILLIS + ); } /** @@ -101,21 +106,26 @@ private void initializeDraggableView() { */ private void initializeGridView() { tvShowsGridView.setAdapter(adapter); - tvShowsGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { - @Override public void onItemClick(AdapterView adapterView, View view, int position, - long id) { - TvShowViewModel tvShow = adapter.getItem(position); - tvShowSelected = tvShow; - Picasso.with(getBaseContext()) - .load(tvShow.getFanArt()) - .placeholder(R.drawable.tv_show_placeholder) - .into(fanArtImageView); - renderEpisodesHeader(tvShow); - renderEpisodes(tvShow); - draggableView.setVisibility(View.VISIBLE); - draggableView.maximize(); - } - }); + tvShowsGridView.setOnItemClickListener( + new AdapterView.OnItemClickListener(){ + + @Override + public void onItemClick( + AdapterView adapterView, View view, int position, long id + ){ + TvShowViewModel tvShow = adapter.getItem(position); + tvShowSelected = tvShow; + Picasso.with(getBaseContext()) + .load(tvShow.getFanArt()) + .placeholder(R.drawable.tv_show_placeholder) + .into(fanArtImageView); + renderEpisodesHeader(tvShow); + renderEpisodes(tvShow); + draggableView.setVisibility(View.VISIBLE); + draggableView.maximize(); + } + } + ); } /** @@ -123,23 +133,33 @@ private void initializeGridView() { * information. */ private void hookListeners() { - draggableView.setDraggableListener(new DraggableListener() { - @Override public void onMaximized() { - updateActionBarTitle(); - } - - @Override public void onMinimized() { - updateActionBarTitle(); - } - - @Override public void onClosedToLeft() { - resetActionBarTitle(); - } - - @Override public void onClosedToRight() { - resetActionBarTitle(); - } - }); + draggableView.setDraggableListener( + new DraggableListener(){ + + @Override + public void onMaximized(){ + updateActionBarTitle(); + } + + + @Override + public void onMinimized(){ + updateActionBarTitle(); + } + + + @Override + public void onClosedToLeft(){ + resetActionBarTitle(); + } + + + @Override + public void onClosedToRight(){ + resetActionBarTitle(); + } + } + ); } /** @@ -185,18 +205,29 @@ private void renderEpisodesHeader(TvShowViewModel tvShow) { header.setText(tvShow.getTitle().toUpperCase() + " - SEASON 1"); episodesListView.setAdapter(null); episodesListView.addHeaderView(header); - episodesListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { - @Override public void onItemClick(AdapterView adapterView, View view, int position, - long id) { - if (tvShowSelected != null) { - if (position > 0) { - EpisodeViewModel episodeViewModel = tvShowSelected.getEpisodes().get(position - 1); - Toast.makeText(getBaseContext(), - tvShowSelected.getTitle() + " - " + episodeViewModel.getTitle(), Toast.LENGTH_LONG) - .show(); + episodesListView.setOnItemClickListener( + new AdapterView.OnItemClickListener(){ + + @Override + public void onItemClick( + AdapterView adapterView, View view, int position, long id + ){ + if(tvShowSelected != null){ + if(position > 0){ + EpisodeViewModel episodeViewModel = tvShowSelected.getEpisodes().get(position - 1); + Toast.makeText( + getBaseContext(), tvShowSelected.getTitle() + " - " + episodeViewModel.getTitle(), Toast.LENGTH_LONG + ).show(); + } + } } } - } - }); + ); + } + + + public void onConfigurationChanged(Configuration newConfig){ + super.onConfigurationChanged(newConfig); + } } \ No newline at end of file diff --git a/sample/src/main/java/com/github/pedrovgs/sample/activity/VideoSampleActivity.java b/sample/src/main/java/com/github/pedrovgs/sample/activity/VideoSampleActivity.java index 83e2dbf..401eca0 100644 --- a/sample/src/main/java/com/github/pedrovgs/sample/activity/VideoSampleActivity.java +++ b/sample/src/main/java/com/github/pedrovgs/sample/activity/VideoSampleActivity.java @@ -15,6 +15,7 @@ */ package com.github.pedrovgs.sample.activity; +import android.content.res.Configuration; import android.net.Uri; import android.os.Bundle; import android.support.v4.app.FragmentActivity; @@ -83,24 +84,34 @@ public class VideoSampleActivity extends FragmentActivity { * Hook DraggableListener to draggableView to pause or resume VideoView. */ private void hookDraggableViewListener() { - draggableView.setDraggableListener(new DraggableListener() { - @Override public void onMaximized() { - startVideo(); - } - - //Empty - @Override public void onMinimized() { - //Empty - } - - @Override public void onClosedToLeft() { - pauseVideo(); - } - - @Override public void onClosedToRight() { - pauseVideo(); - } - }); + draggableView.setDraggableListener( + new DraggableListener(){ + + @Override + public void onMaximized(){ + startVideo(); + } + + + //Empty + @Override + public void onMinimized(){ + //Empty + } + + + @Override + public void onClosedToLeft(){ + pauseVideo(); + } + + + @Override + public void onClosedToRight(){ + pauseVideo(); + } + } + ); } /** @@ -143,4 +154,10 @@ private void initializePoster() { .placeholder(R.drawable.spiderman_placeholder) .into(thumbnailImageView); } + + + public void onConfigurationChanged(Configuration newConfig){ + super.onConfigurationChanged(newConfig); + + } } diff --git a/sample/src/main/java/com/github/pedrovgs/sample/activity/YoutubeSampleActivity.java b/sample/src/main/java/com/github/pedrovgs/sample/activity/YoutubeSampleActivity.java index 756e20d..2606b24 100644 --- a/sample/src/main/java/com/github/pedrovgs/sample/activity/YoutubeSampleActivity.java +++ b/sample/src/main/java/com/github/pedrovgs/sample/activity/YoutubeSampleActivity.java @@ -15,12 +15,11 @@ */ package com.github.pedrovgs.sample.activity; +import android.content.res.Configuration; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.widget.ImageView; -import butterknife.ButterKnife; -import butterknife.InjectView; -import butterknife.OnClick; + import com.github.pedrovgs.DraggableListener; import com.github.pedrovgs.DraggablePanel; import com.github.pedrovgs.sample.R; @@ -30,128 +29,162 @@ import com.google.android.youtube.player.YouTubePlayerSupportFragment; import com.squareup.picasso.Picasso; +import butterknife.ButterKnife; +import butterknife.InjectView; +import butterknife.OnClick; + /** * Sample activity created to show a video from YouTube using a YouTubePlayer. * * @author Pedro Vicente Gómez Sánchez. */ -public class YoutubeSampleActivity extends FragmentActivity { - - private static final String YOUTUBE_API_KEY = "AIzaSyC1rMU-mkhoyTvBIdTnYU0dss0tU9vtK48"; - private static final String VIDEO_KEY = "gsjtg7m1MMM"; - private static final String VIDEO_POSTER_THUMBNAIL = - "http://4.bp.blogspot.com/-BT6IshdVsoA/UjfnTo_TkBI/AAAAAAAAMWk/JvDCYCoFRlQ/s1600/" - + "xmenDOFP.wobbly.1.jpg"; - private static final String SECOND_VIDEO_POSTER_THUMBNAIL = - "http://media.comicbook.com/wp-content/uploads/2013/07/x-men-days-of-future-past" - + "-wolverine-poster.jpg"; - private static final String VIDEO_POSTER_TITLE = "X-Men: Days of Future Past"; - - @InjectView(R.id.iv_thumbnail) ImageView thumbnailImageView; - @InjectView(R.id.draggable_panel) DraggablePanel draggablePanel; - - private YouTubePlayer youtubePlayer; - private YouTubePlayerSupportFragment youtubeFragment; - - /** - * Initialize the Activity with some injected data. - */ - @Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_youtube_sample); - ButterKnife.inject(this); - initializeYoutubeFragment(); - initializeDraggablePanel(); - hookDraggablePanelListeners(); - } - - /** - * Method triggered when the iv_thumbnail widget is clicked. This method maximize the - * DraggablePanel. - */ - @OnClick(R.id.iv_thumbnail) void onContainerClicked() { - draggablePanel.maximize(); - } - - /** - * Initialize the YouTubeSupportFrament attached as top fragment to the DraggablePanel widget and - * reproduce the YouTube video represented with a YouTube url. - */ - private void initializeYoutubeFragment() { - youtubeFragment = new YouTubePlayerSupportFragment(); - youtubeFragment.initialize(YOUTUBE_API_KEY, new YouTubePlayer.OnInitializedListener() { - - @Override public void onInitializationSuccess(YouTubePlayer.Provider provider, - YouTubePlayer player, boolean wasRestored) { - if (!wasRestored) { - youtubePlayer = player; - youtubePlayer.loadVideo(VIDEO_KEY); - youtubePlayer.setShowFullscreenButton(true); - } - } - - @Override public void onInitializationFailure(YouTubePlayer.Provider provider, - YouTubeInitializationResult error) { - } - }); - } - - /** - * Initialize and configure the DraggablePanel widget with two fragments and some attributes. - */ - private void initializeDraggablePanel() { - draggablePanel.setFragmentManager(getSupportFragmentManager()); - draggablePanel.setTopFragment(youtubeFragment); - MoviePosterFragment moviePosterFragment = new MoviePosterFragment(); - moviePosterFragment.setPoster(VIDEO_POSTER_THUMBNAIL); - moviePosterFragment.setPosterTitle(VIDEO_POSTER_TITLE); - draggablePanel.setBottomFragment(moviePosterFragment); - draggablePanel.initializeView(); - Picasso.with(this) - .load(SECOND_VIDEO_POSTER_THUMBNAIL) - .placeholder(R.drawable.xmen_placeholder) - .into(thumbnailImageView); - } - - /** - * Hook the DraggableListener to DraggablePanel to pause or resume the video when the - * DragglabePanel is maximized or closed. - */ - private void hookDraggablePanelListeners() { - draggablePanel.setDraggableListener(new DraggableListener() { - @Override public void onMaximized() { - playVideo(); - } - - @Override public void onMinimized() { - //Empty - } - - @Override public void onClosedToLeft() { - pauseVideo(); - } - - @Override public void onClosedToRight() { - pauseVideo(); - } - }); - } - - /** - * Pause the video reproduced in the YouTubePlayer. - */ - private void pauseVideo() { - if (youtubePlayer.isPlaying()) { - youtubePlayer.pause(); - } - } - - /** - * Resume the video reproduced in the YouTubePlayer. - */ - private void playVideo() { - if (!youtubePlayer.isPlaying()) { - youtubePlayer.play(); - } - } +public class YoutubeSampleActivity extends FragmentActivity{ + + private static final String YOUTUBE_API_KEY = "AIzaSyC1rMU-mkhoyTvBIdTnYU0dss0tU9vtK48"; + private static final String VIDEO_KEY = "gsjtg7m1MMM"; + private static final String VIDEO_POSTER_THUMBNAIL = + "http://4.bp.blogspot.com/-BT6IshdVsoA/UjfnTo_TkBI/AAAAAAAAMWk/JvDCYCoFRlQ/s1600/" + "xmenDOFP.wobbly.1.jpg"; + private static final String SECOND_VIDEO_POSTER_THUMBNAIL = + "http://media.comicbook.com/wp-content/uploads/2013/07/x-men-days-of-future-past" + "-wolverine-poster.jpg"; + private static final String VIDEO_POSTER_TITLE = "X-Men: Days of Future Past"; + + @InjectView(R.id.iv_thumbnail) ImageView thumbnailImageView; + @InjectView(R.id.draggable_panel) DraggablePanel draggablePanel; + + private YouTubePlayer youtubePlayer; + private YouTubePlayerSupportFragment youtubeFragment; + + + /** + * Initialize the Activity with some injected data. + */ + @Override + protected void onCreate(Bundle savedInstanceState){ + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_youtube_sample); + ButterKnife.inject(this); + initializeYoutubeFragment(); + initializeDraggablePanel(); + hookDraggablePanelListeners(); + } + + + /** + * Method triggered when the iv_thumbnail widget is clicked. This method maximize the + * DraggablePanel. + */ + @OnClick(R.id.iv_thumbnail) + void onContainerClicked(){ + draggablePanel.maximize(); + } + + + /** + * Initialize the YouTubeSupportFrament attached as top fragment to the DraggablePanel widget and + * reproduce the YouTube video represented with a YouTube url. + */ + private void initializeYoutubeFragment(){ + youtubeFragment = new YouTubePlayerSupportFragment(); + youtubeFragment.initialize( + YOUTUBE_API_KEY, new YouTubePlayer.OnInitializedListener(){ + + @Override + public void onInitializationSuccess( + YouTubePlayer.Provider provider, YouTubePlayer player, boolean wasRestored + ){ + if(!wasRestored){ + youtubePlayer = player; + youtubePlayer.loadVideo(VIDEO_KEY); + youtubePlayer.setShowFullscreenButton(true); + } + } + + + @Override + public void onInitializationFailure( + YouTubePlayer.Provider provider, YouTubeInitializationResult error + ){ + } + } + ); + } + + + /** + * Initialize and configure the DraggablePanel widget with two fragments and some attributes. + */ + private void initializeDraggablePanel(){ + draggablePanel.setFragmentManager(getSupportFragmentManager()); + draggablePanel.setTopFragment(youtubeFragment); + MoviePosterFragment moviePosterFragment = new MoviePosterFragment(); + moviePosterFragment.setPoster(VIDEO_POSTER_THUMBNAIL); + moviePosterFragment.setPosterTitle(VIDEO_POSTER_TITLE); + draggablePanel.setBottomFragment(moviePosterFragment); + draggablePanel.initializeView(); + Picasso.with(this) + .load(SECOND_VIDEO_POSTER_THUMBNAIL) + .placeholder(R.drawable.xmen_placeholder) + .into(thumbnailImageView); + } + + + /** + * Hook the DraggableListener to DraggablePanel to pause or resume the video when the + * DragglabePanel is maximized or closed. + */ + private void hookDraggablePanelListeners(){ + draggablePanel.setDraggableListener( + new DraggableListener(){ + + @Override + public void onMaximized(){ + playVideo(); + } + + + @Override + public void onMinimized(){ + //Empty + } + + + @Override + public void onClosedToLeft(){ + pauseVideo(); + } + + + @Override + public void onClosedToRight(){ + pauseVideo(); + } + } + ); + } + + + /** + * Pause the video reproduced in the YouTubePlayer. + */ + private void pauseVideo(){ + if(youtubePlayer.isPlaying()){ + youtubePlayer.pause(); + } + } + + + /** + * Resume the video reproduced in the YouTubePlayer. + */ + private void playVideo(){ + if(!youtubePlayer.isPlaying()){ + youtubePlayer.play(); + } + } + + + public void onConfigurationChanged(Configuration newConfig){ + super.onConfigurationChanged(newConfig); + + } } From 959e71e70abbff89190e0e8253bc21b79d9ce5d4 Mon Sep 17 00:00:00 2001 From: Yarh Date: Tue, 6 Oct 2015 21:04:21 +0300 Subject: [PATCH 2/4] fixed positioning --- .../com/github/pedrovgs/DraggableView.java | 47 ++++-- .../pedrovgs/DraggableViewCallback.java | 135 +++++++++--------- .../activity/YoutubeSampleActivity.java | 3 +- 3 files changed, 105 insertions(+), 80 deletions(-) diff --git a/draggablepanel/src/main/java/com/github/pedrovgs/DraggableView.java b/draggablepanel/src/main/java/com/github/pedrovgs/DraggableView.java index e4b1e47..6040125 100644 --- a/draggablepanel/src/main/java/com/github/pedrovgs/DraggableView.java +++ b/draggablepanel/src/main/java/com/github/pedrovgs/DraggableView.java @@ -280,6 +280,7 @@ public void minimize(){ * Close the custom view applying an animation to close the view to the right side of the screen. */ public void closeToRight(){ + DisplayMetrics dm = getResources().getDisplayMetrics(); int maxSize = Math.max(dm.widthPixels, dm.heightPixels); if(viewDragHelper.smoothSlideViewTo( @@ -298,21 +299,12 @@ public void closeToLeft(){ DisplayMetrics dm = getResources().getDisplayMetrics(); int maxSize = Math.max(dm.widthPixels, dm.heightPixels); if(viewDragHelper.smoothSlideViewTo( - dragView, -(transformer.getOriginalWidth() + maxSize), getHeight() - transformer.getMinHeightPlusMargin() + dragView, -maxSize * 20, getHeight() - transformer.getMinHeightPlusMargin() )){ ViewCompat.postInvalidateOnAnimation(this); notifyCloseToLeftListener(); } } - // public void closeToLeft(boolean internal){ - // if(viewDragHelper.smoothSlideViewTo( - // dragView, -transformer.getOriginalWidth(), getHeight() - transformer.getMinHeightPlusMargin() - // )){ - // ViewCompat.postInvalidateOnAnimation(this); - // if(notifyCloseToLeftListener(); - // } - // } - // /** @@ -341,7 +333,7 @@ public boolean isMaximized(){ * @return true if the view is closed at right. */ public boolean isClosedAtRight(){ - return dragView.getLeft() >= getWidth(); + return dragView.getLeft() >= transformer.getOriginalWidth(); } @@ -472,11 +464,14 @@ private MotionEvent cloneMotionEventWithAction(MotionEvent event, int action){ } + private int oldOrientation = -1; /** * Override method to configure the dragged view and secondView layout properly. */ @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom){ + DisplayMetrics dm = getResources().getDisplayMetrics(); + if(oldOrientation == -1){ oldOrientation = getResources().getConfiguration().orientation; } if(isInEditMode()){ super.onLayout(changed, left, top, right, bottom); } else if(isDragViewAtTop()){ @@ -485,13 +480,38 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto ViewHelper.setY(dragView, top); ViewHelper.setY(secondView, transformer.getOriginalHeight()); } else{ - // secondView.layout(left, transformer.getOriginalHeight(), right, bottom); + dragView.setVisibility(INVISIBLE); if(isClosedAtLeft()){ + if(oldOrientation != getResources().getConfiguration().orientation){ + dragView.layout(left, top, right, transformer.getOriginalHeight()); + + secondView.layout(left, transformer.getOriginalHeight(), right, bottom); + oldOrientation = getResources().getConfiguration().orientation; + + } + closeToLeft(); } else if(isClosedAtRight()){ + if(oldOrientation != getResources().getConfiguration().orientation){ + dragView.layout(left, top, right, transformer.getOriginalHeight()); + secondView.layout(left, transformer.getOriginalHeight(), right, bottom); + oldOrientation = getResources().getConfiguration().orientation; + + } + + closeToRight(); + } else{ + if(oldOrientation != getResources().getConfiguration().orientation){ + dragView.layout(left, top, right, transformer.getOriginalHeight()); + secondView.layout(left, transformer.getOriginalHeight(), right, bottom); + oldOrientation = getResources().getConfiguration().orientation; + + } smoothSlideTo(SLIDE_BOTTOM); } + dragView.setVisibility(VISIBLE); } + oldOrientation = getResources().getConfiguration().orientation; } @@ -787,9 +807,8 @@ private void initializeAttributes(AttributeSet attrs){ */ private boolean smoothSlideTo(float slideOffset){ final int topBound = getPaddingTop(); - int x = (int) (slideOffset * (getWidth() - transformer.getMinWidthPlusMarginRight())); int y = (int) (topBound + slideOffset * getVerticalDragRange()); - if(viewDragHelper.smoothSlideViewTo(dragView, x, y)){ + if(viewDragHelper.smoothSlideViewTo(dragView, 0, y)){ ViewCompat.postInvalidateOnAnimation(this); return true; } diff --git a/draggablepanel/src/main/java/com/github/pedrovgs/DraggableViewCallback.java b/draggablepanel/src/main/java/com/github/pedrovgs/DraggableViewCallback.java index 08016ba..b7df872 100644 --- a/draggablepanel/src/main/java/com/github/pedrovgs/DraggableViewCallback.java +++ b/draggablepanel/src/main/java/com/github/pedrovgs/DraggableViewCallback.java @@ -24,77 +24,84 @@ * * @author Pedro Vicente Gómez Sánchez. */ -class DraggableViewCallback extends ViewDragHelper.Callback { +class DraggableViewCallback extends ViewDragHelper.Callback{ - private static final int MINIMUM_DX_FOR_HORIZONTAL_DRAG = 5; - private static final int MINIMUM_DY_FOR_VERTICAL_DRAG = 15; - private static final float X_MIN_VELOCITY = 1500; - private static final float Y_MIN_VELOCITY = 1000; + private static final int MINIMUM_DX_FOR_HORIZONTAL_DRAG = 5; + private static final int MINIMUM_DY_FOR_VERTICAL_DRAG = 15; + private static final float X_MIN_VELOCITY = 1500; + private static final float Y_MIN_VELOCITY = 1000; - private DraggableView draggableView; - private View draggedView; + private DraggableView draggableView; + private View draggedView; - /** - * Main constructor. - * - * @param draggableView instance used to apply some animations or visual effects. - */ - public DraggableViewCallback(DraggableView draggableView, View draggedView) { - this.draggableView = draggableView; - this.draggedView = draggedView; - } - /** - * Override method used to apply different scale and alpha effects while the view is being - * dragged. - * - * @param left position. - * @param top position. - * @param dx change in X position from the last call. - * @param dy change in Y position from the last call. - */ - @Override public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { - if (draggableView.isDragViewAtBottom()) { - draggableView.changeDragViewViewAlpha(); - } else { - draggableView.restoreAlpha(); - draggableView.changeDragViewScale(); - draggableView.changeDragViewPosition(); - draggableView.changeSecondViewAlpha(); - draggableView.changeSecondViewPosition(); - draggableView.changeBackgroundAlpha(); - } - } + /** + * Main constructor. + * + * @param draggableView instance used to apply some animations or visual effects. + */ + public DraggableViewCallback(DraggableView draggableView, View draggedView){ + this.draggableView = draggableView; + this.draggedView = draggedView; + } - /** - * Override method used to apply different animations when the dragged view is released. The - * dragged view is going to be maximized or minimized if the view is above the middle of the - * custom view and the velocity is greater than a constant value. - * - * @param releasedChild the captured child view now being released. - * @param xVel X velocity of the pointer as it left the screen in pixels per second. - * @param yVel Y velocity of the pointer as it left the screen in pixels per second. - */ - @Override public void onViewReleased(View releasedChild, float xVel, float yVel) { - super.onViewReleased(releasedChild, xVel, yVel); - if (draggableView.isDragViewAtBottom() && !draggableView.isDragViewAtRight()) { - triggerOnReleaseActionsWhileHorizontalDrag(xVel); - } else { - triggerOnReleaseActionsWhileVerticalDrag(yVel); - } - } + /** + * Override method used to apply different scale and alpha effects while the view is being + * dragged. + * + * @param left position. + * @param top position. + * @param dx change in X position from the last call. + * @param dy change in Y position from the last call. + */ + @Override + public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy){ + if(draggableView.isDragViewAtBottom()){ + draggableView.changeDragViewViewAlpha(); + } else{ + draggableView.restoreAlpha(); + draggableView.changeDragViewScale(); + draggableView.changeDragViewPosition(); + draggableView.changeSecondViewAlpha(); + draggableView.changeSecondViewPosition(); + draggableView.changeBackgroundAlpha(); + } + } - /** - * Override method used to configure which is going to be the dragged view. - * - * @param view child the user is attempting to capture. - * @param pointerId ID of the pointer attempting the capture, - * @return true if capture should be allowed, false otherwise. - */ - @Override public boolean tryCaptureView(View view, int pointerId) { - return view.equals(draggedView); - } + + /** + * Override method used to apply different animations when the dragged view is released. The + * dragged view is going to be maximized or minimized if the view is above the middle of the + * custom view and the velocity is greater than a constant value. + * + * @param releasedChild the captured child view now being released. + * @param xVel X velocity of the pointer as it left the screen in pixels per second. + * @param yVel Y velocity of the pointer as it left the screen in pixels per second. + */ + @Override + public void onViewReleased(View releasedChild, float xVel, float yVel){ + super.onViewReleased(releasedChild, xVel, yVel); + + if(draggableView.isDragViewAtBottom() && !draggableView.isDragViewAtRight()){ + triggerOnReleaseActionsWhileHorizontalDrag(xVel); + } else{ + triggerOnReleaseActionsWhileVerticalDrag(yVel); + } + } + + + /** + * Override method used to configure which is going to be the dragged view. + * + * @param view child the user is attempting to capture. + * @param pointerId ID of the pointer attempting the capture, + * @return true if capture should be allowed, false otherwise. + */ + @Override + public boolean tryCaptureView(View view, int pointerId){ + return view.equals(draggedView); + } /** * Override method used to configure the horizontal drag. Restrict the motion of the dragged diff --git a/sample/src/main/java/com/github/pedrovgs/sample/activity/YoutubeSampleActivity.java b/sample/src/main/java/com/github/pedrovgs/sample/activity/YoutubeSampleActivity.java index 2606b24..965940f 100644 --- a/sample/src/main/java/com/github/pedrovgs/sample/activity/YoutubeSampleActivity.java +++ b/sample/src/main/java/com/github/pedrovgs/sample/activity/YoutubeSampleActivity.java @@ -144,7 +144,7 @@ public void onMaximized(){ @Override public void onMinimized(){ - //Empty + } @@ -185,6 +185,5 @@ private void playVideo(){ public void onConfigurationChanged(Configuration newConfig){ super.onConfigurationChanged(newConfig); - } } From 04aa20f82d9144905ac8a9f057cdbc249d8d572e Mon Sep 17 00:00:00 2001 From: Yarh Date: Tue, 6 Oct 2015 21:10:58 +0300 Subject: [PATCH 3/4] travis fix? --- draggablepanel/res/layout/draggable_panel.xml | 9 +- draggablepanel/res/values/attrs.xml | 60 +- .../com/github/pedrovgs/DraggablePanel.java | 1 - .../com/github/pedrovgs/DraggableView.java | 1647 ++++++++--------- .../pedrovgs/DraggableViewCallback.java | 148 +- .../transformer/ResizeTransformer.java | 9 +- .../transformer/ScaleTransformer.java | 1 - 7 files changed, 898 insertions(+), 977 deletions(-) diff --git a/draggablepanel/res/layout/draggable_panel.xml b/draggablepanel/res/layout/draggable_panel.xml index 97545a0..1132578 100644 --- a/draggablepanel/res/layout/draggable_panel.xml +++ b/draggablepanel/res/layout/draggable_panel.xml @@ -5,19 +5,22 @@ android:layout_width="fill_parent" android:layout_height="fill_parent" draggable_view:bottom_view_id="@+id/second_view" - draggable_view:top_view_id="@+id/drag_view"> + draggable_view:top_view_id="@+id/drag_view" + > + android:layout_below="@+id/drag_view" + /> + android:orientation="vertical" + /> \ No newline at end of file diff --git a/draggablepanel/res/values/attrs.xml b/draggablepanel/res/values/attrs.xml index 7521a99..1d6b267 100644 --- a/draggablepanel/res/values/attrs.xml +++ b/draggablepanel/res/values/attrs.xml @@ -1,29 +1,49 @@ - - - - - - - - - + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + \ No newline at end of file diff --git a/draggablepanel/src/main/java/com/github/pedrovgs/DraggablePanel.java b/draggablepanel/src/main/java/com/github/pedrovgs/DraggablePanel.java index f1f0556..75453d8 100644 --- a/draggablepanel/src/main/java/com/github/pedrovgs/DraggablePanel.java +++ b/draggablepanel/src/main/java/com/github/pedrovgs/DraggablePanel.java @@ -146,7 +146,6 @@ public void setClickToMinimizeEnabled(boolean enableClickToMinimize) { } /** - * * Slide the view based on scroll of the nav drawer. * "setEnableTouch" user prevents click to expand while the drawer is moving. * It's only possible to maximize the view when @slideOffset is equals to 0.0, diff --git a/draggablepanel/src/main/java/com/github/pedrovgs/DraggableView.java b/draggablepanel/src/main/java/com/github/pedrovgs/DraggableView.java index 6040125..12aedab 100644 --- a/draggablepanel/src/main/java/com/github/pedrovgs/DraggableView.java +++ b/draggablepanel/src/main/java/com/github/pedrovgs/DraggableView.java @@ -28,7 +28,6 @@ import android.view.MotionEvent; import android.view.View; import android.widget.RelativeLayout; - import com.github.pedrovgs.transformer.Transformer; import com.github.pedrovgs.transformer.TransformerFactory; import com.nineoldandroids.view.ViewHelper; @@ -38,871 +37,783 @@ * * @author Pedro Vicente Gómez Sánchez */ -public class DraggableView extends RelativeLayout{ - - private static final int DEFAULT_SCALE_FACTOR = 2; - private static final int DEFAULT_TOP_VIEW_MARGIN = 30; - private static final int DEFAULT_TOP_VIEW_HEIGHT = -1; - private static final float SLIDE_TOP = 0f; - private static final float SLIDE_BOTTOM = 1f; - private static final float MIN_SLIDE_OFFSET = 0.1f; - private static final boolean DEFAULT_ENABLE_HORIZONTAL_ALPHA_EFFECT = true; - private static final boolean DEFAULT_ENABLE_CLICK_TO_MAXIMIZE = false; - private static final boolean DEFAULT_ENABLE_CLICK_TO_MINIMIZE = false; - private static final boolean DEFAULT_ENABLE_TOUCH_LISTENER = true; - private static final int MIN_SLIDING_DISTANCE_ON_CLICK = 10; - private static final int ONE_HUNDRED = 100; - private static final float SENSITIVITY = 1f; - private static final boolean DEFAULT_TOP_VIEW_RESIZE = false; - private static final int INVALID_POINTER = -1; - - private int activePointerId = INVALID_POINTER; - private float lastTouchActionDownXPosition; - - private View dragView; - private View secondView; - private TypedArray attributes; - - private FragmentManager fragmentManager; - private ViewDragHelper viewDragHelper; - private Transformer transformer; - - private boolean enableHorizontalAlphaEffect; - private boolean topViewResize; - private boolean enableClickToMaximize; - private boolean enableClickToMinimize; - private boolean touchEnabled; - - private DraggableListener listener; - - - public DraggableView(Context context){ - super(context); - } - - - public DraggableView(Context context, AttributeSet attrs){ - super(context, attrs); - initializeAttributes(attrs); - } - - - public DraggableView(Context context, AttributeSet attrs, int defStyle){ - super(context, attrs, defStyle); - initializeAttributes(attrs); - } - - - /** - * Return if user can maximize minimized view on click. - */ - public boolean isClickToMaximizeEnabled(){ - return enableClickToMaximize; - } - - - /** - * Enable or disable click to maximize view when dragged view is minimized - * If your content have a touch/click listener (like YoutubePlayer), you - * need disable it to active this feature. - * - * @param enableClickToMaximize to enable or disable the click. - */ - public void setClickToMaximizeEnabled(boolean enableClickToMaximize){ - this.enableClickToMaximize = enableClickToMaximize; - } - - - /** - * Return if user can minimize maximized view on click. - */ - public boolean isClickToMinimizeEnabled(){ - return enableClickToMinimize; - } - - - /** - * Enable or disable click to minimize view when dragged view is maximized - * If your content have a touch/click listener (like YoutubePlayer), you - * need disable it to active this feature. - * - * @param enableClickToMinimize to enable or disable the click. - */ - public void setClickToMinimizeEnabled(boolean enableClickToMinimize){ - this.enableClickToMinimize = enableClickToMinimize; - } - - - /** - * Return if touch listener is enable or disable - */ - private boolean isTouchEnabled(){ - return this.touchEnabled; - } - - - /** - * Enable or disable the touch listener - * - * @param touchEnabled to enable or disable the touch event. - */ - public void setTouchEnabled(boolean touchEnabled){ - this.touchEnabled = touchEnabled; - } - - - /** - * Slide the view based on scroll of the nav drawer. - * "setEnableTouch" user prevents click to expand while the drawer is moving, it will be - * set to false when the @slideOffset is bigger than MIN_SLIDE_OFFSET. - * When the slideOffset is bigger than 0.1 and dragView isn't close, set the dragView - * to minimized. - * It's only possible to maximize the view when @slideOffset is equals to 0.0, - * in other words, closed. - * - * @param slideOffset Value between 0 and 1, represent the value of slide: - * 0.0 is equal to close drawer and 1.0 equals open drawer. - * @param drawerPosition Represent the position of nav drawer on X axis. - * @param width Width of nav drawer - */ - public void slideHorizontally(float slideOffset, float drawerPosition, int width){ - if(slideOffset > MIN_SLIDE_OFFSET && !isClosed() && isMaximized()){ - minimize(); - } - setTouchEnabled(slideOffset <= MIN_SLIDE_OFFSET); - ViewHelper.setX(this, width - Math.abs(drawerPosition)); - } - - - /** - * Configure the horizontal scale factor applied when the view is dragged to the bottom of the - * custom view. - */ - public void setXTopViewScaleFactor(float xScaleFactor){ - transformer.setXScaleFactor(xScaleFactor); - } - - - /** - * Configure the vertical scale factor applied when the view is dragged to the bottom of the - * custom view. - */ - public void setYTopViewScaleFactor(float yScaleFactor){ - transformer.setYScaleFactor(yScaleFactor); - } - - - /** - * Configure the dragged view margin right applied when the dragged view is minimized. - * - * @param topFragmentMarginRight in pixels. - */ - public void setTopViewMarginRight(int topFragmentMarginRight){ - transformer.setMarginRight(topFragmentMarginRight); - } - - - /** - * Configure the dragView margin bottom applied when the dragView is minimized. - */ - public void setTopViewMarginBottom(int topFragmentMarginBottom){ - transformer.setMarginBottom(topFragmentMarginBottom); - } - - - /** - * Configure the dragged view height. - * - * @param topFragmentHeight in pixels - */ - public void setTopViewHeight(int topFragmentHeight){ - transformer.setViewHeight(topFragmentHeight); - } - - - /** - * Configure the disabling of the alpha effect applied when the dragView is dragged horizontally. - */ - public void setHorizontalAlphaEffectEnabled(boolean enableHorizontalAlphaEffect){ - this.enableHorizontalAlphaEffect = enableHorizontalAlphaEffect; - } - - - /** - * Configure the DraggableListener notified when the view is minimized, maximized, closed to the - * right or closed to the left. - */ - public void setDraggableListener(DraggableListener listener){ - this.listener = listener; - } - - - /** - * Configure DraggableView to resize top view instead of scale it. - */ - public void setTopViewResize(boolean topViewResize){ - this.topViewResize = topViewResize; - } - - - /** - * To ensure the animation is going to work this method has been override to call - * postInvalidateOnAnimation if the view is not settled yet. - */ - @Override - public void computeScroll(){ - if(!isInEditMode() && viewDragHelper.continueSettling(true)){ - ViewCompat.postInvalidateOnAnimation(this); - } - } - - - /** - * Maximize the custom view applying an animation to return the view to the initial position. - */ - public void maximize(){ - smoothSlideTo(SLIDE_TOP); - notifyMaximizeToListener(); - } - - - /** - * Minimize the custom view applying an animation to put the top fragment on the bottom right - * corner of the screen. - */ - public void minimize(){ - smoothSlideTo(SLIDE_BOTTOM); - notifyMinimizeToListener(); - } - - - /** - * Close the custom view applying an animation to close the view to the right side of the screen. - */ - public void closeToRight(){ - - DisplayMetrics dm = getResources().getDisplayMetrics(); - int maxSize = Math.max(dm.widthPixels, dm.heightPixels); - if(viewDragHelper.smoothSlideViewTo( - dragView, transformer.getOriginalWidth() + maxSize, getHeight() - transformer.getMinHeightPlusMargin() - )){ - ViewCompat.postInvalidateOnAnimation(this); - notifyCloseToRightListener(); - } - } - - - /** - * Close the custom view applying an animation to close the view to the left side of the screen. - */ - public void closeToLeft(){ - DisplayMetrics dm = getResources().getDisplayMetrics(); - int maxSize = Math.max(dm.widthPixels, dm.heightPixels); - if(viewDragHelper.smoothSlideViewTo( - dragView, -maxSize * 20, getHeight() - transformer.getMinHeightPlusMargin() - )){ - ViewCompat.postInvalidateOnAnimation(this); - notifyCloseToLeftListener(); - } - } - - - /** - * Checks if the top view is minimized. - * - * @return true if the view is minimized. - */ - public boolean isMinimized(){ - return isDragViewAtBottom() && isDragViewAtRight(); - } - - - /** - * Checks if the top view is maximized. - * - * @return true if the view is maximized. - */ - public boolean isMaximized(){ - return isDragViewAtTop(); - } - - - /** - * Checks if the top view closed at the right place. - * - * @return true if the view is closed at right. - */ - public boolean isClosedAtRight(){ - return dragView.getLeft() >= transformer.getOriginalWidth(); - } - - - /** - * Checks if the top view is closed at the left place. - * - * @return true if the view is closed at left. - */ - public boolean isClosedAtLeft(){ - return dragView.getRight() <= 0; - } - - - /** - * Checks if the top view is closed at the right or left place. - * - * @return true if the view is closed. - */ - public boolean isClosed(){ - return isClosedAtLeft() || isClosedAtRight(); - } - - - /** - * Override method to intercept only touch events over the drag view and to cancel the drag when - * the action associated to the MotionEvent is equals to ACTION_CANCEL or ACTION_UP. - * - * @param ev captured. - * @return true if the view is going to process the touch event or false if not. - */ - @Override - public boolean onInterceptTouchEvent(MotionEvent ev){ - if(!isEnabled()){ - return false; - } - switch(MotionEventCompat.getActionMasked(ev) & MotionEventCompat.ACTION_MASK){ - case MotionEvent.ACTION_CANCEL: - case MotionEvent.ACTION_UP: - viewDragHelper.cancel(); - return false; - case MotionEvent.ACTION_DOWN: - int index = MotionEventCompat.getActionIndex(ev); - activePointerId = MotionEventCompat.getPointerId(ev, index); - if(activePointerId == INVALID_POINTER){ - return false; - } - break; - default: - break; - } - boolean interceptTap = - viewDragHelper.isViewUnder(dragView, (int) ev.getX(), (int) ev.getY()); - return viewDragHelper.shouldInterceptTouchEvent(ev) || interceptTap; - } - - - /** - * Override method to dispatch touch event to the dragged view. - * - * @param ev captured. - * @return true if the touch event is realized over the drag or second view. - */ - @Override - public boolean onTouchEvent(MotionEvent ev){ - int actionMasked = MotionEventCompat.getActionMasked(ev); - if((actionMasked & MotionEventCompat.ACTION_MASK) == MotionEvent.ACTION_DOWN){ - activePointerId = MotionEventCompat.getPointerId(ev, actionMasked); - } - if(activePointerId == INVALID_POINTER){ - return false; - } - viewDragHelper.processTouchEvent(ev); - if(isClosed()){ - return false; - } - boolean isDragViewHit = isViewHit(dragView, (int) ev.getX(), (int) ev.getY()); - boolean isSecondViewHit = isViewHit(secondView, (int) ev.getX(), (int) ev.getY()); - analyzeTouchToMaximizeIfNeeded(ev, isDragViewHit); - if(isMaximized()){ - dragView.dispatchTouchEvent(ev); - } else{ - dragView.dispatchTouchEvent(cloneMotionEventWithAction(ev, MotionEvent.ACTION_CANCEL)); - } - return isDragViewHit || isSecondViewHit; - } - - - private void analyzeTouchToMaximizeIfNeeded(MotionEvent ev, boolean isDragViewHit){ - switch(ev.getAction()){ - case MotionEvent.ACTION_DOWN: - lastTouchActionDownXPosition = ev.getX(); - break; - case MotionEvent.ACTION_UP: - float clickOffset = ev.getX() - lastTouchActionDownXPosition; - if(shouldMaximizeOnClick(ev, clickOffset, isDragViewHit)){ - if(isMinimized() && isClickToMaximizeEnabled()){ - maximize(); - } else if(isMaximized() && isClickToMinimizeEnabled()){ - minimize(); - } - } - break; - default: - break; - } - } - - - public boolean shouldMaximizeOnClick(MotionEvent ev, float deltaX, boolean isDragViewHit){ - return (Math.abs(deltaX) < MIN_SLIDING_DISTANCE_ON_CLICK) && ev.getAction() != MotionEvent.ACTION_MOVE && isDragViewHit; - } - - - /** - * Clone given motion event and set specified action. This method is useful, when we want to - * cancel event propagation in child views by sending event with {@link - * android.view.MotionEvent#ACTION_CANCEL} - * action. - * - * @param event event to clone - * @param action new action - * @return cloned motion event - */ - private MotionEvent cloneMotionEventWithAction(MotionEvent event, int action){ - return MotionEvent.obtain( - event.getDownTime(), event.getEventTime(), action, event.getX(), event.getY(), event.getMetaState() - ); - } - - - private int oldOrientation = -1; - /** - * Override method to configure the dragged view and secondView layout properly. - */ - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom){ - DisplayMetrics dm = getResources().getDisplayMetrics(); - if(oldOrientation == -1){ oldOrientation = getResources().getConfiguration().orientation; } - if(isInEditMode()){ - super.onLayout(changed, left, top, right, bottom); - } else if(isDragViewAtTop()){ - dragView.layout(left, top, right, transformer.getOriginalHeight()); - secondView.layout(left, transformer.getOriginalHeight(), right, bottom); - ViewHelper.setY(dragView, top); - ViewHelper.setY(secondView, transformer.getOriginalHeight()); - } else{ - dragView.setVisibility(INVISIBLE); - if(isClosedAtLeft()){ - if(oldOrientation != getResources().getConfiguration().orientation){ - dragView.layout(left, top, right, transformer.getOriginalHeight()); - - secondView.layout(left, transformer.getOriginalHeight(), right, bottom); - oldOrientation = getResources().getConfiguration().orientation; - - } - closeToLeft(); - } else if(isClosedAtRight()){ - if(oldOrientation != getResources().getConfiguration().orientation){ - dragView.layout(left, top, right, transformer.getOriginalHeight()); - secondView.layout(left, transformer.getOriginalHeight(), right, bottom); - oldOrientation = getResources().getConfiguration().orientation; - - } - - closeToRight(); - - } else{ - if(oldOrientation != getResources().getConfiguration().orientation){ - dragView.layout(left, top, right, transformer.getOriginalHeight()); - secondView.layout(left, transformer.getOriginalHeight(), right, bottom); - oldOrientation = getResources().getConfiguration().orientation; - - } - smoothSlideTo(SLIDE_BOTTOM); - } - dragView.setVisibility(VISIBLE); - } - oldOrientation = getResources().getConfiguration().orientation; - } - - - /** - * Override method to map dragged view, secondView to view objects, to configure dragged - * view height and to initialize DragViewHelper. - */ - @Override - protected void onFinishInflate(){ - super.onFinishInflate(); - if(!isInEditMode()){ - mapGUI(attributes); - initializeTransformer(attributes); - attributes.recycle(); - initializeViewDragHelper(); - } - } - - - private void mapGUI(TypedArray attributes){ - int dragViewId = - attributes.getResourceId(R.styleable.draggable_view_top_view_id, R.id.drag_view); - int secondViewId = - attributes.getResourceId(R.styleable.draggable_view_bottom_view_id, R.id.second_view); - dragView = findViewById(dragViewId); - secondView = findViewById(secondViewId); - } - - - /** - * Configure the FragmentManager used to attach top and bottom Fragments to the view. The - * FragmentManager is going to be provided only by DraggablePanel view. - */ - void setFragmentManager(FragmentManager fragmentManager){ - this.fragmentManager = fragmentManager; - } - - - /** - * Attach one fragment to the dragged view. - * - * @param topFragment to be attached. - */ - void attachTopFragment(Fragment topFragment){ - addFragmentToView(R.id.drag_view, topFragment); - } - - - /** - * Attach one fragment to the secondView. - * - * @param bottomFragment to be attached. - */ - void attachBottomFragment(Fragment bottomFragment){ - addFragmentToView(R.id.second_view, bottomFragment); - } - - - /** - * Modify dragged view pivot based on the dragged view vertical position to simulate a horizontal - * displacement while the view is dragged. - */ - void changeDragViewPosition(){ - transformer.updatePosition(getVerticalDragOffset()); - } - - - /** - * Modify secondView position to be always below dragged view. - */ - void changeSecondViewPosition(){ - ViewHelper.setY(secondView, dragView.getBottom()); - } - - - /** - * Modify dragged view scale based on the dragged view vertical position and the scale factor. - */ - void changeDragViewScale(){ - transformer.updateScale(getVerticalDragOffset()); - } - - - /** - * Modify the background alpha if has been configured to applying an alpha effect when the view - * is dragged. - */ - void changeBackgroundAlpha(){ - Drawable background = getBackground(); - if(background != null){ - int newAlpha = (int) (ONE_HUNDRED * (1 - getVerticalDragOffset())); - background.setAlpha(newAlpha); - } - } - - - /** - * Modify the second view alpha based on dragged view vertical position. - */ - void changeSecondViewAlpha(){ - ViewHelper.setAlpha(secondView, 1 - getVerticalDragOffset()); - } - - - /** - * Modify dragged view alpha based on the horizontal position while the view is being - * horizontally dragged. - */ - void changeDragViewViewAlpha(){ - if(enableHorizontalAlphaEffect){ - float alpha = 1 - getHorizontalDragOffset(); - if(alpha == 0){ - alpha = 1; - } - ViewHelper.setAlpha(dragView, alpha); - } - } - - - /** - * Restore view alpha to 1 - */ - void restoreAlpha(){ - if(enableHorizontalAlphaEffect && ViewHelper.getAlpha(dragView) < 1){ - ViewHelper.setAlpha(dragView, 1); - } - } - - - /** - * Check if dragged view is above the middle of the custom view. - * - * @return true if dragged view is above the middle of the custom view or false if is below. - */ - boolean isDragViewAboveTheMiddle(){ - return transformer.isAboveTheMiddle(); - } - - - /** - * Check if dragged view is next to the left bound. - * - * @return true if dragged view right position is behind the right half of the custom view. - */ - boolean isNextToLeftBound(){ - return transformer.isNextToLeftBound(); - } - - - /** - * Check if dragged view is next to the right bound. - * - * @return true if dragged view left position is behind the left quarter of the custom view. - */ - boolean isNextToRightBound(){ - return transformer.isNextToRightBound(); - } - - - /** - * Check if dragged view is at the top of the custom view. - * - * @return true if dragged view top position is equals to zero. - */ - boolean isDragViewAtTop(){ - return transformer.isViewAtTop(); - } - - - /** - * Check if dragged view is at the right of the custom view. - * - * @return true if dragged view right position is equals to custom view width. - */ - boolean isDragViewAtRight(){ - return transformer.isViewAtRight(); - } - - - /** - * Check if dragged view is at the bottom of the custom view. - * - * @return true if dragged view bottom position is equals to custom view height. - */ - boolean isDragViewAtBottom(){ - return transformer.isViewAtBottom(); - } - - - /** - * Calculate if one position is above any view. - * - * @param view to analyze. - * @param x position. - * @param y position. - * @return true if x and y positions are below the view. - */ - 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(); - } - - - /** - * Use FragmentManager to attach one fragment to one view using the viewId. - * - * @param viewId used to obtain the view. - * @param fragment to be attached. - */ - private void addFragmentToView(final int viewId, final Fragment fragment){ - fragmentManager.beginTransaction().replace(viewId, fragment).commit(); - } - - - /** - * Initialize the viewDragHelper. - */ - private void initializeViewDragHelper(){ - viewDragHelper = - ViewDragHelper.create(this, SENSITIVITY, new DraggableViewCallback(this, dragView)); - } - - - /** - * Initialize Transformer with a scalable or change width/height implementation. - */ - private void initializeTransformer(TypedArray attributes){ - topViewResize = - attributes.getBoolean(R.styleable.draggable_view_top_view_resize, DEFAULT_TOP_VIEW_RESIZE); - TransformerFactory transformerFactory = new TransformerFactory(); - transformer = transformerFactory.getTransformer(topViewResize, dragView, this); - transformer.setViewHeight( - attributes.getDimensionPixelSize( - R.styleable.draggable_view_top_view_height, DEFAULT_TOP_VIEW_HEIGHT - ) - ); - transformer.setXScaleFactor( - attributes.getFloat( - R.styleable.draggable_view_top_view_x_scale_factor, DEFAULT_SCALE_FACTOR - ) - ); - transformer.setYScaleFactor( - attributes.getFloat( - R.styleable.draggable_view_top_view_y_scale_factor, DEFAULT_SCALE_FACTOR - ) - ); - transformer.setMarginRight( - attributes.getDimensionPixelSize( - R.styleable.draggable_view_top_view_margin_right, DEFAULT_TOP_VIEW_MARGIN - ) - ); - transformer.setMarginBottom( - attributes.getDimensionPixelSize( - R.styleable.draggable_view_top_view_margin_bottom, DEFAULT_TOP_VIEW_MARGIN - ) - ); - } - - - /** - * Initialize XML attributes. - * - * @param attrs to be analyzed. - */ - private void initializeAttributes(AttributeSet attrs){ - TypedArray attributes = - getContext().obtainStyledAttributes(attrs, R.styleable.draggable_view); - this.enableHorizontalAlphaEffect = attributes.getBoolean( - R.styleable.draggable_view_enable_minimized_horizontal_alpha_effect, DEFAULT_ENABLE_HORIZONTAL_ALPHA_EFFECT - ); - this.enableClickToMaximize = attributes.getBoolean( - R.styleable.draggable_view_enable_click_to_maximize_view, DEFAULT_ENABLE_CLICK_TO_MAXIMIZE - ); - this.enableClickToMinimize = attributes.getBoolean( - R.styleable.draggable_view_enable_click_to_minimize_view, DEFAULT_ENABLE_CLICK_TO_MINIMIZE - ); - this.attributes = attributes; - } - - - /** - * Realize an smooth slide to an slide offset passed as argument. This method is the base of - * maximize, minimize and close methods. - * - * @param slideOffset to apply - * @return true if the view is slided. - */ - private boolean smoothSlideTo(float slideOffset){ - final int topBound = getPaddingTop(); - int y = (int) (topBound + slideOffset * getVerticalDragRange()); - if(viewDragHelper.smoothSlideViewTo(dragView, 0, y)){ - ViewCompat.postInvalidateOnAnimation(this); - return true; - } - return false; - } - - - /** - * @return configured dragged view margin right configured. - */ - private int getDragViewMarginRight(){ - return transformer.getMarginRight(); - } - - - /** - * @return configured dragged view margin bottom. - */ - private int getDragViewMarginBottom(){ - return transformer.getMarginBottom(); - } - - - /** - * Calculate the dragged view left position normalized between 1 and 0. - * - * @return absolute value between the dragged view left position divided by custon view width - */ - private float getHorizontalDragOffset(){ - return (float) Math.abs(dragView.getLeft()) / (float) getWidth(); - } - - - /** - * Calculate the dragged view top position normalized between 1 and 0. - * - * @return dragged view top divided by vertical drag range. - */ - private float getVerticalDragOffset(){ - return dragView.getTop() / getVerticalDragRange(); - } - - - /** - * Calculate the vertical drag range between the custom view and dragged view. - * - * @return the difference between the custom view height and the dragged view height. - */ - private float getVerticalDragRange(){ - return getHeight() - transformer.getMinHeightPlusMargin(); - } - - - /** - * Notify te view is maximized to the DraggableListener - */ - private void notifyMaximizeToListener(){ - if(listener != null){ - listener.onMaximized(); - } - } - - - /** - * Notify te view is minimized to the DraggableListener - */ - private void notifyMinimizeToListener(){ - if(listener != null){ - listener.onMinimized(); - } - } - - - /** - * Notify te view is closed to the right to the DraggableListener - */ - private void notifyCloseToRightListener(){ - if(listener != null){ - listener.onClosedToRight(); - } - } - - - /** - * Notify te view is closed to the left to the DraggableListener - */ - private void notifyCloseToLeftListener(){ - if(listener != null){ - listener.onClosedToLeft(); - } - } - - - public int getDraggedViewHeightPlusMarginTop(){ - return transformer.getMinHeightPlusMargin(); - } +public class DraggableView extends RelativeLayout { + + private static final int DEFAULT_SCALE_FACTOR = 2; + private static final int DEFAULT_TOP_VIEW_MARGIN = 30; + private static final int DEFAULT_TOP_VIEW_HEIGHT = -1; + private static final float SLIDE_TOP = 0f; + private static final float SLIDE_BOTTOM = 1f; + private static final float MIN_SLIDE_OFFSET = 0.1f; + private static final boolean DEFAULT_ENABLE_HORIZONTAL_ALPHA_EFFECT = true; + private static final boolean DEFAULT_ENABLE_CLICK_TO_MAXIMIZE = false; + private static final boolean DEFAULT_ENABLE_CLICK_TO_MINIMIZE = false; + private static final boolean DEFAULT_ENABLE_TOUCH_LISTENER = true; + private static final int MIN_SLIDING_DISTANCE_ON_CLICK = 10; + private static final int ONE_HUNDRED = 100; + private static final float SENSITIVITY = 1f; + private static final boolean DEFAULT_TOP_VIEW_RESIZE = false; + private static final int INVALID_POINTER = -1; + + private int activePointerId = INVALID_POINTER; + private float lastTouchActionDownXPosition; + + private View dragView; + private View secondView; + private TypedArray attributes; + + private FragmentManager fragmentManager; + private ViewDragHelper viewDragHelper; + private Transformer transformer; + + private boolean enableHorizontalAlphaEffect; + private boolean topViewResize; + private boolean enableClickToMaximize; + private boolean enableClickToMinimize; + private boolean touchEnabled; + + private DraggableListener listener; + + public DraggableView(Context context) { + super(context); + } + + public DraggableView(Context context, AttributeSet attrs) { + super(context, attrs); + initializeAttributes(attrs); + } + + public DraggableView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + initializeAttributes(attrs); + } + + /** + * Return if user can maximize minimized view on click. + */ + public boolean isClickToMaximizeEnabled() { + return enableClickToMaximize; + } + + /** + * Enable or disable click to maximize view when dragged view is minimized + * If your content have a touch/click listener (like YoutubePlayer), you + * need disable it to active this feature. + * + * @param enableClickToMaximize to enable or disable the click. + */ + public void setClickToMaximizeEnabled(boolean enableClickToMaximize) { + this.enableClickToMaximize = enableClickToMaximize; + } + + /** + * Return if user can minimize maximized view on click. + */ + public boolean isClickToMinimizeEnabled() { + return enableClickToMinimize; + } + + /** + * Enable or disable click to minimize view when dragged view is maximized + * If your content have a touch/click listener (like YoutubePlayer), you + * need disable it to active this feature. + * + * @param enableClickToMinimize to enable or disable the click. + */ + public void setClickToMinimizeEnabled(boolean enableClickToMinimize) { + this.enableClickToMinimize = enableClickToMinimize; + } + + /** + * Return if touch listener is enable or disable + */ + private boolean isTouchEnabled() { + return this.touchEnabled; + } + + /** + * Enable or disable the touch listener + * + * @param touchEnabled to enable or disable the touch event. + */ + public void setTouchEnabled(boolean touchEnabled) { + this.touchEnabled = touchEnabled; + } + + /** + * Slide the view based on scroll of the nav drawer. + * "setEnableTouch" user prevents click to expand while the drawer is moving, it will be + * set to false when the @slideOffset is bigger than MIN_SLIDE_OFFSET. + * When the slideOffset is bigger than 0.1 and dragView isn't close, set the dragView + * to minimized. + * It's only possible to maximize the view when @slideOffset is equals to 0.0, + * in other words, closed. + * + * @param slideOffset Value between 0 and 1, represent the value of slide: + * 0.0 is equal to close drawer and 1.0 equals open drawer. + * @param drawerPosition Represent the position of nav drawer on X axis. + * @param width Width of nav drawer + */ + public void slideHorizontally(float slideOffset, float drawerPosition, int width) { + if (slideOffset > MIN_SLIDE_OFFSET && !isClosed() && isMaximized()) { + minimize(); + } + setTouchEnabled(slideOffset <= MIN_SLIDE_OFFSET); + ViewHelper.setX(this, width - Math.abs(drawerPosition)); + } + + /** + * Configure the horizontal scale factor applied when the view is dragged to the bottom of the + * custom view. + */ + public void setXTopViewScaleFactor(float xScaleFactor) { + transformer.setXScaleFactor(xScaleFactor); + } + + /** + * Configure the vertical scale factor applied when the view is dragged to the bottom of the + * custom view. + */ + public void setYTopViewScaleFactor(float yScaleFactor) { + transformer.setYScaleFactor(yScaleFactor); + } + + /** + * Configure the dragged view margin right applied when the dragged view is minimized. + * + * @param topFragmentMarginRight in pixels. + */ + public void setTopViewMarginRight(int topFragmentMarginRight) { + transformer.setMarginRight(topFragmentMarginRight); + } + + /** + * Configure the dragView margin bottom applied when the dragView is minimized. + */ + public void setTopViewMarginBottom(int topFragmentMarginBottom) { + transformer.setMarginBottom(topFragmentMarginBottom); + } + + /** + * Configure the dragged view height. + * + * @param topFragmentHeight in pixels + */ + public void setTopViewHeight(int topFragmentHeight) { + transformer.setViewHeight(topFragmentHeight); + } + + /** + * Configure the disabling of the alpha effect applied when the dragView is dragged horizontally. + */ + public void setHorizontalAlphaEffectEnabled(boolean enableHorizontalAlphaEffect) { + this.enableHorizontalAlphaEffect = enableHorizontalAlphaEffect; + } + + /** + * Configure the DraggableListener notified when the view is minimized, maximized, closed to the + * right or closed to the left. + */ + public void setDraggableListener(DraggableListener listener) { + this.listener = listener; + } + + /** + * Configure DraggableView to resize top view instead of scale it. + */ + public void setTopViewResize(boolean topViewResize) { + this.topViewResize = topViewResize; + } + + /** + * To ensure the animation is going to work this method has been override to call + * postInvalidateOnAnimation if the view is not settled yet. + */ + @Override public void computeScroll() { + if (!isInEditMode() && viewDragHelper.continueSettling(true)) { + ViewCompat.postInvalidateOnAnimation(this); + } + } + + /** + * Maximize the custom view applying an animation to return the view to the initial position. + */ + public void maximize() { + smoothSlideTo(SLIDE_TOP); + notifyMaximizeToListener(); + } + + /** + * Minimize the custom view applying an animation to put the top fragment on the bottom right + * corner of the screen. + */ + public void minimize() { + smoothSlideTo(SLIDE_BOTTOM); + notifyMinimizeToListener(); + } + + /** + * Close the custom view applying an animation to close the view to the right side of the screen. + */ + public void closeToRight() { + + DisplayMetrics dm = getResources().getDisplayMetrics(); + int maxSize = Math.max(dm.widthPixels, dm.heightPixels); + if (viewDragHelper.smoothSlideViewTo(dragView, transformer.getOriginalWidth() + maxSize, + getHeight() - transformer.getMinHeightPlusMargin())) { + ViewCompat.postInvalidateOnAnimation(this); + notifyCloseToRightListener(); + } + } + + /** + * Close the custom view applying an animation to close the view to the left side of the screen. + */ + public void closeToLeft() { + DisplayMetrics dm = getResources().getDisplayMetrics(); + int maxSize = Math.max(dm.widthPixels, dm.heightPixels); + if (viewDragHelper.smoothSlideViewTo(dragView, -maxSize * 20, + getHeight() - transformer.getMinHeightPlusMargin())) { + ViewCompat.postInvalidateOnAnimation(this); + notifyCloseToLeftListener(); + } + } + + /** + * Checks if the top view is minimized. + * + * @return true if the view is minimized. + */ + public boolean isMinimized() { + return isDragViewAtBottom() && isDragViewAtRight(); + } + + /** + * Checks if the top view is maximized. + * + * @return true if the view is maximized. + */ + public boolean isMaximized() { + return isDragViewAtTop(); + } + + /** + * Checks if the top view closed at the right place. + * + * @return true if the view is closed at right. + */ + public boolean isClosedAtRight() { + return dragView.getLeft() >= transformer.getOriginalWidth(); + } + + /** + * Checks if the top view is closed at the left place. + * + * @return true if the view is closed at left. + */ + public boolean isClosedAtLeft() { + return dragView.getRight() <= 0; + } + + /** + * Checks if the top view is closed at the right or left place. + * + * @return true if the view is closed. + */ + public boolean isClosed() { + return isClosedAtLeft() || isClosedAtRight(); + } + + /** + * Override method to intercept only touch events over the drag view and to cancel the drag when + * the action associated to the MotionEvent is equals to ACTION_CANCEL or ACTION_UP. + * + * @param ev captured. + * @return true if the view is going to process the touch event or false if not. + */ + @Override public boolean onInterceptTouchEvent(MotionEvent ev) { + if (!isEnabled()) { + return false; + } + switch (MotionEventCompat.getActionMasked(ev) & MotionEventCompat.ACTION_MASK) { + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: + viewDragHelper.cancel(); + return false; + case MotionEvent.ACTION_DOWN: + int index = MotionEventCompat.getActionIndex(ev); + activePointerId = MotionEventCompat.getPointerId(ev, index); + if (activePointerId == INVALID_POINTER) { + return false; + } + break; + default: + break; + } + boolean interceptTap = viewDragHelper.isViewUnder(dragView, (int) ev.getX(), (int) ev.getY()); + return viewDragHelper.shouldInterceptTouchEvent(ev) || interceptTap; + } + + /** + * Override method to dispatch touch event to the dragged view. + * + * @param ev captured. + * @return true if the touch event is realized over the drag or second view. + */ + @Override public boolean onTouchEvent(MotionEvent ev) { + int actionMasked = MotionEventCompat.getActionMasked(ev); + if ((actionMasked & MotionEventCompat.ACTION_MASK) == MotionEvent.ACTION_DOWN) { + activePointerId = MotionEventCompat.getPointerId(ev, actionMasked); + } + if (activePointerId == INVALID_POINTER) { + return false; + } + viewDragHelper.processTouchEvent(ev); + if (isClosed()) { + return false; + } + boolean isDragViewHit = isViewHit(dragView, (int) ev.getX(), (int) ev.getY()); + boolean isSecondViewHit = isViewHit(secondView, (int) ev.getX(), (int) ev.getY()); + analyzeTouchToMaximizeIfNeeded(ev, isDragViewHit); + if (isMaximized()) { + dragView.dispatchTouchEvent(ev); + } else { + dragView.dispatchTouchEvent(cloneMotionEventWithAction(ev, MotionEvent.ACTION_CANCEL)); + } + return isDragViewHit || isSecondViewHit; + } + + private void analyzeTouchToMaximizeIfNeeded(MotionEvent ev, boolean isDragViewHit) { + switch (ev.getAction()) { + case MotionEvent.ACTION_DOWN: + lastTouchActionDownXPosition = ev.getX(); + break; + case MotionEvent.ACTION_UP: + float clickOffset = ev.getX() - lastTouchActionDownXPosition; + if (shouldMaximizeOnClick(ev, clickOffset, isDragViewHit)) { + if (isMinimized() && isClickToMaximizeEnabled()) { + maximize(); + } else if (isMaximized() && isClickToMinimizeEnabled()) { + minimize(); + } + } + break; + default: + break; + } + } + + public boolean shouldMaximizeOnClick(MotionEvent ev, float deltaX, boolean isDragViewHit) { + return (Math.abs(deltaX) < MIN_SLIDING_DISTANCE_ON_CLICK) + && ev.getAction() != MotionEvent.ACTION_MOVE && isDragViewHit; + } + + /** + * Clone given motion event and set specified action. This method is useful, when we want to + * cancel event propagation in child views by sending event with {@link + * android.view.MotionEvent#ACTION_CANCEL} + * action. + * + * @param event event to clone + * @param action new action + * @return cloned motion event + */ + private MotionEvent cloneMotionEventWithAction(MotionEvent event, int action) { + return MotionEvent.obtain(event.getDownTime(), event.getEventTime(), action, event.getX(), + event.getY(), event.getMetaState()); + } + + private int oldOrientation = -1; + + /** + * Override method to configure the dragged view and secondView layout properly. + */ + @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + DisplayMetrics dm = getResources().getDisplayMetrics(); + if (oldOrientation == -1) { + oldOrientation = getResources().getConfiguration().orientation; + } + if (isInEditMode()) { + super.onLayout(changed, left, top, right, bottom); + } else if (isDragViewAtTop()) { + dragView.layout(left, top, right, transformer.getOriginalHeight()); + secondView.layout(left, transformer.getOriginalHeight(), right, bottom); + ViewHelper.setY(dragView, top); + ViewHelper.setY(secondView, transformer.getOriginalHeight()); + } else { + dragView.setVisibility(INVISIBLE); + if (isClosedAtLeft()) { + if (oldOrientation != getResources().getConfiguration().orientation) { + dragView.layout(left, top, right, transformer.getOriginalHeight()); + + secondView.layout(left, transformer.getOriginalHeight(), right, bottom); + oldOrientation = getResources().getConfiguration().orientation; + } + closeToLeft(); + } else if (isClosedAtRight()) { + if (oldOrientation != getResources().getConfiguration().orientation) { + dragView.layout(left, top, right, transformer.getOriginalHeight()); + secondView.layout(left, transformer.getOriginalHeight(), right, bottom); + oldOrientation = getResources().getConfiguration().orientation; + } + + closeToRight(); + } else { + if (oldOrientation != getResources().getConfiguration().orientation) { + dragView.layout(left, top, right, transformer.getOriginalHeight()); + secondView.layout(left, transformer.getOriginalHeight(), right, bottom); + oldOrientation = getResources().getConfiguration().orientation; + } + smoothSlideTo(SLIDE_BOTTOM); + } + dragView.setVisibility(VISIBLE); + } + oldOrientation = getResources().getConfiguration().orientation; + } + + /** + * Override method to map dragged view, secondView to view objects, to configure dragged + * view height and to initialize DragViewHelper. + */ + @Override protected void onFinishInflate() { + super.onFinishInflate(); + if (!isInEditMode()) { + mapGUI(attributes); + initializeTransformer(attributes); + attributes.recycle(); + initializeViewDragHelper(); + } + } + + private void mapGUI(TypedArray attributes) { + int dragViewId = + attributes.getResourceId(R.styleable.draggable_view_top_view_id, R.id.drag_view); + int secondViewId = + attributes.getResourceId(R.styleable.draggable_view_bottom_view_id, R.id.second_view); + dragView = findViewById(dragViewId); + secondView = findViewById(secondViewId); + } + + /** + * Configure the FragmentManager used to attach top and bottom Fragments to the view. The + * FragmentManager is going to be provided only by DraggablePanel view. + */ + void setFragmentManager(FragmentManager fragmentManager) { + this.fragmentManager = fragmentManager; + } + + /** + * Attach one fragment to the dragged view. + * + * @param topFragment to be attached. + */ + void attachTopFragment(Fragment topFragment) { + addFragmentToView(R.id.drag_view, topFragment); + } + + /** + * Attach one fragment to the secondView. + * + * @param bottomFragment to be attached. + */ + void attachBottomFragment(Fragment bottomFragment) { + addFragmentToView(R.id.second_view, bottomFragment); + } + + /** + * Modify dragged view pivot based on the dragged view vertical position to simulate a horizontal + * displacement while the view is dragged. + */ + void changeDragViewPosition() { + transformer.updatePosition(getVerticalDragOffset()); + } + + /** + * Modify secondView position to be always below dragged view. + */ + void changeSecondViewPosition() { + ViewHelper.setY(secondView, dragView.getBottom()); + } + + /** + * Modify dragged view scale based on the dragged view vertical position and the scale factor. + */ + void changeDragViewScale() { + transformer.updateScale(getVerticalDragOffset()); + } + + /** + * Modify the background alpha if has been configured to applying an alpha effect when the view + * is dragged. + */ + void changeBackgroundAlpha() { + Drawable background = getBackground(); + if (background != null) { + int newAlpha = (int) (ONE_HUNDRED * (1 - getVerticalDragOffset())); + background.setAlpha(newAlpha); + } + } + + /** + * Modify the second view alpha based on dragged view vertical position. + */ + void changeSecondViewAlpha() { + ViewHelper.setAlpha(secondView, 1 - getVerticalDragOffset()); + } + + /** + * Modify dragged view alpha based on the horizontal position while the view is being + * horizontally dragged. + */ + void changeDragViewViewAlpha() { + if (enableHorizontalAlphaEffect) { + float alpha = 1 - getHorizontalDragOffset(); + if (alpha == 0) { + alpha = 1; + } + ViewHelper.setAlpha(dragView, alpha); + } + } + + /** + * Restore view alpha to 1 + */ + void restoreAlpha() { + if (enableHorizontalAlphaEffect && ViewHelper.getAlpha(dragView) < 1) { + ViewHelper.setAlpha(dragView, 1); + } + } + + /** + * Check if dragged view is above the middle of the custom view. + * + * @return true if dragged view is above the middle of the custom view or false if is below. + */ + boolean isDragViewAboveTheMiddle() { + return transformer.isAboveTheMiddle(); + } + + /** + * Check if dragged view is next to the left bound. + * + * @return true if dragged view right position is behind the right half of the custom view. + */ + boolean isNextToLeftBound() { + return transformer.isNextToLeftBound(); + } + + /** + * Check if dragged view is next to the right bound. + * + * @return true if dragged view left position is behind the left quarter of the custom view. + */ + boolean isNextToRightBound() { + return transformer.isNextToRightBound(); + } + + /** + * Check if dragged view is at the top of the custom view. + * + * @return true if dragged view top position is equals to zero. + */ + boolean isDragViewAtTop() { + return transformer.isViewAtTop(); + } + + /** + * Check if dragged view is at the right of the custom view. + * + * @return true if dragged view right position is equals to custom view width. + */ + boolean isDragViewAtRight() { + return transformer.isViewAtRight(); + } + + /** + * Check if dragged view is at the bottom of the custom view. + * + * @return true if dragged view bottom position is equals to custom view height. + */ + boolean isDragViewAtBottom() { + return transformer.isViewAtBottom(); + } + + /** + * Calculate if one position is above any view. + * + * @param view to analyze. + * @param x position. + * @param y position. + * @return true if x and y positions are below the view. + */ + 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(); + } + + /** + * Use FragmentManager to attach one fragment to one view using the viewId. + * + * @param viewId used to obtain the view. + * @param fragment to be attached. + */ + private void addFragmentToView(final int viewId, final Fragment fragment) { + fragmentManager.beginTransaction().replace(viewId, fragment).commit(); + } + + /** + * Initialize the viewDragHelper. + */ + private void initializeViewDragHelper() { + viewDragHelper = + ViewDragHelper.create(this, SENSITIVITY, new DraggableViewCallback(this, dragView)); + } + + /** + * Initialize Transformer with a scalable or change width/height implementation. + */ + private void initializeTransformer(TypedArray attributes) { + topViewResize = + attributes.getBoolean(R.styleable.draggable_view_top_view_resize, DEFAULT_TOP_VIEW_RESIZE); + TransformerFactory transformerFactory = new TransformerFactory(); + transformer = transformerFactory.getTransformer(topViewResize, dragView, this); + transformer.setViewHeight( + attributes.getDimensionPixelSize(R.styleable.draggable_view_top_view_height, + DEFAULT_TOP_VIEW_HEIGHT)); + transformer.setXScaleFactor( + attributes.getFloat(R.styleable.draggable_view_top_view_x_scale_factor, + DEFAULT_SCALE_FACTOR)); + transformer.setYScaleFactor( + attributes.getFloat(R.styleable.draggable_view_top_view_y_scale_factor, + DEFAULT_SCALE_FACTOR)); + transformer.setMarginRight( + attributes.getDimensionPixelSize(R.styleable.draggable_view_top_view_margin_right, + DEFAULT_TOP_VIEW_MARGIN)); + transformer.setMarginBottom( + attributes.getDimensionPixelSize(R.styleable.draggable_view_top_view_margin_bottom, + DEFAULT_TOP_VIEW_MARGIN)); + } + + /** + * Initialize XML attributes. + * + * @param attrs to be analyzed. + */ + private void initializeAttributes(AttributeSet attrs) { + TypedArray attributes = getContext().obtainStyledAttributes(attrs, R.styleable.draggable_view); + this.enableHorizontalAlphaEffect = + attributes.getBoolean(R.styleable.draggable_view_enable_minimized_horizontal_alpha_effect, + DEFAULT_ENABLE_HORIZONTAL_ALPHA_EFFECT); + this.enableClickToMaximize = + attributes.getBoolean(R.styleable.draggable_view_enable_click_to_maximize_view, + DEFAULT_ENABLE_CLICK_TO_MAXIMIZE); + this.enableClickToMinimize = + attributes.getBoolean(R.styleable.draggable_view_enable_click_to_minimize_view, + DEFAULT_ENABLE_CLICK_TO_MINIMIZE); + this.attributes = attributes; + } + + /** + * Realize an smooth slide to an slide offset passed as argument. This method is the base of + * maximize, minimize and close methods. + * + * @param slideOffset to apply + * @return true if the view is slided. + */ + private boolean smoothSlideTo(float slideOffset) { + final int topBound = getPaddingTop(); + int y = (int) (topBound + slideOffset * getVerticalDragRange()); + if (viewDragHelper.smoothSlideViewTo(dragView, 0, y)) { + ViewCompat.postInvalidateOnAnimation(this); + return true; + } + return false; + } + + /** + * @return configured dragged view margin right configured. + */ + private int getDragViewMarginRight() { + return transformer.getMarginRight(); + } + + /** + * @return configured dragged view margin bottom. + */ + private int getDragViewMarginBottom() { + return transformer.getMarginBottom(); + } + + /** + * Calculate the dragged view left position normalized between 1 and 0. + * + * @return absolute value between the dragged view left position divided by custon view width + */ + private float getHorizontalDragOffset() { + return (float) Math.abs(dragView.getLeft()) / (float) getWidth(); + } + + /** + * Calculate the dragged view top position normalized between 1 and 0. + * + * @return dragged view top divided by vertical drag range. + */ + private float getVerticalDragOffset() { + return dragView.getTop() / getVerticalDragRange(); + } + + /** + * Calculate the vertical drag range between the custom view and dragged view. + * + * @return the difference between the custom view height and the dragged view height. + */ + private float getVerticalDragRange() { + return getHeight() - transformer.getMinHeightPlusMargin(); + } + + /** + * Notify te view is maximized to the DraggableListener + */ + private void notifyMaximizeToListener() { + if (listener != null) { + listener.onMaximized(); + } + } + + /** + * Notify te view is minimized to the DraggableListener + */ + private void notifyMinimizeToListener() { + if (listener != null) { + listener.onMinimized(); + } + } + + /** + * Notify te view is closed to the right to the DraggableListener + */ + private void notifyCloseToRightListener() { + if (listener != null) { + listener.onClosedToRight(); + } + } + + /** + * Notify te view is closed to the left to the DraggableListener + */ + private void notifyCloseToLeftListener() { + if (listener != null) { + listener.onClosedToLeft(); + } + } + + public int getDraggedViewHeightPlusMarginTop() { + return transformer.getMinHeightPlusMargin(); + } } diff --git a/draggablepanel/src/main/java/com/github/pedrovgs/DraggableViewCallback.java b/draggablepanel/src/main/java/com/github/pedrovgs/DraggableViewCallback.java index b7df872..f12528c 100644 --- a/draggablepanel/src/main/java/com/github/pedrovgs/DraggableViewCallback.java +++ b/draggablepanel/src/main/java/com/github/pedrovgs/DraggableViewCallback.java @@ -24,84 +24,77 @@ * * @author Pedro Vicente Gómez Sánchez. */ -class DraggableViewCallback extends ViewDragHelper.Callback{ +class DraggableViewCallback extends ViewDragHelper.Callback { - private static final int MINIMUM_DX_FOR_HORIZONTAL_DRAG = 5; - private static final int MINIMUM_DY_FOR_VERTICAL_DRAG = 15; - private static final float X_MIN_VELOCITY = 1500; - private static final float Y_MIN_VELOCITY = 1000; + private static final int MINIMUM_DX_FOR_HORIZONTAL_DRAG = 5; + private static final int MINIMUM_DY_FOR_VERTICAL_DRAG = 15; + private static final float X_MIN_VELOCITY = 1500; + private static final float Y_MIN_VELOCITY = 1000; - private DraggableView draggableView; - private View draggedView; - - - /** - * Main constructor. - * - * @param draggableView instance used to apply some animations or visual effects. - */ - public DraggableViewCallback(DraggableView draggableView, View draggedView){ - this.draggableView = draggableView; - this.draggedView = draggedView; - } - - - /** - * Override method used to apply different scale and alpha effects while the view is being - * dragged. - * - * @param left position. - * @param top position. - * @param dx change in X position from the last call. - * @param dy change in Y position from the last call. - */ - @Override - public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy){ - if(draggableView.isDragViewAtBottom()){ - draggableView.changeDragViewViewAlpha(); - } else{ - draggableView.restoreAlpha(); - draggableView.changeDragViewScale(); - draggableView.changeDragViewPosition(); - draggableView.changeSecondViewAlpha(); - draggableView.changeSecondViewPosition(); - draggableView.changeBackgroundAlpha(); - } - } + private DraggableView draggableView; + private View draggedView; + /** + * Main constructor. + * + * @param draggableView instance used to apply some animations or visual effects. + */ + public DraggableViewCallback(DraggableView draggableView, View draggedView) { + this.draggableView = draggableView; + this.draggedView = draggedView; + } - /** - * Override method used to apply different animations when the dragged view is released. The - * dragged view is going to be maximized or minimized if the view is above the middle of the - * custom view and the velocity is greater than a constant value. - * - * @param releasedChild the captured child view now being released. - * @param xVel X velocity of the pointer as it left the screen in pixels per second. - * @param yVel Y velocity of the pointer as it left the screen in pixels per second. - */ - @Override - public void onViewReleased(View releasedChild, float xVel, float yVel){ - super.onViewReleased(releasedChild, xVel, yVel); + /** + * Override method used to apply different scale and alpha effects while the view is being + * dragged. + * + * @param left position. + * @param top position. + * @param dx change in X position from the last call. + * @param dy change in Y position from the last call. + */ + @Override public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { + if (draggableView.isDragViewAtBottom()) { + draggableView.changeDragViewViewAlpha(); + } else { + draggableView.restoreAlpha(); + draggableView.changeDragViewScale(); + draggableView.changeDragViewPosition(); + draggableView.changeSecondViewAlpha(); + draggableView.changeSecondViewPosition(); + draggableView.changeBackgroundAlpha(); + } + } - if(draggableView.isDragViewAtBottom() && !draggableView.isDragViewAtRight()){ - triggerOnReleaseActionsWhileHorizontalDrag(xVel); - } else{ - triggerOnReleaseActionsWhileVerticalDrag(yVel); - } - } + /** + * Override method used to apply different animations when the dragged view is released. The + * dragged view is going to be maximized or minimized if the view is above the middle of the + * custom view and the velocity is greater than a constant value. + * + * @param releasedChild the captured child view now being released. + * @param xVel X velocity of the pointer as it left the screen in pixels per second. + * @param yVel Y velocity of the pointer as it left the screen in pixels per second. + */ + @Override public void onViewReleased(View releasedChild, float xVel, float yVel) { + super.onViewReleased(releasedChild, xVel, yVel); + if (draggableView.isDragViewAtBottom() && !draggableView.isDragViewAtRight()) { + triggerOnReleaseActionsWhileHorizontalDrag(xVel); + } else { + triggerOnReleaseActionsWhileVerticalDrag(yVel); + } + } - /** - * Override method used to configure which is going to be the dragged view. - * - * @param view child the user is attempting to capture. - * @param pointerId ID of the pointer attempting the capture, - * @return true if capture should be allowed, false otherwise. - */ - @Override - public boolean tryCaptureView(View view, int pointerId){ - return view.equals(draggedView); - } + /** + * Override method used to configure which is going to be the dragged view. + * + * @param view child the user is attempting to capture. + * @param pointerId ID of the pointer attempting the capture, + * @return true if capture should be allowed, false otherwise. + */ + @Override public boolean tryCaptureView(View view, int pointerId) { + return view.equals(draggedView); + } /** * Override method used to configure the horizontal drag. Restrict the motion of the dragged @@ -115,8 +108,7 @@ public boolean tryCaptureView(View view, int pointerId){ @Override public int clampViewPositionHorizontal(View child, int left, int dx) { int newLeft = draggedView.getLeft(); if ((draggableView.isMinimized() && Math.abs(dx) > MINIMUM_DX_FOR_HORIZONTAL_DRAG) || ( - draggableView.isDragViewAtBottom() - && !draggableView.isDragViewAtRight())) { + draggableView.isDragViewAtBottom() && !draggableView.isDragViewAtRight())) { newLeft = left; } return newLeft; @@ -133,13 +125,13 @@ public boolean tryCaptureView(View view, int pointerId){ */ @Override public int clampViewPositionVertical(View child, int top, int dy) { int newTop = draggableView.getHeight() - draggableView.getDraggedViewHeightPlusMarginTop(); - if (draggableView.isMinimized() && Math.abs(dy) >= MINIMUM_DY_FOR_VERTICAL_DRAG - || (!draggableView.isMinimized() && !draggableView.isDragViewAtBottom())) { + if (draggableView.isMinimized() && Math.abs(dy) >= MINIMUM_DY_FOR_VERTICAL_DRAG || ( + !draggableView.isMinimized() && !draggableView.isDragViewAtBottom())) { final int topBound = draggableView.getPaddingTop(); - final int bottomBound = draggableView.getHeight() - - draggableView.getDraggedViewHeightPlusMarginTop() - - draggedView.getPaddingBottom(); + final int bottomBound = + draggableView.getHeight() - draggableView.getDraggedViewHeightPlusMarginTop() + - draggedView.getPaddingBottom(); newTop = Math.min(Math.max(top, topBound), bottomBound); } diff --git a/draggablepanel/src/main/java/com/github/pedrovgs/transformer/ResizeTransformer.java b/draggablepanel/src/main/java/com/github/pedrovgs/transformer/ResizeTransformer.java index 6af7bc3..d3b4a06 100644 --- a/draggablepanel/src/main/java/com/github/pedrovgs/transformer/ResizeTransformer.java +++ b/draggablepanel/src/main/java/com/github/pedrovgs/transformer/ResizeTransformer.java @@ -40,19 +40,18 @@ class ResizeTransformer extends Transformer { */ @Override public void updateScale(float verticalDragOffset) { layoutParams.width = (int) (getOriginalWidth() * (1 - verticalDragOffset / getXScaleFactor())); - layoutParams.height = (int) (getOriginalHeight() * (1 - verticalDragOffset / getYScaleFactor())); + layoutParams.height = + (int) (getOriginalHeight() * (1 - verticalDragOffset / getYScaleFactor())); getView().setLayoutParams(layoutParams); } - /** * Changes X view position using layout() method. * * @param verticalDragOffset used to calculate the new X position. */ - @Override - public void updatePosition(float verticalDragOffset) { + @Override public void updatePosition(float verticalDragOffset) { int right = getViewRightPosition(verticalDragOffset); int left = right - layoutParams.width; int top = getView().getTop(); @@ -61,7 +60,6 @@ public void updatePosition(float verticalDragOffset) { getView().layout(left, top, right, bottom); } - /** * @return true if the right position of the view plus the right margin is equals to the parent * width. @@ -116,5 +114,4 @@ public void updatePosition(float verticalDragOffset) { private int getViewRightPosition(float verticalDragOffset) { return (int) ((getOriginalWidth()) - getMarginRight() * verticalDragOffset); } - } diff --git a/draggablepanel/src/main/java/com/github/pedrovgs/transformer/ScaleTransformer.java b/draggablepanel/src/main/java/com/github/pedrovgs/transformer/ScaleTransformer.java index e49a13e..5dce565 100644 --- a/draggablepanel/src/main/java/com/github/pedrovgs/transformer/ScaleTransformer.java +++ b/draggablepanel/src/main/java/com/github/pedrovgs/transformer/ScaleTransformer.java @@ -94,5 +94,4 @@ class ScaleTransformer extends Transformer { @Override public int getMinWidthPlusMarginRight() { return getOriginalWidth(); } - } From 369bfce33a606e865ac107c71129350f3e8d6f09 Mon Sep 17 00:00:00 2001 From: Yarh Date: Tue, 6 Oct 2015 21:31:50 +0300 Subject: [PATCH 4/4] travis fix 2? --- config/checkstyle/checkstyle.xml | 3 +- draggablepanel/AndroidManifest.xml | 6 +- draggablepanel/build.gradle | 2 +- .../sample/activity/DIFragmentActivity.java | 4 +- .../sample/activity/MainActivity.java | 4 +- .../sample/activity/TvShowsActivity.java | 64 ++-- .../sample/activity/VideoSampleActivity.java | 25 +- .../activity/YoutubeSampleActivity.java | 281 ++++++++---------- 8 files changed, 164 insertions(+), 225 deletions(-) diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index cc50471..1214657 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -111,7 +111,6 @@ - @@ -131,4 +130,4 @@ - \ No newline at end of file + diff --git a/draggablepanel/AndroidManifest.xml b/draggablepanel/AndroidManifest.xml index 13e81a2..1ec2fc0 100644 --- a/draggablepanel/AndroidManifest.xml +++ b/draggablepanel/AndroidManifest.xml @@ -1,9 +1,11 @@ + package="com.github.pedrovgs" + > + android:targetSdkVersion="20" + /> diff --git a/draggablepanel/build.gradle b/draggablepanel/build.gradle index 149fbde..272e796 100644 --- a/draggablepanel/build.gradle +++ b/draggablepanel/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.library' apply plugin: 'checkstyle' dependencies { - compile 'com.android.support:support-v4:20.0.0' + compile 'com.android.support:support-v4:20.0.0' compile 'com.nineoldandroids:library:2.4.0' } diff --git a/sample/src/main/java/com/github/pedrovgs/sample/activity/DIFragmentActivity.java b/sample/src/main/java/com/github/pedrovgs/sample/activity/DIFragmentActivity.java index 43e4363..f06b68f 100644 --- a/sample/src/main/java/com/github/pedrovgs/sample/activity/DIFragmentActivity.java +++ b/sample/src/main/java/com/github/pedrovgs/sample/activity/DIFragmentActivity.java @@ -34,9 +34,7 @@ public class DIFragmentActivity extends SherlockFragmentActivity { ((DraggablePanelApplication) getApplication()).inject(this); } - - public void onConfigurationChanged(Configuration newConfig){ + public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); - } } diff --git a/sample/src/main/java/com/github/pedrovgs/sample/activity/MainActivity.java b/sample/src/main/java/com/github/pedrovgs/sample/activity/MainActivity.java index 1fe4e77..a32a372 100644 --- a/sample/src/main/java/com/github/pedrovgs/sample/activity/MainActivity.java +++ b/sample/src/main/java/com/github/pedrovgs/sample/activity/MainActivity.java @@ -54,9 +54,7 @@ public class MainActivity extends Activity { startActivity(intent); } - - public void onConfigurationChanged(Configuration newConfig){ + public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); - } } diff --git a/sample/src/main/java/com/github/pedrovgs/sample/activity/TvShowsActivity.java b/sample/src/main/java/com/github/pedrovgs/sample/activity/TvShowsActivity.java index ea3a89d..9c463c8 100644 --- a/sample/src/main/java/com/github/pedrovgs/sample/activity/TvShowsActivity.java +++ b/sample/src/main/java/com/github/pedrovgs/sample/activity/TvShowsActivity.java @@ -89,16 +89,13 @@ public class TvShowsActivity extends DIFragmentActivity { */ private void initializeDraggableView() { Handler handler = new Handler(); - handler.postDelayed( - new Runnable(){ + handler.postDelayed(new Runnable() { - @Override - public void run(){ + @Override public void run() { draggableView.setVisibility(View.GONE); draggableView.closeToRight(); } - }, DELAY_MILLIS - ); + }, DELAY_MILLIS); } /** @@ -106,13 +103,10 @@ public void run(){ */ private void initializeGridView() { tvShowsGridView.setAdapter(adapter); - tvShowsGridView.setOnItemClickListener( - new AdapterView.OnItemClickListener(){ + tvShowsGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override - public void onItemClick( - AdapterView adapterView, View view, int position, long id - ){ + public void onItemClick(AdapterView adapterView, View view, int position, long id) { TvShowViewModel tvShow = adapter.getItem(position); tvShowSelected = tvShow; Picasso.with(getBaseContext()) @@ -124,8 +118,7 @@ public void onItemClick( draggableView.setVisibility(View.VISIBLE); draggableView.maximize(); } - } - ); + }); } /** @@ -133,33 +126,24 @@ public void onItemClick( * information. */ private void hookListeners() { - draggableView.setDraggableListener( - new DraggableListener(){ + draggableView.setDraggableListener(new DraggableListener() { - @Override - public void onMaximized(){ + @Override public void onMaximized() { updateActionBarTitle(); } - - @Override - public void onMinimized(){ + @Override public void onMinimized() { updateActionBarTitle(); } - - @Override - public void onClosedToLeft(){ + @Override public void onClosedToLeft() { resetActionBarTitle(); } - - @Override - public void onClosedToRight(){ + @Override public void onClosedToRight() { resetActionBarTitle(); } - } - ); + }); } /** @@ -205,29 +189,23 @@ private void renderEpisodesHeader(TvShowViewModel tvShow) { header.setText(tvShow.getTitle().toUpperCase() + " - SEASON 1"); episodesListView.setAdapter(null); episodesListView.addHeaderView(header); - episodesListView.setOnItemClickListener( - new AdapterView.OnItemClickListener(){ + episodesListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override - public void onItemClick( - AdapterView adapterView, View view, int position, long id - ){ - if(tvShowSelected != null){ - if(position > 0){ + public void onItemClick(AdapterView adapterView, View view, int position, long id) { + if (tvShowSelected != null) { + if (position > 0) { EpisodeViewModel episodeViewModel = tvShowSelected.getEpisodes().get(position - 1); - Toast.makeText( - getBaseContext(), tvShowSelected.getTitle() + " - " + episodeViewModel.getTitle(), Toast.LENGTH_LONG - ).show(); + Toast.makeText(getBaseContext(), + tvShowSelected.getTitle() + " - " + episodeViewModel.getTitle(), + Toast.LENGTH_LONG).show(); } } } - } - ); + }); } - - public void onConfigurationChanged(Configuration newConfig){ + public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); - } } \ No newline at end of file diff --git a/sample/src/main/java/com/github/pedrovgs/sample/activity/VideoSampleActivity.java b/sample/src/main/java/com/github/pedrovgs/sample/activity/VideoSampleActivity.java index 401eca0..6f72f2d 100644 --- a/sample/src/main/java/com/github/pedrovgs/sample/activity/VideoSampleActivity.java +++ b/sample/src/main/java/com/github/pedrovgs/sample/activity/VideoSampleActivity.java @@ -84,34 +84,25 @@ public class VideoSampleActivity extends FragmentActivity { * Hook DraggableListener to draggableView to pause or resume VideoView. */ private void hookDraggableViewListener() { - draggableView.setDraggableListener( - new DraggableListener(){ + draggableView.setDraggableListener(new DraggableListener() { - @Override - public void onMaximized(){ + @Override public void onMaximized() { startVideo(); } - //Empty - @Override - public void onMinimized(){ + @Override public void onMinimized() { //Empty } - - @Override - public void onClosedToLeft(){ + @Override public void onClosedToLeft() { pauseVideo(); } - - @Override - public void onClosedToRight(){ + @Override public void onClosedToRight() { pauseVideo(); } - } - ); + }); } /** @@ -155,9 +146,7 @@ private void initializePoster() { .into(thumbnailImageView); } - - public void onConfigurationChanged(Configuration newConfig){ + public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); - } } diff --git a/sample/src/main/java/com/github/pedrovgs/sample/activity/YoutubeSampleActivity.java b/sample/src/main/java/com/github/pedrovgs/sample/activity/YoutubeSampleActivity.java index 965940f..c24975d 100644 --- a/sample/src/main/java/com/github/pedrovgs/sample/activity/YoutubeSampleActivity.java +++ b/sample/src/main/java/com/github/pedrovgs/sample/activity/YoutubeSampleActivity.java @@ -19,7 +19,9 @@ import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.widget.ImageView; - +import butterknife.ButterKnife; +import butterknife.InjectView; +import butterknife.OnClick; import com.github.pedrovgs.DraggableListener; import com.github.pedrovgs.DraggablePanel; import com.github.pedrovgs.sample.R; @@ -29,161 +31,134 @@ import com.google.android.youtube.player.YouTubePlayerSupportFragment; import com.squareup.picasso.Picasso; -import butterknife.ButterKnife; -import butterknife.InjectView; -import butterknife.OnClick; - /** * Sample activity created to show a video from YouTube using a YouTubePlayer. * * @author Pedro Vicente Gómez Sánchez. */ -public class YoutubeSampleActivity extends FragmentActivity{ - - private static final String YOUTUBE_API_KEY = "AIzaSyC1rMU-mkhoyTvBIdTnYU0dss0tU9vtK48"; - private static final String VIDEO_KEY = "gsjtg7m1MMM"; - private static final String VIDEO_POSTER_THUMBNAIL = - "http://4.bp.blogspot.com/-BT6IshdVsoA/UjfnTo_TkBI/AAAAAAAAMWk/JvDCYCoFRlQ/s1600/" + "xmenDOFP.wobbly.1.jpg"; - private static final String SECOND_VIDEO_POSTER_THUMBNAIL = - "http://media.comicbook.com/wp-content/uploads/2013/07/x-men-days-of-future-past" + "-wolverine-poster.jpg"; - private static final String VIDEO_POSTER_TITLE = "X-Men: Days of Future Past"; - - @InjectView(R.id.iv_thumbnail) ImageView thumbnailImageView; - @InjectView(R.id.draggable_panel) DraggablePanel draggablePanel; - - private YouTubePlayer youtubePlayer; - private YouTubePlayerSupportFragment youtubeFragment; - - - /** - * Initialize the Activity with some injected data. - */ - @Override - protected void onCreate(Bundle savedInstanceState){ - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_youtube_sample); - ButterKnife.inject(this); - initializeYoutubeFragment(); - initializeDraggablePanel(); - hookDraggablePanelListeners(); - } - - - /** - * Method triggered when the iv_thumbnail widget is clicked. This method maximize the - * DraggablePanel. - */ - @OnClick(R.id.iv_thumbnail) - void onContainerClicked(){ - draggablePanel.maximize(); - } - - - /** - * Initialize the YouTubeSupportFrament attached as top fragment to the DraggablePanel widget and - * reproduce the YouTube video represented with a YouTube url. - */ - private void initializeYoutubeFragment(){ - youtubeFragment = new YouTubePlayerSupportFragment(); - youtubeFragment.initialize( - YOUTUBE_API_KEY, new YouTubePlayer.OnInitializedListener(){ - - @Override - public void onInitializationSuccess( - YouTubePlayer.Provider provider, YouTubePlayer player, boolean wasRestored - ){ - if(!wasRestored){ - youtubePlayer = player; - youtubePlayer.loadVideo(VIDEO_KEY); - youtubePlayer.setShowFullscreenButton(true); - } - } - - - @Override - public void onInitializationFailure( - YouTubePlayer.Provider provider, YouTubeInitializationResult error - ){ - } - } - ); - } - - - /** - * Initialize and configure the DraggablePanel widget with two fragments and some attributes. - */ - private void initializeDraggablePanel(){ - draggablePanel.setFragmentManager(getSupportFragmentManager()); - draggablePanel.setTopFragment(youtubeFragment); - MoviePosterFragment moviePosterFragment = new MoviePosterFragment(); - moviePosterFragment.setPoster(VIDEO_POSTER_THUMBNAIL); - moviePosterFragment.setPosterTitle(VIDEO_POSTER_TITLE); - draggablePanel.setBottomFragment(moviePosterFragment); - draggablePanel.initializeView(); - Picasso.with(this) - .load(SECOND_VIDEO_POSTER_THUMBNAIL) - .placeholder(R.drawable.xmen_placeholder) - .into(thumbnailImageView); - } - - - /** - * Hook the DraggableListener to DraggablePanel to pause or resume the video when the - * DragglabePanel is maximized or closed. - */ - private void hookDraggablePanelListeners(){ - draggablePanel.setDraggableListener( - new DraggableListener(){ - - @Override - public void onMaximized(){ - playVideo(); - } - - - @Override - public void onMinimized(){ - - } - - - @Override - public void onClosedToLeft(){ - pauseVideo(); - } - - - @Override - public void onClosedToRight(){ - pauseVideo(); - } - } - ); - } - - - /** - * Pause the video reproduced in the YouTubePlayer. - */ - private void pauseVideo(){ - if(youtubePlayer.isPlaying()){ - youtubePlayer.pause(); - } - } - - - /** - * Resume the video reproduced in the YouTubePlayer. - */ - private void playVideo(){ - if(!youtubePlayer.isPlaying()){ - youtubePlayer.play(); - } - } - - - public void onConfigurationChanged(Configuration newConfig){ - super.onConfigurationChanged(newConfig); - } +public class YoutubeSampleActivity extends FragmentActivity { + + private static final String YOUTUBE_API_KEY = "AIzaSyC1rMU-mkhoyTvBIdTnYU0dss0tU9vtK48"; + private static final String VIDEO_KEY = "gsjtg7m1MMM"; + private static final String VIDEO_POSTER_THUMBNAIL = + "http://4.bp.blogspot.com/-BT6IshdVsoA/UjfnTo_TkBI/AAAAAAAAMWk/JvDCYCoFRlQ/s1600/" + + "xmenDOFP.wobbly.1.jpg"; + private static final String SECOND_VIDEO_POSTER_THUMBNAIL = + "http://media.comicbook.com/wp-content/uploads/2013/07/x-men-days-of-future-past" + + "-wolverine-poster.jpg"; + private static final String VIDEO_POSTER_TITLE = "X-Men: Days of Future Past"; + + @InjectView(R.id.iv_thumbnail) ImageView thumbnailImageView; + @InjectView(R.id.draggable_panel) DraggablePanel draggablePanel; + + private YouTubePlayer youtubePlayer; + private YouTubePlayerSupportFragment youtubeFragment; + + /** + * Initialize the Activity with some injected data. + */ + @Override protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_youtube_sample); + ButterKnife.inject(this); + initializeYoutubeFragment(); + initializeDraggablePanel(); + hookDraggablePanelListeners(); + } + + /** + * Method triggered when the iv_thumbnail widget is clicked. This method maximize the + * DraggablePanel. + */ + @OnClick(R.id.iv_thumbnail) void onContainerClicked() { + draggablePanel.maximize(); + } + + /** + * Initialize the YouTubeSupportFrament attached as top fragment to the DraggablePanel widget and + * reproduce the YouTube video represented with a YouTube url. + */ + private void initializeYoutubeFragment() { + youtubeFragment = new YouTubePlayerSupportFragment(); + youtubeFragment.initialize(YOUTUBE_API_KEY, new YouTubePlayer.OnInitializedListener() { + + @Override + public void onInitializationSuccess(YouTubePlayer.Provider provider, YouTubePlayer player, + boolean wasRestored) { + if (!wasRestored) { + youtubePlayer = player; + youtubePlayer.loadVideo(VIDEO_KEY); + youtubePlayer.setShowFullscreenButton(true); + } + } + + @Override public void onInitializationFailure(YouTubePlayer.Provider provider, + YouTubeInitializationResult error) { + } + }); + } + + /** + * Initialize and configure the DraggablePanel widget with two fragments and some attributes. + */ + private void initializeDraggablePanel() { + draggablePanel.setFragmentManager(getSupportFragmentManager()); + draggablePanel.setTopFragment(youtubeFragment); + MoviePosterFragment moviePosterFragment = new MoviePosterFragment(); + moviePosterFragment.setPoster(VIDEO_POSTER_THUMBNAIL); + moviePosterFragment.setPosterTitle(VIDEO_POSTER_TITLE); + draggablePanel.setBottomFragment(moviePosterFragment); + draggablePanel.initializeView(); + Picasso.with(this) + .load(SECOND_VIDEO_POSTER_THUMBNAIL) + .placeholder(R.drawable.xmen_placeholder) + .into(thumbnailImageView); + } + + /** + * Hook the DraggableListener to DraggablePanel to pause or resume the video when the + * DragglabePanel is maximized or closed. + */ + private void hookDraggablePanelListeners() { + draggablePanel.setDraggableListener(new DraggableListener() { + + @Override public void onMaximized() { + playVideo(); + } + + @Override public void onMinimized() { + + } + + @Override public void onClosedToLeft() { + pauseVideo(); + } + + @Override public void onClosedToRight() { + pauseVideo(); + } + }); + } + + /** + * Pause the video reproduced in the YouTubePlayer. + */ + private void pauseVideo() { + if (youtubePlayer.isPlaying()) { + youtubePlayer.pause(); + } + } + + /** + * Resume the video reproduced in the YouTubePlayer. + */ + private void playVideo() { + if (!youtubePlayer.isPlaying()) { + youtubePlayer.play(); + } + } + + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + } }