팝 애니메이션을 재생하지 않고 조각 백 스택 팝
다음 코드를 사용하여 조각 스택에 조각을 푸시합니다.
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_right,
R.anim.slide_in_left, R.anim.slide_out_left);
fragmentTransaction.replace(getId(), newFragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
이렇게하면 예를 들어 뒤로 버튼을 눌러 조각 스택이 팝될 때 조각 팝 애니메이션이 재생됩니다. 그러나이 애니메이션을 표시하지 않고 프래그먼트 백 스택을 팝하고 싶은 상황이 있습니다. 예를 들어 다른 활동에서 방금 돌아 왔고 애니메이션없이 이전 프래그먼트를 한 번에 표시하고 싶기 때문입니다.
예제 탐색은 다음과 같습니다.
- 사용자는 루트 조각이있는 시작 화면에 있습니다.
- 그는 루트 조각에서 항목을 선택한 다음 해당 항목의 세부 정보를 표시하는 새 조각을 표시합니다. 푸시 및 팝 케이스 모두에 대해 애니메이션을 설정하는 조각 트랜잭션을 사용하여 수행합니다 (따라서 사용자가 뒤로 버튼을 누르면 전환이 애니메이션됩니다).
- 이 조각에서 그는 (어떤 이유로 든) 방금 표시된 항목을 삭제하는 활동을 시작합니다.
- 이 활동이 끝나면 "세부 조각"의 "팝 애니메이션"을 표시하지 않고 루트 조각으로 돌아가고 싶습니다.
지정된 팝 애니메이션을 재생하지 않고 조각 백 스택을 팝하는 방법이 있습니까?
그래서 Warpzit은 올바른 길을 가고 있었으며 그는 당신의 특정 문제를 너무 잘 다루지 않았습니다. 나는 똑같은 문제를 만났고 여기에 내가 어떻게 해결했는지가 있습니다.
먼저 정적 부울 변수를 만들었습니다 (간단하게하기 위해 FragmentUtils 클래스에 넣습니다) ...
public class FragmentUtils {
public static boolean sDisableFragmentAnimations = false;
}
그런 다음 가지고있는 모든 조각에서 onCreateAnimation 메서드를 재정의해야합니다.
@Override
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
if (FragmentUtils.sDisableFragmentAnimations) {
Animation a = new Animation() {};
a.setDuration(0);
return a;
}
return super.onCreateAnimation(transit, enter, nextAnim);
}
그런 다음 활동에서 백 스택을 제거해야 할 때 다음을 수행하십시오.
public void clearBackStack() {
FragmentUtils.sDisableFragmentAnimations = true;
getSupportFragmentManager().popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
FragmentUtils.sDisableFragmentAnimations = false;
}
그리고 짜잔, clearBackStack ()을 호출하면 전환 애니메이션없이 루트 조각으로 돌아갑니다.
바라건대 큰 G가 앞으로이 일을하는 덜 어리석은 방법을 추가 할 것입니다.
사용자는 루트 조각이있는 시작 화면에 있습니다.
루트 조각이 활동 A에 포함되어 있다고 가정 해 보겠습니다.
그는 루트 조각에서 항목을 선택한 다음 해당 항목의 세부 정보를 표시하는 새 조각을 표시합니다. 푸시 및 팝 케이스 모두에 대해 애니메이션을 설정하는 조각 트랜잭션을 사용하여 수행합니다 (따라서 사용자가 뒤로 버튼을 누르면 전환이 애니메이션됩니다).
트랜잭션이 백 스택에 추가됩니다. 즉, 세부 조각에서 뒤로 버튼을 누르면 팝핑 프로세스가 애니메이션으로 표시됩니다.
이 조각에서 그는 방금 표시된 항목을 (어떤 이유로 든) 삭제하는 활동을 시작합니다.
활동 B라고 가정 해 보겠습니다.
이 활동이 끝나면 "세부 조각"의 "팝 애니메이션"을 표시하지 않고 루트 조각으로 돌아가고 싶습니다.
이 동작을 얻는 한 가지 방법은 활동 B에서 수행하는 것입니다.
Intent intent = new Intent(this, A.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
그러면 문서 에 따라 활동 A가 루트 상태로 재설정되어 시작 됩니다 ( "이 시작 모드는 FLAG_ACTIVITY_NEW_TASK : ......"와 함께 좋은 효과를 낼 수도있는 섹션의 마지막 단락을 확인하십시오. "). )
이 구성을 사용하면 애니메이션이 기본 케이스에 표시되고 특별한 경우 다음을 사용하여 애니메이션을 제어 할 수 있습니다.
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
애니메이션없이 새로운 활동을 시작합니다. 애니메이션이 필요하면 overridePendingTransition
방법을 사용하여 할 수 있습니다 .
따라서 지원 라이브러리의 경우 다음 작업이 수행됩니다.
커스텀 팝 애니메이션이 있어야하는 프래그먼트에서 onCreateAnimation을 커스텀 애니메이션으로 재정의합니다. 당신은 그것을 얻고 원하는 것에 따라 어떤 종류의 매개 변수를 설정할 수 있습니다. 일반 조각으로 작동하려면 추가 작업을 수행해야 할 수 있습니다.
다음은이를 재정의하고 설정된 기간을 변경하는 예입니다.
@Override
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
Animation anim = (Animation) super.onCreateAnimation(transit, enter, nextAnim);
if(!enter) {
if(anim != null) {
anim.setDuration(0); // This doesn't seem to be called.
return anim;
} else {
Animation test = new TestAnimation();
test.setDuration(0);
return test;
}
}
return anim;
}
private class TestAnimation extends Animation {
}
그래서 @Geoff의 대답에 약간의 변경을 제안하고 싶습니다.
전역 정적 부울을 사용하는 대신 로컬 비 정적 부울을 사용하는 것이 좋습니다. 이것이 제가 생각 해낸 것입니다.
인터페이스 만들기
public interface TransitionAnimator {
void disableTransitionAnimation();
void enableTransitionAnimation();
}
조각이 해당 인터페이스를 구현하도록합니다.
public class MyFragment extends Fragment implements TransitionAnimator {
private boolean mTransitionAnimation;
@Override
public void disableTransitionAnimation() {
mTransitionAnimation = false;
}
@Override
public void enableTransitionAnimation() {
mTransitionAnimation = true;
}
@Override
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
Animation result;
if (!mTransitionAnimation) {
Animation dummyAnimation = new Animation() {
};
dummyAnimation.setDuration(0);
result = dummyAnimation;
} else {
result = super.onCreateAnimation(transit, enter, nextAnim);
}
return result;
}
그런 다음 조각에 대한 전환 애니메이션을 비활성화하려면
if (fragment instanceof TransitionAnimator) {
((TransitionAnimator) fragment).disableTransitionAnimation();
}
활성화하려면
if (fragment instanceof TransitionAnimator) {
((TransitionAnimator) fragment).enableTransitionAnimation();
}
조각 관리자의 모든 조각에 대해 동일한 작업을 수행하려면
List<Fragment> fragments = getSupportFragmentManager().getFragments();
for (Fragment fragment : fragments) {
if (fragment instanceof TransitionAnimator) {
// disable animations
((TransitionAnimator) fragment).disableTransitionAnimation();
}
}
매우 유사하지만 정적 필드가 없습니다.
R.anim.slide_out을setCustomAnimation()
설정하지 않는 또 다른 오버로드 방법을 사용 하면 문제가 해결됩니다.
건배 :)
질문에 답하기 전에 직접 질문해야합니다.
두 번째 활동의 onBackPressed () 메서드에서 첫 번째 활동의 백 스택에 액세스 할 수 있습니까?
그렇다면 popBackStackImmediate (String trnaisiotnName, int inclusive)를 호출하면 백 스택에서 조각 전환이 제거되므로 애니메이션에 대해 걱정할 필요가 없습니다.
이전 활동의 백 스택에 액세스 할 수 있다고 가정합니다. 그렇지 않으면 작동하지 않습니다.
이것은 애니메이션없이 overridePendingTransition(int enterAnim, int exitAnim)
두 가지 모두 0
를 통해 쉽게 달성 할 수 있습니다.
FragmentManager fm = getSupportFragmentManager();
if (fm.getBackStackEntryCount() > 0) {
fm.popBackStack();
overridePendingTransition(0, 0);
}
이것은 @Geoff의 훌륭한 답변에 대한 후속 조치이지만 더 역동적이고 실제적인 시나리오에 적합합니다.
나는 이것이 멋진 작은 게시물이라고 상상했지만 이제는 그것이 약간의 손에서 벗어났다는 것을 깨달았습니다. 그러나 코드는 모두 거기에 있으며 전환 애니메이션을 비활성화하는 방법보다 훨씬 많은 것을 다루지 만 정말 유용하다고 생각합니다.
일반적으로 Fragments로 작업 할 때 BaseActivityCallback에 연결되는 BaseFragment를 갖고 싶습니다. 이 BaseActivityCallback은 내 Fragments에서 자체 위에 새 Fragment를 추가하거나 그 아래에 Fragment를 팝하는 데 사용할 수 있으므로 팝 애니메이션을 비활성화하거나 조용히 팝하려는 욕구가 있습니다 .
interface BaseActivityCallback
{
void addFragment ( BaseFragment f, int containerResId );
void popFragment ( boolean silently );
}
class BaseActivity extends android.support.v4.app.FragmentActivity implements BaseActivityCallback
{
public void addFragment ( BaseFragment f, int containerResId )
{
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.enter, R.anim.exit, R.anim.enter, R.anim.pop_exit); // http://stackoverflow.com/a/17488542/2412477
ft.addToBackStack(DEFAULT_FRAGMENT_STACK_NAME);
ft.replace(containerResId, fragment);
ft.commitAllowingStateLoss();
}
public void popFragment ( boolean silently )
{
FragmentManager fm = getSupportFragmentManager();
if ( silently ) {
int count = fm.getFragments().size();
BaseFragment f = (BaseFragment)fm.getFragments().get(count-1);
f.setDisableTransitionAnimations(true);
}
fm.popBackStackImmediate();
}
}
public abstract class BaseFragment extends android.support.v4.app.Fragment
{
private static final String TAG = "BaseFragment";
private final String STATE_DISABLE_TRANSITION_ANIMATIONS = TAG+".stateDisableTransitionAnimations";
protected BaseActivityCallback baseActivityCallback;
private boolean disableTransitionAnimations;
@Override
public void onCreate ( @Nullable Bundle savedInstanceState )
{
super.onCreate(savedInstanceState);
disableTransitionAnimations = (savedInstanceState==null ? false : savedInstanceState.getBoolean(STATE_DISABLE_TRANSITION_ANIMATIONS, false));
}
@Override
public void onAttach ( Context context )
{
super.onAttach(context);
baseActivityCallback = (BaseActivityCallback)context;
}
@Override
public void onSaveInstanceState ( Bundle outState )
{
super.onSaveInstanceState(outState);
outState.putBoolean(STATE_DISABLE_TRANSITION_ANIMATIONS, disableTransitionAnimations);
}
@Override
public Animation onCreateAnimation ( int transit, boolean enter, int nextAnim )
{
if ( disableTransitionAnimations ) {
Animation nop = new Animation(){};
nop.setDuration(0);
return nop;
}
return super.onCreateAnimation(transit, enter, nextAnim);
}
public void setDisableTransitionAnimations ( boolean disableTransitionAnimations )
{
this.disableTransitionAnimations = disableTransitionAnimations; // http://stackoverflow.com/a/11253987/2412477
}
}
지금 당신은 당신을 만들 수 있습니다 MainActivity
쇼가와가 Fragment1
또 다른 추가 할 수있는 Fragment2
다시 팝업 수있는 Fragment1
자동을 :
public class MainActivity extends BaseActivity
{
protected void onCreate ( Bundle savedInstanceState )
{
setContentView(R.layout.main_activity);
...
if ( getSupportFragmentManager().getFragments() != null && !getSupportFragmentManager().getFragments().isEmpty() ) {
addFragment( FragmentA.newInstance(), R.id.main_activity_fragment_container );
}
}
...
}
public class FragmentA extends BaseFragment
{
public View onCreateView ( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState )
{
ViewGroup root = (ViewGroup)inflater.inflate(R.layout.fragment_a, container, false);
...
root.findViewById(R.id.fragment_a_next_button)
.setOnClickListener( new View.OnClickListener() {
public void onClick ( View v ) {
baseActivityCallback.addFragment( FragmentB.newInstance(), R.id.main_activity_fragment_container );
}
});
}
}
public class FragmentB extends BaseFragment
{
public View onCreateView ( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState )
{
ViewGroup root = (ViewGroup)inflater.inflate(R.layout.fragment_b, container, false);
...
root.findViewById(R.id.fragment_b_pop_silently_button)
.setOnClickListener( new View.OnClickListener() {
public void onClick ( View v ) {
baseActivityCallback.popFragment( true );
}
});
}
}
애니메이션없이 팝하려는 조각에서이를 재정의하고 진입 할 때 애니메이션을 유지합니다.
@Override
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
if(!enter){
Animation a = new Animation() {};
a.setDuration(0);
return a;
}
return super.onCreateAnimation(transit, enter, nextAnim);
}
Easier solution:
for (fragment in supportFragmentManager.fragments) {
removeFragment(fragment)
}
if (supportFragmentManager.backStackEntryCount > 0) {
supportFragmentManager.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE)
}
Android actually now has a way to do this without the work around @Geoff answered.
To avoid the animation to run on popBackStack()
, when inflating your fragment
s add .setReorderingAllowed(true)
to your fragmentTransaction
.
So for example:
supportFragmentTransaction.beginTransaction()
.setReorderingAllowed(true)
.addToBackStack(null)
.setCustomAnimations(
android.R.anim.fade_in,
android.R.anim.fade_out,
android.R.anim.fade_in,
android.R.anim.fade_out
)
.replace(yourContainer.id, yourFragment)
.commit()
You'll notice that if you set setReorderingAllowed(true)
, the pop animation would no longer play. The results are actually similar to the result of @Geoff's answer.
Reply to Geoff and plackemacher comment.
You can try to remove all views from this Fragment. Then fragment will show but it should be transparent.
Remove all-1 (I use navigate drawer so drawer fragment should stay) fragment:
int size = fragmentsList.size ()-1;
FragmentTransaction transaction = fragmentManager.beginTransaction ();
transaction.setTransition (FragmentTransaction.TRANSIT_NONE);
Fragment fragment;
for (int i = size ; i > 0 ; i--)
{
fragment = fragmentsList.get (i);
if(fragment != null)
{
View viewContainer = fragment.getView ();
if (viewContainer != null)
{
((ViewGroup) viewContainer).removeAllViews ();
}
transaction.remove (fragment);
}
}
size = fragmentManager.getBackStackEntryCount ();
for (int i = 0; i < size ; i++)
{
fragmentManager.popBackStack (null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
Sorry for my English
ReferenceURL : https://stackoverflow.com/questions/9194311/pop-the-fragment-backstack-without-playing-the-pop-animation
'UFO ET IT' 카테고리의 다른 글
VIM에서 특정 탭으로 전환 (0) | 2021.01.07 |
---|---|
Beyond Compare에서 Delphi Form Files 버전을 비교하는 동안 특정 차이점을 무시하도록하려면 어떻게해야합니까? (0) | 2021.01.07 |
배포 배포와 스냅 샷을 구별하는 방법 (0) | 2021.01.07 |
'auto const'와 'const auto'는 같은가요? (0) | 2021.01.07 |
Vagrant는 동일한 시스템에서 여러 포트를 어떻게 전달할 수 있습니까? (0) | 2021.01.07 |