android 多方向抽屉,Android开发之自定义Panel实现多方向抽屉(上下左右)效果

前面讲过了一下抽屉的多方向开发,可能有部分代码没贴出来,有些朋友还没办法完全实现出四个方向的效果,

我也不多说了,下面就把所有的代码都贴出来,这也是从一些高手那里学来的,跟大伙分享分享。

首先是实现自定义的控件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();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值