Android: Add support for custom-button on-press JS callback + refactoring and cleanup

This commit is contained in:
Amit Davidi 2017-02-28 15:00:21 +02:00
parent 11c77b5aa1
commit fd901d3bbe
6 changed files with 169 additions and 165 deletions

View File

@ -9,6 +9,9 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.uimanager.UIManagerModule;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -23,6 +26,24 @@ public class GalleryAdapter extends RecyclerView.Adapter<GalleryAdapter.AbsViewH
private static int VIEW_TYPE_IMAGE = 0;
private static int VIEW_TYPE_TAKE_PICTURE = 1;
public static final String[] PROJECTION = new String[]{
MediaStore.Images.Media.DATA,
MediaStore.Images.Media._ID,
MediaStore.Images.Media.MIME_TYPE
};
private class Image {
String uri;
Integer id;
String mimeType;
public Image(String uri, Integer id, String mimeType) {
this.uri = uri;
this.id = id;
this.mimeType = mimeType;
}
}
abstract class AbsViewHolder extends RecyclerView.ViewHolder {
AbsViewHolder(View itemView) {
super(itemView);
@ -50,14 +71,14 @@ public class GalleryAdapter extends RecyclerView.Adapter<GalleryAdapter.AbsViewH
final SelectableImage selectableImageView = (SelectableImage) this.itemView;
selectableImageView.setUnsupportedUIParams(overlayColor, unsupportedFinalImage, unsupportedText, unsupportedTextColor);
selectableImageView.setDrawables(selectedDrawable, unselectedDrawable);
selectableImageView.bind(executor, selected, forceBind, image.id, this.isSupported);
selectableImageView.bind(executor, selected, forceBind, image.id, isSupported);
selectableImageView.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (this.isSupported) {
view.onTapImage(this.image.uri);
if (isSupported) {
onTapImage(image.uri);
v.setSelected(!v.isSelected());
}
}
@ -92,19 +113,27 @@ public class GalleryAdapter extends RecyclerView.Adapter<GalleryAdapter.AbsViewH
}
}
class OpenCameraButtonHolder extends AbsViewHolder {
class OpenCameraButtonHolder extends AbsViewHolder implements View.OnClickListener {
OpenCameraButtonHolder() {
super(new ImageView(GalleryAdapter.this.view.getContext()));
final ImageView imageView = (ImageView) this.itemView;
imageView.setScaleType(ImageView.ScaleType.CENTER);
imageView.setOnClickListener(this);
}
@Override
public void bind(int position) {
ImageView imageView = (ImageView) this.itemView;
final ImageView imageView = (ImageView) this.itemView;
imageView.setImageDrawable(GalleryAdapter.this.customButtonImage);
imageView.setScaleType(ImageView.ScaleType.CENTER);
imageView.setBackgroundColor(Color.parseColor(GalleryAdapter.this.customButtonBackgroundColor));
}
@Override
public void onClick(View v) {
onTapCustomButton();
}
}
private String overlayColor;
@ -112,35 +141,30 @@ public class GalleryAdapter extends RecyclerView.Adapter<GalleryAdapter.AbsViewH
private String unsupportedText;
private String unsupportedTextColor;
private List<String> dirtyUris = new ArrayList<>();
private Drawable customButtonImage;
private String customButtonBackgroundColor = DEFAULT_CUSTOM_BUTTON_BACKGROUND_COLOR;
private class Image {
String uri;
Integer id;
String mimeType;
public Image(String uri, Integer id, String mimeType) {
this.uri = uri;
this.id = id;
this.mimeType = mimeType;
}
}
public static final String[] PROJECTION = new String[]{
MediaStore.Images.Media.DATA,
MediaStore.Images.Media._ID,
MediaStore.Images.Media.MIME_TYPE
};
private ArrayList<Image> images = new ArrayList<>();
private ArrayList<String> selectedUris = new ArrayList<>();
private ArrayList<String> supportedFileTypes = new ArrayList<>();
private String albumName = "";
private Drawable selectedDrawable;
private Drawable unselectedDrawable;
private Drawable customButtonImage;
private String customButtonBackgroundColor = DEFAULT_CUSTOM_BUTTON_BACKGROUND_COLOR;
private ArrayList<Image> images = new ArrayList<>();
private boolean refreshing = false;
private GalleryView view;
private ThreadPoolExecutor executor;
public GalleryAdapter(GalleryView view) {
this.view = view;
setHasStableIds(true);
int cores = Runtime.getRuntime().availableProcessors();
executor = new ThreadPoolExecutor(cores, cores, 1, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>());
setAlbum(albumName);
}
public void setAlbum(String albumName) {
this.albumName = albumName;
}
public void setSelectedUris(ArrayList<String> selectedUris) {
this.selectedUris = selectedUris;
@ -162,6 +186,13 @@ public class GalleryAdapter extends RecyclerView.Adapter<GalleryAdapter.AbsViewH
this.supportedFileTypes = supportedFileTypes;
}
public void setUnsupportedUIParams(String overlayColor, Drawable unsupportedFinalImage, String unsupportedText, String unsupportedTextColor) {
this.overlayColor = overlayColor;
this.unsupportedFinalImage = unsupportedFinalImage;
this.unsupportedText = unsupportedText;
this.unsupportedTextColor = unsupportedTextColor;
}
public void setCustomButtonImage(Drawable customButtonImage) {
this.customButtonImage = customButtonImage;
}
@ -170,21 +201,6 @@ public class GalleryAdapter extends RecyclerView.Adapter<GalleryAdapter.AbsViewH
this.customButtonBackgroundColor = color;
}
private GalleryView view;
private ThreadPoolExecutor executor;
public GalleryAdapter(GalleryView context) {
this.view = context;
setHasStableIds(true);
int cores = Runtime.getRuntime().availableProcessors();
executor = new ThreadPoolExecutor(cores, cores, 1, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>());
setAlbum(albumName);
}
public void setAlbum(String albumName) {
this.albumName = albumName;
}
@Override
public int getItemViewType(int position) {
if (shouldShowCustomButton() && position == 0) {
@ -265,14 +281,6 @@ public class GalleryAdapter extends RecyclerView.Adapter<GalleryAdapter.AbsViewH
});
}
public void setUnsupportedUIParams(String overlayColor, Drawable unsupportedFinalImage, String unsupportedText, String unsupportedTextColor) {
this.overlayColor = overlayColor;
this.unsupportedFinalImage = unsupportedFinalImage;
this.unsupportedText = unsupportedText;
this.unsupportedTextColor = unsupportedTextColor;
}
@Override
public AbsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == VIEW_TYPE_IMAGE) {
@ -307,4 +315,18 @@ public class GalleryAdapter extends RecyclerView.Adapter<GalleryAdapter.AbsViewH
private boolean shouldShowCustomButton() {
return customButtonImage != null;
}
public void onTapImage(String uri) {
final ReactContext reactContext = ((ReactContext) view.getContext());
reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher().dispatchEvent(new TapImageEvent(getRootViewId(), uri));
}
public void onTapCustomButton() {
final ReactContext reactContext = ((ReactContext) view.getContext());
reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher().dispatchEvent(new TapCustomButtonEvent(getRootViewId()));
}
private int getRootViewId() {
return view.getId();
}
}

View File

@ -2,21 +2,11 @@ package com.wix.RNCameraKit.gallery;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.events.Event;
import com.facebook.react.uimanager.events.RCTEventEmitter;
import java.util.ArrayList;
public class GalleryView extends RecyclerView {
private class GridLayoutViewManagerWrapper extends GridLayoutManager {
@ -35,15 +25,12 @@ public class GalleryView extends RecyclerView {
}
}
private GalleryAdapter adapter;
private int itemSpacing;
private int lineSpacing;
public GalleryView(Context context) {
super(context);
setHasFixedSize(true);
adapter = new GalleryAdapter(this);
setAdapter(adapter);
getRecycledViewPool().setMaxRecycledViews(0, 20);
}
@ -59,10 +46,6 @@ public class GalleryView extends RecyclerView {
});
}
public void setAlbumName(String albumName) {
adapter.setAlbum(albumName);
}
public void setItemSpacing(int itemSpacing) {
this.itemSpacing = itemSpacing;
updateDecorator();
@ -79,66 +62,4 @@ public class GalleryView extends RecyclerView {
setLayoutManager(layoutManager);
}
public void onTapImage(String uri) {
final ReactContext reactContext = ((ReactContext)getContext());
reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher().dispatchEvent(new TapImageEvent(uri));
}
public void setSelectedUris(ArrayList<String> selectedUris) {
adapter.setSelectedUris(selectedUris);
}
public void setDirtyImages(ArrayList<String> dirtyUris) {
adapter.setDirtyUris(dirtyUris);
}
public void setSelectedDrawable(Drawable drawable) {
adapter.setSelectedDrawable(drawable);
}
public void setUnselectedDrawable(Drawable drawable) {
adapter.setUnselectedDrawable(drawable);
}
public void setUnsupportedUIParams(String overlayColor, Drawable unsupportedFinalImage, String unsupportedText, String unsupportedTextColor) {
adapter.setUnsupportedUIParams(overlayColor, unsupportedFinalImage, unsupportedText, unsupportedTextColor);
}
public void setCustomButtonImage(Drawable customButtonImage) {
adapter.setCustomButtonImage(customButtonImage);
}
public void setCustomButtonBackgroundColor(String color) {
adapter.setCustomButtonBackgroundColor(color);
}
public void refresh() {
adapter.refreshData();
}
private class TapImageEvent extends Event<TapImageEvent> {
private WritableMap event;
TapImageEvent(String uri) {
event = Arguments.createMap();
event.putString("selected", uri);
event.putString("id", "onTapImage");
init(0);
}
@Override
public String getEventName() {
return "onTapImage";
}
@Override
public void dispatch(RCTEventEmitter rctEventEmitter) {
rctEventEmitter.receiveEvent(getId(), "onTapImage", event);
}
}
public void setSupportedFileTypes(ArrayList<String> supportedFileTypes) {
adapter.setSupportedFileTypes(supportedFileTypes);
}
}

View File

@ -24,7 +24,7 @@ public class GalleryViewManager extends SimpleViewManager<GalleryView> {
private final String UNSUPPORTED_TEXT_COLOR_KEY = "unsupportedTextColor";
private final String SUPPORTED_TYPES_KEY = "supportedFileTypes";
private final String UNSUPPORTED_OVERLAY_KEY = "unsupportedOverlayColor";
private final String CUSTOM_BUTTON_IMAGE_KEY = "customImage";
private final String CUSTOM_BUTTON_IMAGE_KEY = "image";
private final String CUSTOM_BUTTON_BCK_COLOR_KEY = "backgroundColor";
private ThemedReactContext reactContext;
@ -37,17 +37,15 @@ public class GalleryViewManager extends SimpleViewManager<GalleryView> {
@Override
protected GalleryView createViewInstance(ThemedReactContext reactContext) {
this.reactContext = reactContext;
return new GalleryView(reactContext);
GalleryView view = new GalleryView(reactContext);
view.setAdapter(new GalleryAdapter(view));
return view;
}
@Override
protected void onAfterUpdateTransaction(GalleryView view) {
view.refresh();
}
@ReactProp(name = "albumName")
public void setAlbumName(GalleryView view, String albumName) {
view.setAlbumName(albumName);
getViewAdapter(view).refreshData();
}
@ReactProp(name = "minimumInteritemSpacing")
@ -60,6 +58,11 @@ public class GalleryViewManager extends SimpleViewManager<GalleryView> {
view.setLineSpacing(lineSpacing/2);
}
@ReactProp(name = "albumName")
public void setAlbumName(GalleryView view, String albumName) {
getViewAdapter(view).setAlbum(albumName);
}
@ReactProp(name = "columnCount")
public void setColumnCount(GalleryView view, int columnCount) {
view.setColumnCount(columnCount);
@ -67,12 +70,12 @@ public class GalleryViewManager extends SimpleViewManager<GalleryView> {
@ReactProp(name = "selectedImages")
public void setSelectedUris(GalleryView view, ReadableArray uris) {
view.setSelectedUris(readableArrayToList(uris));
getViewAdapter(view).setSelectedUris(readableArrayToList(uris));
}
@ReactProp(name = "dirtyImages")
public void setDirtyImages(GalleryView view, final ReadableArray uris) {
view.setDirtyImages(readableArrayToList(uris));
getViewAdapter(view).setDirtyUris(readableArrayToList(uris));
}
@ReactProp(name = "selectedImageIcon")
@ -84,7 +87,7 @@ public class GalleryViewManager extends SimpleViewManager<GalleryView> {
reactContext.runOnUiQueueThread(new Runnable() {
@Override
public void run() {
view.setSelectedDrawable(drawable);
getViewAdapter(view).setSelectedDrawable(drawable);
}
});
}
@ -100,21 +103,13 @@ public class GalleryViewManager extends SimpleViewManager<GalleryView> {
reactContext.runOnUiQueueThread(new Runnable() {
@Override
public void run() {
view.setUnselectedDrawable(drawable);
getViewAdapter(view).setUnselectedDrawable(drawable);
}
});
}
}).start();
}
// fileTypeSupport={{
// supportedFileTypes: ['image/jpeg', 'image/png'],
// unsupportedOverlayColor: "#00000055",
// unsupportedImage: require('./images/unsupportedImage.png'),
// unsupportedText: 'Unsupported',
// unsupportedTextColor: '#ffffff'
// }}
@ReactProp(name = "fileTypeSupport")
public void setFileTypeSupport(final GalleryView view, final ReadableMap fileTypeSupport) {
final ReadableArray supportedFileTypes = fileTypeSupport.getArray(SUPPORTED_TYPES_KEY);
@ -141,19 +136,20 @@ public class GalleryViewManager extends SimpleViewManager<GalleryView> {
reactContext.runOnUiQueueThread(new Runnable() {
@Override
public void run() {
view.setUnsupportedUIParams(
unsupportedOverlayColor,
unsupportedFinalImage,
unsupportedText,
unsupportedTextColor);
view.setSupportedFileTypes(supportedFileTypesList);
getViewAdapter(view)
.setUnsupportedUIParams(
unsupportedOverlayColor,
unsupportedFinalImage,
unsupportedText,
unsupportedTextColor);
getViewAdapter(view).setSupportedFileTypes(supportedFileTypesList);
}
});
}
}).start();
}
@ReactProp(name = "customButton")
@ReactProp(name = "customButtonStyle")
public void setCustomButton(final GalleryView view, final ReadableMap props) {
new Thread(new Runnable() {
@Override
@ -164,9 +160,9 @@ public class GalleryViewManager extends SimpleViewManager<GalleryView> {
reactContext.runOnUiQueueThread(new Runnable() {
@Override
public void run() {
view.setCustomButtonImage(drawable);
getViewAdapter(view).setCustomButtonImage(drawable);
if (backgroundColor != null) {
view.setCustomButtonBackgroundColor(backgroundColor);
getViewAdapter(view).setCustomButtonBackgroundColor(backgroundColor);
}
}
});
@ -179,6 +175,7 @@ public class GalleryViewManager extends SimpleViewManager<GalleryView> {
public Map getExportedCustomDirectEventTypeConstants() {
return MapBuilder.builder()
.put("onTapImage", MapBuilder.of("registrationName", "onTapImage"))
.put("onCustomButtonPress", MapBuilder.of("registrationName", "onCustomButtonPress"))
.build();
}
@ -189,14 +186,14 @@ public class GalleryViewManager extends SimpleViewManager<GalleryView> {
}
@Override
public void receiveCommand(GalleryView root, int commandId, @Nullable ReadableArray args) {
public void receiveCommand(GalleryView view, int commandId, @Nullable ReadableArray args) {
if (commandId == COMMAND_REFRESH_GALLERY) {
root.refresh();
getViewAdapter(view).refreshData();
}
}
private @Nullable String getStringSafe(ReadableMap map, String key) {
if(map.hasKey(key)) {
if (map.hasKey(key)) {
return map.getString(key);
}
return null;
@ -209,4 +206,8 @@ public class GalleryViewManager extends SimpleViewManager<GalleryView> {
}
return list;
}
private GalleryAdapter getViewAdapter(GalleryView view) {
return ((GalleryAdapter) view.getAdapter());
}
}

View File

@ -0,0 +1,29 @@
package com.wix.RNCameraKit.gallery;
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;
public class TapCustomButtonEvent extends Event<TapCustomButtonEvent> {
private final int targetTag;
private WritableMap event;
TapCustomButtonEvent(int targetTag) {
this.targetTag = targetTag;
event = Arguments.createMap();
event.putString("id", "onCustomButtonPress");
init(0);
}
@Override
public String getEventName() {
return "onCustomButtonPress";
}
@Override
public void dispatch(RCTEventEmitter rctEventEmitter) {
rctEventEmitter.receiveEvent(targetTag, "onCustomButtonPress", event);
}
}

View File

@ -0,0 +1,31 @@
package com.wix.RNCameraKit.gallery;
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;
public class TapImageEvent extends Event<TapImageEvent> {
private final int targetTag;
private WritableMap event;
TapImageEvent(int targetTag, String uri) {
this.targetTag = targetTag;
event = Arguments.createMap();
event.putString("selected", uri);
event.putString("id", "onTapImage");
init(0);
}
@Override
public String getEventName() {
return "onTapImage";
}
@Override
public void dispatch(RCTEventEmitter rctEventEmitter) {
rctEventEmitter.receiveEvent(targetTag, "onTapImage", event);
}
}

View File

@ -32,8 +32,8 @@ export default class CameraKitGalleryView extends Component {
if (transformedProps.fileTypeSupport && transformedProps.fileTypeSupport.unsupportedImage) {
_.update(transformedProps, 'fileTypeSupport.unsupportedImage', (image) => resolveAssetSource(image).uri);
}
if (_.get(transformedProps, 'customButton.customImage')) {
_.update(transformedProps, 'customButton.customImage', (image) => resolveAssetSource(image).uri);
if (_.get(transformedProps, 'customButtonStyle.image')) {
_.update(transformedProps, 'customButtonStyle.image', (image) => resolveAssetSource(image).uri);
}
if (transformedProps.selectedImageIcon) {
transformedProps.selectedImageIcon = resolveAssetSource(transformedProps.selectedImageIcon).uri;