You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用ViewGroupManager和FrameLayout开发RN安卓原生组件失败求助

问题描述

我正在为React Native开发安卓原生UI组件,因要制作播放器组件,参考了react-native-video项目并查阅了React Native官方文档。编写了一段渲染TextView的简单Java代码后,运行应用发现安卓端的TextView组件并未在屏幕上显示。请问如何通过ViewGroupManager和FrameLayout让该组件正常显示?

现有代码

MyPackage implements ReactPackage

public class MyPackage implements ReactPackage {
  @Override
  public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
    return Arrays.<ViewManager>asList(
      new ReactTextViewManager(reactContext)
    );
  }

  @Override
  public List<NativeModule> createNativeModules(
          ReactApplicationContext reactContext) {
    List<NativeModule> modules = new ArrayList<>();

    return modules;
  }
}

ReactTextViewManager extends ViewGroupManager

我使用ViewGroupManager是因为react-native-video项目将其用作视图管理器。

public class ReactTextViewManager extends ViewGroupManager<ReactTextView> {
  public static final String REACT_CLASS = "RCTTextView";
  private static final String TAG = "ReactTextViewManager";
  ReactApplicationContext mCallerContext;
  public ReactTextViewManager(ReactApplicationContext context) {
    mCallerContext = context;
  }

  @NonNull
  @Override
  public String getName() {
    return REACT_CLASS;
  }

  @NonNull
  @Override
  public ReactTextView createViewInstance(@NonNull ThemedReactContext context) {
    return new ReactTextView(context);
  }

  @ReactProp(name = "text")
  public void setText(ReactTextView view, String text) {
    Log.i(TAG, "ReactProp: " + text);
    view.setText(text);
  }
}

ReactTextView extends FrameLayout

我使用FrameLayout是因为react-native-video项目将其用作视图。

public class ReactTextView extends FrameLayout {
  private final TextView textView;

  public ReactTextView(ThemedReactContext context) {
    super(context);

    textView = new TextView(context);
    textView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
    addView(textView);
  }

  public void setText(String text) {
    if (textView != null) {
      textView.setText(text);
    }
  }
}

注册与使用

MainApplication

public class MainApplication extends Application implements ReactApplication {

  private final ReactNativeHost mReactNativeHost =
      new DefaultReactNativeHost(this) {
        // ...
        @Override
        protected List<ReactPackage> getPackages() {
          @SuppressWarnings("UnnecessaryLocalVariable")
          List<ReactPackage> packages = new PackageList(this).getPackages();
          // 无法自动链接的包可在此手动添加,例如:
          // packages.add(new MyReactNativePackage());

          packages.add(new MyPackage());

          return packages;
        }
        //...
}

React Native端代码

import { HostComponent, requireNativeComponent } from 'react-native';

interface TextViewProps {
  text?: string;
}

export type VideoComponentType = HostComponent<TextViewProps>;

export default requireNativeComponent<TextViewProps>(
  'RCTTextView',
) as VideoComponentType;

以及App组件:

import React from 'react';
import { SafeAreaView, StyleSheet, Text } from 'react-native';
import TextView from './components/TextView';

function App(): JSX.Element {
  return (
    <SafeAreaView style={styles.container}>
      <Text>Top</Text>
      <TextView text="Hello World" />
      <Text>Bottom</Text>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#dedede',
  },
});

export default App;
解决方案

问题核心是React Native中基于ViewGroupManager的组件默认不会自动测量自身尺寸,导致你的FrameLayout宽高为0,内部TextView自然无法显示。需要通过重写测量方法来指定组件尺寸,具体修改如下:

1. 修改ReactTextView类,重写onMeasure方法

在ReactTextView中添加onMeasure方法,让FrameLayout根据内部TextView的尺寸来设置自身大小:

public class ReactTextView extends FrameLayout {
    private final TextView textView;

    public ReactTextView(ThemedReactContext context) {
        super(context);
        textView = new TextView(context);
        textView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
        addView(textView);
    }

    public void setText(String text) {
        if (textView != null) {
            textView.setText(text);
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // 先测量内部TextView的尺寸
        textView.measure(widthMeasureSpec, heightMeasureSpec);
        // 将当前FrameLayout的尺寸设置为TextView的测量结果
        setMeasuredDimension(textView.getMeasuredWidth(), textView.getMeasuredHeight());
    }
}

2. (可选)在React Native端添加样式约束

如果希望组件能响应React Native的样式设置,可以给TextView组件添加样式属性,比如指定宽高或flex布局:

<TextView text="Hello World" style={{width: '100%', padding: 16}} />

完成上述修改后,重新编译运行安卓项目,就能看到TextView正常显示了。

内容的提问来源于stack exchange,提问作者junep

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 21:43:10