1
1
package com .sothree .slidinguppanel ;
2
2
3
3
import android .annotation .SuppressLint ;
4
+ import android .annotation .TargetApi ;
4
5
import android .content .Context ;
5
6
import android .content .res .TypedArray ;
6
7
import android .graphics .Canvas ;
7
8
import android .graphics .Paint ;
8
9
import android .graphics .PixelFormat ;
10
+ import android .graphics .Point ;
9
11
import android .graphics .Rect ;
10
12
import android .graphics .drawable .Drawable ;
11
13
import android .os .Build ;
16
18
import android .support .v4 .view .ViewCompat ;
17
19
import android .support .v7 .widget .RecyclerView ;
18
20
import android .util .AttributeSet ;
21
+ import android .util .Log ;
19
22
import android .view .Gravity ;
20
23
import android .view .MotionEvent ;
21
24
import android .view .View ;
22
25
import android .view .ViewGroup ;
26
+ import android .view .WindowManager ;
23
27
import android .view .accessibility .AccessibilityEvent ;
24
28
import android .widget .ListView ;
25
29
import android .widget .ScrollView ;
@@ -41,6 +45,11 @@ public class SlidingUpPanelLayout extends ViewGroup {
41
45
*/
42
46
private static final float DEFAULT_ANCHOR_POINT = 1.0f ; // In relative %
43
47
48
+ /**
49
+ * Default position of the panel
50
+ */
51
+ private static final boolean DEFAULT_PANEL_OFF_SCREEN = false ;
52
+
44
53
/**
45
54
* Default initial state for the component
46
55
*/
@@ -105,6 +114,11 @@ public class SlidingUpPanelLayout extends ViewGroup {
105
114
*/
106
115
private int mPanelHeight = -1 ;
107
116
117
+ /**
118
+ * True if we want to slide the visible panel off screen; false by default
119
+ */
120
+ private boolean mPanelOffScreen ;
121
+
108
122
/**
109
123
* The size of the shadow in pixels.
110
124
*/
@@ -212,6 +226,8 @@ public enum PanelState {
212
226
213
227
private final ViewDragHelper mDragHelper ;
214
228
229
+ private Context mContext ;
230
+
215
231
/**
216
232
* Stores whether or not the pane was expanded the last time it was slideable.
217
233
* If expand/collapse operations are invoked this state is modified. Used by
@@ -299,6 +315,8 @@ public SlidingUpPanelLayout(Context context, AttributeSet attrs) {
299
315
public SlidingUpPanelLayout (Context context , AttributeSet attrs , int defStyle ) {
300
316
super (context , attrs , defStyle );
301
317
318
+ mContext = context ;
319
+
302
320
if (isInEditMode ()) {
303
321
mShadowDrawable = null ;
304
322
mDragHelper = null ;
@@ -334,6 +352,8 @@ public SlidingUpPanelLayout(Context context, AttributeSet attrs, int defStyle) {
334
352
mAnchorPoint = ta .getFloat (R .styleable .SlidingUpPanelLayout_umanoAnchorPoint , DEFAULT_ANCHOR_POINT );
335
353
336
354
mSlideState = PanelState .values ()[ta .getInt (R .styleable .SlidingUpPanelLayout_umanoInitialState , DEFAULT_SLIDE_STATE .ordinal ())];
355
+
356
+ mPanelOffScreen = ta .getBoolean (R .styleable .SlidingUpPanelLayout_panelOffScreen , DEFAULT_PANEL_OFF_SCREEN );
337
357
}
338
358
339
359
ta .recycle ();
@@ -374,6 +394,13 @@ public SlidingUpPanelLayout(Context context, AttributeSet attrs, int defStyle) {
374
394
@ Override
375
395
protected void onFinishInflate () {
376
396
super .onFinishInflate ();
397
+
398
+ if (mPanelOffScreen ) {
399
+ // Get scrollable view (always second child) and expand its size in order to put
400
+ // the panel above the screen
401
+ View slidingUpPanelLayout = getChildAt (1 );
402
+ setExpandedPanelOffScreen (slidingUpPanelLayout );
403
+ }
377
404
if (mDragViewResId != -1 ) {
378
405
setDragView (findViewById (mDragViewResId ));
379
406
}
@@ -382,6 +409,30 @@ protected void onFinishInflate() {
382
409
}
383
410
}
384
411
412
+ /**
413
+ * Expands the height of the SlidingUpPanelLayout by 'mPanelHeight' so that there's no
414
+ * empty space at the bottom when the view is expanded
415
+ *
416
+ * @param slidingUpPanelLayout (SlidingUpPanelLayout)
417
+ */
418
+ @ TargetApi (13 )
419
+ public void setExpandedPanelOffScreen (View slidingUpPanelLayout ) {
420
+ if (slidingUpPanelLayout != null ) {
421
+ // Get screen dimensions
422
+ final Point size = new Point ();
423
+ ((WindowManager ) mContext .getSystemService (Context .WINDOW_SERVICE )).getDefaultDisplay ().getSize (size );
424
+ final int screenHeight = size .y ;
425
+ final int screenWidth = size .x ;
426
+
427
+ SlidingUpPanelLayout .LayoutParams params ;
428
+ params = new SlidingUpPanelLayout .LayoutParams (screenWidth , screenHeight + mPanelHeight );
429
+
430
+ slidingUpPanelLayout .setLayoutParams (params );
431
+ } else {
432
+ Log .e (TAG , "slidingUpPanelLayout is null in setExpandedPanelOffScreen" );
433
+ }
434
+ }
435
+
385
436
public void setGravity (int gravity ) {
386
437
if (gravity != Gravity .TOP && gravity != Gravity .BOTTOM ) {
387
438
throw new IllegalArgumentException ("gravity must be set to either top or bottom" );
@@ -799,14 +850,29 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
799
850
800
851
child .measure (childWidthSpec , childHeightSpec );
801
852
802
- if (child == mSlideableView ) {
853
+ if (mPanelOffScreen ) {
854
+ // In order to place the panel off the screen,
855
+ // the sliding distance will be the height of the entire sliding view
856
+ // minus the panel height and the notification bar
857
+ mSlideRange = mSlideableView .getMeasuredHeight () - mPanelHeight - getNotificationBarHeight ();
858
+ } else {
803
859
mSlideRange = mSlideableView .getMeasuredHeight () - mPanelHeight ;
804
860
}
805
861
}
806
862
807
863
setMeasuredDimension (widthSize , heightSize );
808
864
}
809
865
866
+ // Returns the height of the notification bar
867
+ private int getNotificationBarHeight () {
868
+ int resourceId = getResources ().getIdentifier ("status_bar_height" , "dimen" , "android" );
869
+ if (resourceId > 0 ) {
870
+ return getResources ().getDimensionPixelSize (resourceId );
871
+ } else {
872
+ return 0 ;
873
+ }
874
+ }
875
+
810
876
@ Override
811
877
protected void onLayout (boolean changed , int l , int t , int r , int b ) {
812
878
final int paddingLeft = getPaddingLeft ();
0 commit comments