Cómo crear una animación de diapositivas en Android?

Introduzca aquí la descripción de la imagen

Hola, Quiero crear una animación de diapositivas en Mi actividad como se muestra en Imágenes. Cuando hago clic en el botón More el diseño de Orange debería aparecer como un deslizador sobre el diseño blanco y cuando haga clic en el botón Less , debería bajar como un deslizador.

Por favor, me sugiero cualquier código de ejemplo o cualquier tutorial para la mejor manera de crear tal enfoque.

¡Gracias!

Utilice esta Panel class para cumplir con su requisito y también puede manejar el evento.

Referencia: http://code.google.com/p/android-misc-widgets/

Panel.java

 public class Panel extends LinearLayout { /** * 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() { int initX; int initY; boolean setInitialPosition; public boolean onTouch(View v, MotionEvent event) { if (mState == State.ANIMATING) { // we are animating return false; } // //Log.d(TAG, "state: " + mState + " x: " + event.getX() + " y: " + event.getY()); int action = event.getAction(); if (action == MotionEvent.ACTION_DOWN) { if (mBringToFront) { bringToFront(); } 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; } }; 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() { callPanListener(); // 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); if (mState == State.FLYING && mLinearFlying) { animation.setInterpolator(new LinearInterpolator()); } else if (mInterpolator != null) { animation.setInterpolator(mInterpolator); } startAnimation(animation); } }; @Override protected void onAnimationEnd() { super.onAnimationEnd(); mState = State.READY; if (mIsShrinking) { mContent.setVisibility(GONE); } postProcess(); } @Override protected void onAnimationStart() { super.onAnimationStart(); 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 callPanListener(); } public void callPanListener() { 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; callPanListener(); initChange(); return true; } public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { mState = State.FLYING; // velocityX=400; // velocityY=400; mVelocity = mOrientation == VERTICAL? velocityY : velocityX; // mVelocity=400; 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; } } } 

Main.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/packagename" android:layout_width="fill_parent" android:layout_height="fill_parent""> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:gravity="center_horizontal" > <packagename.Panel android:id="@+id/panel_menu" android:layout_width="fill_parent" android:layout_height="fill_parent" panel:animationDuration="1000" panel:closedHandle="#0000FF" panel:content="@+id/panelContent" panel:handle="@+id/panelHandle" panel:linearFlying="false" panel:openedHandle="#0000FF" android:paddingTop="4dip" panel:position="bottom" > <Button android:id="@+id/panelHandle" android:layout_width="33dp" android:layout_height="33dp" android:layout_gravity="center_horizontal" android:text="^" android:textColor="@android:color/white" /> <RelativeLayout android:id="@+id/panelContent" android:layout_width="fill_parent" android:layout_height="50dp" android:background="#0000FF" > </RelativeLayout> </packagename.Panel> </RelativeLayout> 

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> 

Para jugar con esto en tu Actividad tienes

SampleActivity.java

 public class SampleActivity extends Activity implements OnPanelListener { public Panel samplePanel; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.panel_main)_layout; samplePanel = (Panel) findViewById(R.id.panel_id); samplePanel.setOnPanelListener(this); samplePanel.setInterpolator(new ExpoInterpolator(Type.OUT)); } public void onPanelClosed(Panel panel) {}//Interface Listener public void onPanelOpened(Panel panel) {}//Interface Listener } 
  • Android, hacer un texto de animación desplazarse hacia arriba en la pantalla como la primera parte de Star Wars
  • Objeto de desplazamiento de Android a lo largo de un trazado
  • Lista de animación no funciona en Android 5.0 (Lollipop)
  • Cómo agregar animación a DialogFragment?
  • animation.start () o animation.startNow () no inicia la animación inmediatamente
  • ¿Cómo puedo hacer una animación de log de introducción como la aplicación de skype?
  • OverridePendingTransition no funciona en android
  • ¿Hay algún tipo de emisor de partículas en Android como iOS CAEmitterLayer para el emisor de círculo?
  • ANDROID - cómo comprobar si la animación se está ejecutando antes de comenzar la nueva animación
  • Cómo animar un camino en el lienzo - android
  • Android: Flip Animation utilizando XML para animación en android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.