Pełna próbka robocza Trójczłonowego scenariusza animacji Gmaila?

TL;DR: Szukam pełnej próbki roboczej tego, co będę nazywał scenariuszem "trzyczęściowej animacji Gmaila". W szczególności chcemy zacząć od dwóch fragmentów, takich jak: [17]}

dwa fragmenty

Po jakimś zdarzeniu UI (np. dotknięciu czegoś w fragmencie B), chcemy:

  • Fragment A, aby zsunąć się z ekranu w lewo
  • Fragment B, aby przesunąć się na lewą krawędź ekranu i zmniejszyć się, aby zająć miejsce opuszczone przez Fragment A
  • Fragment C, aby wsunąć się z prawej strony ekranu i zająć miejsce opuszczone przez Fragment B

I po naciśnięciu przycisku Wstecz chcemy, aby ten zestaw operacji został odwrócony.

Teraz widziałem wiele częściowych implementacji; przejrzę cztery z nich poniżej. Poza tym, że są niekompletne, wszystkie mają swoje problemy.


@ Reto Meier dodał tę popularną odpowiedź do tego samego podstawowego pytania, wskazując, że użyłbyś setCustomAnimations() z FragmentTransaction. Jeśli chodzi o scenariusz dwuczęściowy (np. początkowo widzisz tylko Fragment A i chcesz go zastąpić nowym fragmentem B za pomocą animowanych efektów), jestem w pełni zgodny. Jednakże:

  • ponieważ możesz podać tylko jedną animację" w "i jedną" poza", nie widzę, jak poradzisz sobie ze wszystkimi różnymi animacjami wymaganymi dla scenariusza z trzema fragmentami
  • <objectAnimator> w swoim przykładowym kodzie używa sztywnych pozycji w pikselach, co wydaje się niepraktyczne ze względu na różne rozmiary ekranu, jednak setCustomAnimations() wymaga zasobów animacji, wykluczając możliwość definiowania tych rzeczy w Javie
  • Nie wiem, jak animatorzy obiektów do skalowania łączą się z rzeczami takimi jak android:layout_weight w {[5] } do przydzielania przestrzeni w procentach
  • jestem w rozterce co do sposobu postępowania z fragmentem C na początku (GONE? android:layout_weight z 0? pre-animowane w skali 0? coś jeszcze?)

@Roman Nurik zwraca uwagę, że możesz Animuj dowolne właściwości {38]}, w tym te, które sam zdefiniujesz. Może to pomóc rozwiązać problem pozycji przewodowych, kosztem wymyślenia własnej podklasy custom layout manager. To trochę pomaga, ale nadal jestem zaskoczony resztą rozwiązania Reto.


Autor ten wpis pastebin pokazuje jakiś kuszący pseudokod, w zasadzie mówiąc, że wszystkie trzy fragmenty będą początkowo znajdować się w kontenerze, z fragmentem C ukrytym na początku przez hide() obsługa transakcji. Następnie show() C i hide() A, gdy wystąpi zdarzenie UI. Nie widzę jednak, jak to sobie radzi z tym, że B zmienia rozmiar. Opiera się również na tym, że najwyraźniej można dodać wiele fragmentów do tego samego kontenera i nie jestem pewien, czy jest to wiarygodne zachowanie w dłuższej perspektywie (nie wspominając o tym, że powinno się zepsuć findFragmentById(), chociaż mogę z tym żyć).


Autor tego posta na blogu wskazuje, że Gmail nie używa setCustomAnimations() w wszystkie, ale zamiast tego bezpośrednio używa animatorów obiektów ("wystarczy zmienić lewy margines widoku głównego + zmienić szerokość prawego widoku"). Jest to jednak nadal rozwiązanie dwuczłonowe, a implementacja pokazana po raz kolejny-wymiary przewodów w pikselach.


Będę dalej nad tym pracował, więc może kiedyś sam na to odpowiem, ale naprawdę mam nadzieję, że ktoś opracował trzyczęściowe rozwiązanie dla tego scenariusza animacji i może opublikować kod (lub link do niego). Animacje w Androidzie sprawiają, że chcę wyciągnąć włosy, a ci z Was, którzy mnie widzieli, wiedzą, że jest to w dużej mierze bezowocne przedsięwzięcie.

Author: Community, 2012-09-04

6 answers

Uploaded my proposal at github (Działa ze wszystkimi wersjami Androida, choć akceleracja sprzętowa widoku jest zdecydowanie zalecana dla tego rodzaju animacji. W przypadku urządzeń bez akceleracji sprzętowej implementacja buforowania bitmap powinna pasować lepiej)

Demo wideo z animacją jest tutaj (wolna liczba klatek na sekundę powoduje rzucanie ekranu. Rzeczywista wydajność jest bardzo fast)


Użycie:

layout = new ThreeLayout(this, 3);
layout.setAnimationDuration(1000);
setContentView(layout);
layout.getLeftView();   //<---inflate FragmentA here
layout.getMiddleView(); //<---inflate FragmentB here
layout.getRightView();  //<---inflate FragmentC here

//Left Animation set
layout.startLeftAnimation();

//Right Animation set
layout.startRightAnimation();

//You can even set interpolators

Explaination :

W 2009 roku, w ramach projektu, stworzono nowy custom RelativeLayout(ThreeLayout) oraz 2 animacje (MyScalAnimation, MyTranslateAnimation)

ThreeLayout pobiera wagę lewego panelu jako param, zakładając, że drugi widoczny Widok ma weight=1.

Więc new ThreeLayout(context,3) tworzy nowy widok z 3 dzieci i lewy panel z Mają 1/3 całkowitego ekranu. Drugi widok zajmuje wszystkie dostępne miejsce.

Oblicza szerokość w czasie wykonywania, bezpieczniejszą implementacją jest to, że wymiary są obliczane po raz pierwszy w draw(). zamiast in post ()

Skalowanie i tłumaczenie animacji faktycznie zmienia rozmiar i przesuwa widok, a nie pseudo - [skaluj, przesuń]. Zauważ, że fillAfter(true) nie jest nigdzie używany.

View2 is right_of View1

I

View3 is right_of View2

Po ustawieniu tych zasad RelativeLayout zajmuje się wszystkim innym. Animacje zmieniają margins (w ruchu) i [width,height] w skali

Aby uzyskać dostęp do każdego dziecka (aby można było nadmuchać go swoim fragmentem, można zadzwonić

public FrameLayout getLeftLayout() {}

public FrameLayout getMiddleLayout() {}

public FrameLayout getRightLayout() {}

Poniżej przedstawiono 2 animacje


Stage1

---na ekranie----------!----- OUT - - - -

[View1] [_____View2_____][_____View3_____]

Stage2

--OUT-!-------- Na ekranie - - - - - - -

[View1][View2] [_____View3_____]

 64
Author: weakwire,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-15 10:10:22

OK, oto moje własne rozwiązanie, pochodzące z aplikacji e-mail AOSP, na sugestię @ Christopher w komentarzach pytania.

Https://github.com/commonsguy/cw-omnibus/tree/master/Animation/ThreePane

@ weakwire rozwiązanie przypomina moje, choć używa klasycznych Animation zamiast animatorów, i używa RelativeLayout zasad wymuszających pozycjonowanie. Z punktu widzenia bounty pewnie dostanie bounty, chyba że ktoś inny ma jeszcze lepsze rozwiązanie zamieszcza odpowiedź.


W skrócie, ThreePaneLayout w tym projekcie jest LinearLayout podklasa, zaprojektowana do pracy w krajobrazie z trójką dzieci. Te dziecięce szerokości mogą być ustawione w layout XML, za pomocą dowolnych pożądanych środków -- pokazuję używając wag, ale możesz mieć określone szerokości ustawione przez zasoby wymiarów lub cokolwiek innego. Trzecie dziecko -- Fragment C w pytaniu -- powinno mieć szerokość zero.

package com.commonsware.android.anim.threepane;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;

public class ThreePaneLayout extends LinearLayout {
  private static final int ANIM_DURATION=500;
  private View left=null;
  private View middle=null;
  private View right=null;
  private int leftWidth=-1;
  private int middleWidthNormal=-1;

  public ThreePaneLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    initSelf();
  }

  void initSelf() {
    setOrientation(HORIZONTAL);
  }

  @Override
  public void onFinishInflate() {
    super.onFinishInflate();

    left=getChildAt(0);
    middle=getChildAt(1);
    right=getChildAt(2);
  }

  public View getLeftView() {
    return(left);
  }

  public View getMiddleView() {
    return(middle);
  }

  public View getRightView() {
    return(right);
  }

  public void hideLeft() {
    if (leftWidth == -1) {
      leftWidth=left.getWidth();
      middleWidthNormal=middle.getWidth();
      resetWidget(left, leftWidth);
      resetWidget(middle, middleWidthNormal);
      resetWidget(right, middleWidthNormal);
      requestLayout();
    }

    translateWidgets(-1 * leftWidth, left, middle, right);

    ObjectAnimator.ofInt(this, "middleWidth", middleWidthNormal,
                         leftWidth).setDuration(ANIM_DURATION).start();
  }

  public void showLeft() {
    translateWidgets(leftWidth, left, middle, right);

    ObjectAnimator.ofInt(this, "middleWidth", leftWidth,
                         middleWidthNormal).setDuration(ANIM_DURATION)
                  .start();
  }

  public void setMiddleWidth(int value) {
    middle.getLayoutParams().width=value;
    requestLayout();
  }

  private void translateWidgets(int deltaX, View... views) {
    for (final View v : views) {
      v.setLayerType(View.LAYER_TYPE_HARDWARE, null);

      v.animate().translationXBy(deltaX).setDuration(ANIM_DURATION)
       .setListener(new AnimatorListenerAdapter() {
         @Override
         public void onAnimationEnd(Animator animation) {
           v.setLayerType(View.LAYER_TYPE_NONE, null);
         }
       });
    }
  }

  private void resetWidget(View v, int width) {
    LinearLayout.LayoutParams p=
        (LinearLayout.LayoutParams)v.getLayoutParams();

    p.width=width;
    p.weight=0;
  }
}

Jednak w czasie wykonywania, bez względu na to, jak pierwotnie skonfigurowano szerokości, zarządzanie szerokością jest przejmowane przez ThreePaneLayout, gdy po raz pierwszy użyjesz hideLeft(), aby przełączyć się z pokazywania tego, co pytanie określa jako fragmenty a i B na fragmenty B i C. w terminologii ThreePaneLayout - która nie ma specyficznych powiązań z fragmentami - trzy kawałki są left, middle, i right. W momencie wywołania hideLeft(), rejestrujemy rozmiary left i middle i zerujemy wszelkie ciężary, które zostały użyte na którymkolwiek z trzech, więc możemy całkowicie kontrolować rozmiary. W momencie hideLeft() ustawiamy rozmiar right to oryginalny rozmiar middle.

Animacje są dwojakie:

    Widżety są wyświetlane na ekranie, a widżety są wyświetlane na ekranie.]}
  • użyj ObjectAnimator na niestandardowej pseudo-właściwości middleWidth, aby zmienić szerokość middle z tego, od czego się zaczęła, na oryginalną szerokość left

(jest możliwe, że lepszym pomysłem jest użycie AnimatorSet i ObjectAnimators do tych wszystkich, choć to działa na razie)

(jest również możliwe, że middleWidth ObjectAnimator jest to możliwe dzięki temu, że warstwa sprzętowa nie jest w żaden sposób zabezpieczona.]} Jest to możliwe, że nadal mam luki w moim pojmowaniu animacji i że lubię nawiasowe stwierdzenia.]}

Efekt netto jest taki, że left ślizga się z ekranu, middle ślizga się do pierwotnej pozycji i rozmiaru left, a right przekłada się tuż za middle.

showLeft() po prostu odwraca proces, z tą samą mieszanką animatorów, tylko z odwróconymi kierunkami.

Aktywność wykorzystuje ThreePaneLayout do przechowywania pary widżetów ListFragment i Button. Zaznaczenie czegoś w lewym fragmencie dodaje (lub aktualizuje zawartość) środkowego fragmentu. Zaznaczenie czegoś w środkowym fragmencie ustawia podpis Button, plus wykonuje hideLeft() na ThreePaneLayout. Naciśnięcie wstecz, jeśli ukryliśmy lewą stronę, wykonamy showLeft(); w przeciwnym razie BACK wychodzi aktywność. Ponieważ to nie używa FragmentTransactions do wpływania na animacje, utknęliśmy w zarządzaniu "tylnym stosem".

Projekt linked-to above wykorzystuje natywne fragmenty i natywny framework animatora. Mam inną wersję tego samego projektu, który używa Android wsparcie fragmenty backport i NineOldAndroids do animacji:

Https://github.com/commonsguy/cw-omnibus/tree/master/Animation/ThreePaneBC

Backport działa w porządku na Kindle Fire 1. generacji, choć animacja jest nieco jerky biorąc pod uwagę niższe specyfikacje sprzętowe i brak wsparcia akceleracji sprzętowej. Obie implementacje wydają się płynne na Nexusie 7 i innych tabletach obecnej generacji.

Jestem na pewno otwarty na pomysły, jak ulepszyć To rozwiązanie, lub inne rozwiązania, które oferują wyraźną przewagę nad tym, co zrobiłem tutaj (lub czego użył @weakwire).

Jeszcze raz dziękuję wszystkim, którzy przyczynili się do tego!

 30
Author: CommonsWare,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-07 15:17:18

Zbudowaliśmy bibliotekę o nazwie PanesLibrary, która rozwiązuje ten problem. Jest jeszcze bardziej elastyczny niż wcześniej oferowany, ponieważ:

  • każdy panel może mieć dynamiczny rozmiar
  • pozwala na dowolną liczbę paneli (nie tylko 2 lub 3)
  • fragmenty wewnątrz szyb są prawidłowo zachowywane przy zmianach orientacji.

Możesz to sprawdzić tutaj: https://github.com/Mapsaurus/Android-PanesLibrary

Oto demo: http://www.youtube.com/watch?v=UA-lAGVXoLU&feature=youtu.be

To w zasadzie pozwala łatwo dodać dowolną liczbę dynamicznie wielkości paneli i dołączyć fragmenty do tych paneli. Mam nadzieję, że okaże się to przydatne! :)

 13
Author: coda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-25 23:49:59

Budowanie na podstawie jednego z przykładów, z którymi się łączyłeś ( http://android.amberfog.com/?p=758 ), a może ożywimy obiekt layout_weight? W ten sposób możesz animować zmianę wagi 3 fragmentów razem, a otrzymasz bonus, że wszystkie ładnie się ze sobą ślizgają: {]}

Zacznij od prostego układu. Ponieważ będziemy animować layout_weight, potrzebujemy LinearLayout jako głównego widoku dla 3 paneli.:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">

<LinearLayout
    android:id="@+id/panel1"
    android:layout_width="0dip"
    android:layout_weight="1"
    android:layout_height="match_parent"/>

<LinearLayout
    android:id="@+id/panel2"
    android:layout_width="0dip"
    android:layout_weight="2"
    android:layout_height="match_parent"/>

<LinearLayout
    android:id="@+id/panel3"
    android:layout_width="0dip"
    android:layout_weight="0"
    android:layout_height="match_parent"/>
</LinearLayout>

Następnie Klasa demo:

public class DemoActivity extends Activity implements View.OnClickListener {
    public static final int ANIM_DURATION = 500;
    private static final Interpolator interpolator = new DecelerateInterpolator();

    boolean isCollapsed = false;

    private Fragment frag1, frag2, frag3;
    private ViewGroup panel1, panel2, panel3;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        panel1 = (ViewGroup) findViewById(R.id.panel1);
        panel2 = (ViewGroup) findViewById(R.id.panel2);
        panel3 = (ViewGroup) findViewById(R.id.panel3);

        frag1 = new ColorFrag(Color.BLUE);
        frag2 = new InfoFrag();
        frag3 = new ColorFrag(Color.RED);

        final FragmentManager fm = getFragmentManager();
        final FragmentTransaction trans = fm.beginTransaction();

        trans.replace(R.id.panel1, frag1);
        trans.replace(R.id.panel2, frag2);
        trans.replace(R.id.panel3, frag3);

        trans.commit();
    }

    @Override
    public void onClick(View view) {
        toggleCollapseState();
    }

    private void toggleCollapseState() {
        //Most of the magic here can be attributed to: http://android.amberfog.com/?p=758

        if (isCollapsed) {
            PropertyValuesHolder[] arrayOfPropertyValuesHolder = new PropertyValuesHolder[3];
            arrayOfPropertyValuesHolder[0] = PropertyValuesHolder.ofFloat("Panel1Weight", 0.0f, 1.0f);
            arrayOfPropertyValuesHolder[1] = PropertyValuesHolder.ofFloat("Panel2Weight", 1.0f, 2.0f);
            arrayOfPropertyValuesHolder[2] = PropertyValuesHolder.ofFloat("Panel3Weight", 2.0f, 0.0f);
            ObjectAnimator localObjectAnimator = ObjectAnimator.ofPropertyValuesHolder(this, arrayOfPropertyValuesHolder).setDuration(ANIM_DURATION);
            localObjectAnimator.setInterpolator(interpolator);
            localObjectAnimator.start();
        } else {
            PropertyValuesHolder[] arrayOfPropertyValuesHolder = new PropertyValuesHolder[3];
            arrayOfPropertyValuesHolder[0] = PropertyValuesHolder.ofFloat("Panel1Weight", 1.0f, 0.0f);
            arrayOfPropertyValuesHolder[1] = PropertyValuesHolder.ofFloat("Panel2Weight", 2.0f, 1.0f);
            arrayOfPropertyValuesHolder[2] = PropertyValuesHolder.ofFloat("Panel3Weight", 0.0f, 2.0f);
            ObjectAnimator localObjectAnimator = ObjectAnimator.ofPropertyValuesHolder(this, arrayOfPropertyValuesHolder).setDuration(ANIM_DURATION);
            localObjectAnimator.setInterpolator(interpolator);
            localObjectAnimator.start();
        }
        isCollapsed = !isCollapsed;
    }

    @Override
    public void onBackPressed() {
        //TODO: Very basic stack handling. Would probably want to do something relating to fragments here..
        if(isCollapsed) {
            toggleCollapseState();
        } else {
            super.onBackPressed();
        }
    }

    /*
     * Our magic getters/setters below!
     */

    public float getPanel1Weight() {
        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)     panel1.getLayoutParams();
        return params.weight;
    }

    public void setPanel1Weight(float newWeight) {
        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) panel1.getLayoutParams();
        params.weight = newWeight;
        panel1.setLayoutParams(params);
    }

    public float getPanel2Weight() {
        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) panel2.getLayoutParams();
        return params.weight;
    }

    public void setPanel2Weight(float newWeight) {
        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) panel2.getLayoutParams();
        params.weight = newWeight;
        panel2.setLayoutParams(params);
    }

    public float getPanel3Weight() {
        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) panel3.getLayoutParams();
        return params.weight;
    }

    public void setPanel3Weight(float newWeight) {
        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) panel3.getLayoutParams();
        params.weight = newWeight;
        panel3.setLayoutParams(params);
    }


    /**
     * Crappy fragment which displays a toggle button
     */
    public static class InfoFrag extends Fragment {
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle     savedInstanceState) {
            LinearLayout layout = new LinearLayout(getActivity());
            layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
            layout.setBackgroundColor(Color.DKGRAY);

            Button b = new Button(getActivity());
            b.setOnClickListener((DemoActivity) getActivity());
            b.setText("Toggle Me!");

            layout.addView(b);

            return layout;
        }
    }

    /**
     * Crappy fragment which just fills the screen with a color
     */
    public static class ColorFrag extends Fragment {
        private int mColor;

        public ColorFrag() {
            mColor = Color.BLUE; //Default
        }

        public ColorFrag(int color) {
            mColor = color;
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            FrameLayout layout = new FrameLayout(getActivity());
            layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));

            layout.setBackgroundColor(mColor);
            return layout;
        }
    }
}

Również ten przykład nie używa FragmentTransactions, aby uzyskać animacje (raczej animuje widoki, do których są dołączone fragmenty), więc musisz wykonać wszystkie transakcje backstack / fragment samodzielnie, ale w porównaniu z wysiłkiem poprawienia działania animacji, nie wydaje się to złym kompromisem:)]}

Straszne wideo o niskiej rozdzielczości w akcji: http://youtu.be/Zm517j3bFCo

 6
Author: DanielGrech,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-06 15:56:33

To nie jest użycie fragmentów.... To niestandardowy układ z trójką dzieci. Po kliknięciu na wiadomość, przesuwa się 3 dzieci za pomocą offsetLeftAndRight() i animatora.

W JellyBean możesz włączyć "Pokaż granice układu" w Ustawieniach "Opcje programisty". Po zakończeniu animacji slajdu nadal można zobaczyć, że menu po lewej stronie nadal istnieje, ale pod środkowym panelem.

[[7]}jest podobny do Cyril Mottier ' s Fly-in app menu , ale z 3 elementami zamiast 2.

Dodatkowo, ViewPager trzeciego dziecka jest kolejną wskazówką tego zachowania: ViewPager zazwyczaj używa fragmentów (wiem, że nie muszą, ale nigdy nie widziałem implementacji innej niż Fragment), A ponieważ nie można używać Fragments wewnątrz innego Fragment dzieci te prawdopodobnie nie są fragmentami....

 5
Author: Thierry-Dimitri Roy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-09 03:28:57

Obecnie staram się zrobić coś takiego, poza tym, że skala fragmentu B zajmuje dostępną przestrzeń i że okno 3 może być otwarte w tym samym czasie, jeśli jest wystarczająco dużo miejsca. Oto moje rozwiązanie na razie, ale nie jestem pewien, czy będę się go trzymać. Mam nadzieję, że ktoś udzieli odpowiedzi wskazującej właściwą drogę.

Zamiast używać LinearLayout i animować wagę, używam RelativeLayout i animować marginesy. Nie jestem pewien, czy to najlepszy sposób, ponieważ wymaga połączenia requestLayout() przy każdej aktualizacji. Jest gładka na wszystkich moich urządzeniach.

Więc animuję układ, nie używam transakcji fragmentów. Obsługuję przycisk Wstecz ręcznie, aby zamknąć fragment C, jeśli jest otwarty.

FragmentB użyj layout_toLeftOf / ToRightOf, aby zachować jego wyrównanie do fragmentu A i C.

Kiedy moja aplikacja uruchomi zdarzenie, aby wyświetlić fragment C, wsuwam fragment C, a wsuwam fragment a w tym samym czasie. (2 osobne animacje). Odwrotnie, gdy Fragment a otwarty, i Zamknij C w tym samym czasie.

W trybie portretowym lub na mniejszym ekranie, używam nieco innego układu i przesuwam Fragment C po ekranie.

Aby użyć procentu dla szerokości fragmentu A i C, myślę, że będziesz musiał go obliczyć w czasie wykonywania... (?)

Oto układ działania:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rootpane"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <!-- FRAGMENT A -->
    <fragment
        android:id="@+id/fragment_A"
        android:layout_width="300dp"
        android:layout_height="fill_parent"
        class="com.xyz.fragA" />

    <!-- FRAGMENT C -->
    <fragment
        android:id="@+id/fragment_C"
        android:layout_width="600dp"
        android:layout_height="match_parent"
        android:layout_alignParentRight="true"
        class="com.xyz.fragC"/>

    <!-- FRAGMENT B -->
    <fragment
        android:id="@+id/fragment_B"
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:layout_marginLeft="0dip"
        android:layout_marginRight="0dip"
        android:layout_toLeftOf="@id/fragment_C"
        android:layout_toRightOf="@id/fragment_A"
        class="com.xyz.fragB" />

</RelativeLayout>

Animacja do przesuwania FragmentC wewnątrz lub na zewnątrz:

private ValueAnimator createFragmentCAnimation(final View fragmentCRootView, boolean slideIn) {

    ValueAnimator anim = null;

    final RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) fragmentCRootView.getLayoutParams();
    if (slideIn) {
        // set the rightMargin so the view is just outside the right edge of the screen.
        lp.rightMargin = -(lp.width);
        // the view's visibility was GONE, make it VISIBLE
        fragmentCRootView.setVisibility(View.VISIBLE);
        anim = ValueAnimator.ofInt(lp.rightMargin, 0);
    } else
        // slide out: animate rightMargin until the view is outside the screen
        anim = ValueAnimator.ofInt(0, -(lp.width));

    anim.setInterpolator(new DecelerateInterpolator(5));
    anim.setDuration(300);
    anim.addUpdateListener(new AnimatorUpdateListener() {

        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            Integer rightMargin = (Integer) animation.getAnimatedValue();
            lp.rightMargin = rightMargin;
            fragmentCRootView.requestLayout();
        }
    });

    if (!slideIn) {
        // if the view was sliding out, set visibility to GONE once the animation is done
        anim.addListener(new AnimatorListenerAdapter() {

            @Override
            public void onAnimationEnd(Animator animation) {
                fragmentCRootView.setVisibility(View.GONE);
            }
        });
    }
    return anim;
}
 2
Author: boblebel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-06 19:31:39