New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Android][Native UI] Couldn't make self-implemented android native ui work. #2856

Closed
rayshih opened this Issue Sep 19, 2015 · 18 comments

Comments

Projects
None yet
@rayshih

rayshih commented Sep 19, 2015

I kind of go though the guide from the official document https://facebook.github.io/react-native/docs/native-components-android.html#content. But I couldn't make it work. Here is my source code:

(this is just a test so I didn't implement the updateView function

package com.awesomeproject;

import android.support.design.widget.FloatingActionButton;

import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;

public class FloatingActionButtonManager extends SimpleViewManager<FloatingActionButton> {
    @Override
    public String getName() {
        return "RCTFloatingActionButton";
    }

    @Override
    protected FloatingActionButton createViewInstance(ThemedReactContext themedReactContext) {
        return new FloatingActionButton(themedReactContext);
    }
}
package com.awesomeproject;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

import java.util.Collections;
import java.util.List;
import java.util.Arrays;

public class MyReactPackage implements ReactPackage {
    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactApplicationContext) {
        return Collections.emptyList();
    }

    @Override
    public List<Class<? extends JavaScriptModule>> createJSModules() {
        return Collections.emptyList();
    }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactApplicationContext) {
        return Arrays.asList(new ViewManager[]{new FloatingActionButtonManager()});
    }
}
var {requireNativeComponent} = require('react-native');

var iface = {
  name: 'FloatingActionButton',
  propTypes: {},
};

module.exports = requireNativeComponent('RCTFloatingActionButton', iface);

And I encounter these errors:

Warning: Native component for "RCTModalHostView" does not exist
Warning: Native component for "RCTTextView" does not exist
Warning: Native component for "RCTTextField" does not exist
Warning: Native component for "RCTFloatingActionButton" does not exist
@mkonicek

This comment has been minimized.

Show comment
Hide comment
@mkonicek

mkonicek Sep 19, 2015

Contributor

I assume you used MyReactPackage in your MainActivity?

You'll still need all the views and modules from the default package:
https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java

You can use CompositeReactPackage to create a package that combines both MyReactPackage and MainReactPackage: in your MainActivity, you can do:

new CompositeReactPackage(new MainReactPackage(), new MyReactPackage())

Thanks for reporting the docs are not clear enough! Hope this helps and feel free to send a pull request for making the docs clearer or tell me which part you found unclear and I'll fix it.

Contributor

mkonicek commented Sep 19, 2015

I assume you used MyReactPackage in your MainActivity?

You'll still need all the views and modules from the default package:
https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java

You can use CompositeReactPackage to create a package that combines both MyReactPackage and MainReactPackage: in your MainActivity, you can do:

new CompositeReactPackage(new MainReactPackage(), new MyReactPackage())

Thanks for reporting the docs are not clear enough! Hope this helps and feel free to send a pull request for making the docs clearer or tell me which part you found unclear and I'll fix it.

@mkonicek mkonicek self-assigned this Sep 19, 2015

@mkonicek mkonicek added the Android label Sep 19, 2015

@mkonicek

This comment has been minimized.

Show comment
Hide comment
@mkonicek

mkonicek Sep 19, 2015

Contributor

Btw, good idea to expose the FloatingActionButton!

Contributor

mkonicek commented Sep 19, 2015

Btw, good idea to expose the FloatingActionButton!

@rayshih

This comment has been minimized.

Show comment
Hide comment
@rayshih

rayshih Sep 19, 2015

Thanks for reply. But after I use CompositeReactPackage the errors stay the same.
I have tried clean & rebuild.

rayshih commented Sep 19, 2015

Thanks for reply. But after I use CompositeReactPackage the errors stay the same.
I have tried clean & rebuild.

@ide

This comment has been minimized.

Show comment
Hide comment
@ide

ide Sep 19, 2015

Collaborator

Those messages are warnings, not errors. I don't think they are causing your issue (try loading a clean project and seeing if the warnings are still there).

Collaborator

ide commented Sep 19, 2015

Those messages are warnings, not errors. I don't think they are causing your issue (try loading a clean project and seeing if the warnings are still there).

@rayshih

This comment has been minimized.

Show comment
Hide comment
@rayshih

rayshih Sep 19, 2015

This is a clean project actually.

rayshih commented Sep 19, 2015

This is a clean project actually.

@Wingie

This comment has been minimized.

Show comment
Hide comment
@Wingie

Wingie Sep 20, 2015

i'm also facing an issue while trying to develop a native UI component.
have reported it here@ stackoverflow

Wingie commented Sep 20, 2015

i'm also facing an issue while trying to develop a native UI component.
have reported it here@ stackoverflow

@andreaskeller

This comment has been minimized.

Show comment
Hide comment
@andreaskeller

andreaskeller Sep 21, 2015

@rayshih I had the same problem and after a while I found out that the UIManagerModule doesn't export view managers with no properties

Map<String, UIProp.Type> viewManagerNativeProps = viewManager.getNativeProps();
if (!viewManagerNativeProps.isEmpty()) {
Map<String, String> nativeProps = new HashMap<>();
for (Map.Entry<String, UIProp.Type> entry : viewManagerNativeProps.entrySet()) {
nativeProps.put(entry.getKey(), entry.getValue().toString());
}
viewManagerConstants.put("NativeProps", nativeProps);
}
if (!viewManagerConstants.isEmpty()) {
constants.put(viewManager.getName(), viewManagerConstants);
}
. Adding a property solved it for me.

andreaskeller commented Sep 21, 2015

@rayshih I had the same problem and after a while I found out that the UIManagerModule doesn't export view managers with no properties

Map<String, UIProp.Type> viewManagerNativeProps = viewManager.getNativeProps();
if (!viewManagerNativeProps.isEmpty()) {
Map<String, String> nativeProps = new HashMap<>();
for (Map.Entry<String, UIProp.Type> entry : viewManagerNativeProps.entrySet()) {
nativeProps.put(entry.getKey(), entry.getValue().toString());
}
viewManagerConstants.put("NativeProps", nativeProps);
}
if (!viewManagerConstants.isEmpty()) {
constants.put(viewManager.getName(), viewManagerConstants);
}
. Adding a property solved it for me.

@corbt

This comment has been minimized.

Show comment
Hide comment
@corbt

corbt Sep 23, 2015

Contributor

Can confirm @andreaskeller -- RN wasn't recognizing my custom component, and adding a prop to the view manager caused everything to work as expected.

Contributor

corbt commented Sep 23, 2015

Can confirm @andreaskeller -- RN wasn't recognizing my custom component, and adding a prop to the view manager caused everything to work as expected.

@ide

This comment has been minimized.

Show comment
Hide comment
@ide

ide Sep 23, 2015

Collaborator

cc @mkonicek @kmagiera see @andreaskeller's comment about components without props.

Collaborator

ide commented Sep 23, 2015

cc @mkonicek @kmagiera see @andreaskeller's comment about components without props.

@kmagiera

This comment has been minimized.

Show comment
Hide comment
@kmagiera

kmagiera Sep 24, 2015

Contributor

I'm landing large changes to the ViewManager API, will verify that component with no props get properly registered

Contributor

kmagiera commented Sep 24, 2015

I'm landing large changes to the ViewManager API, will verify that component with no props get properly registered

@gs-akhan

This comment has been minimized.

Show comment
Hide comment
@gs-akhan

gs-akhan Sep 27, 2015

@rayshih Are all these files siblings to MainActivity.java file under com>project ??

Thanks

gs-akhan commented Sep 27, 2015

@rayshih Are all these files siblings to MainActivity.java file under com>project ??

Thanks

@gs-akhan

This comment has been minimized.

Show comment
Hide comment
@gs-akhan

gs-akhan Sep 27, 2015

@mkonicek
Hi, I had hard time getting my first Native module to work. The missing pieces in the docs were these. I have added a PR though. Thanks..
#3078

gs-akhan commented Sep 27, 2015

@mkonicek
Hi, I had hard time getting my first Native module to work. The missing pieces in the docs were these. I have added a PR though. Thanks..
#3078

@yanni858

This comment has been minimized.

Show comment
Hide comment
@yanni858

yanni858 Sep 29, 2015

I'm also having a hard time adding a native Android component, even though I'm getting closer thanks to this thread.
If there were just one complete working example checked in somewhere it would help tremendously. Ideally it would be something extremely simple, say exposing the native RadioButton to JS.

yanni858 commented Sep 29, 2015

I'm also having a hard time adding a native Android component, even though I'm getting closer thanks to this thread.
If there were just one complete working example checked in somewhere it would help tremendously. Ideally it would be something extremely simple, say exposing the native RadioButton to JS.

@kmagiera

This comment has been minimized.

Show comment
Hide comment
@kmagiera

kmagiera Oct 6, 2015

Contributor

Hey. Landed this 5623c83 couple of days ago, can you verify whether the issue still persists on master?

Contributor

kmagiera commented Oct 6, 2015

Hey. Landed this 5623c83 couple of days ago, can you verify whether the issue still persists on master?

@rayshih

This comment has been minimized.

Show comment
Hide comment
@rayshih

rayshih Oct 7, 2015

Thanks. I'll check that today.

rayshih commented Oct 7, 2015

Thanks. I'll check that today.

@zenlambda

This comment has been minimized.

Show comment
Hide comment
@zenlambda

zenlambda Oct 11, 2015

@kmagiera I'm still finding it necessary to use a dummy property on react-native 0.12.0.

@rayshih I was actually trying to do the same thing as you. This is my code, perhaps it will help you. I am still not happy about the button icon size, it is still too small. The material ui guide gives specific measurements (in dp) but I'm still confused on the relationship with react units (px?).

Component:

import android.support.design.widget.FloatingActionButton;
import android.support.v4.content.ContextCompat;
import android.widget.ImageView;
import com.facebook.react.common.ReactConstants;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.UIProp;
import com.facebook.react.uimanager.CatalystStylesDiffMap;
import com.facebook.react.views.image.ImageResizeMode;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.ViewProps;
import javax.annotation.Nullable;

public class FloatingActionButtonManager extends SimpleViewManager<FloatingActionButton> {

    @UIProp(UIProp.Type.STRING)
    public static final String PROP_TEXT_INPUT_TEXT = "text"; // dummy prop

    public static final String REACT_CLASS = "MyFloatingActionButton";

    private final @Nullable Object mCallerContext;

    public FloatingActionButtonManager(
        Object callerContext) {
        mCallerContext = callerContext;
    }

    public FloatingActionButtonManager() {
        mCallerContext = null;
    }

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

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

    @Override
    public void updateView(final FloatingActionButton view,
            final CatalystStylesDiffMap props) {
        view.setImageDrawable(
            ContextCompat.getDrawable(view.getContext(), R.drawable.ic_add));
        view.setImageTintList(
            ContextCompat.getColorStateList(view.getContext(), android.R.color.white));
        view.setScaleType(ImageView.ScaleType.CENTER);
        super.updateView(view, props);
    }

}

Package:

class FabReactPackage implements ReactPackage {

    @Override
    public List<NativeModule> createNativeModules(
        ReactApplicationContext reactContext) {

        List<NativeModule> modules = new ArrayList<>();

        modules.add(new ToastModule(reactContext));

        return modules;
    }

    @Override
    public List<ViewManager> createViewManagers(
            ReactApplicationContext reactContext) {
        return Arrays.<ViewManager>asList(
            new ReactImageManager(),
            new FloatingActionButtonManager()
        );
    }

    @Override
    public List<Class<? extends JavaScriptModule>> createJSModules() {
      return Collections.emptyList();
    }
}

Main Activity:

public class MainActivity extends Activity implements DefaultHardwareBackBtnHandler {

    private ReactInstanceManager mReactInstanceManager;
    private ReactRootView mReactRootView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mReactRootView = new ReactRootView(this);
        mReactInstanceManager = ReactInstanceManager.builder()
                .setApplication(getApplication())
                .setBundleAssetName("index.android.bundle")
                .setJSMainModuleName("index.android")
                .addPackage(new MainReactPackage())
                .addPackage(new FabReactPackage()) // <--- add fab package here
                .setUseDeveloperSupport(BuildConfig.DEBUG)
                .setInitialLifecycleState(LifecycleState.RESUMED)
                .build();

        mReactRootView.startReactApplication(mReactInstanceManager, "FabApp", null);

        setContentView(mReactRootView);
    }

// the rest of your activity methods

JS component module

var { PropTypes, requireNativeComponent } = require('react-native');

var iface = {
    name: 'MyFloatingActionButton',
    propTypes: {
        text: PropTypes.string
    }
}

module.exports = requireNativeComponent('MyFloatingActionButton', iface);

Usage

var FloatingActionButton = require('./components/FloatingActionButton');

renderFloatingButton() {
  return (
    <FloatingActionButton
      style={
        {
          position: 'absolute', bottom: 25, right: 25,
          width:56, height:56
        }
      }
      text="foo"/>
  );
},

Edit: Here's a picture of the component! :-)
floatingactionbutton

zenlambda commented Oct 11, 2015

@kmagiera I'm still finding it necessary to use a dummy property on react-native 0.12.0.

@rayshih I was actually trying to do the same thing as you. This is my code, perhaps it will help you. I am still not happy about the button icon size, it is still too small. The material ui guide gives specific measurements (in dp) but I'm still confused on the relationship with react units (px?).

Component:

import android.support.design.widget.FloatingActionButton;
import android.support.v4.content.ContextCompat;
import android.widget.ImageView;
import com.facebook.react.common.ReactConstants;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.UIProp;
import com.facebook.react.uimanager.CatalystStylesDiffMap;
import com.facebook.react.views.image.ImageResizeMode;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.ViewProps;
import javax.annotation.Nullable;

public class FloatingActionButtonManager extends SimpleViewManager<FloatingActionButton> {

    @UIProp(UIProp.Type.STRING)
    public static final String PROP_TEXT_INPUT_TEXT = "text"; // dummy prop

    public static final String REACT_CLASS = "MyFloatingActionButton";

    private final @Nullable Object mCallerContext;

    public FloatingActionButtonManager(
        Object callerContext) {
        mCallerContext = callerContext;
    }

    public FloatingActionButtonManager() {
        mCallerContext = null;
    }

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

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

    @Override
    public void updateView(final FloatingActionButton view,
            final CatalystStylesDiffMap props) {
        view.setImageDrawable(
            ContextCompat.getDrawable(view.getContext(), R.drawable.ic_add));
        view.setImageTintList(
            ContextCompat.getColorStateList(view.getContext(), android.R.color.white));
        view.setScaleType(ImageView.ScaleType.CENTER);
        super.updateView(view, props);
    }

}

Package:

class FabReactPackage implements ReactPackage {

    @Override
    public List<NativeModule> createNativeModules(
        ReactApplicationContext reactContext) {

        List<NativeModule> modules = new ArrayList<>();

        modules.add(new ToastModule(reactContext));

        return modules;
    }

    @Override
    public List<ViewManager> createViewManagers(
            ReactApplicationContext reactContext) {
        return Arrays.<ViewManager>asList(
            new ReactImageManager(),
            new FloatingActionButtonManager()
        );
    }

    @Override
    public List<Class<? extends JavaScriptModule>> createJSModules() {
      return Collections.emptyList();
    }
}

Main Activity:

public class MainActivity extends Activity implements DefaultHardwareBackBtnHandler {

    private ReactInstanceManager mReactInstanceManager;
    private ReactRootView mReactRootView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mReactRootView = new ReactRootView(this);
        mReactInstanceManager = ReactInstanceManager.builder()
                .setApplication(getApplication())
                .setBundleAssetName("index.android.bundle")
                .setJSMainModuleName("index.android")
                .addPackage(new MainReactPackage())
                .addPackage(new FabReactPackage()) // <--- add fab package here
                .setUseDeveloperSupport(BuildConfig.DEBUG)
                .setInitialLifecycleState(LifecycleState.RESUMED)
                .build();

        mReactRootView.startReactApplication(mReactInstanceManager, "FabApp", null);

        setContentView(mReactRootView);
    }

// the rest of your activity methods

JS component module

var { PropTypes, requireNativeComponent } = require('react-native');

var iface = {
    name: 'MyFloatingActionButton',
    propTypes: {
        text: PropTypes.string
    }
}

module.exports = requireNativeComponent('MyFloatingActionButton', iface);

Usage

var FloatingActionButton = require('./components/FloatingActionButton');

renderFloatingButton() {
  return (
    <FloatingActionButton
      style={
        {
          position: 'absolute', bottom: 25, right: 25,
          width:56, height:56
        }
      }
      text="foo"/>
  );
},

Edit: Here's a picture of the component! :-)
floatingactionbutton

@rayshih

This comment has been minimized.

Show comment
Hide comment
@rayshih

rayshih Oct 14, 2015

wow thx for the code snippet.

rayshih commented Oct 14, 2015

wow thx for the code snippet.

@mkonicek

This comment has been minimized.

Show comment
Hide comment
@mkonicek

mkonicek Mar 16, 2016

Contributor

Hi there! This issue is being closed because it has been inactive for a while.

But don't worry, it will live on with ProductPains! Check out its new home: https://productpains.com/post/react-native/androidnative-ui-couldnt-make-self-implemented-android-native-ui-work

ProductPains helps the community prioritize the most important issues thanks to its voting feature.
It is easy to use - just login with GitHub.

Also, if this issue is a bug, please consider sending a PR with a fix. We rely on the community to provide
bugfixes as the core team is focused on performance.

Contributor

mkonicek commented Mar 16, 2016

Hi there! This issue is being closed because it has been inactive for a while.

But don't worry, it will live on with ProductPains! Check out its new home: https://productpains.com/post/react-native/androidnative-ui-couldnt-make-self-implemented-android-native-ui-work

ProductPains helps the community prioritize the most important issues thanks to its voting feature.
It is easy to use - just login with GitHub.

Also, if this issue is a bug, please consider sending a PR with a fix. We rely on the community to provide
bugfixes as the core team is focused on performance.

@mkonicek mkonicek added the Icebox label Mar 16, 2016

@mkonicek mkonicek closed this Mar 16, 2016

@facebook facebook locked as resolved and limited conversation to collaborators Jul 21, 2018

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.