자, 여기는 질문의 의견에 대한 @Christopher의 제안에 따라 Email AOSP 앱에서 파생 된 내 솔루션입니다.
https://github.com/commonsguy/cw-omnibus/tree/master/Animation/ThreePane
@weakwire의 솔루션은 Animation
애니메이터보다는 클래식을 사용하지만 RelativeLayout
규칙을 사용하여 위치를 강제합니다. 현상금 관점에서 볼 때, 그는 더 매끄러운 솔루션을 가진 다른 누군가가 아직 답변을 게시하지 않는 한 현상금을 얻을 것입니다.
간단히 말해 ThreePaneLayout
해당 프로젝트의 LinearLayout
하위 클래스는 세 명의 자녀가있는 환경에서 작동하도록 설계된 하위 클래스입니다. 이 아이들의 너비는 원하는 방법을 통해 레이아웃 XML에서 설정할 수 있습니다-가중치를 사용하여 표시하지만 차원 리소스 또는 기타로 특정 너비를 설정할 수 있습니다. 세 번째 자식-문제의 조각 C는 너비가 0이어야합니다.
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;
}
}
그러나 런타임시 너비를 처음 설정 한 방법에 관계없이 ThreePaneLayout
처음 hideLeft()
으로 조각 A 및 B라는 질문을 조각 A 및 B로 표시하는 것에서 조각 B 및 C로 전환 할 때 너비 관리가 사용 됩니다. ThreePaneLayout
- 단편에 특정한 관계를 갖지 않는 - 세 조각은 left
, middle
, 및 right
. 전화 할 당시 hideLeft()
, 우리는의 크기를 기록 left
하고 middle
우리가 완전히 크기를 제어 할 수 있도록 세 가지 중 하나에서 사용 된 모든 무게를 제로. 시점에서 hideLeft()
의 크기를 right
원래 크기로 설정했습니다 middle
.
애니메이션은 두 가지입니다.
- a
ViewPropertyAnimator
를 left
사용하여 하드웨어 계층을 사용하여 너비로 3 개의 위젯을 왼쪽으로 변환합니다.
- 를 사용하여
ObjectAnimator
사용자 지정 의사 재산 middleWidth
의 변화에 middle
가의 원래 너비로 시작 어떤에서 폭left
(현재로서는 효과가 있지만 AnimatorSet
과 ObjectAnimators
모두 를 사용하는 것이 더 좋습니다. )
(이는 middleWidth
ObjectAnimator
상당히 지속적인 무효화를 요구하기 때문에 하드웨어 계층의 가치를 무효화 할 수도 있습니다 )
(이다 확실히 나는 아직도 내 애니메이션 이해의 간격을 가지고, 내가 괄호 문을 좋아하는 것이 가능)
순 효과는 즉 left
화면 오프 슬라이드, middle
원래의 위치와 크기에 슬라이드 left
, 그리고 right
바로 뒤에 번역 middle
.
showLeft()
동일한 방향의 애니메이터를 사용하여 방향을 반대로하여 프로세스를 간단히 되돌립니다.
활동은 a ThreePaneLayout
를 사용하여 한 쌍의 ListFragment
위젯과 a 를 보유 합니다 Button
. 왼쪽 조각에서 무언가를 선택하면 중간 조각이 추가되거나 내용이 업데이트됩니다. 중간 조각에서 무언가를 선택하면의 캡션이 설정되고에서 Button
실행 hideLeft()
됩니다 ThreePaneLayout
. 왼쪽을 숨기면 BACK을 누르면 실행됩니다 showLeft()
. 그렇지 않으면 BACK은 활동을 종료합니다. 이것은 FragmentTransactions
애니메이션에 영향을주는 데 사용되지 않기 때문에 "백 스택"을 직접 관리해야합니다.
위에 링크 된 프로젝트는 네이티브 프래그먼트와 네이티브 애니메이터 프레임 워크를 사용합니다. 애니메이션에 Android 지원 조각 백 포트와 NineOldAndroids 를 사용하는 동일한 프로젝트의 다른 버전이 있습니다 .
https://github.com/commonsguy/cw-omnibus/tree/master/Animation/ThreePaneBC
백 포트는 1 세대 Kindle Fire에서 잘 작동하지만 하드웨어 사양이 낮고 하드웨어 가속 지원이 부족하기 때문에 애니메이션이 약간 흔들립니다. Nexus 7 및 기타 최신 세대 태블릿에서는 두 가지 구현이 모두 매끄럽게 보입니다.
나는이 솔루션을 개선하는 방법에 대한 아이디어 또는 여기서 내가 한 일 (또는 @weakwire가 사용한 것)보다 명확한 이점을 제공하는 다른 솔루션에 대해 분명히 열려 있습니다.
기여한 모든 분들께 다시 한번 감사드립니다!