简体   繁体   English

方向更改后,Android翻转动画会闪烁

[英]Android flip animation flashes after orientation change

I'm working on a flashcard like app and i've been wrestling with the flip animation. 我正在使用像app这样的闪卡,我一直在和翻转动画进行摔跤。 I've based my code on the AnimationsDemo from android with the difference being that it is done inside a fragment instead of an activity. 我将我的代码基于Android上的AnimationsDemo ,不同之处在于它是在片段而不是活动中完成的。 It works fine, not entirely as the preview of the aforementioned demo, but decent enough. 它工作正常,不完全像上述演示的预览,但足够体面。 Except... after changing orientation. 改变方向后...... If the app is started in landscape, it works fine in landscape, but freaks in portrait and if the app is launched in portrait it works in portrait and freaks in landscape. 如果应用程序是在风景中启动的,它在风景中工作得很好,但是在肖像方面很怪异,如果应用程序是以肖像方式启动的,那么它可以在纵向和怪异的环境中工作。

可视化的“怪胎”

This is my code ( i skimmed the datamodel obviously) 这是我的代码(我明显地略去了数据模型)

public class MyFlashCardFragment extends Fragment {
private MyDataModel model;
private Handler mHandler = new Handler();
private boolean mShowingBack = false;
FrameLayout frameLayout;

public static MyFlashCardFragment create(MyDataModel m) {
    MyFlashCardFragment fragment = new MyFlashCardFragment();
    Bundle bundle = new Bundle();
    bundle.putString(AppKeys.FRONT_KEY,m.getFrontText());
    bundle.putString(AppKeys.BACK_KEY,m.getBackText());
    fragment.setArguments(bundle);
    return fragment;
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (!getArguments().isEmpty()) {
        model = new MyDataModel();
        model.setFrontText(getArguments().getString(AppKeys.FRONT_KEY));
        model.setBackText(getArguments().getString(AppKeys.BACK_KEY));
    }
}

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
    if (model == null) {
        return super.onCreateView(inflater, container, savedInstanceState);
    } else {
        ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_flashcard, container, false);
        frameLayout = (FrameLayout) root.findViewById(R.id.chilfd_frame);
        Button btn_overlay = (Button) root.findViewById(R.id.overlaybutton);
        btn_overlay.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                flipCard();
            }
        });

        return root;
    }
}

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    if(savedInstanceState == null) {
        getChildFragmentManager()
                .beginTransaction()
                .add(R.id.chilfd_frame, CardFrontFragment.create(model.getFrontText()))
                .commit();
    } else {
        mShowingBack = (getChildFragmentManager().getBackStackEntryCount() > 0);
    }
    getChildFragmentManager().addOnBackStackChangedListener(new android.app.FragmentManager.OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {
            mShowingBack = (getChildFragmentManager().getBackStackEntryCount() > 0);
            getActivity().invalidateOptionsMenu();
        }
    });
}

private void flipCard() {
    if (mShowingBack) {
        getChildFragmentManager().popBackStack();
        return;
    }

    mShowingBack = true;

    getChildFragmentManager()
            .beginTransaction()
            .setCustomAnimations(
                    R.animator.card_flip_right_in, R.animator.card_flip_right_out,
                    R.animator.card_flip_left_in, R.animator.card_flip_left_out)
            .replace(frameLayout.getId(), CardBackFragment.create(model.getBackText()))
            .addToBackStack(null)
            .commit();
    mHandler.post(new Runnable() {
        @Override
        public void run() {
            getActivity().invalidateOptionsMenu();
        }
    });
}


/**
 * A fragment representing the front of the card.
 */
public static class CardFrontFragment extends Fragment {
    String frontText;

    public static CardFrontFragment create(String frontText) {
        CardFrontFragment fragment = new CardFrontFragment();
        Bundle bundle = new Bundle();
        bundle.putString(AppKeys.FRONT_KEY,frontText);
        fragment.setArguments(bundle);
        return fragment;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (!getArguments().isEmpty()) {
            frontText = getArguments().getString(AppKeys.FRONT_KEY);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        if (TextUtils.isEmpty(frontText)) {
            return super.onCreateView(inflater, container, savedInstanceState);
        } else {
            ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_flashcard_front, container, false);

            ((TextView) rootView.findViewById(R.id.tv_name)).setText(frontText);


            return rootView;
        }
    }
}

/**
 * A fragment representing the back of the card.
 */
public static class CardBackFragment extends Fragment {
    String backText;

    public static CardBackFragment create(String backText) {
        CardBackFragment fragment = new CardBackFragment();
        Bundle bundle = new Bundle();
        bundle.putString(AppKeys.BACK_KEY,backText);
        fragment.setArguments(bundle);
        return fragment;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (!getArguments().isEmpty()) {
            backText = getArguments().getString(AppKeys.BACK_KEY);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        if (TextUtils.isEmpty(backText)) {
            return super.onCreateView(inflater, container, savedInstanceState);
        } else {
            ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_flashcard_back, container, false);

            ((TextView) rootView.findViewById(R.id.tv_name)).setText(backText);


            return rootView;
        }
    }
}

} }

The parentfragment is loaded form a viewpager: parentfragment从viewpager加载:

pager = (ViewPager) findViewById(R.id.pager);
    adapter = new FlashCardPageAdapter(getFragmentManager(), getAllFrom(ref));
    pager.setAdapter(adapter);
    pager.setCurrentItem(position,true);

    pager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
        @Override
        public void onPageSelected(int position) {
            invalidateOptionsMenu();
        }
    });

and the adapter used is: 并使用的适配器是:

public class FlashCardPageAdapter  extends FragmentStatePagerAdapter {
private ArrayList<MyDataModel> Models;

public FlashCardPageAdapter(FragmentManager fm, ArrayList<MyDataModel> list) {
    super(fm);
    this.Models = list;
}

@Override
public Fragment getItem(int position) {
    return FlashCardFragment.create(Models.get(position));
}

@Override
public int getCount() {
    return Models.size();
}

} }

I also tried to create the animations form an Animator object and add that to a transparent button and animating views in and out and toggling the visibility and the result is the same. 我还尝试从Animator对象创建动画,并将其添加到透明按钮,进出动画视图并切换可见性,结果是相同的。

Any ideas/suggestions would be welcome. 任何想法/建议都会受到欢迎。

It turns out there's nothing missing in my code and the problem is emulator related. 事实证明我的代码中没有任何遗漏,问题与模拟器有关。 Well at least it seems that way. 好吧,至少看起来那样。 I tried it on 2 real devices (1 phone/1 tablet) and the problem didn't manifest on them, so might be an AVD bug or simple shortcoming of the simulated orientation change. 我在2个真实设备(1个电话/ 1个平板电脑)上尝试过它并且问题没有在它们上面显示,因此可能是AVD错误或模拟方向改变的简单缺点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM