Created
July 30, 2016 01:57
-
-
Save maolion/f10cea541c496ab66d273e11556d455a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.maornandroidkit.kits.widgets; | |
| import android.content.Context; | |
| import android.support.annotation.IntDef; | |
| import android.support.annotation.Nullable; | |
| import android.view.LayoutInflater; | |
| import android.view.MotionEvent; | |
| import android.view.SoundEffectConstants; | |
| import android.view.View; | |
| import android.widget.LinearLayout; | |
| import com.facebook.react.bridge.Arguments; | |
| import com.facebook.react.bridge.ReactContext; | |
| import com.facebook.react.bridge.WritableMap; | |
| import com.facebook.react.common.MapBuilder; | |
| import com.facebook.react.common.SystemClock; | |
| import com.facebook.react.uimanager.ThemedReactContext; | |
| import com.facebook.react.uimanager.UIManagerModule; | |
| import com.facebook.react.uimanager.ViewGroupManager; | |
| import com.facebook.react.uimanager.annotations.ReactProp; | |
| import com.facebook.react.uimanager.events.Event; | |
| import com.facebook.react.uimanager.events.RCTEventEmitter; | |
| import com.maornandroidkit.kits.R; | |
| import java.util.Map; | |
| import java.util.zip.Inflater; | |
| public class ClickableManager extends ViewGroupManager<LinearLayout> { | |
| public static final String NAME = "MaoKitsClickableAndroid"; | |
| private static final int TAP_TIMEOUT = 300; | |
| private static final int LONG_PRESS_TIMEOUT = 1000; | |
| private LinearLayout view; | |
| private ReactContext context; | |
| private boolean disabled; | |
| private long actionDownStartAt; | |
| public String getName() { | |
| return ClickableManager.NAME; | |
| } | |
| @Override | |
| public LinearLayout createViewInstance(ThemedReactContext reactContext) { | |
| //this.view = new LinearLayout(reactContext); | |
| this.view = (LinearLayout) LayoutInflater.from((Context) reactContext).inflate(R.layout.clickable, null); | |
| this.context = (ReactContext) reactContext; | |
| this.view.setClickable(true); | |
| this.view.setLayoutParams(new LinearLayout.LayoutParams( | |
| LinearLayout.LayoutParams.WRAP_CONTENT, | |
| LinearLayout.LayoutParams.WRAP_CONTENT | |
| )); | |
| this.initTouchableListener(); | |
| return this.view; | |
| } | |
| @ReactProp(name = "disabled") | |
| public void setDisabled(LinearLayout view, boolean disabled) { | |
| this.view.setEnabled(disabled); | |
| for (int i = 0, l = this.view.getChildCount(); i < l; i++) { | |
| View childView = (View) this.view.getChildAt(i); | |
| childView.setEnabled(disabled); | |
| childView.setAlpha(0.6F); | |
| } | |
| } | |
| private void initTouchableListener() { | |
| final ClickableManager _this = this; | |
| this.view.setOnTouchListener(new View.OnTouchListener() { | |
| @Override | |
| public boolean onTouch(View v, MotionEvent event) { | |
| int viewId = _this.view.getId(); | |
| switch (event.getAction()) { | |
| case MotionEvent.ACTION_DOWN: | |
| _this.actionDownStartAt = event.getEventTime(); | |
| _this.dispatchEvent( | |
| new ClickableEvent(viewId, ClickableEvent.ON_PRESS_IN) | |
| ); | |
| break; | |
| case MotionEvent.ACTION_UP: | |
| final long diffTimeStamp = event.getEventTime() - _this.actionDownStartAt; | |
| _this.view.playSoundEffect(SoundEffectConstants.CLICK); | |
| _this.dispatchEvent( | |
| new ClickableEvent(viewId, ClickableEvent.ON_PRESS_OUT) | |
| ); | |
| if (diffTimeStamp >= ClickableManager.LONG_PRESS_TIMEOUT) { | |
| _this.dispatchEvent( | |
| new ClickableEvent(viewId, ClickableEvent.ON_LONG_PRESS) | |
| ); | |
| } else if (diffTimeStamp <= ClickableManager.TAP_TIMEOUT) { | |
| _this.dispatchEvent( | |
| new ClickableEvent(viewId, ClickableEvent.ON_PRESS) | |
| ); | |
| _this.dispatchEvent( | |
| new ClickableEvent(viewId, ClickableEvent.ON_TAP) | |
| ); | |
| } else { | |
| _this.dispatchEvent( | |
| new ClickableEvent(viewId, ClickableEvent.ON_PRESS) | |
| ); | |
| } | |
| break; | |
| } | |
| return true; | |
| } | |
| }); | |
| } | |
| public boolean needsCustomLayoutForChildren() { | |
| return true; | |
| } | |
| @Override | |
| public @Nullable Map getExportedCustomDirectEventTypeConstants() { | |
| return MapBuilder.of( | |
| ClickableEvent.getEventNameForType(ClickableEvent.ON_TAP), | |
| MapBuilder.of("registrationName", "onTap"), | |
| ClickableEvent.getEventNameForType(ClickableEvent.ON_LONG_PRESS), | |
| MapBuilder.of("registrationName", "onLongPress"), | |
| ClickableEvent.getEventNameForType(ClickableEvent.ON_PRESS), | |
| MapBuilder.of("registrationName", "onPress"), | |
| ClickableEvent.getEventNameForType(ClickableEvent.ON_PRESS_IN), | |
| MapBuilder.of("registrationName", "onPressIn"), | |
| ClickableEvent.getEventNameForType(ClickableEvent.ON_PRESS_OUT), | |
| MapBuilder.of("registrationName", "onPressOut") | |
| ); | |
| } | |
| private void dispatchEvent(Event event) { | |
| this.context.getNativeModule(UIManagerModule.class) | |
| .getEventDispatcher() | |
| .dispatchEvent( | |
| event | |
| ); | |
| } | |
| } | |
| class ClickableEvent extends Event<ClickableEvent> { | |
| @IntDef({ ON_PRESS, ON_PRESS_IN, ON_PRESS_OUT, ON_LONG_PRESS, ON_TAP}) | |
| @interface ClickableEventType {} | |
| public static final int ON_PRESS = 1; | |
| public static final int ON_PRESS_IN = 2; | |
| public static final int ON_PRESS_OUT = 3; | |
| public static final int ON_LONG_PRESS = 4; | |
| public static final int ON_TAP = 5; | |
| private static final String ON_S_PRESS = "topPress"; | |
| private static final String ON_S_PRESS_IN = "topPressIn"; | |
| private static final String ON_S_PRESS_OUT = "topPressOut"; | |
| private static final String ON_S_LONG_PRESS = "topLongPress"; | |
| private static final String ON_S_TAP = "topTap"; | |
| private int eventType; | |
| public static String getEventNameForType(@ClickableEventType int eventType) { | |
| switch (eventType) { | |
| case ClickableEvent.ON_PRESS: | |
| return ClickableEvent.ON_S_PRESS; | |
| case ClickableEvent.ON_PRESS_IN: | |
| return ClickableEvent.ON_S_PRESS_IN; | |
| case ClickableEvent.ON_LONG_PRESS: | |
| return ClickableEvent.ON_S_LONG_PRESS; | |
| case ClickableEvent.ON_PRESS_OUT: | |
| return ClickableEvent.ON_S_PRESS_OUT; | |
| case ClickableEvent.ON_TAP: | |
| return ClickableEvent.ON_S_TAP; | |
| default: | |
| throw new IllegalStateException("Invalid Clickable event:" + Integer.toString(eventType)); | |
| } | |
| } | |
| public ClickableEvent( | |
| int viewId, | |
| @ClickableEventType int eventType | |
| ) { | |
| super(viewId, SystemClock.currentTimeMillis()); | |
| this.eventType = eventType; | |
| } | |
| @Override | |
| public String getEventName() { | |
| return ClickableEvent.getEventNameForType(this.eventType); | |
| } | |
| @Override | |
| public short getCoalescingKey() { | |
| return (short)this.eventType; | |
| } | |
| @Override | |
| public void dispatch(RCTEventEmitter rctEventEmitter) { | |
| WritableMap eventData = Arguments.createMap(); | |
| eventData.putDouble("timeStamp", this.getTimestampMs()); | |
| rctEventEmitter.receiveEvent(this.getViewTag(), this.getEventName(), eventData); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment