布局animationAndroid

我想animation两个不同的布局

我想要的方式

我已经有了我想要的animation,我只是想animation一个不同的XML布局。 有一个类的LayoutAnimationController,但我真的不知道如何使用它。 有人能指出我正确的方向,有一个例子或好的解释。

inheritance人我使用animation的代码。

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

更新由于许多最后票,我决定把一个示例项目放到一个Git仓库中。 看到我的答案的链接。

Solutions Collecting From Web of "布局animationAndroid"

好了花了两天的时间阅读了相似的问题以及人们如何解决这些问题,终于能够创造出我想要的东西。 我不能用2个不同的XML文件来做,但我怀疑这是不可能的。

我遇到了一些问题。

第一个animation结束后,该button不可点击。 这是因为animation显示所有内容都被移动了,但不会更新布局,所以button仍然在animation开始的位置。 所以我不得不计算布局的新位置。

我认为我在某个地方读到这个问题已经不再是3.0的问题了,但如果我错了,请纠正我

另一个原因是当我的animation最终以我想要的方式工作时,我的底层视图在animation完成之前就view.setVisabilty(View.GONE);因为我调用了view.setVisabilty(View.GONE); 。 现在问题是当我没有调用这个方法的时候,animation只是暂停一下,然后射击到animation的结束位置。 所以我在animation开始时将一个空的LinearLayout(可以是任何东西),GONE上的Default属性添加到Visible上。 当你恢复animation时,再次设置它。 这样做后,animation是我想要的方式工作。

如果您使用的是Rel,Linear或其他布局。 那么你不能以Z顺序堆栈视图,所以你必须使用SurfaceView。

所以inheritancemain.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> 

inheritance人的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); } } 

我在触摸视图和东西上做了一些额外的编码。

最后的结果

animation之前

在这里输入图像说明

第一个animation之后

在这里输入图像说明

在第二个animation返回到左边之后,它返回为第一个图像。

那些帮助我真的值得信任的post,但我找不到任何。

编辑

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

更新: https : //github.com/jfeinstein10/SlidingMenu这个lib与Actionbar Sherlock兼容。

希望这可以帮助

我有类似的要求,使像Facebook应用程序的布局animation。 为此,我做了一个自定义的ViewGroup(称为AnimationLayout)。 希望这些代码的帮助。

AnimationLayout需要两个孩子:侧边栏和内容。 (通过分配@ + id / animation_sidebar和@ + id / animation_content到相应的一个)

这是布局xml,SideBar有一个button和一个列表视图。 内容有一个文本视图和一个button(它绑定到一个callback函数)。

 <?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> 

这是testing活动。 它初始化一个ListView并将其自身分配为一个监听器给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; } } 

这是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(); } } 

当SideBarclosures时,看起来像这样。

http://i.stack.imgur.com/tynLw.png

当SideBar打开时,看起来像这样。

http://i.stack.imgur.com/QJC8q.png

我从walkice( https://github.com/walkingice/gui-sliding-sidebar )中获得了解决scheme,并添加到它中,从而创build一个“侧边栏”可以从顶部或底部以及左侧进入的小部件或者正确。 您也可以将边栏宽度(或高度)指定为父宽度(或高度)的百分比。 侧栏可以在主内容视图后面静止或滑入。

该项目是由SolutionStream,它可在这里: https : //github.com/solutionstream/sidebarlayout

它是开源的(Apache 2.0许可证),所以请随时查看代码并使用它(根据许可证),作为示例或直接使用。

披露:上面的链接是我在SolutionStream创build自己的项目。