자, 여기는 질문의 의견에 대한 @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가 사용한 것)보다 명확한 이점을 제공하는 다른 솔루션에 대해 분명히 열려 있습니다.
기여한 모든 분들께 다시 한번 감사드립니다!