Skip to content

Instantly share code, notes, and snippets.

@maolion
Created July 30, 2016 01:57
Show Gist options
  • Select an option

  • Save maolion/f10cea541c496ab66d273e11556d455a to your computer and use it in GitHub Desktop.

Select an option

Save maolion/f10cea541c496ab66d273e11556d455a to your computer and use it in GitHub Desktop.
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