@phucprime/react-native-image-editor 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +247 -0
- package/android/build.gradle +62 -0
- package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +5 -0
- package/android/gradlew +240 -0
- package/android/gradlew.bat +91 -0
- package/android/libs/photo-editor-android.jar +0 -0
- package/android/src/main/AndroidManifest.xml +5 -0
- package/android/src/main/java/com/ahmedadeltito/photoeditor/BaseActivity.java +300 -0
- package/android/src/main/java/com/ahmedadeltito/photoeditor/ColorPickerAdapter.java +129 -0
- package/android/src/main/java/com/ahmedadeltito/photoeditor/EmojiAdapter.java +91 -0
- package/android/src/main/java/com/ahmedadeltito/photoeditor/EmojiFragment.java +56 -0
- package/android/src/main/java/com/ahmedadeltito/photoeditor/GalleryUtils.java +73 -0
- package/android/src/main/java/com/ahmedadeltito/photoeditor/ImageAdapter.java +69 -0
- package/android/src/main/java/com/ahmedadeltito/photoeditor/ImageFragment.java +93 -0
- package/android/src/main/java/com/ahmedadeltito/photoeditor/MainActivity.java +29 -0
- package/android/src/main/java/com/ahmedadeltito/photoeditor/MediaActivity.java +95 -0
- package/android/src/main/java/com/ahmedadeltito/photoeditor/PhotoEditorActivity.java +1055 -0
- package/android/src/main/java/com/ahmedadeltito/photoeditor/TranslationService.java +31 -0
- package/android/src/main/java/com/ahmedadeltito/photoeditor/UtilFunctions.java +176 -0
- package/android/src/main/java/com/ahmedadeltito/photoeditor/widget/RealtimeBlurView.java +359 -0
- package/android/src/main/java/com/ahmedadeltito/photoeditor/widget/SlidingUpPanelLayout.java +1527 -0
- package/android/src/main/java/com/ahmedadeltito/photoeditor/widget/ViewDragHelper.java +1466 -0
- package/android/src/main/java/ui/photoeditor/RNPhotoEditorModule.java +108 -0
- package/android/src/main/java/ui/photoeditor/RNPhotoEditorPackage.java +29 -0
- package/android/src/main/res/drawable/above_shadow.xml +7 -0
- package/android/src/main/res/drawable/below_shadow.xml +7 -0
- package/android/src/main/res/drawable/fading_shadow.xml +7 -0
- package/android/src/main/res/drawable/rounded_border_text_view.xml +13 -0
- package/android/src/main/res/drawable-xhdpi/aa.png +0 -0
- package/android/src/main/res/drawable-xhdpi/bb.png +0 -0
- package/android/src/main/res/drawable-xhdpi/c.png +0 -0
- package/android/src/main/res/drawable-xhdpi/cc.png +0 -0
- package/android/src/main/res/drawable-xhdpi/d.png +0 -0
- package/android/src/main/res/drawable-xhdpi/dd.png +0 -0
- package/android/src/main/res/drawable-xhdpi/e.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ee.png +0 -0
- package/android/src/main/res/drawable-xhdpi/i.png +0 -0
- package/android/src/main/res/drawable-xhdpi/j.png +0 -0
- package/android/src/main/res/drawable-xhdpi/k.png +0 -0
- package/android/src/main/res/drawable-xhdpi/l.png +0 -0
- package/android/src/main/res/drawable-xhdpi/m.png +0 -0
- package/android/src/main/res/drawable-xhdpi/n.png +0 -0
- package/android/src/main/res/drawable-xhdpi/o.png +0 -0
- package/android/src/main/res/drawable-xhdpi/p.png +0 -0
- package/android/src/main/res/drawable-xhdpi/q.png +0 -0
- package/android/src/main/res/drawable-xhdpi/r.png +0 -0
- package/android/src/main/res/drawable-xhdpi/s.png +0 -0
- package/android/src/main/res/drawable-xhdpi/t.png +0 -0
- package/android/src/main/res/drawable-xhdpi/u.png +0 -0
- package/android/src/main/res/drawable-xhdpi/v.png +0 -0
- package/android/src/main/res/drawable-xhdpi/w.png +0 -0
- package/android/src/main/res/drawable-xhdpi/x.png +0 -0
- package/android/src/main/res/drawable-xhdpi/y.png +0 -0
- package/android/src/main/res/drawable-xhdpi/z.png +0 -0
- package/android/src/main/res/layout/activity_main.xml +28 -0
- package/android/src/main/res/layout/activity_photo_editor.xml +316 -0
- package/android/src/main/res/layout/add_text_popup_window.xml +47 -0
- package/android/src/main/res/layout/color_picker_item_list.xml +15 -0
- package/android/src/main/res/layout/fragment_main_photo_edit_emoji.xml +11 -0
- package/android/src/main/res/layout/fragment_main_photo_edit_image.xml +10 -0
- package/android/src/main/res/layout/fragment_photo_edit_emoji_item_list.xml +17 -0
- package/android/src/main/res/layout/fragment_photo_edit_image_item_list.xml +16 -0
- package/android/src/main/res/raw/emojioneandroid +0 -0
- package/android/src/main/res/raw/eventtusicons +0 -0
- package/android/src/main/res/raw/font_awesome_solid.otf +0 -0
- package/android/src/main/res/raw/icomoon.ttf +0 -0
- package/android/src/main/res/values/arrays.xml +447 -0
- package/android/src/main/res/values/attrs.xml +30 -0
- package/android/src/main/res/values/colors.xml +21 -0
- package/android/src/main/res/values/dimens.xml +4 -0
- package/android/src/main/res/values/strings.xml +33 -0
- package/android/src/main/res/values/styles.xml +27 -0
- package/ios/RNImageEditor.podspec +26 -0
- package/ios/RNPhotoEditor.h +13 -0
- package/ios/RNPhotoEditor.m +163 -0
- package/ios/RNPhotoEditor.xcodeproj/project.pbxproj +362 -0
- package/lib/index.d.ts +125 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +114 -0
- package/lib/index.js.map +1 -0
- package/package.json +73 -0
- package/react-native-image-editor.podspec +39 -0
- package/src/index.ts +232 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
package com.ahmedadeltito.photoeditor;
|
|
2
|
+
|
|
3
|
+
import android.animation.AnimatorSet;
|
|
4
|
+
import android.animation.ObjectAnimator;
|
|
5
|
+
import android.content.Context;
|
|
6
|
+
import android.graphics.Color;
|
|
7
|
+
import android.graphics.Path;
|
|
8
|
+
import android.graphics.Rect;
|
|
9
|
+
import android.graphics.drawable.Drawable;
|
|
10
|
+
import android.graphics.drawable.LayerDrawable;
|
|
11
|
+
import android.graphics.drawable.ShapeDrawable;
|
|
12
|
+
import android.graphics.drawable.shapes.OvalShape;
|
|
13
|
+
import android.graphics.drawable.shapes.PathShape;
|
|
14
|
+
import android.view.LayoutInflater;
|
|
15
|
+
import android.view.View;
|
|
16
|
+
import android.view.ViewGroup;
|
|
17
|
+
import android.view.animation.BounceInterpolator;
|
|
18
|
+
import androidx.annotation.NonNull;
|
|
19
|
+
import androidx.recyclerview.widget.RecyclerView;
|
|
20
|
+
import java.util.List;
|
|
21
|
+
import ui.photoeditor.R;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Created by Ahmed Adel on 5/8/17.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
public class ColorPickerAdapter extends RecyclerView.Adapter<ColorPickerAdapter.ViewHolder> {
|
|
28
|
+
|
|
29
|
+
private Context context;
|
|
30
|
+
private LayoutInflater inflater;
|
|
31
|
+
private List<Integer> colorPickerColors;
|
|
32
|
+
private OnColorPickerClickListener onColorPickerClickListener;
|
|
33
|
+
private int selectedPosition = 0;
|
|
34
|
+
|
|
35
|
+
public ColorPickerAdapter(@NonNull Context context, @NonNull List<Integer> colorPickerColors) {
|
|
36
|
+
this.context = context;
|
|
37
|
+
this.inflater = LayoutInflater.from(context);
|
|
38
|
+
this.colorPickerColors = colorPickerColors;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@Override
|
|
42
|
+
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
|
43
|
+
View view = inflater.inflate(R.layout.color_picker_item_list, parent, false);
|
|
44
|
+
return new ViewHolder(view);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@Override
|
|
48
|
+
public void onBindViewHolder(ViewHolder holder, int position) {
|
|
49
|
+
boolean isSelected = position == selectedPosition; // replace with your selection logic
|
|
50
|
+
buildColorPickerView(holder.colorPickerView, colorPickerColors.get(position), isSelected);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@Override
|
|
54
|
+
public int getItemCount() {
|
|
55
|
+
return colorPickerColors.size();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
private ShapeDrawable createShapeDrawable(String shapeType, int size, int color) {
|
|
59
|
+
ShapeDrawable shapeDrawable;
|
|
60
|
+
|
|
61
|
+
if ("diamond".equals(shapeType)) {
|
|
62
|
+
Path path = new Path();
|
|
63
|
+
path.moveTo(size / 2f, 0);
|
|
64
|
+
path.lineTo(size, size / 2f);
|
|
65
|
+
path.lineTo(size / 2f, size);
|
|
66
|
+
path.lineTo(0, size / 2f);
|
|
67
|
+
path.close();
|
|
68
|
+
|
|
69
|
+
shapeDrawable = new ShapeDrawable(new PathShape(path, size, size));
|
|
70
|
+
} else {
|
|
71
|
+
shapeDrawable = new ShapeDrawable(new OvalShape());
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
shapeDrawable.setIntrinsicHeight(size);
|
|
75
|
+
shapeDrawable.setIntrinsicWidth(size);
|
|
76
|
+
shapeDrawable.setBounds(new Rect(0, 0, size, size));
|
|
77
|
+
shapeDrawable.getPaint().setColor(color);
|
|
78
|
+
|
|
79
|
+
return shapeDrawable;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
private void buildColorPickerView(View view, int colorCode, boolean isSelected) {
|
|
83
|
+
view.setVisibility(View.VISIBLE);
|
|
84
|
+
String shapeType = isSelected ? "diamond" : "circle";
|
|
85
|
+
ShapeDrawable biggerShape = createShapeDrawable(shapeType, 20, colorCode);
|
|
86
|
+
ShapeDrawable smallerShape = createShapeDrawable(shapeType, 5, Color.WHITE);
|
|
87
|
+
smallerShape.setPadding(10, 10, 10, 10);
|
|
88
|
+
|
|
89
|
+
Drawable[] drawables = { smallerShape, biggerShape };
|
|
90
|
+
|
|
91
|
+
LayerDrawable layerDrawable = new LayerDrawable(drawables);
|
|
92
|
+
|
|
93
|
+
view.setBackgroundDrawable(layerDrawable);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
public void setOnColorPickerClickListener(
|
|
97
|
+
OnColorPickerClickListener onColorPickerClickListener
|
|
98
|
+
) {
|
|
99
|
+
this.onColorPickerClickListener = onColorPickerClickListener;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
class ViewHolder extends RecyclerView.ViewHolder {
|
|
103
|
+
|
|
104
|
+
View colorPickerView;
|
|
105
|
+
|
|
106
|
+
public ViewHolder(View itemView) {
|
|
107
|
+
super(itemView);
|
|
108
|
+
colorPickerView = itemView.findViewById(R.id.color_picker_view);
|
|
109
|
+
itemView.setOnClickListener(
|
|
110
|
+
new View.OnClickListener() {
|
|
111
|
+
@Override
|
|
112
|
+
public void onClick(View v) {
|
|
113
|
+
if (
|
|
114
|
+
onColorPickerClickListener != null
|
|
115
|
+
) onColorPickerClickListener.onColorPickerClickListener(
|
|
116
|
+
colorPickerColors.get(getAdapterPosition())
|
|
117
|
+
);
|
|
118
|
+
selectedPosition = getAdapterPosition();
|
|
119
|
+
notifyDataSetChanged();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
public interface OnColorPickerClickListener {
|
|
127
|
+
void onColorPickerClickListener(int colorCode);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
package com.ahmedadeltito.photoeditor;
|
|
2
|
+
|
|
3
|
+
import android.content.Context;
|
|
4
|
+
import androidx.annotation.NonNull;
|
|
5
|
+
import androidx.recyclerview.widget.RecyclerView;
|
|
6
|
+
import android.view.LayoutInflater;
|
|
7
|
+
import android.view.View;
|
|
8
|
+
import android.view.ViewGroup;
|
|
9
|
+
import android.widget.TextView;
|
|
10
|
+
|
|
11
|
+
import java.util.List;
|
|
12
|
+
|
|
13
|
+
import ui.photoeditor.R;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Created by Ahmed Adel on 5/5/17.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
public class EmojiAdapter extends RecyclerView.Adapter<EmojiAdapter.ViewHolder> {
|
|
20
|
+
|
|
21
|
+
// private Typeface emojiFont;
|
|
22
|
+
private Context context;
|
|
23
|
+
private List<String> emojiIds;
|
|
24
|
+
private LayoutInflater inflater;
|
|
25
|
+
private OnEmojiClickListener onEmojiClickListener;
|
|
26
|
+
|
|
27
|
+
public EmojiAdapter(@NonNull Context context, @NonNull List<String> emojiIds) {
|
|
28
|
+
this.context = context;
|
|
29
|
+
this.inflater = LayoutInflater.from(context);
|
|
30
|
+
this.emojiIds = emojiIds;
|
|
31
|
+
// emojiFont = Typeface.createFromAsset(context.getAssets(), "emojione-android.ttf");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@Override
|
|
35
|
+
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
|
36
|
+
View view = inflater.inflate(R.layout.fragment_photo_edit_emoji_item_list, parent, false);
|
|
37
|
+
return new ViewHolder(view);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@Override
|
|
41
|
+
public void onBindViewHolder(ViewHolder holder, int position) {
|
|
42
|
+
String emojiId = emojiIds.get(position);
|
|
43
|
+
holder.emojiTextView.setText(convertEmoji(emojiId));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@Override
|
|
47
|
+
public int getItemCount() {
|
|
48
|
+
return emojiIds.size();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public void setOnEmojiClickListener(OnEmojiClickListener onEmojiClickListener) {
|
|
52
|
+
this.onEmojiClickListener = onEmojiClickListener;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private String convertEmoji(String emoji) {
|
|
56
|
+
String returnedEmoji = "";
|
|
57
|
+
try {
|
|
58
|
+
int convertEmojiToInt = Integer.parseInt(emoji.substring(2), 16);
|
|
59
|
+
returnedEmoji = getEmojiByUnicode(convertEmojiToInt);
|
|
60
|
+
} catch (NumberFormatException e) {
|
|
61
|
+
returnedEmoji = "";
|
|
62
|
+
}
|
|
63
|
+
return returnedEmoji;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private String getEmojiByUnicode(int unicode) {
|
|
67
|
+
return new String(Character.toChars(unicode));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// stores and recycles views as they are scrolled off screen
|
|
71
|
+
class ViewHolder extends RecyclerView.ViewHolder {
|
|
72
|
+
TextView emojiTextView;
|
|
73
|
+
|
|
74
|
+
public ViewHolder(View itemView) {
|
|
75
|
+
super(itemView);
|
|
76
|
+
emojiTextView = (TextView) itemView.findViewById(R.id.fragment_photo_edit_emoji_tv);
|
|
77
|
+
emojiTextView.setTypeface(PhotoEditorActivity.emojiFont);
|
|
78
|
+
emojiTextView.setOnClickListener(new View.OnClickListener() {
|
|
79
|
+
@Override
|
|
80
|
+
public void onClick(View v) {
|
|
81
|
+
if (onEmojiClickListener != null)
|
|
82
|
+
onEmojiClickListener.onEmojiClickListener(emojiIds.get(getAdapterPosition()));
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
public interface OnEmojiClickListener {
|
|
89
|
+
void onEmojiClickListener(String emojiName);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
package com.ahmedadeltito.photoeditor;
|
|
2
|
+
|
|
3
|
+
import android.os.Bundle;
|
|
4
|
+
import androidx.annotation.Nullable;
|
|
5
|
+
import androidx.fragment.app.Fragment;
|
|
6
|
+
import androidx.recyclerview.widget.GridLayoutManager;
|
|
7
|
+
import androidx.recyclerview.widget.RecyclerView;
|
|
8
|
+
import android.view.LayoutInflater;
|
|
9
|
+
import android.view.View;
|
|
10
|
+
import android.view.ViewGroup;
|
|
11
|
+
|
|
12
|
+
import java.util.ArrayList;
|
|
13
|
+
import java.util.Collections;
|
|
14
|
+
import ui.photoeditor.R;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Created by Ahmed Adel on 5/5/17.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
public class EmojiFragment extends Fragment implements EmojiAdapter.OnEmojiClickListener {
|
|
21
|
+
|
|
22
|
+
private ArrayList<String> emojiIds;
|
|
23
|
+
private PhotoEditorActivity photoEditorActivity;
|
|
24
|
+
RecyclerView emojiRecyclerView;
|
|
25
|
+
|
|
26
|
+
@Override
|
|
27
|
+
public void onCreate(@Nullable Bundle savedInstanceState) {
|
|
28
|
+
super.onCreate(savedInstanceState);
|
|
29
|
+
photoEditorActivity = (PhotoEditorActivity) getActivity();
|
|
30
|
+
|
|
31
|
+
String[] emojis = photoEditorActivity.getResources().getStringArray(R.array.photo_editor_emoji);
|
|
32
|
+
|
|
33
|
+
emojiIds = new ArrayList<>();
|
|
34
|
+
Collections.addAll(emojiIds, emojis);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@Nullable
|
|
38
|
+
@Override
|
|
39
|
+
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
|
40
|
+
View rootView = inflater.inflate(R.layout.fragment_main_photo_edit_emoji, container, false);
|
|
41
|
+
|
|
42
|
+
emojiRecyclerView = (RecyclerView) rootView.findViewById(R.id.fragment_main_photo_edit_emoji_rv);
|
|
43
|
+
emojiRecyclerView.setHasFixedSize(true);
|
|
44
|
+
emojiRecyclerView.setLayoutManager(new GridLayoutManager(photoEditorActivity, 4));
|
|
45
|
+
EmojiAdapter adapter = new EmojiAdapter(photoEditorActivity, emojiIds);
|
|
46
|
+
adapter.setOnEmojiClickListener(this);
|
|
47
|
+
emojiRecyclerView.setAdapter(adapter);
|
|
48
|
+
|
|
49
|
+
return rootView;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@Override
|
|
53
|
+
public void onEmojiClickListener(String emojiName) {
|
|
54
|
+
photoEditorActivity.addEmoji(emojiName);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
package com.ahmedadeltito.photoeditor;
|
|
2
|
+
|
|
3
|
+
import android.content.Context;
|
|
4
|
+
import android.database.Cursor;
|
|
5
|
+
import android.net.Uri;
|
|
6
|
+
|
|
7
|
+
public class GalleryUtils {
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Get the value of the data column for this Uri. This is useful for
|
|
11
|
+
* MediaStore Uris, and other file-based ContentProviders.
|
|
12
|
+
*
|
|
13
|
+
* @param context
|
|
14
|
+
* The context.
|
|
15
|
+
* @param uri
|
|
16
|
+
* The Uri to query.
|
|
17
|
+
* @param selection
|
|
18
|
+
* (Optional) Filter used in the query.
|
|
19
|
+
* @param selectionArgs
|
|
20
|
+
* (Optional) Selection arguments used in the query.
|
|
21
|
+
* @return The value of the _data column, which is typically a file path.
|
|
22
|
+
*/
|
|
23
|
+
public static String getDataColumn(Context context, Uri uri,
|
|
24
|
+
String selection, String[] selectionArgs) {
|
|
25
|
+
|
|
26
|
+
Cursor cursor = null;
|
|
27
|
+
final String column = "_data";
|
|
28
|
+
final String[] projection = { column };
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
cursor = context.getContentResolver().query(uri, projection,
|
|
32
|
+
selection, selectionArgs, null);
|
|
33
|
+
if (cursor != null && cursor.moveToFirst()) {
|
|
34
|
+
final int column_index = cursor.getColumnIndexOrThrow(column);
|
|
35
|
+
return cursor.getString(column_index);
|
|
36
|
+
}
|
|
37
|
+
} finally {
|
|
38
|
+
if (cursor != null)
|
|
39
|
+
cursor.close();
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @param uri
|
|
46
|
+
* The Uri to check.
|
|
47
|
+
* @return Whether the Uri authority is ExternalStorageProvider.
|
|
48
|
+
*/
|
|
49
|
+
public static boolean isExternalStorageDocument(Uri uri) {
|
|
50
|
+
return "com.android.externalstorage.documents".equals(uri
|
|
51
|
+
.getAuthority());
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @param uri
|
|
56
|
+
* The Uri to check.
|
|
57
|
+
* @return Whether the Uri authority is DownloadsProvider.
|
|
58
|
+
*/
|
|
59
|
+
public static boolean isDownloadsDocument(Uri uri) {
|
|
60
|
+
return "com.android.providers.downloads.documents".equals(uri
|
|
61
|
+
.getAuthority());
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @param uri
|
|
66
|
+
* The Uri to check.
|
|
67
|
+
* @return Whether the Uri authority is MediaProvider.
|
|
68
|
+
*/
|
|
69
|
+
public static boolean isMediaDocument(Uri uri) {
|
|
70
|
+
return "com.android.providers.media.documents".equals(uri
|
|
71
|
+
.getAuthority());
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
package com.ahmedadeltito.photoeditor;
|
|
2
|
+
|
|
3
|
+
import android.content.Context;
|
|
4
|
+
import android.graphics.Bitmap;
|
|
5
|
+
import androidx.annotation.NonNull;
|
|
6
|
+
import androidx.recyclerview.widget.RecyclerView;
|
|
7
|
+
import android.view.LayoutInflater;
|
|
8
|
+
import android.view.View;
|
|
9
|
+
import android.view.ViewGroup;
|
|
10
|
+
import android.widget.ImageView;
|
|
11
|
+
|
|
12
|
+
import java.util.List;
|
|
13
|
+
import ui.photoeditor.R;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Created by Ahmed Adel on 5/4/17.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
public class ImageAdapter extends RecyclerView.Adapter<ImageAdapter.ViewHolder> {
|
|
20
|
+
|
|
21
|
+
private List<Bitmap> imageBitmaps;
|
|
22
|
+
private LayoutInflater inflater;
|
|
23
|
+
private OnImageClickListener onImageClickListener;
|
|
24
|
+
|
|
25
|
+
public ImageAdapter(@NonNull Context context, @NonNull List<Bitmap> imageBitmaps) {
|
|
26
|
+
this.inflater = LayoutInflater.from(context);
|
|
27
|
+
this.imageBitmaps = imageBitmaps;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@Override
|
|
31
|
+
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
|
32
|
+
View view = inflater.inflate(R.layout.fragment_photo_edit_image_item_list, parent, false);
|
|
33
|
+
return new ViewHolder(view);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@Override
|
|
37
|
+
public void onBindViewHolder(ViewHolder holder, int position) {
|
|
38
|
+
holder.imageView.setImageBitmap(imageBitmaps.get(position));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@Override
|
|
42
|
+
public int getItemCount() {
|
|
43
|
+
return imageBitmaps.size();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public void setOnImageClickListener(OnImageClickListener onImageClickListener) {
|
|
47
|
+
this.onImageClickListener = onImageClickListener;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
class ViewHolder extends RecyclerView.ViewHolder {
|
|
51
|
+
ImageView imageView;
|
|
52
|
+
|
|
53
|
+
public ViewHolder(View itemView) {
|
|
54
|
+
super(itemView);
|
|
55
|
+
imageView = (ImageView) itemView.findViewById(R.id.fragment_photo_edit_image_iv);
|
|
56
|
+
imageView.setOnClickListener(new View.OnClickListener() {
|
|
57
|
+
@Override
|
|
58
|
+
public void onClick(View v) {
|
|
59
|
+
if (onImageClickListener != null)
|
|
60
|
+
onImageClickListener.onImageClickListener(imageBitmaps.get(getAdapterPosition()));
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
public interface OnImageClickListener {
|
|
67
|
+
void onImageClickListener(Bitmap image);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
package com.ahmedadeltito.photoeditor;
|
|
2
|
+
|
|
3
|
+
import android.content.res.Resources;
|
|
4
|
+
import android.content.res.TypedArray;
|
|
5
|
+
import android.graphics.Bitmap;
|
|
6
|
+
import android.graphics.BitmapFactory;
|
|
7
|
+
import android.os.Bundle;
|
|
8
|
+
import androidx.annotation.Nullable;
|
|
9
|
+
import androidx.fragment.app.Fragment;
|
|
10
|
+
import androidx.recyclerview.widget.GridLayoutManager;
|
|
11
|
+
import androidx.recyclerview.widget.RecyclerView;
|
|
12
|
+
import android.view.LayoutInflater;
|
|
13
|
+
import android.view.View;
|
|
14
|
+
import android.view.ViewGroup;
|
|
15
|
+
|
|
16
|
+
import java.util.ArrayList;
|
|
17
|
+
import ui.photoeditor.R;
|
|
18
|
+
/**
|
|
19
|
+
* Created by Ahmed Adel on 5/4/17.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
public class ImageFragment extends Fragment implements ImageAdapter.OnImageClickListener {
|
|
23
|
+
|
|
24
|
+
private ArrayList<Bitmap> stickerBitmaps;
|
|
25
|
+
private PhotoEditorActivity photoEditorActivity;
|
|
26
|
+
RecyclerView imageRecyclerView;
|
|
27
|
+
|
|
28
|
+
@Override
|
|
29
|
+
public void onCreate(@Nullable Bundle savedInstanceState) {
|
|
30
|
+
super.onCreate(savedInstanceState);
|
|
31
|
+
photoEditorActivity = (PhotoEditorActivity) getActivity();
|
|
32
|
+
|
|
33
|
+
TypedArray images = getResources().obtainTypedArray(R.array.photo_editor_photos);
|
|
34
|
+
|
|
35
|
+
ArrayList<Integer> stickers = (ArrayList<Integer>) getActivity().getIntent().getExtras().getSerializable("stickers");
|
|
36
|
+
|
|
37
|
+
if (stickers != null && stickers.size() > 0) {
|
|
38
|
+
stickerBitmaps = new ArrayList<>();
|
|
39
|
+
|
|
40
|
+
for (int i = 0;i < stickers.size();i++) {
|
|
41
|
+
stickerBitmaps.add(decodeSampledBitmapFromResource(getActivity().getResources(), stickers.get(i), 120, 120));
|
|
42
|
+
}
|
|
43
|
+
} else {
|
|
44
|
+
stickerBitmaps = new ArrayList<>();
|
|
45
|
+
for (int i = 0; i < images.length(); i++) {
|
|
46
|
+
stickerBitmaps.add(decodeSampledBitmapFromResource(photoEditorActivity.getResources(), images.getResourceId(i, -1), 120, 120));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@Nullable
|
|
52
|
+
@Override
|
|
53
|
+
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
|
54
|
+
View rootView = inflater.inflate(R.layout.fragment_main_photo_edit_image, container, false);
|
|
55
|
+
|
|
56
|
+
imageRecyclerView = (RecyclerView) rootView.findViewById(R.id.fragment_main_photo_edit_image_rv);
|
|
57
|
+
imageRecyclerView.setLayoutManager(new GridLayoutManager(photoEditorActivity, 3));
|
|
58
|
+
ImageAdapter adapter = new ImageAdapter(photoEditorActivity, stickerBitmaps);
|
|
59
|
+
adapter.setOnImageClickListener(this);
|
|
60
|
+
imageRecyclerView.setAdapter(adapter);
|
|
61
|
+
|
|
62
|
+
return rootView;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
public Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) {
|
|
66
|
+
final BitmapFactory.Options options = new BitmapFactory.Options();
|
|
67
|
+
options.inJustDecodeBounds = true;
|
|
68
|
+
BitmapFactory.decodeResource(res, resId, options);
|
|
69
|
+
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
|
|
70
|
+
options.inJustDecodeBounds = false;
|
|
71
|
+
return BitmapFactory.decodeResource(res, resId, options);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
public int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
|
|
75
|
+
final int height = options.outHeight;
|
|
76
|
+
final int width = options.outWidth;
|
|
77
|
+
int inSampleSize = 1;
|
|
78
|
+
if (height > reqHeight || width > reqWidth) {
|
|
79
|
+
final int halfHeight = height / 2;
|
|
80
|
+
final int halfWidth = width / 2;
|
|
81
|
+
while ((halfHeight / inSampleSize) >= reqHeight
|
|
82
|
+
&& (halfWidth / inSampleSize) >= reqWidth) {
|
|
83
|
+
inSampleSize *= 2;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return inSampleSize;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@Override
|
|
90
|
+
public void onImageClickListener(Bitmap image) {
|
|
91
|
+
photoEditorActivity.addImage(image);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
package com.ahmedadeltito.photoeditor;
|
|
2
|
+
|
|
3
|
+
import android.content.Intent;
|
|
4
|
+
import android.os.Bundle;
|
|
5
|
+
import android.view.View;
|
|
6
|
+
import ui.photoeditor.R;
|
|
7
|
+
public class MainActivity extends MediaActivity {
|
|
8
|
+
|
|
9
|
+
@Override
|
|
10
|
+
protected void onCreate(Bundle savedInstanceState) {
|
|
11
|
+
super.onCreate(savedInstanceState);
|
|
12
|
+
setContentView(R.layout.activity_main);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public void openUserGallery(View view) {
|
|
16
|
+
openGallery();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public void openUserCamera(View view) {
|
|
20
|
+
startCameraActivity();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@Override
|
|
24
|
+
protected void onPhotoTaken() {
|
|
25
|
+
Intent intent = new Intent(MainActivity.this, PhotoEditorActivity.class);
|
|
26
|
+
intent.putExtra("selectedImagePath", selectedImagePath);
|
|
27
|
+
startActivity(intent);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
package com.ahmedadeltito.photoeditor;
|
|
2
|
+
|
|
3
|
+
import android.content.Intent;
|
|
4
|
+
import android.graphics.BitmapFactory;
|
|
5
|
+
import android.net.Uri;
|
|
6
|
+
import android.os.Build;
|
|
7
|
+
import android.os.Bundle;
|
|
8
|
+
import androidx.annotation.RequiresApi;
|
|
9
|
+
import android.util.Log;
|
|
10
|
+
import ui.photoeditor.R;
|
|
11
|
+
/**
|
|
12
|
+
* Created by Ahmed Adel on 09/06/2017.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
public abstract class MediaActivity extends BaseActivity {
|
|
16
|
+
|
|
17
|
+
private Uri selectedImageUri;
|
|
18
|
+
|
|
19
|
+
@Override
|
|
20
|
+
protected void onCreate(Bundle savedInstanceState) {
|
|
21
|
+
super.onCreate(savedInstanceState);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
|
25
|
+
@Override
|
|
26
|
+
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
27
|
+
switch (resultCode) {
|
|
28
|
+
case RESULT_CANCELED:
|
|
29
|
+
break;
|
|
30
|
+
case RESULT_OK:
|
|
31
|
+
if (requestCode == GALLERY_INTENT_CALLED || requestCode == CAMERA_CODE
|
|
32
|
+
|| requestCode == GALLERY_KITKAT_INTENT_CALLED) {
|
|
33
|
+
if (requestCode == GALLERY_INTENT_CALLED) {
|
|
34
|
+
selectedImageUri = data.getData();
|
|
35
|
+
selectedImagePath = getPath(selectedImageUri);
|
|
36
|
+
} else if (requestCode == GALLERY_KITKAT_INTENT_CALLED) {
|
|
37
|
+
selectedImageUri = data.getData();
|
|
38
|
+
final int takeFlags = data.getFlags()
|
|
39
|
+
& (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
|
40
|
+
// Check for the freshest data.
|
|
41
|
+
if (selectedImageUri != null) {
|
|
42
|
+
getContentResolver().takePersistableUriPermission(
|
|
43
|
+
selectedImageUri, takeFlags);
|
|
44
|
+
selectedImagePath = getPath(selectedImageUri);
|
|
45
|
+
}
|
|
46
|
+
} else {
|
|
47
|
+
selectedImagePath = selectedOutputPath;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (UtilFunctions.stringIsNotEmpty(selectedImagePath)) {
|
|
51
|
+
// decode image size
|
|
52
|
+
BitmapFactory.Options o = new BitmapFactory.Options();
|
|
53
|
+
o.inJustDecodeBounds = true;
|
|
54
|
+
BitmapFactory.decodeFile(selectedImagePath, o);
|
|
55
|
+
// Find the correct scale value. It should be the power of
|
|
56
|
+
// 2.
|
|
57
|
+
int width_tmp = o.outWidth, height_tmp = o.outHeight;
|
|
58
|
+
Log.d("MediaActivity", "MediaActivity : image size : "
|
|
59
|
+
+ width_tmp + " ; " + height_tmp);
|
|
60
|
+
final int MAX_SIZE = getResources().getDimensionPixelSize(
|
|
61
|
+
R.dimen.image_loader_post_width);
|
|
62
|
+
int scale = 1;
|
|
63
|
+
// while (true) {
|
|
64
|
+
// if (width_tmp / 2 < MAX_SIZE
|
|
65
|
+
// || height_tmp / 2 < MAX_SIZE)
|
|
66
|
+
// break;
|
|
67
|
+
// width_tmp /= 2;
|
|
68
|
+
// height_tmp /= 2;
|
|
69
|
+
// scale *= 2;
|
|
70
|
+
// }
|
|
71
|
+
if (height_tmp > MAX_SIZE || width_tmp > MAX_SIZE) {
|
|
72
|
+
if (width_tmp > height_tmp) {
|
|
73
|
+
scale = Math.round((float) height_tmp
|
|
74
|
+
/ (float) MAX_SIZE);
|
|
75
|
+
} else {
|
|
76
|
+
scale = Math.round((float) width_tmp
|
|
77
|
+
/ (float) MAX_SIZE);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
Log.d("MediaActivity", "MediaActivity : scaling image by factor : " + scale);
|
|
81
|
+
BitmapFactory.Options options = new BitmapFactory.Options();
|
|
82
|
+
options.inSampleSize = scale;
|
|
83
|
+
bitmap = BitmapFactory.decodeFile(selectedImagePath, options);
|
|
84
|
+
_taken = true;
|
|
85
|
+
onPhotoTaken();
|
|
86
|
+
System.gc();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
super.onActivityResult(requestCode, resultCode, data);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
protected abstract void onPhotoTaken();
|
|
95
|
+
}
|