java - 替换片段时的动画问题,使用或不使用 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;
}
我的问题太长了,所以即使您只是阅读了这个问题但无法给我一些帮助,我也非常感谢您。
如果阅读我的问题给您带来不便,我再次向您表示歉意。
解决方案
推荐阅读
- python-3.x - `python -m venv foo` 不在嵌套环境中安装 pip
- r - ggplot2 PDF barplot 有白线,需要大量放大并且看起来不同。在 PowerPoint 上
- ruby - 在 Ruby 中,如何不带括号将多个哈希传递给一个方法?
- numpy - Numpy:通过相对舍入克服机器不精确
- python - 如何将逆向转置应用于 numpy 数组
- swift - 如何从 GRDB 中的只读数据库连接中调用新的数据库连接?
- topojson - 有没有办法改变 topojson 文件中的投影?
- angular - 如何以角度进行多个异步并行获取调用而不等待响应
- ios - 使用 CoreData @NSManaged 子类在不寻常的地方“将无法识别的选择器发送到实例”
- postgresql - 为什么我对索引字段的计数查询很慢?