前面讲过了一下抽屉的多方向开发,可能有部分代码没贴出来,有些朋友还没办法完全实现出四个方向的效果,
我也不多说了,下面就把所有的代码都贴出来,这也是从一些高手那里学来的,跟大伙分享分享。
首先是实现自定义的控件Panel的方法:
Panel.java :
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.TranslateAnimation;
import android.widget.LinearLayout;
public class Panel extends LinearLayout {
private static final String TAG = "Panel";
public static interface OnPanelListener {
public void onPanelClosed(Panel panel);
public void onPanelOpened(Panel panel);
}
private boolean mIsShrinking;
private int mPosition;
private int mDuration;
private boolean mLinearFlying;
private View mHandle;
private View mContent;
private Drawable mOpenedHandle;
private Drawable mClosedHandle;
private float mTrackX;
private float mTrackY;
private float mVelocity;
private OnPanelListener panelListener;
public static final int TOP = 0;
public static final int BOTTOM = 1;
public static final int LEFT = 2;
public static final int RIGHT = 3;
private enum State {
ABOUT_TO_ANIMATE,
ANIMATING,
READY,
TRACKING,
FLYING,
};
private State mState;
private Interpolator mInterpolator;
private GestureDetector
mGestureDetector;
private int mContentHeight;
private int mContentWidth;
private int mOrientation;
private PanelOnGestureListener
mGestureListener;
public Panel(Context context, AttributeSet
attrs) {
super(context,
attrs);
TypedArray a =
context.obtainStyledAttributes(attrs, R.styleable.Panel);
mDuration =
a.getInteger(R.styleable.Panel_animationDuration,
750); // duration
defaults to 750 ms
mPosition =
a.getInteger(R.styleable.Panel_position,
BOTTOM); //
position defaults to BOTTOM
mLinearFlying =
a.getBoolean(R.styleable.Panel_linearFlying,
false); // linearFlying defaults to
false
mOpenedHandle =
a.getDrawable(R.styleable.Panel_openedHandle);
mClosedHandle =
a.getDrawable(R.styleable.Panel_closedHandle);
a.recycle();
mOrientation =
(mPosition == TOP || mPosition == BOTTOM)? VERTICAL :
HORIZONTAL;
setOrientation(mOrientation);
mState =
State.READY;
mGestureListener
= new PanelOnGestureListener();
mGestureDetector
= new GestureDetector(mGestureListener);
mGestureDetector.setIsLongpressEnabled(false);
}
public void setOnPanelListener(OnPanelListener onPanelListener)
{
panelListener = onPanelListener;
}
public View getHandle() {
return
mHandle;
}
public View getContent() {
return
mContent;
}
public void setInterpolator(Interpolator i) {
mInterpolator = i;
}
public void setOpen(boolean open, boolean
animate) {
if (isOpen() ^
open) {
mIsShrinking
= !open;
if
(animate) {
mState
= State.ABOUT_TO_ANIMATE;
if
(!mIsShrinking) {
//
this could make flicker so we test mState in dispatchDraw()
//
to see if is equal to ABOUT_TO_ANIMATE
mContent.setVisibility(VISIBLE);
}
post(startAnimation);
}
else {
mContent.setVisibility(open?
VISIBLE : GONE);
postProcess();
}
}
}
public boolean isOpen() {
return
mContent.getVisibility() == VISIBLE;
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mHandle =
findViewById(R.id.panelHandle);
if (mHandle ==
null) {
throw new RuntimeException("Your Panel must have a View whose id
attribute is 'R.id.panelHandle'");
}
mHandle.setOnTouchListener(touchListener);
mContent =
findViewById(R.id.panelContent);
if (mContent ==
null) {
throw new RuntimeException("Your Panel must have a View whose id
attribute is 'R.id.panelContent'");
}
// reposition
children
removeView(mHandle);
removeView(mContent);
if (mPosition ==
TOP || mPosition == LEFT) {
addView(mContent);
addView(mHandle);
} else {
addView(mHandle);
addView(mContent);
}
if
(mClosedHandle != null) {
mHandle.setBackgroundDrawable(mClosedHandle);
}
mContent.setVisibility(GONE);
}
@Override
protected void onLayout(boolean changed,
int l, int t, int r, int b) {
super.onLayout(changed,
l, t, r, b);
mContentWidth =
mContent.getWidth();
mContentHeight =
mContent.getHeight();
}
@Override
protected void dispatchDraw(Canvas canvas)
{
// String name =
getResources().getResourceEntryName(getId());
// Log.d(TAG, name
+ " ispatchDraw " + mState);
// this is why
'mState' was added:
// avoid flicker
before animation start
if (mState ==
State.ABOUT_TO_ANIMATE &&
!mIsShrinking) {
int
delta = mOrientation == VERTICAL? mContentHeight :
mContentWidth;
if
(mPosition == LEFT || mPosition == TOP) {
delta
= -delta;
}
if
(mOrientation == VERTICAL) {
canvas.translate(0,
delta);
}
else {
canvas.translate(delta,
0);
}
}
if (mState ==
State.TRACKING || mState == State.FLYING) {
canvas.translate(mTrackX,
mTrackY);
}
super.dispatchDraw(canvas);
}
private float ensureRange(float v, int
min, int max) {
v = Math.max(v,
min);
v = Math.min(v,
max);
return v;
}
OnTouchListener touchListener = new
OnTouchListener() {
int initX;
int initY;
boolean
setInitialPosition;
public boolean
onTouch(View v, MotionEvent event) {
// Log.d(TAG,
"state: " + mState + " x: " + event.getX() + " y: " +
event.getY());
int
action = event.getAction();
if
(action == MotionEvent.ACTION_DOWN) {
initX
= 0;
initY
= 0;
if
(mContent.getVisibility() == GONE) {
//
since we may not know content dimensions we use factors here
if
(mOrientation == VERTICAL) {
initY
= mPosition == TOP? -1 : 1;
}
else {
initX
= mPosition == LEFT? -1 : 1;
}
}
setInitialPosition
= true;
}
else {
if
(setInitialPosition) {
//
now we know content dimensions, so we multiply factors...
initX
*= mContentWidth;
initY
*= mContentHeight;
//
... and set initial panel's position
mGestureListener.setScroll(initX,
initY);
setInitialPosition
= false;
//
for offsetLocation we have to invert values
initX
= -initX;
initY
= -initY;
}
//
offset every ACTION_MOVE & ACTION_UP event
event.offsetLocation(initX,
initY);
}
if
(!mGestureDetector.onTouchEvent(event)) {
if
(action == MotionEvent.ACTION_UP) {
//
tup up after scrolling
post(startAnimation);
}
}
return
false;
}
};
// OnTouchListener touchListener = new
OnTouchListener() {
// float touchX, touchY;
// // public boolean onTouch(View v, MotionEvent event) {
// if (mState == State.ANIMATING) {
// return false;
// }
// int action = event.getAction();
// if (action == MotionEvent.ACTION_DOWN) {
if (mBringToFront) {
bringToFront();