我在Android中玩碎片。
我知道我可以通过使用以下代码更改一个片段:
FragmentManager fragMgr = getSupportFragmentManager();
FragmentTransaction fragTrans = fragMgr.beginTransaction();
MyFragment myFragment = new MyFragment(); //my custom fragment
fragTrans.replace(android.R.id.content, myFragment);
fragTrans.addToBackStack(null);
fragTrans.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
fragTrans.commit();
我的问题是,在Java文件中,如何获得当前显示的片段实例?
我最近不得不这样做,这里没有一个答案真正适合这种情况。
如果你确信只有一个片段是可见的(全屏),那么真的要找到backstack顶部的内容。例如,作为Fragment的Kotlin:
import androidx.fragment.app.Fragment
fun Fragment.setVisibilityChangeListener(clazz: Class<out Fragment>, listener: (Boolean) -> Unit) {
fragmentManager?.run {
addOnBackStackChangedListener {
val topFragmentTag = getBackStackEntryAt(backStackEntryCount - 1).name
val topFragment = findFragmentByTag(topFragmentTag)
listener(topFragment != null && topFragment::class.java == clazz)
}
}
}
像这样使用它:
class MyFragment: Fragment {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setVisibilityChangeListener(this::class.java) { visible ->
// Do stuff
}
}
}
在你的活动中,在创建之前初始化你的片段
MyFragment myFragment = new MyFragment(); // add this
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
........
然后调用该方法来查看您的片段
openFragment(this.myFragment);
这是方法
(R.id.frame_container)是xml文件中的片段容器id
(框架布局)
private void openFragment(final Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.frame_container, fragment);
transaction.commit();
}
那么在你的活动中,Override方法应该是这样的
public void onBackPressed() {
if (myFragment.isVisible()) {
myFragment.onBackPressed(this);
return;
}
super.onBackPressed();
}
然后在你的片段中放入这个方法
public void onBackPressed(Activity activity) {
Toast.makeText(activity, "Back Pressed inside Fragment", Toast.LENGTH_SHORT).show();
}
每次当你显示fragment时,你必须把它标签放入backstack:
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setTransition(FragmentTransaction.TRANSIT_ENTER_MASK);
ft.add(R.id.primaryLayout, fragment, tag);
ft.addToBackStack(tag);
ft.commit();
然后当你需要获取当前片段时,你可以使用这个方法:
public BaseFragment getActiveFragment() {
if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
return null;
}
String tag = getSupportFragmentManager().getBackStackEntryAt(getSupportFragmentManager().getBackStackEntryCount() - 1).getName();
return (BaseFragment) getSupportFragmentManager().findFragmentByTag(tag);
}
我遇到了一个类似的问题,我想知道当返回键被按下时最后显示的片段是什么。我用了一个非常简单的方法。每次我打开一个片段,在onCreate()方法中,我在我的单例中设置了一个变量(用你的片段的名称替换“myFragment”)
MySingleton.currentFragment = myFragment.class;
变量在单例中声明为
public static Class currentFragment = null;
然后在onBackPressed()中检查
if (MySingleton.currentFragment == myFragment.class){
// do something
return;
}
super.onBackPressed();
确保调用super.onBackPressed();在“返回”之后,否则应用程序将处理返回键,这在我的情况下导致应用程序终止。
你也可以很容易地在logcat中使用URL,它将重定向到当前片段源代码的源代码。首先,你需要在主机活动中添加一个OnBackStackChangedListener,比如-
activity.getChildFragmentManager().addOnBackStackChangedListener(backStackListener);
OnBackStackChangedListener的实现是-
public FragmentManager.OnBackStackChangedListener backStackListener = () -> {
String simpleName = "";
String stackName = getStackTopName().trim();
if (Validator.isValid(stackName) && stackName.length() > 0) {
simpleName = stackName.substring(Objects.requireNonNull(stackName).lastIndexOf('.') + 1).trim();
List<Fragment >
fragmentList = getChildFragmentManager().getFragments();
Fragment myCurrentFragment;
for (int i = 0; i < fragmentList.size(); i++) {
myCurrentFragment= fragmentList.get(i);
if (myCurrentFragment.getClass().getSimpleName().equals(simpleName)) {
//Now you get the current displaying fragment assigned in myCurrentFragment.
break;
}
myFragment = null;
}
}
//The code below is for the source code redirectable logcat which would be optional for you.
StackTraceElement stackTraceElement = new StackTraceElement(simpleName, "", simpleName + ".java", 50);
String fileName = stackTraceElement.getFileName();
if (fileName == null) fileName = "";
final String info = "Current Fragment is:" + "(" + fileName + ":" +
stackTraceElement.getLineNumber() + ")";
Log.d("now", info + "\n\n");
};
getStackTopName()方法是-
public String getStackTopName() {
FragmentManager.BackStackEntry backEntry = null;
FragmentManager fragmentManager = getChildFragmentManager();
if (fragmentManager != null) {
if (getChildFragmentManager().getBackStackEntryCount() > 0)
backEntry = getChildFragmentManager().getBackStackEntryAt(
getChildFragmentManager().getBackStackEntryCount() - 1
);
}
return backEntry != null ? backEntry.getName() : null;
}