2011-12-21 48 views
9

Tôi muốn Animate hai bố cục khác nhau.Bố cục hoạt ảnh Android [Facebook]

Ví dụ

the way I want

Tôi đã có những hình ảnh động theo cách tôi muốn, tôi chỉ muốn animate một Layout XML khác nhau. Có một lớp LayoutAnimationController, nhưng tôi thực sự không biết cách sử dụng nó. Có thể một số điểm tôi đi đúng hướng, với một ví dụ hoặc giải thích tốt.

heres mã tôi sử dụng để tạo hoạt ảnh.

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

parentlayout.startAnimation(slide); 

Cập nhật Bởi vì trong nhiều up-phiếu tôi quyết định đưa một dự án ví dụ vào một kho Git. Xem câu trả lời của tôi cho liên kết.

Trả lời

16

Ok Sau khi dành 2 ngày để đọc về các vấn đề về similair và cách mọi người giải quyết chúng, cuối cùng tôi đã có thể tạo ra thứ tôi muốn. Tôi không thể làm điều đó với 2 tệp XML khác nhau, nhưng tôi nghi ngờ điều đó là không thể.

Tôi đã gặp phải một số vấn đề tho.

Sau khi hoạt ảnh đầu tiên kết thúc, nút không thể nhấp được. Điều này là do hoạt ảnh cho thấy mọi thứ được di chuyển nhưng không cập nhật bố cục, vì vậy nút vẫn ở vị trí bắt đầu hoạt ảnh. Vì vậy, tôi phải tính toán vị trí mới của bố cục.

Tôi nghĩ tôi đọc ở đâu đó rằng đây không còn là một vấn đề trong 3.0, nhưng chính xác cho tôi nếu tôi sai

khác là khi tôi đã có hình ảnh động của tôi cuối cùng làm việc theo cách mà tôi muốn xem underlaying tôi đã làm disapear trước hoạt ảnh đã hoàn thành vì tôi đã gọi view.setVisabilty(View.GONE);. Bây giờ vấn đề là khi tôi không gọi phương thức đó, hoạt ảnh chỉ treo trong một giây và sau đó bắn súng đến vị trí cuối của hoạt ảnh. Vì vậy, tôi đã thêm một LinearLayout trống (có thể là bất kỳ điều gì), thuộc tính mặc định trên GONE, khi hoạt ảnh bắt đầu đặt nó trên Hiển thị. khi bạn hoàn nguyên hoạt ảnh, hãy đặt lại hoạt ảnh. sau khi thực hiện việc này, hoạt ảnh đang hoạt động theo cách tôi muốn.

Và nếu bạn đang sử dụng bố cục Rel, Linear hoặc bất kỳ bố cục nào khác. sau đó bạn không thể ngăn xếp chế độ xem theo thứ tự Z để bạn phải sử dụng SurfaceView.

để heres 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> 

heres mã 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);     
     } 
} 

tôi đã làm thêm một số mã hóa trên chạm vào quan điểm và các công cụ.

Và kết quả cuối cùng

trước Animation

enter image description here

sau Đầu tiên Animation

enter image description here

Và sau Animation thứ hai trở lại bên trái nó khẳng định lợi nhuận là người đầu tiên Hình ảnh.

Al những bài đăng đó đã giúp tôi thực sự xứng đáng với một số tín dụng nhưng tôi không thể tìm thấy bất kỳ trong số họ.

Sửa

GIThttps://bitbucket.org/maikelbollemeijer/sidepanelswitcher

Cập nhật: https://github.com/jfeinstein10/SlidingMenu lib này tương thích với Actionbar Sherlock.

hy vọng điều này giúp

+0

làm việc tốt ... nhưng cách chọn menu bên trái có thể cho tôi biết .. tôi cũng có thể mở mục cụ thể. –

+0

Bạn có ý nghĩa cách chọn một mục trong listView không? như trong trường hợp của tôi là Android, Blackberry, iPhone? –

+0

có mà item..select bất kỳ mục cụ thể hiển thị nó trên màn hình menu .. –

8

tôi đã có yêu cầu tương tự mà làm cho hình ảnh động bố trí như ứng dụng Facebook. Để làm điều đó, tôi đã tạo một ViewGroup tùy chỉnh (được gọi là AnimationLayout). Hy vọng các mã giúp.

AnimationLayout cần hai con: Thanh bên và Nội dung. (bằng cách chỉ định @ + id/animation_sidebar và @ + id/animation_content cho tương ứng)

Đây là bố cục xml, SideBar có nút và chế độ xem danh sách. Nội dung có một textview và một nút (nó liên kết với một chức năng gọi lại).

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

Đây là hoạt động thử nghiệm. Nó khởi tạo một ListView và gán chính nó như là một Listener để 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; 
    } 
} 

Đây là 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(); 
    } 
} 

Khi SideBar đóng, có vẻ như thế này.

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

Khi SideBar mở ra, nó trông như thế này.

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

+0

Giải pháp tốt đẹp, Đã cố định nó tho nhưng tốt đẹp. Thanx vì đã đóng góp –

+0

trong giải pháp của bạn, các chế độ xem như nút, vv có chuyển vị trí mới sang vị trí ban đầu hay không? – 2cupsOfTech

+0

nó di chuyển đến vị trí mới để bạn có thể nhấp vào nó. Tôi đã tạo một dự án demo cho nó trên github. (Https://github.com/walkingice/gui-sliding-sidebar) – walkingice

0

tôi lấy giải pháp từ walkingice (https://github.com/walkingice/gui-sliding-sidebar) và thêm vào nó, làm cho một widget trong đó "Sidebar" có thể đến từ đầu hoặc cuối cũng như trái hoặc phải. Bạn cũng có thể chỉ định chiều rộng thanh bên (hoặc chiều cao) làm phần trăm chiều rộng của cha mẹ (hoặc chiều cao). Sidebar có thể đứng yên phía sau xem nội dung chính hoặc trượt trong dự án

là bởi SolutionStream, và nó có sẵn ở đây:. https://github.com/solutionstream/sidebarlayout

Đó là mã nguồn mở (Apache 2.0 giấy phép), do đó, cảm thấy tự do để kiểm tra mã và sử dụng nó (theo giấy phép), hoặc là một ví dụ hoặc trực tiếp.

CÔNG BỐ: Liên kết ở trên là một dự án mà tôi đã tạo bản thân tại SolutionStream.

Các vấn đề liên quan