ReactSwitchManager.java

Created Diff never expires
0 removals
Lines
Total
Removed
Words
Total
Removed
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
231 lines
6 additions
Lines
Total
Added
Words
Total
Added
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
237 lines
/*
/*
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Facebook, Inc. and its affiliates.
*
*
* This source code is licensed under the MIT license found in the
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* LICENSE file in the root directory of this source tree.
*/
*/


// switchview because switch is a keyword
// switchview because switch is a keyword
package com.facebook.react.views.switchview;
package com.facebook.react.views.switchview;


import android.content.Context;
import android.content.Context;
import android.view.View;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.CompoundButton;
import androidx.annotation.NonNull;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Nullable;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.uimanager.LayoutShadowNode;
import com.facebook.react.uimanager.LayoutShadowNode;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.ViewManagerDelegate;
import com.facebook.react.uimanager.ViewManagerDelegate;
import com.facebook.react.uimanager.ViewProps;
import com.facebook.react.uimanager.ViewProps;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.viewmanagers.AndroidSwitchManagerDelegate;
import com.facebook.react.viewmanagers.AndroidSwitchManagerDelegate;
import com.facebook.react.viewmanagers.AndroidSwitchManagerInterface;
import com.facebook.react.viewmanagers.AndroidSwitchManagerInterface;
import com.facebook.yoga.YogaMeasureFunction;
import com.facebook.yoga.YogaMeasureFunction;
import com.facebook.yoga.YogaMeasureMode;
import com.facebook.yoga.YogaMeasureMode;
import com.facebook.yoga.YogaMeasureOutput;
import com.facebook.yoga.YogaMeasureOutput;
import com.facebook.yoga.YogaNode;
import com.facebook.yoga.YogaNode;


/** View manager for {@link ReactSwitch} components. */
/** View manager for {@link ReactSwitch} components. */
public class ReactSwitchManager extends SimpleViewManager<ReactSwitch>
public class ReactSwitchManager extends SimpleViewManager<ReactSwitch>
implements AndroidSwitchManagerInterface<ReactSwitch> {
implements AndroidSwitchManagerInterface<ReactSwitch> {


public static final String REACT_CLASS = "AndroidSwitch";
public static final String REACT_CLASS = "AndroidSwitch";


static class ReactSwitchShadowNode extends LayoutShadowNode implements YogaMeasureFunction {
static class ReactSwitchShadowNode extends LayoutShadowNode implements YogaMeasureFunction {


private int mWidth;
private int mWidth;
private int mHeight;
private int mHeight;
private boolean mMeasured;
private boolean mMeasured;


private ReactSwitchShadowNode() {
private ReactSwitchShadowNode() {
initMeasureFunction();
initMeasureFunction();
}
}


private void initMeasureFunction() {
private void initMeasureFunction() {
setMeasureFunction(this);
setMeasureFunction(this);
}
}


@Override
@Override
public long measure(
public long measure(
YogaNode node,
YogaNode node,
float width,
float width,
YogaMeasureMode widthMode,
YogaMeasureMode widthMode,
float height,
float height,
YogaMeasureMode heightMode) {
YogaMeasureMode heightMode) {
if (!mMeasured) {
if (!mMeasured) {
// Create a switch with the default config and measure it; since we don't (currently)
// 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
// support setting custom switch text, this is fine, as all switches will measure the same
// on a specific device/theme/locale combination.
// on a specific device/theme/locale combination.
ReactSwitch reactSwitch = new ReactSwitch(getThemedContext());
ReactSwitch reactSwitch = new ReactSwitch(getThemedContext());
reactSwitch.setShowText(false);
reactSwitch.setShowText(false);
final int spec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
final int spec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
reactSwitch.measure(spec, spec);
reactSwitch.measure(spec, spec);
mWidth = reactSwitch.getMeasuredWidth();
mWidth = reactSwitch.getMeasuredWidth();
mHeight = reactSwitch.getMeasuredHeight();
mHeight = reactSwitch.getMeasuredHeight();
mMeasured = true;
mMeasured = true;
}
}


return YogaMeasureOutput.make(mWidth, mHeight);
return YogaMeasureOutput.make(mWidth, mHeight);
}
}
}
}


private static final CompoundButton.OnCheckedChangeListener ON_CHECKED_CHANGE_LISTENER =
private static final CompoundButton.OnCheckedChangeListener ON_CHECKED_CHANGE_LISTENER =
new CompoundButton.OnCheckedChangeListener() {
new CompoundButton.OnCheckedChangeListener() {
@Override
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
ReactContext reactContext = (ReactContext) buttonView.getContext();
ReactContext reactContext = (ReactContext) buttonView.getContext();


UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class);
UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class);


if (uiManager == null) {
if (uiManager == null) {
return;
return;
}
}


uiManager
uiManager
.getEventDispatcher()
.getEventDispatcher()
.dispatchEvent(new ReactSwitchEvent(buttonView.getId(), isChecked));
.dispatchEvent(new ReactSwitchEvent(buttonView.getId(), isChecked));
}
}
};
};


private final ViewManagerDelegate<ReactSwitch> mDelegate;
private final ViewManagerDelegate<ReactSwitch> mDelegate;


public ReactSwitchManager() {
public ReactSwitchManager() {
mDelegate = new AndroidSwitchManagerDelegate<>(this);
mDelegate = new AndroidSwitchManagerDelegate<>(this);
}
}


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


@Override
@Override
public LayoutShadowNode createShadowNodeInstance() {
public LayoutShadowNode createShadowNodeInstance() {
return new ReactSwitchShadowNode();
return new ReactSwitchShadowNode();
}
}


@Override
@Override
public Class getShadowNodeClass() {
public Class getShadowNodeClass() {
return ReactSwitchShadowNode.class;
return ReactSwitchShadowNode.class;
}
}


@Override
@Override
protected ReactSwitch createViewInstance(ThemedReactContext context) {
protected ReactSwitch createViewInstance(ThemedReactContext context) {
ReactSwitch view = new ReactSwitch(context);
ReactSwitch view = new ReactSwitch(context);
view.setShowText(false);
view.setShowText(false);
return view;
return view;
}
}


@Override
@Override
@ReactProp(name = "disabled", defaultBoolean = false)
@ReactProp(name = "disabled", defaultBoolean = false)
public void setDisabled(ReactSwitch view, boolean disabled) {
public void setDisabled(ReactSwitch view, boolean disabled) {
view.setEnabled(!disabled);
view.setEnabled(!disabled);
}
}


@Override
@Override
@ReactProp(name = ViewProps.ENABLED, defaultBoolean = true)
@ReactProp(name = ViewProps.ENABLED, defaultBoolean = true)
public void setEnabled(ReactSwitch view, boolean enabled) {
public void setEnabled(ReactSwitch view, boolean enabled) {
view.setEnabled(enabled);
view.setEnabled(enabled);
}
}


@Override
@Override
@ReactProp(name = ViewProps.ON)
@ReactProp(name = ViewProps.ON)
public void setOn(ReactSwitch view, boolean on) {
public void setOn(ReactSwitch view, boolean on) {
setValueInternal(view, on);
setValueInternal(view, on);
}
}


@Override
@Override
@ReactProp(name = "value")
@ReactProp(name = "value")
public void setValue(ReactSwitch view, boolean value) {
public void setValue(ReactSwitch view, boolean value) {
setValueInternal(view, value);
setValueInternal(view, value);
}
}


@Override
@Override
@ReactProp(name = "thumbTintColor", customType = "Color")
@ReactProp(name = "thumbTintColor", customType = "Color")
public void setThumbTintColor(ReactSwitch view, @Nullable Integer color) {
public void setThumbTintColor(ReactSwitch view, @Nullable Integer color) {
this.setThumbColor(view, color);
this.setThumbColor(view, color);
}
}


@Override
@Override
@ReactProp(name = "thumbColor", customType = "Color")
@ReactProp(name = "thumbColor", customType = "Color")
public void setThumbColor(ReactSwitch view, @Nullable Integer color) {
public void setThumbColor(ReactSwitch view, @Nullable Integer color) {
view.setThumbColor(color);
view.setThumbColor(color);
}
}


@Override
@Override
@ReactProp(name = "trackColorForFalse", customType = "Color")
@ReactProp(name = "trackColorForFalse", customType = "Color")
public void setTrackColorForFalse(ReactSwitch view, @Nullable Integer color) {
public void setTrackColorForFalse(ReactSwitch view, @Nullable Integer color) {
view.setTrackColorForFalse(color);
view.setTrackColorForFalse(color);
}
}


@Override
@Override
@ReactProp(name = "trackColorForTrue", customType = "Color")
@ReactProp(name = "trackColorForTrue", customType = "Color")
public void setTrackColorForTrue(ReactSwitch view, @Nullable Integer color) {
public void setTrackColorForTrue(ReactSwitch view, @Nullable Integer color) {
view.setTrackColorForTrue(color);
view.setTrackColorForTrue(color);
}
}


@Override
@Override
@ReactProp(name = "trackTintColor", customType = "Color")
@ReactProp(name = "trackTintColor", customType = "Color")
public void setTrackTintColor(ReactSwitch view, @Nullable Integer color) {
public void setTrackTintColor(ReactSwitch view, @Nullable Integer color) {
view.setTrackColor(color);
view.setTrackColor(color);
}
}
@Override
@ReactProp(name = "width")
public void setWidth(ReactSwitch view, @Nullable float width) {
view.setWidth(width);
}


@Override
@Override
public void setNativeValue(ReactSwitch view, boolean value) {
public void setNativeValue(ReactSwitch view, boolean value) {
setValueInternal(view, value);
setValueInternal(view, value);
}
}


@Override
@Override
public void receiveCommand(
public void receiveCommand(
@NonNull ReactSwitch view, String commandId, @Nullable ReadableArray args) {
@NonNull ReactSwitch view, String commandId, @Nullable ReadableArray args) {
switch (commandId) {
switch (commandId) {
case "setNativeValue":
case "setNativeValue":
setValueInternal(view, args != null && args.getBoolean(0));
setValueInternal(view, args != null && args.getBoolean(0));
break;
break;
}
}
}
}


@Override
@Override
protected void addEventEmitters(final ThemedReactContext reactContext, final ReactSwitch view) {
protected void addEventEmitters(final ThemedReactContext reactContext, final ReactSwitch view) {
view.setOnCheckedChangeListener(ON_CHECKED_CHANGE_LISTENER);
view.setOnCheckedChangeListener(ON_CHECKED_CHANGE_LISTENER);
}
}


@Override
@Override
protected ViewManagerDelegate<ReactSwitch> getDelegate() {
protected ViewManagerDelegate<ReactSwitch> getDelegate() {
return mDelegate;
return mDelegate;
}
}


@Override
@Override
public long measure(
public long measure(
Context context,
Context context,
ReadableMap localData,
ReadableMap localData,
ReadableMap props,
ReadableMap props,
ReadableMap state,
ReadableMap state,
float width,
float width,
YogaMeasureMode widthMode,
YogaMeasureMode widthMode,
float height,
float height,
YogaMeasureMode heightMode,
YogaMeasureMode heightMode,
@Nullable float[] attachmentsPositions) {
@Nullable float[] attachmentsPositions) {
ReactSwitch view = new ReactSwitch(context);
ReactSwitch view = new ReactSwitch(context);
view.setShowText(false);
view.setShowText(false);
int measureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
int measureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
view.measure(measureSpec, measureSpec);
view.measure(measureSpec, measureSpec);
return YogaMeasureOutput.make(
return YogaMeasureOutput.make(
PixelUtil.toDIPFromPixel(view.getMeasuredWidth()),
PixelUtil.toDIPFromPixel(view.getMeasuredWidth()),
PixelUtil.toDIPFromPixel(view.getMeasuredHeight()));
PixelUtil.toDIPFromPixel(view.getMeasuredHeight()));
}
}


private static void setValueInternal(ReactSwitch view, boolean value) {
private static void setValueInternal(ReactSwitch view, boolean value) {
// we set the checked change listener to null and then restore it so that we don't fire an
// 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
// onChange event to JS when JS itself is updating the value of the switch
view.setOnCheckedChangeListener(null);
view.setOnCheckedChangeListener(null);
view.setOn(value);
view.setOn(value);
view.setOnCheckedChangeListener(ON_CHECKED_CHANGE_LISTENER);
view.setOnCheckedChangeListener(ON_CHECKED_CHANGE_LISTENER);
}
}
}
}