首页 > 解决方案 > 替换片段时的动画问题,使用或不使用 addToBackStack

问题描述

在提问之前,我先向我糟糕的英语道歉。

我在使用片段动画时遇到问题

我的应用架构如下

只有一个活动(MainActivity)

MainActivity 中有一个框架布局。

我在 MainActivity 中实现了一些方法来替换该框架布局上的片段。

public void fragmentMove(Fragment dest)
{
    FragmentTransaction t = getSupportFragmentManager().beginTransaction();
    t.addToBackStack(null);
    t.setCustomAnimations(R.anim.anim_fade_in, R.anim.anim_fade_out, R.anim.anim_fade_in, R.anim.anim_fade_out);
    t.replace(R.id.fl_main, dest);
    t.commit();
}
public void fragmentMoveNoStack(Fragment dest)
{
    FragmentTransaction t = getSupportFragmentManager().beginTransaction();
    t.setCustomAnimations(R.anim.anim_fade_in, R.anim.anim_fade_out, R.anim.anim_fade_in, R.anim.anim_fade_out);
    t.replace(R.id.fl_main, dest);
    t.commit();
}

我有五个片段类,我将它们分别称为“fragA”、“fragB”、“fragC”、“fragD”、“fragE”。

每个片段上都有一个按钮可以替换片段

例如,fragA 有一个按钮“btn_toFragB”,我将 OnClickListener 设置为将 fragA 替换为 fragB。

代码是

btn_category.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        CategoryFragment dest = new CategoryFragment(mainActivityCtx);

        ((MainActivity)ctx).fragmentMove(dest);
    }
});

我只能按这个顺序导航片段(fragA <-> fragB <-> fragC -> fragD -> fragE -> fragC)

如果我单击此按钮,它将按我的预期工作。

fragA 淡出,fragB 在框架布局上淡入

fragB -> fragC -> fragD 在仅使用 fragmentMove 方法时也可以正常工作。不是fragmentMoveNoStack。

我在 fragD -> fragE 中使用了 fragmetMoveNoStack,所以如果我按下 fragE 上的后退按钮,我可以返回 fragC 而不是 fragD,它可以工作。

但问题是动画。

在我从 fragE 回到 fragC 后,每个片段替换都会显示 fragE 淡出动画。

我的意思是,当我将 fragB 替换为 fragC 时,会出现 fragB 淡出动画和 fragC 淡入动画,因此看起来很流畅。

但是在我导航 fragE 并返回 fragC 之后,如果我按下返回按钮以便片段替换 (fragC -> fragB),则会出现 fragE 淡出动画,然后 fragB 淡入动画。不仅仅是 fragC -> fragB,每个片段变化都会显示 fragE 淡出动画。

如果我在fragD->fragE中使用fragmentMove方法而不是fragmentMoveNoStack,没有动画问题,但是我想在fragE中按下返回按钮时,出现fragC而不是fragD。

fragmentMove 和 fragmentMoveNoStack 的唯一区别是 addToBackStack(null); 我认为这是问题的原因。

我想要片段动画和fragmentTransaction、backstacks等交互的解决方案或信息。

只有上面的那些代码可能不包含问题,所以我在下面添加我的代码。

这是 fragC 我通知这个片段中没有 fragmentMove 方法。它在recyclerview上实现

public class LevelFragment extends Fragment {

    private Context ctx;

    public LevelFragment(Context ctx) {
        // Required empty public constructor
        this.ctx = ctx;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View fragmentView = inflater.inflate(R.layout.fragment_level, container, false);

        final RecyclerView rv_level = fragmentView.findViewById(R.id.rv_level);


        ImageView img_back = fragmentView.findViewById(R.id.img_back);

        img_back.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {

                getFragmentManager().popBackStackImmediate();
            }
        });

        return fragmentView;
    }
}

在适配器类的这个 onBindViewHolder 中有 fragmentMove

@Override
public void onBindViewHolder(RvLevelAdapter.ViewHolder holder, final int position) {

    final View itemView = holder.itemView;

    holder.itemView.findViewById(R.id.cl_touchbox).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //클릭 시 해당 게임을 플레이하는 GameActivity 로 이동
            Fragment dest = new GameFragment(ctx);
            // Fragment 생성
            Bundle bundle = new Bundle();
            bundle.putInt("id", levels[position].getId());
            dest.setArguments(bundle);

%%%%%%%%%%%%%%%%%fragmentMove is here
%%%%%%%%%%%%%%%%%ctx is Context of MainActivity
%%%%%%%%%%%%%%%%%this adapter is called in LevelActivity I wrote above. and LevelActivity Constructor gets MainActivity Context so When I call this adapter in LevelActivity, I pass that MainActivity Context to this adapter as parameter
            ((MainActivity)ctx).fragmentMove(dest);


        }
    });
}

这是fragD

此类中没有 fragmentMoveNoStack 方法。

在 GameBoard 类中调用方法 fragmentMoveNoStack。

我将在此代码下方编写 GameBoard 类代码

public class GameFragment extends Fragment {

    private Context ctx;
    private Context mainActivityContext;
    LevelPlayManager lpm;

    GameBoard gameBoard;

    private int id;

    public GameFragment(Context ctx) {
        mainActivityContext = ctx;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View fragmentView = inflater.inflate(R.layout.fragment_game, container, false);
        ctx = fragmentView.getContext();

        gameBoard = new GameBoard(mainActivityContext, fragmentView, lpm);

        gameBoard.makeGameBoard();

        TextView tv_name = fragmentView.findViewById(R.id.tv_name);
        tv_name.setText(name);


        ImageView img_back = fragmentView.findViewById(R.id.img_back);

        img_back.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {

                getFragmentManager().popBackStackImmediate();

            }
        });

        return fragmentView;
    }
}

这是游戏板类

有fragmentMoveNoStack

我用 '%' 字母表示那部分

public class GameBoard {

    SharedPreferences optionPref;
    boolean smartDrag;
    boolean oneLineDrag;
    boolean autoX;

    Context mainActivityContext;

    private View targetView;

    private RecyclerView rv_board;

    private GridLayoutManager glm;
    public LevelPlayManager lpm;

    ColumnIndexViewMaker civm;
    RowIndexViewMaker rivm;

    private TextView tv_stack;
    private TextView tv_count;

    private ConstraintLayout cl_count;
    private LinearLayout ll_drag;

    private ImageView img_toggle;
    private ImageView img_prev;
    private ImageView img_next;
    private ImageView img_hint;
    private ImageView img_tutorial;

    int touchStartX;
    int touchStartY;
    int touchEndX;
    int touchEndY;

    int[][] dragTemp;

    int touchMode = 0;
    int macroMode = 0;
    
    public GameBoard(Context ctx, View view, LevelPlayManager lpm)
    {
        targetView = view;
        this.lpm = lpm;
        mainActivityContext = ctx;

        initialize();
    }

    public void loadOption()
    { ~ }

    private void initialize()
    {
        dragTemp = new int[lpm.height][lpm.width];
        rv_board = targetView.findViewById(R.id.rv_board);
        //
        ~~~~~~~~
        //
        loadOption();
    }

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    private void moveToEndFragment()
    {
        //클릭 시 해당 게임을 플레이하는 GameActivity 로 이동
        EndFragment endFragment = new EndFragment();
        Bundle bundle = new Bundle();
        bundle.putInt("id", lpm.id);


        endFragment.setArguments(bundle);

        ((MainActivity)mainActivityContext).fragmentMoveNoStack(endFragment);
    }
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    private void clickUpAction()
    {
        if(lpm.isGameEnd())
        {
            moveToEndFragment();
            setGameEnd();
        }
    }


    private BoardItemTouchListener boardTouchListener = new BoardItemTouchListener() {

        //when I press and 'release' the touch from the recycler view item, it calls moveToEndFragment
        @Override
        public void onClickUp(int pos, RecyclerView.ViewHolder holder)
        {
            clickUpAction();
        }
    };


    public void makeGameBoard()
    {
        glm = new GridLayoutManager(targetView.getContext(), lpm.width);

        RvBoardAdapter rba = new RvBoardAdapter(lpm.checkedSet);

        rv_board.setLayoutManager(glm);
        rv_board.addOnItemTouchListener(boardTouchListener);
        rv_board.setAdapter(rba);
    }
}

这是碎片

我认为这个片段的代码解决我的问题并不重要

public class EndFragment extends Fragment {

    private Context ctx;


    public EndFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View fragmentView = inflater.inflate(R.layout.fragment_end, container, false);
        ctx = fragmentView.getContext();


        return fragmentView;
    }

我的问题太长了,所以即使您只是阅读了这个问题但无法给我一些帮助,我也非常感谢您。

如果阅读我的问题给您带来不便,我再次向您表示歉意。

标签: javaandroidandroid-fragmentsanimation

解决方案


推荐阅读