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]}
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, jednaksetCustomAnimations()
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
z0
? 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.
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_____]
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ścimiddleWidth
, 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!
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! :)
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
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.
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....
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;
}
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