studio programacion móviles libros desarrollo desarrollar curso aprende aplicaciones animaciones android animation layout view android-side-navigation

programacion - Diseño de animación Android



manual de programacion android pdf (3)

Quiero animar dos diseños diferentes.

Ejemplo

Ya tengo la animación como quiero, solo quiero animar un diseño XML diferente. Hay una clase LayoutAnimationController, pero realmente no sé cómo usarla. ¿Puede alguien señalarme en la dirección correcta, con un ejemplo o una buena explicación?

Aquí está el código que uso para animar.

TranslateAnimation slide = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 300f, 0,0 ); slide.setAnimationListener(AL); slide.setFillAfter(true); slide.setDuration(1000); parentlayout.startAnimation(slide);

Actualización Debido a los muchos votos positivos, decidí poner un proyecto de ejemplo en un repositorio de Git. Ver mis respuestas para el enlace.


Ok Después de pasar 2 días leyendo sobre problemas similares y cómo la gente los resolvió finalmente pude crear lo que quería. No pude hacerlo con 2 archivos XML diferentes, pero dudo que no sea posible.

Encontré algunos problemas aunque

Una vez que finalizó la primera animación, no se pudo hacer clic en el botón. Esto se debe a que la animación muestra que todo se movió pero no actualiza el diseño, por lo que el botón sigue en la posición donde se inició la animación. Así que tuve que calcular la nueva posición del diseño.

Creo que leí en alguna parte que esto ya no es un problema en 3.0, pero corrígeme si me equivoco

Otra fue que cuando finalmente mi animación comenzó a funcionar de la manera que quería mi vista subyacente desapareció antes de que la animación finalizara porque invocaba view.setVisabilty(View.GONE); . Ahora el problema era que cuando no invoqué ese método, la animación simplemente se cuelga por un segundo y luego tira a la posición final de la animación. Así que agregué una propiedad LinearLayout vacía (puede ser cualquier cosa), predeterminada en GONE, cuando la animación comienza a establecerse en Visible. cuando revierte la animación, configúrela nuevamente como desaparecida. después de hacer esto, la animación funcionaba como yo quería.

Y si está utilizando Rel, Linear o cualquier otro diseño. entonces no puedes apilar las vistas en orden Z, así que debes usar SurfaceView.

Así que aquí está main.xml

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/RelativeLayout1" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <SurfaceView android:id="@+id/surfaceView1" android:layout_width="fill_parent" android:layout_height="fill_parent" /> <RelativeLayout android:id="@+id/layout" android:layout_width="220dp" android:layout_height="fill_parent" android:background="#ffee00" android:orientation="vertical" > <LinearLayout android:id="@+id/fake_layouy" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:visibility="gone"> </LinearLayout> <ListView android:id="@+id/listView1" android:layout_width="match_parent" android:layout_height="wrap_content" > </ListView> </RelativeLayout> <RelativeLayout android:id="@+id/layoutTwo" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#ff00ee" android:orientation="vertical"> <LinearLayout android:id="@+id/linearLayout1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:background="#ff0000" android:layout_margin="2dp"> <Button android:id="@+id/button" android:layout_width="50dp" android:layout_height="wrap_content" android:text="slide" /> </LinearLayout> </RelativeLayout> </RelativeLayout>

aquí está el código java

public class MenuAnimationActivity extends Activity { private Button buttonSwitch; private View subLayout; private View topLayout; private ListView subViewListView; private String listViewDummyContent[]={"Android","iPhone","BlackBerry","AndroidPeople"}; private Display display; private View fakeLayout; private AnimationListener AL; // Values for after the animation private int oldLeft; private int oldTop; private int newleft; private int newTop; private int screenWidth; private int animToPostion; // TODO change the name of the animToPostion for a better explanation. private boolean menuOpen = false; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); buttonSwitch = (Button)findViewById(R.id.button); subLayout = (View) findViewById(R.id.layout); topLayout = (View) findViewById(R.id.layoutTwo); subViewListView=(ListView)findViewById(R.id.listView1); fakeLayout = (View)findViewById(R.id.fake_layouy); subViewListView.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1 , listViewDummyContent)); display = getWindowManager().getDefaultDisplay(); screenWidth = display.getWidth(); int calcAnimationPosition = (screenWidth /3); // Value where the onTop Layer has to animate // also the max width of the layout underneath // Set Layout params for subLayout according to calculation animToPostion = screenWidth - calcAnimationPosition; RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(animToPostion, RelativeLayout.LayoutParams.FILL_PARENT); subLayout.setLayoutParams(params); topLayout.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if(event.getAction() == MotionEvent.ACTION_DOWN) { if (menuOpen == true) { animSlideLeft(); } } return false; } }); buttonSwitch.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(menuOpen == false){ animSlideRight(); } else if (menuOpen == true) { animSlideLeft(); } } }); AL = new AnimationListener() { @Override public void onAnimationStart(Animation animation) { buttonSwitch.setClickable(false); topLayout.setEnabled(false); } @Override public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationEnd(Animation animation) { if(menuOpen == true) { Log.d("", "Open"); topLayout.layout(oldLeft, oldTop, oldLeft + topLayout.getMeasuredWidth(), oldTop + topLayout.getMeasuredHeight() ); menuOpen = false; buttonSwitch.setClickable(true); topLayout.setEnabled(true); } else if(menuOpen == false) { Log.d("","FALSE"); topLayout.layout(newleft, newTop, newleft + topLayout.getMeasuredWidth(), newTop + topLayout.getMeasuredHeight() ); topLayout.setEnabled(true); menuOpen = true; buttonSwitch.setClickable(true); } } }; } public void animSlideRight(){ fakeLayout.setVisibility(View.VISIBLE); newleft = topLayout.getLeft() + animToPostion; newTop = topLayout.getTop(); TranslateAnimation slideRight = new TranslateAnimation(0,newleft,0,0); slideRight.setDuration(500); slideRight.setFillEnabled(true); slideRight.setAnimationListener(AL); topLayout.startAnimation(slideRight); } public void animSlideLeft() { fakeLayout.setVisibility(View.GONE); oldLeft = topLayout.getLeft() - animToPostion; oldTop = topLayout.getTop(); TranslateAnimation slideLeft = new TranslateAnimation(newleft,oldLeft,0,0); slideLeft.setDuration(500); slideLeft.setFillEnabled(true); slideLeft.setAnimationListener(AL); topLayout.startAnimation(slideLeft); } }

Hice algunas codificaciones adicionales para tocar vistas y esas cosas.

Y el resultado final

antes de la animación

después de la primera animación

Y después de la segunda animación de vuelta a la izquierda, muestra devoluciones como la primera imagen.

Todos esos mensajes que me ayudaron realmente merecen algo de crédito, pero no puedo encontrar ninguno de ellos.

Editar

GIT https://bitbucket.org/maikelbollemeijer/sidepanelswitcher

Actualización: https://github.com/jfeinstein10/SlidingMenu esta lib es compatible con Actionbar Sherlock.

espero que esto ayude


Tenía el requisito similar de hacer una animación de diseño como la aplicación de Facebook. Para hacer eso, hice un ViewGroup personalizado (llamado AnimationLayout). Espero que estos códigos ayuden.

AnimationLayout necesita dos hijos: barra lateral y contenido. (asignando @ + id / animation_sidebar y @ + id / animation_content a la correspondiente)

Este es el diseño xml, SideBar tiene un botón y una vista de lista. El contenido tiene una vista de texto y un botón (se une a una función de devolución de llamada).

<?xml version="1.0" encoding="utf-8"?> <org.zeroxlab.widget.AnimationLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/animation_layout" android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:id="@+id/animation_sidebar" android:layout_width="200dip" android:layout_height="match_parent" android:background="#550000" android:orientation="vertical" > <Button android:id="@+id/button_test" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Sidebar Button" /> <ListView android:id="@+id/sidebar_list" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout> <LinearLayout android:id="@+id/animation_content" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#003300" android:clickable="true" > <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Content Button" android:onClick="onClickButton" /> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="The Answer to Life, the Universe, and Everything -- is 42" /> </LinearLayout> </org.zeroxlab.widget.AnimationLayout>

Esta es la actividad de prueba. Inicializa un ListView y se asigna como un Listener a AnimationLayout.

package test.julian.hello; import org.zeroxlab.widget.AnimationLayout; import android.app.Activity; import android.app.ActivityManager; import android.os.Bundle; import android.widget.*; import android.util.Log; import android.view.View; public class HelloAndroid extends Activity implements AnimationLayout.Listener { ListView mList; AnimationLayout mLayout; String[] mStrings = {"a", "b", "c", "d", "e", "f", "g"}; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.app_layout); mLayout = (AnimationLayout) findViewById(R.id.animation_layout); mLayout.setListener(this); mList = (ListView) findViewById(R.id.sidebar_list); mList.setAdapter( new ArrayAdapter<String>( this, android.R.layout.simple_list_item_multiple_choice , mStrings)); mList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); } public void onClickButton(View v) { mLayout.toggleSidebar(); } @Override public void onSidebarOpened() { Log.d("Foo", "opened"); } @Override public void onSidebarClosed() { Log.d("Foo", "opened"); } @Override public boolean onContentTouchedWhenOpening() { Log.d("Foo", "going to close sidebar"); mLayout.closeSidebar(); return true; } }

Este es el AnimationLayout.

/* * Copyright (C) 2012 0xlab - http://0xlab.org/ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Authored by Julian Chu <walkingice AT 0xlab.org> */ package org.zeroxlab.widget; import test.julian.hello.R; import android.content.Context; import android.util.AttributeSet; import android.view.animation.Animation; import android.view.animation.TranslateAnimation; import android.view.MotionEvent; import android.view.View; import android.view.View.MeasureSpec; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; public class AnimationLayout extends ViewGroup { public final static int DURATION = 500; protected boolean mOpened; protected View mSidebar; protected View mContent; protected int mSidebarWidth = 150; // by default protected Animation mAnimation; protected OpenListener mOpenListener; protected CloseListener mCloseListener; protected Listener mListener; protected boolean mPressed = false; public AnimationLayout(Context context) { this(context, null); } public AnimationLayout(Context context, AttributeSet attrs) { super(context, attrs); } @Override public void onFinishInflate() { super.onFinishInflate(); mSidebar = findViewById(R.id.animation_sidebar); mContent = findViewById(R.id.animation_content); if (mSidebar == null) { throw new NullPointerException("no view id = animation_sidebar"); } if (mContent == null) { throw new NullPointerException("no view id = animation_content"); } mOpenListener = new OpenListener(mSidebar, mContent); mCloseListener = new CloseListener(mSidebar, mContent); } @Override public void onLayout(boolean changed, int l, int t, int r, int b) { /* the title bar assign top padding, drop it */ mSidebar.layout(l, 0, l + mSidebarWidth, 0 + mSidebar.getMeasuredHeight()); if (mOpened) { mContent.layout(l + mSidebarWidth, 0, r + mSidebarWidth, b); } else { mContent.layout(l, 0, r, b); } } @Override public void onMeasure(int w, int h) { super.onMeasure(w, h); super.measureChildren(w, h); mSidebarWidth = mSidebar.getMeasuredWidth(); } @Override protected void measureChild(View child, int parentWSpec, int parentHSpec) { /* the max width of Sidebar is 90% of Parent */ if (child == mSidebar) { int mode = MeasureSpec.getMode(parentWSpec); int width = (int)(getMeasuredWidth() * 0.9); super.measureChild(child, MeasureSpec.makeMeasureSpec(width, mode), parentHSpec); } else { super.measureChild(child, parentWSpec, parentHSpec); } } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (!isOpening()) { return false; } int action = ev.getAction(); if (action != MotionEvent.ACTION_UP && action != MotionEvent.ACTION_DOWN) { return false; } /* if user press and release both on Content while * sidebar is opening, call listener. otherwise, pass * the event to child. */ int x = (int)ev.getX(); int y = (int)ev.getY(); if (mContent.getLeft() < x && mContent.getRight() > x && mContent.getTop() < y && mContent.getBottom() > y) { if (action == MotionEvent.ACTION_DOWN) { mPressed = true; } if (mPressed && action == MotionEvent.ACTION_UP && mListener != null) { mPressed = false; return mListener.onContentTouchedWhenOpening(); } } else { mPressed = false; } return false; } public void setListener(Listener l) { mListener = l; } /* to see if the Sidebar is visible */ public boolean isOpening() { return mOpened; } public void toggleSidebar() { if (mContent.getAnimation() != null) { return; } if (mOpened) { /* opened, make close animation*/ mAnimation = new TranslateAnimation(0, -mSidebarWidth, 0, 0); mAnimation.setAnimationListener(mCloseListener); } else { /* not opened, make open animation */ mAnimation = new TranslateAnimation(0, mSidebarWidth, 0, 0); mAnimation.setAnimationListener(mOpenListener); } mAnimation.setDuration(DURATION); mAnimation.setFillAfter(true); mAnimation.setFillEnabled(true); mContent.startAnimation(mAnimation); } public void openSidebar() { if (!mOpened) { toggleSidebar(); } } public void closeSidebar() { if (mOpened) { toggleSidebar(); } } class OpenListener implements Animation.AnimationListener { View iSidebar; View iContent; OpenListener(View sidebar, View content) { iSidebar = sidebar; iContent = content; } public void onAnimationRepeat(Animation animation) { } public void onAnimationStart(Animation animation) { iSidebar.setVisibility(View.VISIBLE); } public void onAnimationEnd(Animation animation) { iContent.clearAnimation(); mOpened = !mOpened; requestLayout(); if (mListener != null) { mListener.onSidebarOpened(); } } } class CloseListener implements Animation.AnimationListener { View iSidebar; View iContent; CloseListener(View sidebar, View content) { iSidebar = sidebar; iContent = content; } public void onAnimationRepeat(Animation animation) { } public void onAnimationStart(Animation animation) { } public void onAnimationEnd(Animation animation) { iContent.clearAnimation(); iSidebar.setVisibility(View.INVISIBLE); mOpened = !mOpened; requestLayout(); if (mListener != null) { mListener.onSidebarClosed(); } } } public interface Listener { public void onSidebarOpened(); public void onSidebarClosed(); public boolean onContentTouchedWhenOpening(); } }

Cuando SideBar se cerró, se ve así.

Cuando se abrió SideBar, se ve así.


Tomé la solución de walkingice ( https://github.com/walkingice/gui-sliding-sidebar ) y la agregué, haciendo un widget en el que la "barra lateral" puede entrar desde la parte superior o inferior, así como desde la izquierda o hacia la derecha. También puede especificar el ancho (o la altura) de la barra lateral como porcentaje del ancho (o alto) principal. La barra lateral puede estar estacionaria detrás de la vista de contenido principal o deslizarse hacia adentro.

El proyecto es por SolutionStream, y está disponible aquí: https://github.com/solutionstream/sidebarlayout

Es de código abierto (licencia Apache 2.0), por lo que puede consultar el código y usarlo (bajo la licencia), ya sea como ejemplo o directamente.

DIVULGACIÓN: El enlace de arriba es para un proyecto que creé en SolutionStream.