From 95e9ddf95ae4e465c905f4ab7926d8e7f44e7b82 Mon Sep 17 00:00:00 2001 From: Yarh Date: Tue, 22 Sep 2015 12:16:51 +0300 Subject: [PATCH 1/5] 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 5ed4e8492579b49f085585ace3abbbf60d85b186 Mon Sep 17 00:00:00 2001 From: Yarh Date: Tue, 22 Sep 2015 13:08:33 +0300 Subject: [PATCH 2/5] add setLockDragMode to disable/enable dragging --- .../com/github/pedrovgs/DraggablePanel.java | 717 ++++---- .../com/github/pedrovgs/DraggableView.java | 1612 ++++++++--------- .../activity/YoutubeSampleActivity.java | 3 +- 3 files changed, 1151 insertions(+), 1181 deletions(-) diff --git a/draggablepanel/src/main/java/com/github/pedrovgs/DraggablePanel.java b/draggablepanel/src/main/java/com/github/pedrovgs/DraggablePanel.java index f1f0556..6b3ca06 100644 --- a/draggablepanel/src/main/java/com/github/pedrovgs/DraggablePanel.java +++ b/draggablepanel/src/main/java/com/github/pedrovgs/DraggablePanel.java @@ -32,334 +32,391 @@ * * @author Pedro Vicente Gómez Sánchez. */ -public class DraggablePanel extends FrameLayout { - - private static final int DEFAULT_TOP_FRAGMENT_HEIGHT = 200; - private static final int DEFAULT_TOP_FRAGMENT_MARGIN = 0; - private static final float DEFAULT_SCALE_FACTOR = 2; - 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 boolean DEFAULT_TOP_FRAGMENT_RESIZE = false; - - private DraggableView draggableView; - private DraggableListener draggableListener; - - private FragmentManager fragmentManager; - private Fragment topFragment; - private Fragment bottomFragment; - private int topFragmentHeight; - private int topFragmentMarginRight; - private int topFragmentMarginBottom; - private float xScaleFactor; - private float yScaleFactor; - private boolean enableHorizontalAlphaEffect; - private boolean enableClickToMaximize; - private boolean enableClickToMinimize; - private boolean enableTouchListener; - - public DraggablePanel(Context context) { - super(context); - } - - public DraggablePanel(Context context, AttributeSet attrs) { - super(context, attrs); - initializeAttrs(attrs); - } - - public DraggablePanel(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - initializeAttrs(attrs); - } - - /** - * Configure the FragmentManager used to attach top and bottom fragment inside the view. - */ - public void setFragmentManager(FragmentManager fragmentManager) { - this.fragmentManager = fragmentManager; - } - - /** - * Configure the Fragment that will work as draggable element inside this custom view. This - * Fragment has to be configured before initialize the view. - * - * @param topFragment used as draggable element. - */ - public void setTopFragment(Fragment topFragment) { - this.topFragment = topFragment; - } - - /** - * Configure the Fragment that will work as secondary element inside this custom view. This - * Fragment has to be configured before initialize the view. - * - * @param bottomFragment used as secondary element. - */ - public void setBottomFragment(Fragment bottomFragment) { - this.bottomFragment = bottomFragment; - } - - /** - * Configure the height associated to the top Fragment used inside the view as draggable element. - * - * @param topFragmentHeight in pixels. - */ - public void setTopViewHeight(int topFragmentHeight) { - this.topFragmentHeight = topFragmentHeight; - } - - /** - * 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; - } - - /** - * - * 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, - * 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) { - draggableView.slideHorizontally(slideOffset, drawerPosition, width); - } - - /** - * Configure the horizontal scale factor applied when the top fragment is dragged to the bottom - * of the custom view. - */ - public void setXScaleFactor(float xScaleFactor) { - this.xScaleFactor = xScaleFactor; - } - - /** - * Configure the vertical scale factor applied when the top fragment is dragged to the bottom of - * the custom view. - */ - public void setYScaleFactor(float yScaleFactor) { - this.yScaleFactor = yScaleFactor; - } - - /** - * Configure the top Fragment margin right applied when the view has been minimized. - * - * @param topFragmentMarginRight in pixels. - */ - public void setTopFragmentMarginRight(int topFragmentMarginRight) { - this.topFragmentMarginRight = topFragmentMarginRight; - } - - /** - * Configure the top Fragment margin bottom applied when the view has been minimized. - * - * @param topFragmentMarginBottom in pixels. - */ - public void setTopFragmentMarginBottom(int topFragmentMarginBottom) { - this.topFragmentMarginBottom = topFragmentMarginBottom; - } - - /** - * Configure the DraggableListener that is going to be invoked when the view be minimized, - * maximized, closed to the left or right. - */ - public void setDraggableListener(DraggableListener draggableListener) { - this.draggableListener = draggableListener; - } - - /** - * Configure the disabling of the alpha effect applied when the view is being dragged - * horizontally. - * - * @param enableHorizontalAlphaEffect to enable or disable the effect. - */ - public void setEnableHorizontalAlphaEffect(boolean enableHorizontalAlphaEffect) { - this.enableHorizontalAlphaEffect = enableHorizontalAlphaEffect; - } - - /** - * Close the custom view applying an animation to close the view to the left side of the screen. - */ - public void closeToLeft() { - draggableView.closeToLeft(); - } - - /** - * Close the custom view applying an animation to close the view to the right side of the screen. - */ - public void closeToRight() { - draggableView.closeToRight(); - } - - /** - * Maximize the custom view applying an animation to return the view to the initial position. - */ - public void maximize() { - draggableView.maximize(); - } - - /** - * Minimize the custom view applying an animation to put the top fragment on the bottom right - * corner of the screen. - */ - public void minimize() { - draggableView.minimize(); - } - - /** - * Apply all the custom view configuration and inflate the main widgets. The view won't be - * visible if this method is not called. - *

- * FragmentManager, top Fragment and bottom Fragment have to be configured before initialize this - * view. If not, this method will throw and IllegalStateException. - */ - public void initializeView() { - checkFragmentConsistency(); - checkSupportFragmentManagerConsistency(); - - inflate(getContext(), R.layout.draggable_panel, this); - draggableView = (DraggableView) findViewById(R.id.draggable_view); - draggableView.setTopViewHeight(topFragmentHeight); - draggableView.setFragmentManager(fragmentManager); - draggableView.attachTopFragment(topFragment); - draggableView.setXTopViewScaleFactor(xScaleFactor); - draggableView.setYTopViewScaleFactor(yScaleFactor); - draggableView.setTopViewMarginRight(topFragmentMarginRight); - draggableView.setTopViewMarginBottom(topFragmentMarginBottom); - draggableView.attachBottomFragment(bottomFragment); - draggableView.setDraggableListener(draggableListener); - draggableView.setHorizontalAlphaEffectEnabled(enableHorizontalAlphaEffect); - draggableView.setClickToMaximizeEnabled(enableClickToMaximize); - draggableView.setClickToMinimizeEnabled(enableClickToMinimize); - draggableView.setTouchEnabled(enableTouchListener); - } - - /** - * Checks if the top Fragment is maximized. - * - * @return true if the view is maximized. - */ - public boolean isMaximized() { - return draggableView.isMaximized(); - } - - /** - * Checks if the top Fragment is minimized. - * - * @return true if the view is minimized. - */ - public boolean isMinimized() { - return draggableView.isMinimized(); - } - - /** - * Checks if the top Fragment closed at the right place. - * - * @return true if the view is closed at right. - */ - public boolean isClosedAtRight() { - return draggableView.isClosedAtRight(); - } - - /** - * Checks if the top Fragment is closed at the left place. - * - * @return true if the view is closed at left. - */ - public boolean isClosedAtLeft() { - return draggableView.isClosedAtLeft(); - } - - /** - * Initialize the xml configuration based on styleable attributes - * - * @param attrs to analyze. - */ - private void initializeAttrs(AttributeSet attrs) { - TypedArray attributes = getContext().obtainStyledAttributes(attrs, R.styleable.draggable_panel); - this.topFragmentHeight = - attributes.getDimensionPixelSize(R.styleable.draggable_panel_top_fragment_height, - DEFAULT_TOP_FRAGMENT_HEIGHT); - this.xScaleFactor = - attributes.getFloat(R.styleable.draggable_panel_x_scale_factor, DEFAULT_SCALE_FACTOR); - this.yScaleFactor = - attributes.getFloat(R.styleable.draggable_panel_y_scale_factor, DEFAULT_SCALE_FACTOR); - this.topFragmentMarginRight = - attributes.getDimensionPixelSize(R.styleable.draggable_panel_top_fragment_margin_right, - DEFAULT_TOP_FRAGMENT_MARGIN); - this.topFragmentMarginBottom = - attributes.getDimensionPixelSize(R.styleable.draggable_panel_top_fragment_margin_bottom, - DEFAULT_TOP_FRAGMENT_MARGIN); - this.enableHorizontalAlphaEffect = - attributes.getBoolean(R.styleable.draggable_panel_enable_horizontal_alpha_effect, - DEFAULT_ENABLE_HORIZONTAL_ALPHA_EFFECT); - this.enableClickToMaximize = - attributes.getBoolean(R.styleable.draggable_panel_enable_click_to_maximize_panel, - DEFAULT_ENABLE_CLICK_TO_MAXIMIZE); - this.enableClickToMinimize = - attributes.getBoolean(R.styleable.draggable_panel_enable_click_to_minimize_panel, - DEFAULT_ENABLE_CLICK_TO_MINIMIZE); - this.enableTouchListener = - attributes.getBoolean(R.styleable.draggable_panel_enable_touch_listener_panel, - DEFAULT_ENABLE_TOUCH_LISTENER); - attributes.recycle(); - } - - /** - * Validate FragmentManager configuration. If is not initialized, this method will throw an - * IllegalStateException. - */ - private void checkSupportFragmentManagerConsistency() { - if (fragmentManager == null) { - throw new IllegalStateException( - "You have to set the support FragmentManager before initialize DraggablePanel"); - } - } - - /** - * Validate top and bottom Fragment configuration. If are not initialized, this method will throw - * an IllegalStateException. - */ - private void checkFragmentConsistency() { - if (topFragment == null || bottomFragment == null) { - throw new IllegalStateException( - "You have to set top and bottom fragment before initialize DraggablePanel"); - } - } +public class DraggablePanel extends FrameLayout{ + + private static final int DEFAULT_TOP_FRAGMENT_HEIGHT = 200; + private static final int DEFAULT_TOP_FRAGMENT_MARGIN = 0; + private static final float DEFAULT_SCALE_FACTOR = 2; + 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 boolean DEFAULT_TOP_FRAGMENT_RESIZE = false; + + private DraggableView draggableView; + private DraggableListener draggableListener; + + private FragmentManager fragmentManager; + private Fragment topFragment; + private Fragment bottomFragment; + private int topFragmentHeight; + private int topFragmentMarginRight; + private int topFragmentMarginBottom; + private float xScaleFactor; + private float yScaleFactor; + private boolean enableHorizontalAlphaEffect; + private boolean enableClickToMaximize; + private boolean enableClickToMinimize; + private boolean enableTouchListener; + private boolean initialised = false; + + + public DraggablePanel(Context context){ + super(context); + } + + + public DraggablePanel(Context context, AttributeSet attrs){ + super(context, attrs); + initializeAttrs(attrs); + } + + + public DraggablePanel(Context context, AttributeSet attrs, int defStyle){ + super(context, attrs, defStyle); + initializeAttrs(attrs); + } + + + /** + * Configure the FragmentManager used to attach top and bottom fragment inside the view. + */ + public void setFragmentManager(FragmentManager fragmentManager){ + this.fragmentManager = fragmentManager; + } + + + /** + * Configure the Fragment that will work as draggable element inside this custom view. This + * Fragment has to be configured before initialize the view. + * + * @param topFragment used as draggable element. + */ + public void setTopFragment(Fragment topFragment){ + this.topFragment = topFragment; + } + + + /** + * Configure the Fragment that will work as secondary element inside this custom view. This + * Fragment has to be configured before initialize the view. + * + * @param bottomFragment used as secondary element. + */ + public void setBottomFragment(Fragment bottomFragment){ + this.bottomFragment = bottomFragment; + } + + + /** + * Configure the height associated to the top Fragment used inside the view as draggable element. + * + * @param topFragmentHeight in pixels. + */ + public void setTopViewHeight(int topFragmentHeight){ + this.topFragmentHeight = topFragmentHeight; + } + + + /** + * 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; + } + + + /** + * Disables dragging the view + * + * @param lock - true to disable, false to enable + */ + public void setLockDragMode(boolean lock){ + if(initialised){ draggableView.setLockDragMode(lock); } else{ + throw new IllegalStateException("You have to initialise draggable panel first"); + } + } + + + /** + * Return if dragging is locked or unlocked + */ + public boolean isLockDragMode(){ + if(initialised){ return draggableView.isLockDragMode(); } else{ + throw new IllegalStateException("You have to initialise draggable panel first"); + } + + } + + + /** + * 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, + * 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){ + draggableView.slideHorizontally(slideOffset, drawerPosition, width); + } + + + /** + * Configure the horizontal scale factor applied when the top fragment is dragged to the bottom + * of the custom view. + */ + public void setXScaleFactor(float xScaleFactor){ + this.xScaleFactor = xScaleFactor; + } + + + /** + * Configure the vertical scale factor applied when the top fragment is dragged to the bottom of + * the custom view. + */ + public void setYScaleFactor(float yScaleFactor){ + this.yScaleFactor = yScaleFactor; + } + + + /** + * Configure the top Fragment margin right applied when the view has been minimized. + * + * @param topFragmentMarginRight in pixels. + */ + public void setTopFragmentMarginRight(int topFragmentMarginRight){ + this.topFragmentMarginRight = topFragmentMarginRight; + } + + + /** + * Configure the top Fragment margin bottom applied when the view has been minimized. + * + * @param topFragmentMarginBottom in pixels. + */ + public void setTopFragmentMarginBottom(int topFragmentMarginBottom){ + this.topFragmentMarginBottom = topFragmentMarginBottom; + } + + + /** + * Configure the DraggableListener that is going to be invoked when the view be minimized, + * maximized, closed to the left or right. + */ + public void setDraggableListener(DraggableListener draggableListener){ + this.draggableListener = draggableListener; + } + + + /** + * Configure the disabling of the alpha effect applied when the view is being dragged + * horizontally. + * + * @param enableHorizontalAlphaEffect to enable or disable the effect. + */ + public void setEnableHorizontalAlphaEffect(boolean enableHorizontalAlphaEffect){ + this.enableHorizontalAlphaEffect = enableHorizontalAlphaEffect; + } + + + /** + * Close the custom view applying an animation to close the view to the left side of the screen. + */ + public void closeToLeft(){ + draggableView.closeToLeft(); + } + + + /** + * Close the custom view applying an animation to close the view to the right side of the screen. + */ + public void closeToRight(){ + draggableView.closeToRight(); + } + + + /** + * Maximize the custom view applying an animation to return the view to the initial position. + */ + public void maximize(){ + draggableView.maximize(); + } + + + /** + * Minimize the custom view applying an animation to put the top fragment on the bottom right + * corner of the screen. + */ + public void minimize(){ + draggableView.minimize(); + } + + + /** + * Apply all the custom view configuration and inflate the main widgets. The view won't be + * visible if this method is not called. + *

+ * FragmentManager, top Fragment and bottom Fragment have to be configured before initialize this + * view. If not, this method will throw and IllegalStateException. + */ + public void initializeView(){ + checkFragmentConsistency(); + checkSupportFragmentManagerConsistency(); + + inflate(getContext(), R.layout.draggable_panel, this); + draggableView = (DraggableView) findViewById(R.id.draggable_view); + draggableView.setTopViewHeight(topFragmentHeight); + draggableView.setFragmentManager(fragmentManager); + draggableView.attachTopFragment(topFragment); + draggableView.setXTopViewScaleFactor(xScaleFactor); + draggableView.setYTopViewScaleFactor(yScaleFactor); + draggableView.setTopViewMarginRight(topFragmentMarginRight); + draggableView.setTopViewMarginBottom(topFragmentMarginBottom); + draggableView.attachBottomFragment(bottomFragment); + draggableView.setDraggableListener(draggableListener); + draggableView.setHorizontalAlphaEffectEnabled(enableHorizontalAlphaEffect); + draggableView.setClickToMaximizeEnabled(enableClickToMaximize); + draggableView.setClickToMinimizeEnabled(enableClickToMinimize); + draggableView.setTouchEnabled(enableTouchListener); + initialised = true; + } + + + /** + * Checks if the top Fragment is maximized. + * + * @return true if the view is maximized. + */ + public boolean isMaximized(){ + return draggableView.isMaximized(); + } + + + /** + * Checks if the top Fragment is minimized. + * + * @return true if the view is minimized. + */ + public boolean isMinimized(){ + return draggableView.isMinimized(); + } + + + /** + * Checks if the top Fragment closed at the right place. + * + * @return true if the view is closed at right. + */ + public boolean isClosedAtRight(){ + return draggableView.isClosedAtRight(); + } + + + /** + * Checks if the top Fragment is closed at the left place. + * + * @return true if the view is closed at left. + */ + public boolean isClosedAtLeft(){ + return draggableView.isClosedAtLeft(); + } + + + /** + * Initialize the xml configuration based on styleable attributes + * + * @param attrs to analyze. + */ + private void initializeAttrs(AttributeSet attrs){ + TypedArray attributes = + getContext().obtainStyledAttributes(attrs, R.styleable.draggable_panel); + this.topFragmentHeight = attributes.getDimensionPixelSize( + R.styleable.draggable_panel_top_fragment_height, DEFAULT_TOP_FRAGMENT_HEIGHT + ); + this.xScaleFactor = + attributes.getFloat(R.styleable.draggable_panel_x_scale_factor, DEFAULT_SCALE_FACTOR); + this.yScaleFactor = + attributes.getFloat(R.styleable.draggable_panel_y_scale_factor, DEFAULT_SCALE_FACTOR); + this.topFragmentMarginRight = attributes.getDimensionPixelSize( + R.styleable.draggable_panel_top_fragment_margin_right, DEFAULT_TOP_FRAGMENT_MARGIN + ); + this.topFragmentMarginBottom = attributes.getDimensionPixelSize( + R.styleable.draggable_panel_top_fragment_margin_bottom, DEFAULT_TOP_FRAGMENT_MARGIN + ); + this.enableHorizontalAlphaEffect = attributes.getBoolean( + R.styleable.draggable_panel_enable_horizontal_alpha_effect, DEFAULT_ENABLE_HORIZONTAL_ALPHA_EFFECT + ); + this.enableClickToMaximize = attributes.getBoolean( + R.styleable.draggable_panel_enable_click_to_maximize_panel, DEFAULT_ENABLE_CLICK_TO_MAXIMIZE + ); + this.enableClickToMinimize = attributes.getBoolean( + R.styleable.draggable_panel_enable_click_to_minimize_panel, DEFAULT_ENABLE_CLICK_TO_MINIMIZE + ); + this.enableTouchListener = attributes.getBoolean( + R.styleable.draggable_panel_enable_touch_listener_panel, DEFAULT_ENABLE_TOUCH_LISTENER + ); + attributes.recycle(); + } + + + /** + * Validate FragmentManager configuration. If is not initialized, this method will throw an + * IllegalStateException. + */ + private void checkSupportFragmentManagerConsistency(){ + if(fragmentManager == null){ + throw new IllegalStateException( + "You have to set the support FragmentManager before initialize DraggablePanel" + ); + } + } + + + /** + * Validate top and bottom Fragment configuration. If are not initialized, this method will throw + * an IllegalStateException. + */ + private void checkFragmentConsistency(){ + if(topFragment == null || bottomFragment == null){ + throw new IllegalStateException( + "You have to set top and bottom fragment before initialize DraggablePanel" + ); + } + } } diff --git a/draggablepanel/src/main/java/com/github/pedrovgs/DraggableView.java b/draggablepanel/src/main/java/com/github/pedrovgs/DraggableView.java index e4b1e47..548fd95 100644 --- a/draggablepanel/src/main/java/com/github/pedrovgs/DraggableView.java +++ b/draggablepanel/src/main/java/com/github/pedrovgs/DraggableView.java @@ -24,11 +24,9 @@ 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; @@ -38,852 +36,766 @@ * * @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, -(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(); - } +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 boolean lockDragMode =false; + 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; + } + + + /** + * Disables dragging the view + * @param lock - true to disable, false to enable + * + */ + public void setLockDragMode(boolean lock){ + this.lockDragMode =lock; + } + + + /** + * + * Return if dragging is locked or unlocked + */ + public boolean isLockDragMode(){ + return lockDragMode; + } + /** + * 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; + } + if(!lockDragMode) 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(); + } } 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..b4622ac 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 @@ -185,6 +185,7 @@ private void playVideo(){ public void onConfigurationChanged(Configuration newConfig){ super.onConfigurationChanged(newConfig); - + if(getResources().getConfiguration().orientation==Configuration.ORIENTATION_LANDSCAPE)draggablePanel.setLockDragMode(true); + else draggablePanel.setLockDragMode(false); } } From 2e330c9675a1acb1562e3b78ea77c60b770d5137 Mon Sep 17 00:00:00 2001 From: Yarh Date: Tue, 27 Oct 2015 15:38:34 +0200 Subject: [PATCH 3/5] keep state restore on default orientation handling --- config/checkstyle/checkstyle.xml | 3 +- draggablepanel/res/layout/draggable_panel.xml | 2 +- .../com/github/pedrovgs/DraggablePanel.java | 742 +++++++++--------- .../com/github/pedrovgs/DraggableView.java | 253 +++++- .../pedrovgs/DraggableViewCallback.java | 13 +- .../transformer/ResizeTransformer.java | 9 +- .../transformer/ScaleTransformer.java | 1 - sample/AndroidManifest.xml | 1 - .../activity/YoutubeSampleActivity.java | 289 ++++--- 9 files changed, 726 insertions(+), 587 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/res/layout/draggable_panel.xml b/draggablepanel/res/layout/draggable_panel.xml index 97545a0..e4a0d3d 100644 --- a/draggablepanel/res/layout/draggable_panel.xml +++ b/draggablepanel/res/layout/draggable_panel.xml @@ -16,7 +16,7 @@ diff --git a/draggablepanel/src/main/java/com/github/pedrovgs/DraggablePanel.java b/draggablepanel/src/main/java/com/github/pedrovgs/DraggablePanel.java index 6b3ca06..15f6d33 100644 --- a/draggablepanel/src/main/java/com/github/pedrovgs/DraggablePanel.java +++ b/draggablepanel/src/main/java/com/github/pedrovgs/DraggablePanel.java @@ -32,391 +32,359 @@ * * @author Pedro Vicente Gómez Sánchez. */ -public class DraggablePanel extends FrameLayout{ - - private static final int DEFAULT_TOP_FRAGMENT_HEIGHT = 200; - private static final int DEFAULT_TOP_FRAGMENT_MARGIN = 0; - private static final float DEFAULT_SCALE_FACTOR = 2; - 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 boolean DEFAULT_TOP_FRAGMENT_RESIZE = false; - - private DraggableView draggableView; - private DraggableListener draggableListener; - - private FragmentManager fragmentManager; - private Fragment topFragment; - private Fragment bottomFragment; - private int topFragmentHeight; - private int topFragmentMarginRight; - private int topFragmentMarginBottom; - private float xScaleFactor; - private float yScaleFactor; - private boolean enableHorizontalAlphaEffect; - private boolean enableClickToMaximize; - private boolean enableClickToMinimize; - private boolean enableTouchListener; - private boolean initialised = false; - - - public DraggablePanel(Context context){ - super(context); - } - - - public DraggablePanel(Context context, AttributeSet attrs){ - super(context, attrs); - initializeAttrs(attrs); - } - - - public DraggablePanel(Context context, AttributeSet attrs, int defStyle){ - super(context, attrs, defStyle); - initializeAttrs(attrs); - } - - - /** - * Configure the FragmentManager used to attach top and bottom fragment inside the view. - */ - public void setFragmentManager(FragmentManager fragmentManager){ - this.fragmentManager = fragmentManager; - } - - - /** - * Configure the Fragment that will work as draggable element inside this custom view. This - * Fragment has to be configured before initialize the view. - * - * @param topFragment used as draggable element. - */ - public void setTopFragment(Fragment topFragment){ - this.topFragment = topFragment; - } - - - /** - * Configure the Fragment that will work as secondary element inside this custom view. This - * Fragment has to be configured before initialize the view. - * - * @param bottomFragment used as secondary element. - */ - public void setBottomFragment(Fragment bottomFragment){ - this.bottomFragment = bottomFragment; - } - - - /** - * Configure the height associated to the top Fragment used inside the view as draggable element. - * - * @param topFragmentHeight in pixels. - */ - public void setTopViewHeight(int topFragmentHeight){ - this.topFragmentHeight = topFragmentHeight; - } - - - /** - * 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; - } - - - /** - * Disables dragging the view - * - * @param lock - true to disable, false to enable - */ - public void setLockDragMode(boolean lock){ - if(initialised){ draggableView.setLockDragMode(lock); } else{ - throw new IllegalStateException("You have to initialise draggable panel first"); - } - } - - - /** - * Return if dragging is locked or unlocked - */ - public boolean isLockDragMode(){ - if(initialised){ return draggableView.isLockDragMode(); } else{ - throw new IllegalStateException("You have to initialise draggable panel first"); - } - - } - - - /** - * 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, - * 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){ - draggableView.slideHorizontally(slideOffset, drawerPosition, width); - } - - - /** - * Configure the horizontal scale factor applied when the top fragment is dragged to the bottom - * of the custom view. - */ - public void setXScaleFactor(float xScaleFactor){ - this.xScaleFactor = xScaleFactor; - } - - - /** - * Configure the vertical scale factor applied when the top fragment is dragged to the bottom of - * the custom view. - */ - public void setYScaleFactor(float yScaleFactor){ - this.yScaleFactor = yScaleFactor; - } - - - /** - * Configure the top Fragment margin right applied when the view has been minimized. - * - * @param topFragmentMarginRight in pixels. - */ - public void setTopFragmentMarginRight(int topFragmentMarginRight){ - this.topFragmentMarginRight = topFragmentMarginRight; - } - - - /** - * Configure the top Fragment margin bottom applied when the view has been minimized. - * - * @param topFragmentMarginBottom in pixels. - */ - public void setTopFragmentMarginBottom(int topFragmentMarginBottom){ - this.topFragmentMarginBottom = topFragmentMarginBottom; - } - - - /** - * Configure the DraggableListener that is going to be invoked when the view be minimized, - * maximized, closed to the left or right. - */ - public void setDraggableListener(DraggableListener draggableListener){ - this.draggableListener = draggableListener; - } - - - /** - * Configure the disabling of the alpha effect applied when the view is being dragged - * horizontally. - * - * @param enableHorizontalAlphaEffect to enable or disable the effect. - */ - public void setEnableHorizontalAlphaEffect(boolean enableHorizontalAlphaEffect){ - this.enableHorizontalAlphaEffect = enableHorizontalAlphaEffect; - } - - - /** - * Close the custom view applying an animation to close the view to the left side of the screen. - */ - public void closeToLeft(){ - draggableView.closeToLeft(); - } - - - /** - * Close the custom view applying an animation to close the view to the right side of the screen. - */ - public void closeToRight(){ - draggableView.closeToRight(); - } - - - /** - * Maximize the custom view applying an animation to return the view to the initial position. - */ - public void maximize(){ - draggableView.maximize(); - } - - - /** - * Minimize the custom view applying an animation to put the top fragment on the bottom right - * corner of the screen. - */ - public void minimize(){ - draggableView.minimize(); - } - - - /** - * Apply all the custom view configuration and inflate the main widgets. The view won't be - * visible if this method is not called. - *

- * FragmentManager, top Fragment and bottom Fragment have to be configured before initialize this - * view. If not, this method will throw and IllegalStateException. - */ - public void initializeView(){ - checkFragmentConsistency(); - checkSupportFragmentManagerConsistency(); - - inflate(getContext(), R.layout.draggable_panel, this); - draggableView = (DraggableView) findViewById(R.id.draggable_view); - draggableView.setTopViewHeight(topFragmentHeight); - draggableView.setFragmentManager(fragmentManager); - draggableView.attachTopFragment(topFragment); - draggableView.setXTopViewScaleFactor(xScaleFactor); - draggableView.setYTopViewScaleFactor(yScaleFactor); - draggableView.setTopViewMarginRight(topFragmentMarginRight); - draggableView.setTopViewMarginBottom(topFragmentMarginBottom); - draggableView.attachBottomFragment(bottomFragment); - draggableView.setDraggableListener(draggableListener); - draggableView.setHorizontalAlphaEffectEnabled(enableHorizontalAlphaEffect); - draggableView.setClickToMaximizeEnabled(enableClickToMaximize); - draggableView.setClickToMinimizeEnabled(enableClickToMinimize); - draggableView.setTouchEnabled(enableTouchListener); - initialised = true; - } - - - /** - * Checks if the top Fragment is maximized. - * - * @return true if the view is maximized. - */ - public boolean isMaximized(){ - return draggableView.isMaximized(); - } - - - /** - * Checks if the top Fragment is minimized. - * - * @return true if the view is minimized. - */ - public boolean isMinimized(){ - return draggableView.isMinimized(); - } - - - /** - * Checks if the top Fragment closed at the right place. - * - * @return true if the view is closed at right. - */ - public boolean isClosedAtRight(){ - return draggableView.isClosedAtRight(); - } - - - /** - * Checks if the top Fragment is closed at the left place. - * - * @return true if the view is closed at left. - */ - public boolean isClosedAtLeft(){ - return draggableView.isClosedAtLeft(); - } - - - /** - * Initialize the xml configuration based on styleable attributes - * - * @param attrs to analyze. - */ - private void initializeAttrs(AttributeSet attrs){ - TypedArray attributes = - getContext().obtainStyledAttributes(attrs, R.styleable.draggable_panel); - this.topFragmentHeight = attributes.getDimensionPixelSize( - R.styleable.draggable_panel_top_fragment_height, DEFAULT_TOP_FRAGMENT_HEIGHT - ); - this.xScaleFactor = - attributes.getFloat(R.styleable.draggable_panel_x_scale_factor, DEFAULT_SCALE_FACTOR); - this.yScaleFactor = - attributes.getFloat(R.styleable.draggable_panel_y_scale_factor, DEFAULT_SCALE_FACTOR); - this.topFragmentMarginRight = attributes.getDimensionPixelSize( - R.styleable.draggable_panel_top_fragment_margin_right, DEFAULT_TOP_FRAGMENT_MARGIN - ); - this.topFragmentMarginBottom = attributes.getDimensionPixelSize( - R.styleable.draggable_panel_top_fragment_margin_bottom, DEFAULT_TOP_FRAGMENT_MARGIN - ); - this.enableHorizontalAlphaEffect = attributes.getBoolean( - R.styleable.draggable_panel_enable_horizontal_alpha_effect, DEFAULT_ENABLE_HORIZONTAL_ALPHA_EFFECT - ); - this.enableClickToMaximize = attributes.getBoolean( - R.styleable.draggable_panel_enable_click_to_maximize_panel, DEFAULT_ENABLE_CLICK_TO_MAXIMIZE - ); - this.enableClickToMinimize = attributes.getBoolean( - R.styleable.draggable_panel_enable_click_to_minimize_panel, DEFAULT_ENABLE_CLICK_TO_MINIMIZE - ); - this.enableTouchListener = attributes.getBoolean( - R.styleable.draggable_panel_enable_touch_listener_panel, DEFAULT_ENABLE_TOUCH_LISTENER - ); - attributes.recycle(); - } - - - /** - * Validate FragmentManager configuration. If is not initialized, this method will throw an - * IllegalStateException. - */ - private void checkSupportFragmentManagerConsistency(){ - if(fragmentManager == null){ - throw new IllegalStateException( - "You have to set the support FragmentManager before initialize DraggablePanel" - ); - } - } - - - /** - * Validate top and bottom Fragment configuration. If are not initialized, this method will throw - * an IllegalStateException. - */ - private void checkFragmentConsistency(){ - if(topFragment == null || bottomFragment == null){ - throw new IllegalStateException( - "You have to set top and bottom fragment before initialize DraggablePanel" - ); - } - } +public class DraggablePanel extends FrameLayout { + + private static final int DEFAULT_TOP_FRAGMENT_HEIGHT = 200; + private static final int DEFAULT_TOP_FRAGMENT_MARGIN = 0; + private static final float DEFAULT_SCALE_FACTOR = 2; + 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 boolean DEFAULT_TOP_FRAGMENT_RESIZE = false; + + private DraggableView draggableView; + private DraggableListener draggableListener; + + private FragmentManager fragmentManager; + private Fragment topFragment; + private Fragment bottomFragment; + private int topFragmentHeight; + private int topFragmentMarginRight; + private int topFragmentMarginBottom; + private float xScaleFactor; + private float yScaleFactor; + private boolean enableHorizontalAlphaEffect; + private boolean enableClickToMaximize; + private boolean enableClickToMinimize; + private boolean enableTouchListener; + private boolean initialised = false; + + public DraggablePanel(Context context) { + super(context); + } + + public DraggablePanel(Context context, AttributeSet attrs) { + super(context, attrs); + initializeAttrs(attrs); + } + + public DraggablePanel(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + initializeAttrs(attrs); + } + + /** + * Configure the FragmentManager used to attach top and bottom fragment inside the view. + */ + public void setFragmentManager(FragmentManager fragmentManager) { + this.fragmentManager = fragmentManager; + } + + /** + * Configure the Fragment that will work as draggable element inside this custom view. This + * Fragment has to be configured before initialize the view. + * + * @param topFragment used as draggable element. + */ + public void setTopFragment(Fragment topFragment) { + this.topFragment = topFragment; + } + + /** + * Configure the Fragment that will work as secondary element inside this custom view. This + * Fragment has to be configured before initialize the view. + * + * @param bottomFragment used as secondary element. + */ + public void setBottomFragment(Fragment bottomFragment) { + this.bottomFragment = bottomFragment; + } + + /** + * Configure the height associated to the top Fragment used inside the view as draggable element. + * + * @param topFragmentHeight in pixels. + */ + public void setTopViewHeight(int topFragmentHeight) { + this.topFragmentHeight = topFragmentHeight; + } + + /** + * 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; + } + + /** + * Disables dragging the view + * + * @param lock - true to disable, false to enable + */ + public void setLockDragMode(boolean lock) { + if (initialised) { + draggableView.setLockDragMode(lock); + } else { + throw new IllegalStateException("You have to initialise draggable panel first"); + } + } + + /** + * Return if dragging is locked or unlocked + */ + public boolean isLockDragMode() { + if (initialised) { + return draggableView.isLockDragMode(); + } else { + throw new IllegalStateException("You have to initialise draggable panel first"); + } + } + + /** + * 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, + * 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) { + draggableView.slideHorizontally(slideOffset, drawerPosition, width); + } + + /** + * Configure the horizontal scale factor applied when the top fragment is dragged to the bottom + * of the custom view. + */ + public void setXScaleFactor(float xScaleFactor) { + this.xScaleFactor = xScaleFactor; + } + + /** + * Configure the vertical scale factor applied when the top fragment is dragged to the bottom of + * the custom view. + */ + public void setYScaleFactor(float yScaleFactor) { + this.yScaleFactor = yScaleFactor; + } + + /** + * Configure the top Fragment margin right applied when the view has been minimized. + * + * @param topFragmentMarginRight in pixels. + */ + public void setTopFragmentMarginRight(int topFragmentMarginRight) { + this.topFragmentMarginRight = topFragmentMarginRight; + } + + /** + * Configure the top Fragment margin bottom applied when the view has been minimized. + * + * @param topFragmentMarginBottom in pixels. + */ + public void setTopFragmentMarginBottom(int topFragmentMarginBottom) { + this.topFragmentMarginBottom = topFragmentMarginBottom; + } + + /** + * Configure the DraggableListener that is going to be invoked when the view be minimized, + * maximized, closed to the left or right. + */ + public void setDraggableListener(DraggableListener draggableListener) { + this.draggableListener = draggableListener; + } + + /** + * Configure the disabling of the alpha effect applied when the view is being dragged + * horizontally. + * + * @param enableHorizontalAlphaEffect to enable or disable the effect. + */ + public void setEnableHorizontalAlphaEffect(boolean enableHorizontalAlphaEffect) { + this.enableHorizontalAlphaEffect = enableHorizontalAlphaEffect; + } + + /** + * Close the custom view applying an animation to close the view to the left side of the screen. + */ + public void closeToLeft() { + draggableView.closeToLeft(); + } + + /** + * Close the custom view applying an animation to close the view to the right side of the screen. + */ + public void closeToRight() { + draggableView.closeToRight(); + } + + /** + * Maximize the custom view applying an animation to return the view to the initial position. + */ + public void maximize() { + draggableView.maximize(); + } + + /** + * Minimize the custom view applying an animation to put the top fragment on the bottom right + * corner of the screen. + */ + public void minimize() { + draggableView.minimize(); + } + + /** + * Apply all the custom view configuration and inflate the main widgets. The view won't be + * visible if this method is not called. + *

+ * FragmentManager, top Fragment and bottom Fragment have to be configured before initialize this + * view. If not, this method will throw and IllegalStateException. + */ + public void initializeView() { + checkFragmentConsistency(); + checkSupportFragmentManagerConsistency(); + + inflate(getContext(), R.layout.draggable_panel, this); + draggableView = (DraggableView) findViewById(R.id.draggable_view); + draggableView.setTopViewHeight(topFragmentHeight); + draggableView.setFragmentManager(fragmentManager); + draggableView.attachTopFragment(topFragment); + draggableView.setXTopViewScaleFactor(xScaleFactor); + draggableView.setYTopViewScaleFactor(yScaleFactor); + draggableView.setTopViewMarginRight(topFragmentMarginRight); + draggableView.setTopViewMarginBottom(topFragmentMarginBottom); + draggableView.attachBottomFragment(bottomFragment); + draggableView.setDraggableListener(draggableListener); + draggableView.setHorizontalAlphaEffectEnabled(enableHorizontalAlphaEffect); + draggableView.setClickToMaximizeEnabled(enableClickToMaximize); + draggableView.setClickToMinimizeEnabled(enableClickToMinimize); + draggableView.setTouchEnabled(enableTouchListener); + initialised = true; + } + + /** + * Checks if the top Fragment is maximized. + * + * @return true if the view is maximized. + */ + public boolean isMaximized() { + return draggableView.isMaximized(); + } + + /** + * Checks if the top Fragment is minimized. + * + * @return true if the view is minimized. + */ + public boolean isMinimized() { + return draggableView.isMinimized(); + } + + /** + * Checks if the top Fragment closed at the right place. + * + * @return true if the view is closed at right. + */ + public boolean isClosedAtRight() { + return draggableView.isClosedAtRight(); + } + + /** + * Checks if the top Fragment is closed at the left place. + * + * @return true if the view is closed at left. + */ + public boolean isClosedAtLeft() { + return draggableView.isClosedAtLeft(); + } + + /** + * Initialize the xml configuration based on styleable attributes + * + * @param attrs to analyze. + */ + private void initializeAttrs(AttributeSet attrs) { + TypedArray attributes = getContext().obtainStyledAttributes(attrs, R.styleable.draggable_panel); + this.topFragmentHeight = + attributes.getDimensionPixelSize(R.styleable.draggable_panel_top_fragment_height, + DEFAULT_TOP_FRAGMENT_HEIGHT); + this.xScaleFactor = + attributes.getFloat(R.styleable.draggable_panel_x_scale_factor, DEFAULT_SCALE_FACTOR); + this.yScaleFactor = + attributes.getFloat(R.styleable.draggable_panel_y_scale_factor, DEFAULT_SCALE_FACTOR); + this.topFragmentMarginRight = + attributes.getDimensionPixelSize(R.styleable.draggable_panel_top_fragment_margin_right, + DEFAULT_TOP_FRAGMENT_MARGIN); + this.topFragmentMarginBottom = + attributes.getDimensionPixelSize(R.styleable.draggable_panel_top_fragment_margin_bottom, + DEFAULT_TOP_FRAGMENT_MARGIN); + this.enableHorizontalAlphaEffect = + attributes.getBoolean(R.styleable.draggable_panel_enable_horizontal_alpha_effect, + DEFAULT_ENABLE_HORIZONTAL_ALPHA_EFFECT); + this.enableClickToMaximize = + attributes.getBoolean(R.styleable.draggable_panel_enable_click_to_maximize_panel, + DEFAULT_ENABLE_CLICK_TO_MAXIMIZE); + this.enableClickToMinimize = + attributes.getBoolean(R.styleable.draggable_panel_enable_click_to_minimize_panel, + DEFAULT_ENABLE_CLICK_TO_MINIMIZE); + this.enableTouchListener = + attributes.getBoolean(R.styleable.draggable_panel_enable_touch_listener_panel, + DEFAULT_ENABLE_TOUCH_LISTENER); + attributes.recycle(); + } + + /** + * Validate FragmentManager configuration. If is not initialized, this method will throw an + * IllegalStateException. + */ + private void checkSupportFragmentManagerConsistency() { + if (fragmentManager == null) { + throw new IllegalStateException( + "You have to set the support FragmentManager before initialize DraggablePanel"); + } + } + + /** + * Validate top and bottom Fragment configuration. If are not initialized, this method will throw + * an IllegalStateException. + */ + private void checkFragmentConsistency() { + if (topFragment == null || bottomFragment == null) { + throw new IllegalStateException( + "You have to set top and bottom fragment before initialize DraggablePanel"); + } + } } diff --git a/draggablepanel/src/main/java/com/github/pedrovgs/DraggableView.java b/draggablepanel/src/main/java/com/github/pedrovgs/DraggableView.java index 548fd95..5bca451 100644 --- a/draggablepanel/src/main/java/com/github/pedrovgs/DraggableView.java +++ b/draggablepanel/src/main/java/com/github/pedrovgs/DraggableView.java @@ -18,12 +18,15 @@ import android.content.Context; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; +import android.os.Parcel; +import android.os.Parcelable; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.view.MotionEventCompat; import android.support.v4.view.ViewCompat; import android.support.v4.widget.ViewDragHelper; import android.util.AttributeSet; +import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.widget.RelativeLayout; @@ -38,6 +41,11 @@ */ public class DraggableView extends RelativeLayout { + private enum DraggableViewState { + MAXIMISED, MINIMISED, CLOSED_TO_LEFT, CLOSED_TO_RIGHT + } + + private DraggableViewState mState = DraggableViewState.MAXIMISED; 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; @@ -70,9 +78,14 @@ public class DraggableView extends RelativeLayout { private boolean enableClickToMaximize; private boolean enableClickToMinimize; private boolean touchEnabled; - private boolean lockDragMode =false; + private boolean lockDragMode = false; private DraggableListener listener; + private int left = 0; + private int top = 0; + private int right = 0; + private int bottom = 0; + public DraggableView(Context context) { super(context); } @@ -130,24 +143,22 @@ private boolean isTouchEnabled() { return this.touchEnabled; } - /** * Disables dragging the view - * @param lock - true to disable, false to enable * + * @param lock - true to disable, false to enable */ - public void setLockDragMode(boolean lock){ - this.lockDragMode =lock; + public void setLockDragMode(boolean lock) { + this.lockDragMode = lock; } - /** - * * Return if dragging is locked or unlocked */ - public boolean isLockDragMode(){ + public boolean isLockDragMode() { return lockDragMode; } + /** * Enable or disable the touch listener * @@ -380,7 +391,7 @@ public boolean isClosed() { if (activePointerId == INVALID_POINTER) { return false; } - if(!lockDragMode) viewDragHelper.processTouchEvent(ev); + if (!lockDragMode) viewDragHelper.processTouchEvent(ev); if (isClosed()) { return false; } @@ -396,7 +407,7 @@ public boolean isClosed() { } private void analyzeTouchToMaximizeIfNeeded(MotionEvent ev, boolean isDragViewHit) { - switch(ev.getAction()) { + switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: lastTouchActionDownXPosition = ev.getX(); break; @@ -417,8 +428,7 @@ private void analyzeTouchToMaximizeIfNeeded(MotionEvent ev, boolean isDragViewHi public boolean shouldMaximizeOnClick(MotionEvent ev, float deltaX, boolean isDragViewHit) { return (Math.abs(deltaX) < MIN_SLIDING_DISTANCE_ON_CLICK) - && ev.getAction() != MotionEvent.ACTION_MOVE - && isDragViewHit; + && ev.getAction() != MotionEvent.ACTION_MOVE && isDragViewHit; } /** @@ -440,16 +450,130 @@ private MotionEvent cloneMotionEventWithAction(MotionEvent event, int action) { * 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()) + Log.e("drview", + "onLayout " + changed + " | " + left + " | " + top + " | " + right + " | " + 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 (true) { + dragView.layout(left, top, right, transformer.getOriginalHeight()); + secondView.layout(left, transformer.getOriginalHeight(), right, bottom); + ViewHelper.setY(dragView, top); + ViewHelper.setX(dragView, left); + ViewHelper.setY(secondView, transformer.getOriginalHeight()); + ViewHelper.setX(secondView, left); + final int topBound = getPaddingTop(); + int x; + int y; + Drawable background = getBackground(); + switch (mState) { + case MAXIMISED: + transformer.updateScale(0f); + transformer.updatePosition(0f); + ViewHelper.setAlpha(secondView, 0.99864f); + if (background != null) { + int newAlpha = ONE_HUNDRED; + background.setAlpha(newAlpha); + } + //ViewHelper.setX(dragView, 0); + //ViewHelper.setY(dragView, 0); + dragView.offsetLeftAndRight(0); + dragView.offsetTopAndBottom(0); + ViewHelper.setY(secondView, dragView.getBottom()); + mState = DraggableViewState.MAXIMISED; + + //smoothSlideTo(SLIDE_TOP); + break; + case MINIMISED: + transformer.updatePosition(0.99864f); + transformer.updateScale(0.99864f); + ViewHelper.setAlpha(secondView, 0f); + if (background != null) { + int newAlpha = 0; + background.setAlpha(newAlpha); + } + x = (getWidth() - transformer.getMinWidthPlusMarginRight()); + y = (int) getVerticalDragRange(); + //ViewHelper.setX(dragView, x); + //ViewHelper.setY(dragView, y); + dragView.offsetLeftAndRight(x); + dragView.offsetTopAndBottom(y); + ViewHelper.setY(secondView, dragView.getBottom()); + mState = DraggableViewState.MINIMISED; + //smoothSlideTo(SLIDE_BOTTOM); + break; + case CLOSED_TO_LEFT: + x = -transformer.getOriginalWidth(); + y = getHeight() - transformer.getMinHeightPlusMargin(); + dragView.offsetLeftAndRight(x); + dragView.offsetTopAndBottom(y); + //ViewHelper.setX(dragView, -transformer.getOriginalWidth()); + //ViewHelper.setY(dragView, getHeight() - transformer.getMinHeightPlusMargin()); + transformer.updatePosition(0.99864f); + transformer.updateScale(0.99864f); + ViewHelper.setAlpha(secondView, 0f); + if (background != null) { + int newAlpha = 0; + background.setAlpha(newAlpha); + } + ViewHelper.setY(secondView, dragView.getBottom()); + mState = DraggableViewState.CLOSED_TO_LEFT; + + //closeToLeft(); + break; + case CLOSED_TO_RIGHT: + x = transformer.getOriginalWidth(); + y = getHeight() - transformer.getMinHeightPlusMargin(); + dragView.offsetLeftAndRight(x); + dragView.offsetTopAndBottom(y); + //ViewHelper.setX(dragView, transformer.getOriginalWidth()); + //ViewHelper.setY(dragView, getHeight() - transformer.getMinHeightPlusMargin()); + transformer.updatePosition(0.99864f); + transformer.updateScale(0.99864f); + ViewHelper.setAlpha(secondView, 0f); + if (background != null) { + int newAlpha = 0; + background.setAlpha(newAlpha); + } + mState = DraggableViewState.CLOSED_TO_RIGHT; + + ViewHelper.setY(secondView, dragView.getBottom()); + //closeToRight(); + break; + default: + transformer.updatePosition(0.99864f); + transformer.updateScale(0.99864f); + ViewHelper.setAlpha(secondView, 0f); + if (background != null) { + int newAlpha = 0; + background.setAlpha(newAlpha); + } + x = (int) ((getWidth() - transformer.getMinWidthPlusMarginRight())); + y = (int) (topBound + 1 * getVerticalDragRange()); + //ViewHelper.setX(dragView, x); + //ViewHelper.setY(dragView, y); + dragView.offsetLeftAndRight(x); + dragView.offsetTopAndBottom(y); + ViewHelper.setY(secondView, dragView.getBottom()); + mState = DraggableViewState.MINIMISED; + //smoothSlideTo(SLIDE_BOTTOM); + break; + } + } } + //else { + // if (isDragViewAtTop()) { + // dragView.layout(left, top, right, transformer.getOriginalHeight()); + // secondView.layout(left, transformer.getOriginalHeight(), right, bottom); + // ViewHelper.setY(dragView, top); + // ViewHelper.setX(dragView, left); + // ViewHelper.setY(secondView, transformer.getOriginalHeight()); + // ViewHelper.setX(secondView, left); + // } else { + // secondView.layout(left, transformer.getOriginalHeight(), right, bottom); + // } + //} } /** @@ -634,10 +758,8 @@ private boolean isViewHit(View view, int x, int y) { 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(); + return screenX >= viewLocation[0] && screenX < viewLocation[0] + view.getWidth() + && screenY >= viewLocation[1] && screenY < viewLocation[1] + view.getHeight(); } /** @@ -654,7 +776,8 @@ private void addFragmentToView(final int viewId, final Fragment fragment) { * Initialize the viewDragHelper. */ private void initializeViewDragHelper() { - viewDragHelper = ViewDragHelper.create(this, SENSITIVITY, new DraggableViewCallback(this, dragView)); + viewDragHelper = + ViewDragHelper.create(this, SENSITIVITY, new DraggableViewCallback(this, dragView)); } /** @@ -665,8 +788,9 @@ private void initializeTransformer(TypedArray attributes) { 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.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)); @@ -763,6 +887,7 @@ private float getVerticalDragRange() { * Notify te view is maximized to the DraggableListener */ private void notifyMaximizeToListener() { + mState = DraggableViewState.MAXIMISED; if (listener != null) { listener.onMaximized(); } @@ -772,6 +897,7 @@ private void notifyMaximizeToListener() { * Notify te view is minimized to the DraggableListener */ private void notifyMinimizeToListener() { + mState = DraggableViewState.MINIMISED; if (listener != null) { listener.onMinimized(); } @@ -781,6 +907,7 @@ private void notifyMinimizeToListener() { * Notify te view is closed to the right to the DraggableListener */ private void notifyCloseToRightListener() { + mState = DraggableViewState.CLOSED_TO_LEFT; if (listener != null) { listener.onClosedToRight(); } @@ -790,6 +917,7 @@ private void notifyCloseToRightListener() { * Notify te view is closed to the left to the DraggableListener */ private void notifyCloseToLeftListener() { + mState = DraggableViewState.CLOSED_TO_RIGHT; if (listener != null) { listener.onClosedToLeft(); } @@ -798,4 +926,77 @@ private void notifyCloseToLeftListener() { public int getDraggedViewHeightPlusMarginTop() { return transformer.getMinHeightPlusMargin(); } + + @Override protected Parcelable onSaveInstanceState() { + Parcelable superState = super.onSaveInstanceState(); + SavedState ss = new SavedState(superState); + ss.drState = mState; + return ss; + } + + @Override protected void onRestoreInstanceState(Parcelable state) { + if (!(state instanceof SavedState)) { + super.onRestoreInstanceState(state); + return; + } + SavedState ss = (SavedState) state; + super.onRestoreInstanceState(ss.getSuperState()); + mState = ss.drState; + switch (mState) { + case MAXIMISED: + smoothSlideTo(SLIDE_TOP); + break; + case MINIMISED: + smoothSlideTo(SLIDE_BOTTOM); + break; + case CLOSED_TO_LEFT: + closeToLeft(); + break; + case CLOSED_TO_RIGHT: + closeToRight(); + break; + default: + smoothSlideTo(SLIDE_BOTTOM); + break; + } + Log.e("drview", "onRestoreState " + mState.toString()); + } + + /** + * User interface state that is stored by TextView for implementing + * {@link View#onSaveInstanceState}. + */ + public static class SavedState extends BaseSavedState { + DraggableViewState drState; + + SavedState(Parcelable superState) { + super(superState); + } + + @Override public void writeToParcel(Parcel out, int flags) { + super.writeToParcel(out, flags); + out.writeSerializable(drState); + } + + @Override public String toString() { + String str = "DraggableView state: " + drState; + return str; + } + + @SuppressWarnings("hiding") public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + public SavedState createFromParcel(Parcel in) { + return new SavedState(in); + } + + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; + + private SavedState(Parcel in) { + super(in); + drState = (DraggableViewState) in.readSerializable(); + } + } } diff --git a/draggablepanel/src/main/java/com/github/pedrovgs/DraggableViewCallback.java b/draggablepanel/src/main/java/com/github/pedrovgs/DraggableViewCallback.java index 08016ba..f12528c 100644 --- a/draggablepanel/src/main/java/com/github/pedrovgs/DraggableViewCallback.java +++ b/draggablepanel/src/main/java/com/github/pedrovgs/DraggableViewCallback.java @@ -108,8 +108,7 @@ public DraggableViewCallback(DraggableView draggableView, View draggedView) { @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; @@ -126,13 +125,13 @@ public DraggableViewCallback(DraggableView draggableView, View draggedView) { */ @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(); } - } diff --git a/sample/AndroidManifest.xml b/sample/AndroidManifest.xml index 9f99368..01958b3 100755 --- a/sample/AndroidManifest.xml +++ b/sample/AndroidManifest.xml @@ -62,7 +62,6 @@ 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 b4622ac..330b07c 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,11 +15,12 @@ */ 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; @@ -29,163 +30,139 @@ 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 void onConfigurationChanged(Configuration newConfig){ - super.onConfigurationChanged(newConfig); - if(getResources().getConfiguration().orientation==Configuration.ORIENTATION_LANDSCAPE)draggablePanel.setLockDragMode(true); - else draggablePanel.setLockDragMode(false); - } +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); + // if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { + // draggablePanel.setLockDragMode(true); + // } else { + // draggablePanel.setLockDragMode(false); + // } + //} } From f12d49f974d4138255eff171d02a89514d9c6e0a Mon Sep 17 00:00:00 2001 From: Yarh Date: Tue, 27 Oct 2015 16:28:07 +0200 Subject: [PATCH 4/5] keep state restore on manual orientation handling --- .../com/github/pedrovgs/DraggableView.java | 49 +++----- sample/AndroidManifest.xml | 115 ++++++++++-------- 2 files changed, 76 insertions(+), 88 deletions(-) diff --git a/draggablepanel/src/main/java/com/github/pedrovgs/DraggableView.java b/draggablepanel/src/main/java/com/github/pedrovgs/DraggableView.java index 5bca451..cd88045 100644 --- a/draggablepanel/src/main/java/com/github/pedrovgs/DraggableView.java +++ b/draggablepanel/src/main/java/com/github/pedrovgs/DraggableView.java @@ -276,7 +276,8 @@ public void maximize() { * corner of the screen. */ public void minimize() { - smoothSlideTo(SLIDE_BOTTOM); + //if (!isDragViewAtBottom()) + smoothSlideTo(SLIDE_BOTTOM); notifyMinimizeToListener(); } @@ -284,7 +285,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() { - if (viewDragHelper.smoothSlideViewTo(dragView, transformer.getOriginalWidth(), + if (viewDragHelper.smoothSlideViewTo(dragView, getWidth(), getHeight() - transformer.getMinHeightPlusMargin())) { ViewCompat.postInvalidateOnAnimation(this); notifyCloseToRightListener(); @@ -295,7 +296,7 @@ public void closeToRight() { * 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(), + if (viewDragHelper.smoothSlideViewTo(dragView, -getWidth(), getHeight() - transformer.getMinHeightPlusMargin())) { ViewCompat.postInvalidateOnAnimation(this); notifyCloseToLeftListener(); @@ -452,6 +453,9 @@ private MotionEvent cloneMotionEventWithAction(MotionEvent event, int action) { @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { Log.e("drview", "onLayout " + changed + " | " + left + " | " + top + " | " + right + " | " + bottom); + Log.e("drview", + "view size " + dragView.getWidth() + " | " + dragView.getHeight() + " + screen width " + + getWidth()); if (isInEditMode()) { super.onLayout(changed, left, top, right, bottom); } else { @@ -476,14 +480,11 @@ private MotionEvent cloneMotionEventWithAction(MotionEvent event, int action) { int newAlpha = ONE_HUNDRED; background.setAlpha(newAlpha); } - //ViewHelper.setX(dragView, 0); - //ViewHelper.setY(dragView, 0); dragView.offsetLeftAndRight(0); dragView.offsetTopAndBottom(0); ViewHelper.setY(secondView, dragView.getBottom()); mState = DraggableViewState.MAXIMISED; - //smoothSlideTo(SLIDE_TOP); break; case MINIMISED: transformer.updatePosition(0.99864f); @@ -495,21 +496,16 @@ private MotionEvent cloneMotionEventWithAction(MotionEvent event, int action) { } x = (getWidth() - transformer.getMinWidthPlusMarginRight()); y = (int) getVerticalDragRange(); - //ViewHelper.setX(dragView, x); - //ViewHelper.setY(dragView, y); - dragView.offsetLeftAndRight(x); + dragView.offsetLeftAndRight(0); dragView.offsetTopAndBottom(y); ViewHelper.setY(secondView, dragView.getBottom()); mState = DraggableViewState.MINIMISED; - //smoothSlideTo(SLIDE_BOTTOM); break; case CLOSED_TO_LEFT: - x = -transformer.getOriginalWidth(); + x = -getWidth(); y = getHeight() - transformer.getMinHeightPlusMargin(); dragView.offsetLeftAndRight(x); dragView.offsetTopAndBottom(y); - //ViewHelper.setX(dragView, -transformer.getOriginalWidth()); - //ViewHelper.setY(dragView, getHeight() - transformer.getMinHeightPlusMargin()); transformer.updatePosition(0.99864f); transformer.updateScale(0.99864f); ViewHelper.setAlpha(secondView, 0f); @@ -520,15 +516,12 @@ private MotionEvent cloneMotionEventWithAction(MotionEvent event, int action) { ViewHelper.setY(secondView, dragView.getBottom()); mState = DraggableViewState.CLOSED_TO_LEFT; - //closeToLeft(); break; case CLOSED_TO_RIGHT: - x = transformer.getOriginalWidth(); + x = getWidth(); y = getHeight() - transformer.getMinHeightPlusMargin(); dragView.offsetLeftAndRight(x); dragView.offsetTopAndBottom(y); - //ViewHelper.setX(dragView, transformer.getOriginalWidth()); - //ViewHelper.setY(dragView, getHeight() - transformer.getMinHeightPlusMargin()); transformer.updatePosition(0.99864f); transformer.updateScale(0.99864f); ViewHelper.setAlpha(secondView, 0f); @@ -539,7 +532,6 @@ private MotionEvent cloneMotionEventWithAction(MotionEvent event, int action) { mState = DraggableViewState.CLOSED_TO_RIGHT; ViewHelper.setY(secondView, dragView.getBottom()); - //closeToRight(); break; default: transformer.updatePosition(0.99864f); @@ -551,29 +543,14 @@ private MotionEvent cloneMotionEventWithAction(MotionEvent event, int action) { } x = (int) ((getWidth() - transformer.getMinWidthPlusMarginRight())); y = (int) (topBound + 1 * getVerticalDragRange()); - //ViewHelper.setX(dragView, x); - //ViewHelper.setY(dragView, y); - dragView.offsetLeftAndRight(x); + dragView.offsetLeftAndRight(0); dragView.offsetTopAndBottom(y); ViewHelper.setY(secondView, dragView.getBottom()); mState = DraggableViewState.MINIMISED; - //smoothSlideTo(SLIDE_BOTTOM); break; } } } - //else { - // if (isDragViewAtTop()) { - // dragView.layout(left, top, right, transformer.getOriginalHeight()); - // secondView.layout(left, transformer.getOriginalHeight(), right, bottom); - // ViewHelper.setY(dragView, top); - // ViewHelper.setX(dragView, left); - // ViewHelper.setY(secondView, transformer.getOriginalHeight()); - // ViewHelper.setX(secondView, left); - // } else { - // secondView.layout(left, transformer.getOriginalHeight(), right, bottom); - // } - //} } /** @@ -834,8 +811,10 @@ private void initializeAttributes(AttributeSet attrs) { private boolean smoothSlideTo(float slideOffset) { final int topBound = getPaddingTop(); int x = (int) (slideOffset * (getWidth() - transformer.getMinWidthPlusMarginRight())); + Log.e("drview", + "minimise " + x + " + " + transformer.getMinWidthPlusMarginRight() + " = " + getWidth()); 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/sample/AndroidManifest.xml b/sample/AndroidManifest.xml index 01958b3..d35d5ce 100755 --- a/sample/AndroidManifest.xml +++ b/sample/AndroidManifest.xml @@ -1,83 +1,92 @@ + > - + - + - - - - + + + + - + - + - - - + - + - + - - - + - - - + + + - + + + - - android:label="@string/places_sample_activity_title" /> + + android:label="@string/places_sample_activity_title" + /> - + + - - - android:label="@string/youtube_sample_activity_title" /> + - + - + android:label="@string/video_sample_activity_title" + /> - + - + From 504109bfd92219a31f2275d2ffd7a651a6674f45 Mon Sep 17 00:00:00 2001 From: Yarh Date: Tue, 27 Oct 2015 16:35:16 +0200 Subject: [PATCH 5/5] add full screen --- .../main/java/com/github/pedrovgs/DraggablePanel.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/draggablepanel/src/main/java/com/github/pedrovgs/DraggablePanel.java b/draggablepanel/src/main/java/com/github/pedrovgs/DraggablePanel.java index 15f6d33..ed554c2 100644 --- a/draggablepanel/src/main/java/com/github/pedrovgs/DraggablePanel.java +++ b/draggablepanel/src/main/java/com/github/pedrovgs/DraggablePanel.java @@ -110,6 +110,15 @@ public void setTopViewHeight(int topFragmentHeight) { this.topFragmentHeight = topFragmentHeight; } + public void setFullScreen(boolean fullScreen) { + setLockDragMode(fullScreen); + if (fullScreen) { + draggableView.setTopViewHeight(getResources().getDisplayMetrics().heightPixels); + } else { + draggableView.setTopViewHeight(topFragmentHeight); + } + } + /** * Return if user can maximize minimized view on click. */