首页 > 其他分享 >Android从上到下抽屉式效果

Android从上到下抽屉式效果

时间:2023-03-02 13:02:35浏览次数:42  
标签:layout int public 抽屉式 id Android Panel android 从上到下


SlidingDrawerDemo.java:

 

package org.lee.android;

import org.lee.android.ExpoInterpolator.EasingType;
import org.lee.android.ExpoInterpolator.ExpoInterpolator;
import org.lee.android.widget.Panel;
import org.lee.android.widget.Panel.OnPanelListener;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

public class SlidingDrawerDemo extends Activity implements OnPanelListener{


@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
super.setContentView(R.layout.sildingdrawer);

Panel panel;

panel = (Panel) findViewById(R.id.topPanel);
panel.setOnPanelListener(this);
panel.setInterpolator(new ExpoInterpolator(EasingType.OUT));

}

public void onPanelClosed(Panel panel) {
String panelName = getResources().getResourceEntryName(panel.getId());
Log.d("TestPanels", "Panel [" + panelName + "] closed");
}
public void onPanelOpened(Panel panel) {
String panelName = getResources().getResourceEntryName(panel.getId());
Log.d("TestPanels", "Panel [" + panelName + "] opened");
}

}

 

 

 

 

 

sildingdrawer.xml:

 



<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:panel="http://schemas.android.com/apk/res/org.lee.android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffff"
android:orientation="vertical" >

<RelativeLayout
android:id="@+id/listHeader"
android:layout_width="fill_parent"
android:layout_height="48dp"
android:layout_alignParentTop="true"
android:background="#F7BAD6" >

<ImageView
android:id="@+id/header_back"
android:layout_width="12dp"
android:layout_height="30dp"
android:layout_centerVertical="true"
android:layout_marginLeft="12px"
android:background="@drawable/header_back" />

<TextView
android:id="@+id/shop_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="15px"
android:layout_toRightOf="@id/header_back"
android:text="标题"
android:textColor="#ffffff"
android:textSize="28px" />

<ImageView
android:id="@+id/three_rect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="12dp"
android:background="@drawable/three_rect" />
</RelativeLayout>

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/listHeader"
android:orientation="vertical" >

<!-- tab标签栏 -->

<LinearLayout
android:id="@+id/header"
android:layout_width="fill_parent"
android:layout_height="40dp"
android:background="#FFFFFF" >


<TextView
android:id="@+id/text1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1.0"
android:gravity="center"
android:text="页卡1"
android:textColor="#000000"
android:textSize="22.0dip" />

<View
android:layout_width="2dip"
android:layout_height="30dip"
android:layout_gravity="center_vertical"
android:background="#D7D7D7" />


<TextView
android:id="@+id/text2"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1.0"
android:gravity="center"
android:text="页卡2"
android:textColor="#000000"
android:textSize="22.0dip" />

<View
android:layout_width="2dip"
android:layout_height="30dip"
android:layout_gravity="center_vertical"
android:background="#D7D7D7" />


<TextView
android:id="@+id/text3"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1.0"
android:gravity="center"
android:text="页卡3"
android:textColor="#000000"
android:textSize="22.0dip" />

<View
android:layout_width="2dip"
android:layout_height="30dip"
android:layout_gravity="center_vertical"
android:background="#D7D7D7" />


<TextView
android:id="@+id/text4"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1.0"
android:gravity="center"
android:text="页卡4"
android:textColor="#000000"
android:textSize="22.0dip" />

<!-- 最右侧分类标识 -->

<FrameLayout
android:layout_width="50dp"
android:layout_height="fill_parent"
android:layout_marginRight="5dp" >
</FrameLayout>
</LinearLayout>

<TextView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="@id/header"
android:background="#ff6600"
android:text="和哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈和"
android:textColor="#ffffff"
android:textSize="18sp"
android:textStyle="bold" />

<org.lee.android.widget.Panel
android:id="@+id/topPanel"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="top|right"
android:paddingBottom="4dip"
panel:animationDuration="1200"
panel:content="@+id/panelContent"
panel:handle="@+id/panelHandle"
panel:linearFlying="true"
panel:position="top" >

<TextView
android:id="@+id/panelHandle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:background="@drawable/up"
android:gravity="center"
android:padding="5dp"
android:text="分类"
android:textColor="#ffffff"
android:textSize="15sp" />

<LinearLayout
android:id="@+id/panelContent"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >

<CheckBox
android:layout_width="fill_parent"
android:layout_height="60dip"
android:background="#688"
android:gravity="center"
android:text="top check box" />

<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#323299"
android:gravity="center"
android:padding="4dip"
android:text="Bounce\nInterpolator"
android:textColor="#eee"
android:textSize="16dip"
android:textStyle="bold" />
</LinearLayout>
</org.lee.android.widget.Panel>
</RelativeLayout>

</RelativeLayout>

EasingType.java:

 

package org.lee.android.ExpoInterpolator;

public class EasingType {
public static final int IN = 0;
public static final int OUT = 1;
public static final int INOUT = 2;

}

 

 

 

 

 

ExpoInterpolator.java:

 

package org.lee.android.ExpoInterpolator;

/*
*
* Open source under the BSD License.
*
* Copyright © 2001 Robert Penner
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* Neither the name of the author nor the names of contributors may be used to endorse
* or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/


import android.view.animation.Interpolator;


public class ExpoInterpolator implements Interpolator {

private int type;

public ExpoInterpolator(int type) {
this.type = type;
}

public float getInterpolation(float t) {
if (type == EasingType.IN) {
return in(t);
} else
if (type == EasingType.OUT) {
return out(t);
} else
if (type == EasingType.INOUT) {
return inout(t);
}
return 0;
}

private float in(float t) {
return (float) ((t==0) ? 0 : Math.pow(2, 10 * (t - 1)));
}
private float out(float t) {
return (float) ((t>=1) ? 1 : (-Math.pow(2, -10 * t) + 1));
}
private float inout(float t) {
if (t == 0) {
return 0;
}
if (t >= 1) {
return 1;
}
t *= 2;
if (t < 1) {
return (float) (0.5f * Math.pow(2, 10 * (t - 1)));
} else {
return (float) (0.5f * (-Math.pow(2, -10 * --t) + 2));
}
}
}

 

 

 

 

 

Panel.java:

 

package org.lee.android.widget;


import org.lee.android.R;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
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.FrameLayout;
import android.widget.LinearLayout;


public class Panel extends LinearLayout {

private static final String TAG = "Panel";

/**
* Callback invoked when the panel is opened/closed.
*/
public static interface OnPanelListener {
/**
* Invoked when the panel becomes fully closed.
*/
public void onPanelClosed(Panel panel);
/**
* Invoked when the panel becomes fully opened.
*/
public void onPanelOpened(Panel panel);
}

private boolean mIsShrinking;
private int mPosition;
private int mDuration;
private boolean mLinearFlying;
private int mHandleId;
private int mContentId;
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 float mWeight;
private PanelOnGestureListener mGestureListener;
private boolean mBringToFront;

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
mWeight = a.getFraction(R.styleable.Panel_weight, 0, 1, 0.0f); // weight defaults to 0.0
if (mWeight < 0 || mWeight > 1) {
mWeight = 0.0f;
Log.w(TAG, a.getPositionDescription() + ": weight must be > 0 and <= 1");
}
mOpenedHandle = a.getDrawable(R.styleable.Panel_openedHandle);
mClosedHandle = a.getDrawable(R.styleable.Panel_closedHandle);

RuntimeException e = null;
mHandleId = a.getResourceId(R.styleable.Panel_handle, 0);
if (mHandleId == 0) {
e = new IllegalArgumentException(a.getPositionDescription() +
": The handle attribute is required and must refer to a valid child.");
}
mContentId = a.getResourceId(R.styleable.Panel_content, 0);
if (mContentId == 0) {
e = new IllegalArgumentException(a.getPositionDescription() +
": The content attribute is required and must refer to a valid child.");
}
a.recycle();

if (e != null) {
throw e;
}
mOrientation = (mPosition == TOP || mPosition == BOTTOM)? VERTICAL : HORIZONTAL;
setOrientation(mOrientation);
mState = State.READY;
mGestureListener = new PanelOnGestureListener();
mGestureDetector = new GestureDetector(mGestureListener);
mGestureDetector.setIsLongpressEnabled(false);

// i DON'T really know why i need this...
setBaselineAligned(false);
}

/**
* Sets the listener that receives a notification when the panel becomes open/close.
*
* @param onPanelListener The listener to be notified when the panel is opened/closed.
*/
public void setOnPanelListener(OnPanelListener onPanelListener) {
panelListener = onPanelListener;
}

/**
* Gets Panel's mHandle
*
* @return Panel's mHandle
*/
public View getHandle() {
return mHandle;
}

/**
* Gets Panel's mContent
*
* @return Panel's mContent
*/
public View getContent() {
return mContent;
}


/**
* Sets the acceleration curve for panel's animation.
*
* @param i The interpolator which defines the acceleration curve
*/
public void setInterpolator(Interpolator i) {
mInterpolator = i;
}

/**
* Set the opened state of Panel.
*
* @param open True if Panel is to be opened, false if Panel is to be closed.
* @param animate True if use animation, false otherwise.
*
* @return True if operation was performed, false otherwise.
*
*/
public boolean setOpen(boolean open, boolean animate) {
if (mState == State.READY && 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();
}
return true;
}
return false;
}

/**
* Returns the opened status for Panel.
*
* @return True if Panel is opened, false otherwise.
*/
public boolean isOpen() {
return mContent.getVisibility() == VISIBLE;
}

@Override
protected void onFinishInflate() {
super.onFinishInflate();
mHandle = findViewById(mHandleId);
if (mHandle == null) {
String name = getResources().getResourceEntryName(mHandleId);
throw new RuntimeException("Your Panel must have a child View whose id attribute is 'R.id." + name + "'");
}
mHandle.setOnTouchListener(touchListener);
mHandle.setOnClickListener(clickListener);

mContent = findViewById(mContentId);
if (mContent == null) {
String name = getResources().getResourceEntryName(mHandleId);
throw new RuntimeException("Your Panel must have a child View whose id attribute is 'R.id." + name + "'");
}

// 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.setClickable(true);
mContent.setVisibility(GONE);
if (mWeight > 0) {
ViewGroup.LayoutParams params = mContent.getLayoutParams();
if (mOrientation == VERTICAL) {
params.height = ViewGroup.LayoutParams.FILL_PARENT;
} else {
params.width = ViewGroup.LayoutParams.FILL_PARENT;
}
mContent.setLayoutParams(params);
}
}

@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
ViewParent parent = getParent();
if (parent != null && parent instanceof FrameLayout) {
mBringToFront = true;
}
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mWeight > 0 && mContent.getVisibility() == VISIBLE) {
View parent = (View) getParent();
if (parent != null) {
if (mOrientation == VERTICAL) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec((int) (parent.getHeight() * mWeight), MeasureSpec.EXACTLY);
} else {
widthMeasureSpec = MeasureSpec.makeMeasureSpec((int) (parent.getWidth() * mWeight), MeasureSpec.EXACTLY);
}
}
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

@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() {
float touchX, touchY;

public boolean onTouch(View v, MotionEvent event) {
if (mState == State.ANIMATING) {
// we are animating
return false;
}

int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN) {
if (mBringToFront) {
bringToFront();
}
touchX = event.getX();
touchY = event.getY();
}

if (!mGestureDetector.onTouchEvent(event)) {
if (action == MotionEvent.ACTION_UP) {
// tup up after scrolling
int size = (int) (Math.abs(touchX - event.getX()) + Math
.abs(touchY - event.getY()));

if (size == mContentWidth || size == mContentHeight) {
mState = State.ABOUT_TO_ANIMATE;
//Log.e("size", String.valueOf(size));
//Log.e(String.valueOf(mContentWidth),String.valueOf(mContentHeight));
}

post(startAnimation);
}
}
return false;
}
};

OnClickListener clickListener = new OnClickListener() {
public void onClick(View v) {
if (mBringToFront) {
bringToFront();
}
if (initChange()) {
post(startAnimation);
}
}
};

public boolean initChange() {
if (mState != State.READY) {
// we are animating or just about to animate
return false;
}
mState = State.ABOUT_TO_ANIMATE;
mIsShrinking = mContent.getVisibility() == VISIBLE;
if (!mIsShrinking) {
// this could make flicker so we test mState in dispatchDraw()
// to see if is equal to ABOUT_TO_ANIMATE
mContent.setVisibility(VISIBLE);
}
return true;
}

Runnable startAnimation = new Runnable() {
public void run() {
// this is why we post this Runnable couple of lines above:
// now its save to use mContent.getHeight() && mContent.getWidth()
TranslateAnimation animation;
int fromXDelta = 0, toXDelta = 0, fromYDelta = 0, toYDelta = 0;
if (mState == State.FLYING) {
mIsShrinking = (mPosition == TOP || mPosition == LEFT) ^ (mVelocity > 0);
}
int calculatedDuration;
if (mOrientation == VERTICAL) {
int height = mContentHeight;
if (!mIsShrinking) {
fromYDelta = mPosition == TOP? -height : height;
} else {
toYDelta = mPosition == TOP? -height : height;
}
if (mState == State.TRACKING) {
if (Math.abs(mTrackY - fromYDelta) < Math.abs(mTrackY - toYDelta)) {
mIsShrinking = !mIsShrinking;
toYDelta = fromYDelta;
}
fromYDelta = (int) mTrackY;
} else
if (mState == State.FLYING) {
fromYDelta = (int) mTrackY;
}
// for FLYING events we calculate animation duration based on flying velocity
// also for very high velocity make sure duration >= 20 ms
if (mState == State.FLYING && mLinearFlying) {
calculatedDuration = (int) (1000 * Math.abs((toYDelta - fromYDelta) / mVelocity));
calculatedDuration = Math.max(calculatedDuration, 20);
} else {
calculatedDuration = mDuration * Math.abs(toYDelta - fromYDelta) / mContentHeight;
}
} else {
int width = mContentWidth;
if (!mIsShrinking) {
fromXDelta = mPosition == LEFT? -width : width;
} else {
toXDelta = mPosition == LEFT? -width : width;
}
if (mState == State.TRACKING) {
if (Math.abs(mTrackX - fromXDelta) < Math.abs(mTrackX - toXDelta)) {
mIsShrinking = !mIsShrinking;
toXDelta = fromXDelta;
}
fromXDelta = (int) mTrackX;
} else
if (mState == State.FLYING) {
fromXDelta = (int) mTrackX;
}
// for FLYING events we calculate animation duration based on flying velocity
// also for very high velocity make sure duration >= 20 ms
if (mState == State.FLYING && mLinearFlying) {
calculatedDuration = (int) (1000 * Math.abs((toXDelta - fromXDelta) / mVelocity));
calculatedDuration = Math.max(calculatedDuration, 20);
} else {
calculatedDuration = mDuration * Math.abs(toXDelta - fromXDelta) / mContentWidth;
}
}

mTrackX = mTrackY = 0;
if (calculatedDuration == 0) {
mState = State.READY;
if (mIsShrinking) {
mContent.setVisibility(GONE);
}
postProcess();
return;
}

animation = new TranslateAnimation(fromXDelta, toXDelta, fromYDelta, toYDelta);
animation.setDuration(calculatedDuration);
animation.setAnimationListener(animationListener);
if (mState == State.FLYING && mLinearFlying) {
animation.setInterpolator(new LinearInterpolator());
} else
if (mInterpolator != null) {
animation.setInterpolator(mInterpolator);
}
startAnimation(animation);
}
};

private AnimationListener animationListener = new AnimationListener() {
public void onAnimationEnd(Animation animation) {
mState = State.READY;
if (mIsShrinking) {
mContent.setVisibility(GONE);
}
postProcess();
}
public void onAnimationRepeat(Animation animation) {
}
public void onAnimationStart(Animation animation) {
mState = State.ANIMATING;
}
};

private void postProcess() {
if (mIsShrinking && mClosedHandle != null) {
mHandle.setBackgroundDrawable(mClosedHandle);
} else
if (!mIsShrinking && mOpenedHandle != null) {
mHandle.setBackgroundDrawable(mOpenedHandle);
}
// invoke listener if any
if (panelListener != null) {
if (mIsShrinking) {
panelListener.onPanelClosed(Panel.this);
} else {
panelListener.onPanelOpened(Panel.this);
}
}
}

class PanelOnGestureListener implements OnGestureListener {
float scrollY;
float scrollX;
public void setScroll(int initScrollX, int initScrollY) {
scrollX = initScrollX;
scrollY = initScrollY;
}
public boolean onDown(MotionEvent e) {
scrollX = scrollY = 0;
initChange();
return true;
}
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
mState = State.FLYING;
mVelocity = mOrientation == VERTICAL? velocityY : velocityX;
post(startAnimation);
return true;
}
public void onLongPress(MotionEvent e) {
// not used
}
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
mState = State.TRACKING;
float tmpY = 0, tmpX = 0;
if (mOrientation == VERTICAL) {
scrollY -= distanceY;
if (mPosition == TOP) {
tmpY = ensureRange(scrollY, -mContentHeight, 0);
} else {
tmpY = ensureRange(scrollY, 0, mContentHeight);
}
} else {
scrollX -= distanceX;
if (mPosition == LEFT) {
tmpX = ensureRange(scrollX, -mContentWidth, 0);
} else {
tmpX = ensureRange(scrollX, 0, mContentWidth);
}
}
if (tmpX != mTrackX || tmpY != mTrackY) {
mTrackX = tmpX;
mTrackY = tmpY;
invalidate();
}
return true;
}
public void onShowPress(MotionEvent e) {
// not used
}
public boolean onSingleTapUp(MotionEvent e) {
// not used
return false;
}
}
}

 

 

 

 

 

attrs.xml:

 



<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="Panel">
<!-- Defines panel animation duration in ms. -->
<attr name="animationDuration" format="integer" />
<!-- Defines panel position on the screen. -->
<attr name="position">
<!-- Panel placed at top of the screen. -->
<enum name="top" value="0" />
<!-- Panel placed at bottom of the screen. -->
<enum name="bottom" value="1" />
<!-- Panel placed at left of the screen. -->
<enum name="left" value="2" />
<!-- Panel placed at right of the screen. -->
<enum name="right" value="3" />
</attr>
<!-- Identifier for the child that represents the panel's handle. -->
<attr name="handle" format="reference" />
<!-- Identifier for the child that represents the panel's content. -->
<attr name="content" format="reference" />
<!-- Defines if flying gesture forces linear interpolator in animation. -->
<attr name="linearFlying" format="boolean" />
<!-- Defines size relative to parent (must be in form: nn%p). -->
<attr name="weight" format="fraction" />
<!-- Defines opened handle (drawable/color). -->
<attr name="openedHandle" format="reference|color" />
<!-- Defines closed handle (drawable/color). -->
<attr name="closedHandle" format="reference|color" />
</declare-styleable>


</resources>



 

 

 

 

 

 

Android从上到下抽屉式效果_android

Android从上到下抽屉式效果_xml_02

标签:layout,int,public,抽屉式,id,Android,Panel,android,从上到下
From: https://blog.51cto.com/u_4427045/6095989

相关文章

  • Android学习之ExpandableListView
    ExpListActivity.java: packageorg.lee.android;importjava.util.ArrayList;importjava.util.HashMap;importjava.util.List;importjava.util.Map;importandroid.app......
  • Android百度地图添加覆盖物(AndroidSDK_v2.4.1)
     使用网络功能所需权限:<!--使用网络功能所需权限--><uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission><uses-permission......
  • Android病毒分析基础(二)—ChatGPT提问技巧
    今天我们来用最近比较火的“ChatGPT”学习一下Android病毒分析基础,看看和我们之前学的有什么不同,又能学习到什么新的东西,同时了解一下“ChatGPT”提问的一些精髓。和我们......
  • 3月1日Android开学学习
    Android开发的简单控件1.文本显示2.视图基础3.常用布局4.按钮触控5.图像显示文本显示(1)设置文本内容1.在XML文件中通过属性Android:text设置文本Android:text="......
  • Android病毒分析基础(一)
    前期准备环境准备主要就是Android开发的环境,详细的可以参考非充老师白皮书第一章,其中包含了Win、Linux环境,如果需要mac环境配置可以自行检索,或者公众号留言,我们会在后期......
  • Android 获取通话记录和录音文件(直接获取地址)
    获取手机录音通话录音文件的办法, 网上大多的办法是先通过通话记录,查询详细的通话信息,如号码,时长,开始时间,结束时间,然后再到各个机型特定目录里面去查找对比录音文件。(见......
  • Android 开发入门
    文件结构appmainfests下面的AndroidManifest.xml<?xmlversion="1.0"encoding="utf-8"?><manifestxmlns:android="http://schemas.android.com/apk/res/android"......
  • Android 数据的四种存储方式
     简介:作为一个完成的应用程序,数据存储操作是必不可少的。因此,Android系统一共提供了四种数据存储方式。分别是:SharePreference、SQLite、ContentProvider和File。由于And......
  • SkeyeVSS综合安防视频云服务WEB H5无插件播放RTSP摄像机解决方案,拒绝插件,拥抱H5,Window
    SkeyeVSS综合安防视频云服务WEBH5无插件播放RTSP摄像机解决方案,拒绝插件,拥抱H5,WindowsPC、Liunx、Android、iOS全平台支持市场需求视频流媒体监控行业已经进入了互联网......
  • 直播平台制作,Android 悬浮窗延时5秒返回APP问题
    直播平台制作,Android悬浮窗延时5秒返回APP问题案例需求分析:在APP界面,点击Home键后,APP退出后台,同时会打开一个悬浮窗,当用户点击悬浮窗上的按键会返回APP。 出现的问题......