Release React Native for Android

This is an early release and there are several things that are known
not to work if you're porting your iOS app to Android.

See the Known Issues guide on the website.

We will work with the community to reach platform parity with iOS.
This commit is contained in:
Martin Konicek
2015-09-14 15:35:58 +01:00
parent c372dab213
commit 42eb5464fd
571 changed files with 44550 additions and 116 deletions

View File

@@ -0,0 +1,45 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.react.views.switchviewview;
import android.content.Context;
import android.support.v7.widget.SwitchCompat;
import android.widget.Switch;
/**
* Switch that has its value controlled by JS. Whenever the value of the switch changes, we do not
* allow any other changes to that switch until JS sets a value explicitly. This stops the Switch
* from changing its value multiple times, when those changes have not been processed by JS first.
*/
/*package*/ class ReactSwitch extends SwitchCompat {
private boolean mAllowChange;
public ReactSwitch(Context context) {
super(context);
mAllowChange = true;
}
@Override
public void setChecked(boolean checked) {
if (mAllowChange) {
mAllowChange = false;
super.setChecked(checked);
}
}
/*package*/ void setOn(boolean on) {
// If the switch has a different value than the value sent by JS, we must change it.
if (isChecked() != on) {
super.setChecked(on);
}
mAllowChange = true;
}
}

View File

@@ -0,0 +1,57 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.react.views.switchviewview;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.uimanager.events.Event;
import com.facebook.react.uimanager.events.RCTEventEmitter;
/**
* Event emitted by a ReactSwitchManager once a switch is fully switched on/off
*/
/*package*/ class ReactSwitchEvent extends Event<ReactSwitchEvent> {
public static final String EVENT_NAME = "topChange";
private final boolean mIsChecked;
public ReactSwitchEvent(int viewId, long timestampMs, boolean isChecked) {
super(viewId, timestampMs);
mIsChecked = isChecked;
}
public boolean getIsChecked() {
return mIsChecked;
}
@Override
public String getEventName() {
return EVENT_NAME;
}
@Override
public short getCoalescingKey() {
// All switch events for a given view can be coalesced.
return 0;
}
@Override
public void dispatch(RCTEventEmitter rctEventEmitter) {
rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData());
}
private WritableMap serializeEventData() {
WritableMap eventData = Arguments.createMap();
eventData.putInt("target", getViewTag());
eventData.putBoolean("value", getIsChecked());
return eventData;
}
}

View File

@@ -0,0 +1,119 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
// switchview because switch is a keyword
package com.facebook.react.views.switchviewview;
import android.os.SystemClock;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import com.facebook.csslayout.CSSNode;
import com.facebook.csslayout.MeasureOutput;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.uimanager.CatalystStylesDiffMap;
import com.facebook.react.uimanager.ReactShadowNode;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.UIProp;
import com.facebook.react.uimanager.ViewProps;
/**
* View manager for {@link ReactSwitch} components.
*/
public class ReactSwitchManager extends SimpleViewManager<ReactSwitch> {
private static final String REACT_CLASS = "AndroidSwitch";
@UIProp(UIProp.Type.BOOLEAN) public static final String PROP_ENABLED = ViewProps.ENABLED;
@UIProp(UIProp.Type.BOOLEAN) public static final String PROP_ON = ViewProps.ON;
private static class ReactSwitchShadowNode extends ReactShadowNode implements
CSSNode.MeasureFunction {
private int mWidth;
private int mHeight;
private boolean mMeasured;
private ReactSwitchShadowNode() {
setMeasureFunction(this);
}
@Override
public void measure(CSSNode node, float width, MeasureOutput measureOutput) {
if (!mMeasured) {
// Create a switch with the default config and measure it; since we don't (currently)
// support setting custom switch text, this is fine, as all switches will measure the same
// on a specific device/theme/locale combination.
ReactSwitch reactSwitch = new ReactSwitch(getThemedContext());
final int spec = View.MeasureSpec.makeMeasureSpec(
ViewGroup.LayoutParams.WRAP_CONTENT,
View.MeasureSpec.UNSPECIFIED);
reactSwitch.measure(spec, spec);
mWidth = reactSwitch.getMeasuredWidth();
mHeight = reactSwitch.getMeasuredHeight();
mMeasured = true;
}
measureOutput.width = mWidth;
measureOutput.height = mHeight;
}
}
private static final CompoundButton.OnCheckedChangeListener ON_CHECKED_CHANGE_LISTENER =
new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
ReactContext reactContext = (ReactContext) buttonView.getContext();
reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher().dispatchEvent(
new ReactSwitchEvent(
buttonView.getId(),
SystemClock.uptimeMillis(),
isChecked));
}
};
@Override
public String getName() {
return REACT_CLASS;
}
@Override
public ReactShadowNode createCSSNodeInstance() {
return new ReactSwitchShadowNode();
}
@Override
protected ReactSwitch createViewInstance(ThemedReactContext context) {
ReactSwitch view = new ReactSwitch(context);
view.setShowText(false);
return view;
}
@Override
public void updateView(ReactSwitch view, CatalystStylesDiffMap props) {
super.updateView(view, props);
if (props.hasKey(PROP_ENABLED)) {
view.setEnabled(props.getBoolean(PROP_ENABLED, true));
}
if (props.hasKey(PROP_ON)) {
// we set the checked change listener to null and then restore it so that we don't fire an
// onChange event to JS when JS itself is updating the value of the switch
view.setOnCheckedChangeListener(null);
view.setOn(props.getBoolean(PROP_ON, false));
view.setOnCheckedChangeListener(ON_CHECKED_CHANGE_LISTENER);
}
}
@Override
protected void addEventEmitters(final ThemedReactContext reactContext, final ReactSwitch view) {
view.setOnCheckedChangeListener(ON_CHECKED_CHANGE_LISTENER);
}
}