React-Native添加Fragment到View后未显示

5
我已经将一个动态生成的FrameLayout添加到了React Native视图中。Framelayout已经显示出来了,但是当我向视图中添加一个fragment时,什么也没有显示出来。
以下是代码的一部分:
    public FrameLayout createViewInstance(ThemedReactContext context) {

            Fragment fragment = MapFragment.newInstance(mapKey);
            FrameLayout view = new FrameLayout(context);
            view.setWillNotDraw(false);

            LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
            view.setLayoutParams(lp);

            view.setId(View.generateViewId());

            view.setBackgroundColor(Color.parseColor("#1FFDDB"));

            FragmentActivity activity = MainActivity.getFragmentActivity();

            FragmentManager fragmentManager = activity.getSupportFragmentManager();

            fragmentManager.beginTransaction().remove(fragment).commit();
            fragmentManager.executePendingTransactions();

            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

            fragmentTransaction.add(0, fragment);

            fragmentTransaction.show(fragment);
            fragmentTransaction.attach(fragment);
            fragmentTransaction.commit();
            fragmentManager.executePendingTransactions();
            return view;
        }

当我向视图添加 TextView 时,它会显示:
// add a textfield to the view
TextView textView1 = new TextView(context);
textView1.setText("Android");
textView1.setTextSize(30);
textView1.setGravity(Gravity.CENTER);

view.setVisibility(View.VISIBLE);

view.addView(textView1);

所以 Fragment 存在问题。 有任何想法为什么 Fragment 没有显示出来吗?


https://dev59.com/V1sW5IYBdhLWcg3w8rD2 - Danieboy
我按照stackoverflow/34410559中的说明进行了实现,但仍然没有显示出任何内容。 - dirk slootmaekers
我将fragmentTransaction.add(0, fragment);替换为fragmentTransaction.add(view.getId(), fragment);但仍然存在相同的问题(未显示)。 - dirk slootmaekers
各位好,这个问题有最新的消息吗?我也面临同样的情况,现在无法将一个片段用于我的React管理视图。 - Roberto Conte Rosito
我也无法使用getFragmentSupportManager()来使用Fragment。有什么帮助吗? - Tanvi Agarwal
1个回答

8
我是一名能翻译文本的助手。

我也遇到了这个问题,并找到了解决方法。

Android端: 首先,创建一个layout_container.xml文件。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">
    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>

然后在 createViewInstance 方法中填充它,并定义将片段添加到容器的函数。

@Override
public String getName() {
    return "ExampleFragment";
}
@Override
protected View createViewInstance(ThemedReactContext reactContext) {
    mContext = context;
    LinearLayout root = (LinearLayout) LayoutInflater.from(reactContext)
                .inflate(R.layout.layout_container, null);
    return root;
}

@Nullable
@Override
public Map<String, Integer> getCommandsMap() {
    return MapBuilder.of(
            "create", COMMAND_CREATE
    );

}

@Override
public void receiveCommand(View view, int commandId, @Nullable ReadableArray args) {
    Log.d(TAG, "receiveCommand: " + commandId);
    switch (commandId) {
        case COMMAND_CREATE:
            createFragment();
            break;
    }
}

private void createFragment() {
    MapFragment mapFragment = new MapFragment();
    mContext.getCurrentActivity()
            .getFragmentManager()
            .beginTransaction()
            .add(R.id.container, mapFragment)
            .commit();
}

RN方面: 创建本地UI组件Fragment.js
import {NativeModules, requireNativeComponent, View, UIManager, findNodeHandle} from 'react-native';
const fragmentIFace = {
  name: "Fragment",
  propTypes: {
    ...View.propTypes,
  }
};
const NativeFragment = requireNativeComponent("ExampleFragment", fragmentIFace);
class ExampleFragment extends Component {
  fragment;
  render() {
    return <NativeFragment
      ref={c => this.fragment = c}
      {...this.props} style={{flex: 1}}/>
  }

  create = () => {
    UIManager.dispatchViewManagerCommand(
      findNodeHandle(this.fragment),
      UIManager.MapFragment.Commands.create,
      [] // No args
    )
  }
export default ExampleFragment

然后你可以在RN中使用它。
class App extends Component {
    componentDidMount() {
        this.fragment.create();
    }
    render() {
        return (
            <View>
                <ExampleFragment ref={r=>this.fragment = r} />
            </View>
        );
    }
}

这是解释:
在你的代码中,你试图将片段添加到不能成为片段容器的视图中。
通常,View.generateViewId()会返回id 0x1,这与ReactRootView巧合重复,因此你的应用程序不会崩溃。如果你为容器视图设置其他id,你将得到异常并且应用程序将崩溃,因为当前应用程序布局中找不到你的视图的id。
你可以使用Android Studio中的Layout Inspector来检查它。
为了防止id重复,最好的方法是在xml中定义它们。 这就是为什么我从xml中膨胀一个根视图。
但是,如果你为根元素(例如我的例子中的LinearLayout)设置id,当RN将其添加时,该id将被删除,因此需要一个子元素。
在RN获取根视图(didComponentMount())之后,你需要从RN组件调用create(),然后你就可以看到它了。

如果MapFragment(支持片段)使用fragmentPagerAdapter具有viewpager,怎么办?有没有办法获得mContext.getCurrentActivity().getSupportFragmentManager()? - Tanvi Agarwal
由于ReactActivity扩展了Activity而不是AppCompatActivity,因此无法使用getSupportFragmentManager()。尝试使用来自支持库v13的ViewPager。虽然它在Android API 27中已被弃用,但这可能是一个临时解决方案,直到RN进行一些更改。 - jordenchang55

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接