@codebymanan/react-native-photo-editor 0.1.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 +20 -0
- package/PhotoEditor.podspec +23 -0
- package/README.md +200 -0
- package/android/build.gradle +65 -0
- package/android/src/main/AndroidManifest.xml +14 -0
- package/android/src/main/assets/beyond_wonderland.ttf +0 -0
- package/android/src/main/assets/emojione-android.ttf +0 -0
- package/android/src/main/assets/filters/auto_fix.png +0 -0
- package/android/src/main/assets/filters/b_n_w.png +0 -0
- package/android/src/main/assets/filters/brightness.png +0 -0
- package/android/src/main/assets/filters/contrast.png +0 -0
- package/android/src/main/assets/filters/cross_process.png +0 -0
- package/android/src/main/assets/filters/documentary.png +0 -0
- package/android/src/main/assets/filters/dual_tone.png +0 -0
- package/android/src/main/assets/filters/fill_light.png +0 -0
- package/android/src/main/assets/filters/fish_eye.png +0 -0
- package/android/src/main/assets/filters/flip_horizental.png +0 -0
- package/android/src/main/assets/filters/flip_vertical.png +0 -0
- package/android/src/main/assets/filters/grain.png +0 -0
- package/android/src/main/assets/filters/gray_scale.png +0 -0
- package/android/src/main/assets/filters/lomish.png +0 -0
- package/android/src/main/assets/filters/negative.png +0 -0
- package/android/src/main/assets/filters/original.jpg +0 -0
- package/android/src/main/assets/filters/posterize.png +0 -0
- package/android/src/main/assets/filters/rotate.png +0 -0
- package/android/src/main/assets/filters/saturate.png +0 -0
- package/android/src/main/assets/filters/sepia.png +0 -0
- package/android/src/main/assets/filters/sharpen.png +0 -0
- package/android/src/main/assets/filters/temprature.png +0 -0
- package/android/src/main/assets/filters/tint.png +0 -0
- package/android/src/main/assets/filters/vignette.png +0 -0
- package/android/src/main/java/com/photoeditor/PhotoEditorModule.kt +130 -0
- package/android/src/main/java/com/photoeditor/PhotoEditorPackage.kt +31 -0
- package/android/src/main/java/com/photoeditor/editor/ColorPickerAdapter.kt +100 -0
- package/android/src/main/java/com/photoeditor/editor/EditImageActivity.kt +407 -0
- package/android/src/main/java/com/photoeditor/editor/EditorLocale.kt +41 -0
- package/android/src/main/java/com/photoeditor/editor/EditorStrings.kt +46 -0
- package/android/src/main/java/com/photoeditor/editor/EmojiBSFragment.kt +121 -0
- package/android/src/main/java/com/photoeditor/editor/PropertiesBSFragment.kt +76 -0
- package/android/src/main/java/com/photoeditor/editor/ShapeBSFragment.kt +112 -0
- package/android/src/main/java/com/photoeditor/editor/StickerBSFragment.kt +130 -0
- package/android/src/main/java/com/photoeditor/editor/TextEditorDialogFragment.kt +133 -0
- package/android/src/main/java/com/photoeditor/editor/base/BaseActivity.kt +67 -0
- package/android/src/main/java/com/photoeditor/editor/base/BaseFragment.kt +10 -0
- package/android/src/main/java/com/photoeditor/editor/filters/FilterListener.kt +7 -0
- package/android/src/main/java/com/photoeditor/editor/filters/FilterViewAdapter.kt +105 -0
- package/android/src/main/java/com/photoeditor/editor/tools/EditingToolsAdapter.kt +70 -0
- package/android/src/main/java/com/photoeditor/editor/tools/ToolType.kt +10 -0
- package/android/src/main/res/drawable/pe_blank_image.jpg +0 -0
- package/android/src/main/res/drawable/pe_ic_brush.xml +9 -0
- package/android/src/main/res/drawable/pe_ic_close.xml +9 -0
- package/android/src/main/res/drawable/pe_ic_eraser.xml +4 -0
- package/android/src/main/res/drawable/pe_ic_insert_emoticon.xml +9 -0
- package/android/src/main/res/drawable/pe_ic_oval.xml +9 -0
- package/android/src/main/res/drawable/pe_ic_photo_filter.xml +5 -0
- package/android/src/main/res/drawable/pe_ic_rectangle.xml +9 -0
- package/android/src/main/res/drawable/pe_ic_redo.xml +10 -0
- package/android/src/main/res/drawable/pe_ic_redo_disabled.xml +10 -0
- package/android/src/main/res/drawable/pe_ic_save.xml +9 -0
- package/android/src/main/res/drawable/pe_ic_sticker.xml +9 -0
- package/android/src/main/res/drawable/pe_ic_text.xml +9 -0
- package/android/src/main/res/drawable/pe_ic_undo.xml +10 -0
- package/android/src/main/res/drawable/pe_ic_undo_disabled.xml +10 -0
- package/android/src/main/res/drawable/pe_original.jpg +0 -0
- package/android/src/main/res/drawable/pe_redo.xml +6 -0
- package/android/src/main/res/drawable/pe_rounded_border_text_view.xml +14 -0
- package/android/src/main/res/drawable/pe_undo.xml +6 -0
- package/android/src/main/res/font/pe_roboto_medium.xml +7 -0
- package/android/src/main/res/layout/pe_activity_edit_image.xml +111 -0
- package/android/src/main/res/layout/pe_add_text_dialog.xml +56 -0
- package/android/src/main/res/layout/pe_color_picker_item_list.xml +15 -0
- package/android/src/main/res/layout/pe_fragment_bottom_properties_dialog.xml +77 -0
- package/android/src/main/res/layout/pe_fragment_bottom_shapes_dialog.xml +135 -0
- package/android/src/main/res/layout/pe_fragment_bottom_sticker_emoji_dialog.xml +62 -0
- package/android/src/main/res/layout/pe_row_editing_tools.xml +34 -0
- package/android/src/main/res/layout/pe_row_emoji.xml +17 -0
- package/android/src/main/res/layout/pe_row_filter_view.xml +35 -0
- package/android/src/main/res/layout/pe_row_sticker.xml +23 -0
- package/android/src/main/res/values/colors.xml +22 -0
- package/android/src/main/res/values/dimens.xml +7 -0
- package/android/src/main/res/values/font_certs.xml +17 -0
- package/android/src/main/res/values/preloaded_fonts.xml +6 -0
- package/android/src/main/res/values/strings.xml +462 -0
- package/android/src/main/res/values/styles.xml +28 -0
- package/ios/PhotoEditor.h +5 -0
- package/ios/PhotoEditor.mm +58 -0
- package/ios/PhotoEditorManager.swift +164 -0
- package/lib/module/NativePhotoEditor.js +5 -0
- package/lib/module/NativePhotoEditor.js.map +1 -0
- package/lib/module/index.js +4 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/open.js +6 -0
- package/lib/module/open.js.map +1 -0
- package/lib/module/open.native.js +7 -0
- package/lib/module/open.native.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/NativePhotoEditor.d.ts +14 -0
- package/lib/typescript/src/NativePhotoEditor.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +3 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/open.d.ts +3 -0
- package/lib/typescript/src/open.d.ts.map +1 -0
- package/lib/typescript/src/open.native.d.ts +3 -0
- package/lib/typescript/src/open.native.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +39 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/package.json +128 -0
- package/src/NativePhotoEditor.ts +12 -0
- package/src/index.tsx +2 -0
- package/src/open.native.tsx +6 -0
- package/src/open.tsx +7 -0
- package/src/types.ts +36 -0
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
package com.photoeditor.editor
|
|
2
|
+
|
|
3
|
+
import android.annotation.SuppressLint
|
|
4
|
+
import android.content.Context
|
|
5
|
+
import android.content.DialogInterface
|
|
6
|
+
import android.content.Intent
|
|
7
|
+
import android.graphics.Bitmap
|
|
8
|
+
import android.graphics.drawable.Drawable
|
|
9
|
+
import android.os.Bundle
|
|
10
|
+
import android.util.Log
|
|
11
|
+
import android.view.MotionEvent
|
|
12
|
+
import android.view.View
|
|
13
|
+
import android.view.animation.AnticipateOvershootInterpolator
|
|
14
|
+
import android.widget.ImageView
|
|
15
|
+
import android.widget.TextView
|
|
16
|
+
import androidx.appcompat.app.AlertDialog
|
|
17
|
+
import androidx.constraintlayout.widget.ConstraintLayout
|
|
18
|
+
import androidx.constraintlayout.widget.ConstraintSet
|
|
19
|
+
import androidx.lifecycle.lifecycleScope
|
|
20
|
+
import androidx.recyclerview.widget.LinearLayoutManager
|
|
21
|
+
import androidx.recyclerview.widget.RecyclerView
|
|
22
|
+
import androidx.transition.ChangeBounds
|
|
23
|
+
import androidx.transition.TransitionManager
|
|
24
|
+
import com.bumptech.glide.Glide
|
|
25
|
+
import com.bumptech.glide.request.target.CustomTarget
|
|
26
|
+
import com.bumptech.glide.request.transition.Transition
|
|
27
|
+
import com.photoeditor.R
|
|
28
|
+
import com.photoeditor.editor.EmojiBSFragment.EmojiListener
|
|
29
|
+
import com.photoeditor.editor.StickerBSFragment.StickerListener
|
|
30
|
+
import com.photoeditor.editor.base.BaseActivity
|
|
31
|
+
import com.photoeditor.editor.filters.FilterListener
|
|
32
|
+
import com.photoeditor.editor.filters.FilterViewAdapter
|
|
33
|
+
import com.photoeditor.editor.tools.EditingToolsAdapter
|
|
34
|
+
import com.photoeditor.editor.tools.EditingToolsAdapter.OnItemSelected
|
|
35
|
+
import com.photoeditor.editor.tools.ToolType
|
|
36
|
+
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
|
37
|
+
import ja.burhanrashid52.photoeditor.OnPhotoEditorListener
|
|
38
|
+
import ja.burhanrashid52.photoeditor.PhotoEditor
|
|
39
|
+
import ja.burhanrashid52.photoeditor.PhotoEditorView
|
|
40
|
+
import ja.burhanrashid52.photoeditor.PhotoFilter
|
|
41
|
+
import ja.burhanrashid52.photoeditor.SaveFileResult
|
|
42
|
+
import ja.burhanrashid52.photoeditor.SaveSettings
|
|
43
|
+
import ja.burhanrashid52.photoeditor.TextStyleBuilder
|
|
44
|
+
import ja.burhanrashid52.photoeditor.ViewType
|
|
45
|
+
import ja.burhanrashid52.photoeditor.shape.ShapeBuilder
|
|
46
|
+
import ja.burhanrashid52.photoeditor.shape.ShapeType
|
|
47
|
+
import kotlinx.coroutines.launch
|
|
48
|
+
import java.io.File
|
|
49
|
+
import androidx.annotation.StringRes
|
|
50
|
+
|
|
51
|
+
class EditImageActivity : BaseActivity(), OnPhotoEditorListener, View.OnClickListener,
|
|
52
|
+
PropertiesBSFragment.Properties, ShapeBSFragment.Properties, EmojiListener, StickerListener,
|
|
53
|
+
OnItemSelected, FilterListener {
|
|
54
|
+
|
|
55
|
+
lateinit var mPhotoEditor: PhotoEditor
|
|
56
|
+
private lateinit var mPhotoEditorView: PhotoEditorView
|
|
57
|
+
private lateinit var mPropertiesBSFragment: PropertiesBSFragment
|
|
58
|
+
private lateinit var mShapeBSFragment: ShapeBSFragment
|
|
59
|
+
private lateinit var mShapeBuilder: ShapeBuilder
|
|
60
|
+
private lateinit var mEmojiBSFragment: EmojiBSFragment
|
|
61
|
+
private lateinit var mStickerBSFragment: StickerBSFragment
|
|
62
|
+
private lateinit var mTxtCurrentTool: TextView
|
|
63
|
+
private lateinit var mRvTools: RecyclerView
|
|
64
|
+
private lateinit var mRvFilters: RecyclerView
|
|
65
|
+
private lateinit var mImgUndo: View
|
|
66
|
+
private lateinit var mImgRedo: View
|
|
67
|
+
private val mEditingToolsAdapter = EditingToolsAdapter(this)
|
|
68
|
+
private val mFilterViewAdapter = FilterViewAdapter(this)
|
|
69
|
+
private lateinit var mRootView: ConstraintLayout
|
|
70
|
+
private val mConstraintSet = ConstraintSet()
|
|
71
|
+
private var mIsFilterVisible = false
|
|
72
|
+
|
|
73
|
+
override fun attachBaseContext(newBase: Context) {
|
|
74
|
+
super.attachBaseContext(newBase)
|
|
75
|
+
|
|
76
|
+
// getIntent() is still null at this point, so the tag comes from EditorLocale.
|
|
77
|
+
// Applied after super() on purpose: AppCompat installs the app-wide locale
|
|
78
|
+
// during attachBaseContext on API < 33, and overriding afterwards is what
|
|
79
|
+
// keeps the per-call language winning on those versions too.
|
|
80
|
+
EditorLocale.overrideConfiguration(baseContext, EditorLocale.pendingTag)
|
|
81
|
+
?.let(::applyOverrideConfiguration)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
override fun onCreate(savedInstanceState: Bundle?) {
|
|
85
|
+
super.onCreate(savedInstanceState)
|
|
86
|
+
|
|
87
|
+
// The tag lives in a process-global field, so a process kill loses it and
|
|
88
|
+
// attachBaseContext above will have run without a locale. Put it back and
|
|
89
|
+
// start over. This cannot loop: the field is non-null on the second pass.
|
|
90
|
+
val language = intent.getStringExtra(EXTRA_LANGUAGE)
|
|
91
|
+
if (EditorLocale.pendingTag == null && !language.isNullOrBlank()) {
|
|
92
|
+
EditorLocale.pendingTag = language
|
|
93
|
+
recreate()
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
EditorStrings.setOverrides(intent.getBundleExtra(EXTRA_TRANSLATIONS))
|
|
98
|
+
|
|
99
|
+
makeFullScreen()
|
|
100
|
+
setContentView(R.layout.pe_activity_edit_image)
|
|
101
|
+
|
|
102
|
+
initViews()
|
|
103
|
+
mTxtCurrentTool.setEditorText(R.string.pe_app_name)
|
|
104
|
+
|
|
105
|
+
mPropertiesBSFragment = PropertiesBSFragment()
|
|
106
|
+
mEmojiBSFragment = EmojiBSFragment()
|
|
107
|
+
mStickerBSFragment = StickerBSFragment()
|
|
108
|
+
mShapeBSFragment = ShapeBSFragment()
|
|
109
|
+
mStickerBSFragment.setStickerListener(this)
|
|
110
|
+
mEmojiBSFragment.setEmojiListener(this)
|
|
111
|
+
mPropertiesBSFragment.setPropertiesChangeListener(this)
|
|
112
|
+
mShapeBSFragment.setPropertiesChangeListener(this)
|
|
113
|
+
|
|
114
|
+
intent.getStringArrayListExtra(EXTRA_STICKERS)?.let {
|
|
115
|
+
mStickerBSFragment.setStickers(it)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
val llmTools = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
|
|
119
|
+
mRvTools.layoutManager = llmTools
|
|
120
|
+
mRvTools.adapter = mEditingToolsAdapter
|
|
121
|
+
|
|
122
|
+
val llmFilters = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
|
|
123
|
+
mRvFilters.layoutManager = llmFilters
|
|
124
|
+
mRvFilters.adapter = mFilterViewAdapter
|
|
125
|
+
|
|
126
|
+
mPhotoEditor = PhotoEditor.Builder(this, mPhotoEditorView)
|
|
127
|
+
.setPinchTextScalable(true)
|
|
128
|
+
.build()
|
|
129
|
+
|
|
130
|
+
mPhotoEditor.setOnPhotoEditorListener(this)
|
|
131
|
+
|
|
132
|
+
loadSourceImage()
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** Resolves a string, honouring any overrides from the `translations` option. */
|
|
136
|
+
private fun editorString(@StringRes id: Int): String = EditorStrings.get(this, id)
|
|
137
|
+
|
|
138
|
+
private fun loadSourceImage() {
|
|
139
|
+
val path = intent.getStringExtra(EXTRA_IMAGE_PATH)
|
|
140
|
+
if (path.isNullOrBlank()) {
|
|
141
|
+
setResultError("Missing required option: path")
|
|
142
|
+
return
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Glide resolves file paths, file://, content:// and http(s) sources alike
|
|
146
|
+
Glide.with(this)
|
|
147
|
+
.asBitmap()
|
|
148
|
+
.load(path)
|
|
149
|
+
.into(object : CustomTarget<Bitmap>() {
|
|
150
|
+
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
|
|
151
|
+
mPhotoEditorView.source.setImageBitmap(resource)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
override fun onLoadCleared(placeholder: Drawable?) = Unit
|
|
155
|
+
|
|
156
|
+
override fun onLoadFailed(errorDrawable: Drawable?) {
|
|
157
|
+
setResultError("Could not load image: $path")
|
|
158
|
+
}
|
|
159
|
+
})
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
private fun initViews() {
|
|
163
|
+
mPhotoEditorView = findViewById(R.id.photoEditorView)
|
|
164
|
+
mTxtCurrentTool = findViewById(R.id.txtCurrentTool)
|
|
165
|
+
mRvTools = findViewById(R.id.rvConstraintTools)
|
|
166
|
+
mRvFilters = findViewById(R.id.rvFilterView)
|
|
167
|
+
mRootView = findViewById(R.id.rootView)
|
|
168
|
+
|
|
169
|
+
mImgUndo = findViewById(R.id.imgUndo)
|
|
170
|
+
mImgUndo.setOnClickListener(this)
|
|
171
|
+
|
|
172
|
+
mImgRedo = findViewById(R.id.imgRedo)
|
|
173
|
+
mImgRedo.setOnClickListener(this)
|
|
174
|
+
|
|
175
|
+
val imgSave: ImageView = findViewById(R.id.imgSave)
|
|
176
|
+
imgSave.setOnClickListener(this)
|
|
177
|
+
|
|
178
|
+
val imgClose: ImageView = findViewById(R.id.imgClose)
|
|
179
|
+
imgClose.setOnClickListener(this)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
override fun onEditTextChangeListener(rootView: View, text: String, colorCode: Int) {
|
|
183
|
+
val textEditorDialogFragment =
|
|
184
|
+
TextEditorDialogFragment.show(this, text.toString(), colorCode)
|
|
185
|
+
textEditorDialogFragment.setOnTextEditorListener(object :
|
|
186
|
+
TextEditorDialogFragment.TextEditorListener {
|
|
187
|
+
override fun onDone(inputText: String, colorCode: Int) {
|
|
188
|
+
val styleBuilder = TextStyleBuilder()
|
|
189
|
+
styleBuilder.withTextColor(colorCode)
|
|
190
|
+
mPhotoEditor.editText(rootView, inputText, styleBuilder)
|
|
191
|
+
mTxtCurrentTool.setEditorText(R.string.pe_label_text)
|
|
192
|
+
}
|
|
193
|
+
})
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
override fun onAddViewListener(viewType: ViewType, numberOfAddedViews: Int) {
|
|
197
|
+
Log.d(TAG, "onAddViewListener() called with: viewType = [$viewType]")
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
override fun onRemoveViewListener(viewType: ViewType, numberOfAddedViews: Int) {
|
|
201
|
+
Log.d(TAG, "onRemoveViewListener() called with: viewType = [$viewType]")
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
override fun onStartViewChangeListener(viewType: ViewType) {
|
|
205
|
+
Log.d(TAG, "onStartViewChangeListener() called with: viewType = [$viewType]")
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
override fun onStopViewChangeListener(viewType: ViewType) {
|
|
209
|
+
Log.d(TAG, "onStopViewChangeListener() called with: viewType = [$viewType]")
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
override fun onTouchSourceImage(event: MotionEvent) {
|
|
213
|
+
Log.d(TAG, "onTouchView() called with: event = [$event]")
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
@SuppressLint("NonConstantResourceId")
|
|
217
|
+
override fun onClick(view: View) {
|
|
218
|
+
when (view.id) {
|
|
219
|
+
R.id.imgUndo -> mPhotoEditor.undo()
|
|
220
|
+
R.id.imgRedo -> mPhotoEditor.redo()
|
|
221
|
+
|
|
222
|
+
R.id.imgSave -> saveImage()
|
|
223
|
+
R.id.imgClose -> onBackPressed()
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
private fun saveImage() {
|
|
228
|
+
val outputDir = File(cacheDir, "photo_editor")
|
|
229
|
+
if (!outputDir.exists() && !outputDir.mkdirs()) {
|
|
230
|
+
showSnackbar(editorString(R.string.pe_msg_save_failed))
|
|
231
|
+
return
|
|
232
|
+
}
|
|
233
|
+
val outputFile = File(outputDir, "${System.currentTimeMillis()}.png")
|
|
234
|
+
|
|
235
|
+
val saveSettings = SaveSettings.Builder()
|
|
236
|
+
.setClearViewsEnabled(true)
|
|
237
|
+
.setTransparencyEnabled(true)
|
|
238
|
+
.build()
|
|
239
|
+
|
|
240
|
+
showLoading(editorString(R.string.pe_msg_saving))
|
|
241
|
+
lifecycleScope.launch {
|
|
242
|
+
val result = mPhotoEditor.saveAsFile(outputFile.absolutePath, saveSettings)
|
|
243
|
+
hideLoading()
|
|
244
|
+
if (result is SaveFileResult.Success) {
|
|
245
|
+
val data = Intent().putExtra(RESULT_EXTRA_PATH, outputFile.absolutePath)
|
|
246
|
+
setResult(RESULT_OK, data)
|
|
247
|
+
finish()
|
|
248
|
+
} else {
|
|
249
|
+
showSnackbar(editorString(R.string.pe_msg_save_failed))
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
private fun setResultError(message: String) {
|
|
255
|
+
val data = Intent().putExtra(RESULT_EXTRA_ERROR, message)
|
|
256
|
+
setResult(RESULT_ERROR, data)
|
|
257
|
+
finish()
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
override fun onColorChanged(colorCode: Int) {
|
|
261
|
+
mPhotoEditor.setShape(mShapeBuilder.withShapeColor(colorCode))
|
|
262
|
+
mTxtCurrentTool.setEditorText(R.string.pe_label_brush)
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
override fun onOpacityChanged(opacity: Int) {
|
|
266
|
+
mPhotoEditor.setShape(mShapeBuilder.withShapeOpacity(opacity))
|
|
267
|
+
mTxtCurrentTool.setEditorText(R.string.pe_label_brush)
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
override fun onShapeSizeChanged(shapeSize: Int) {
|
|
271
|
+
mPhotoEditor.setShape(mShapeBuilder.withShapeSize(shapeSize.toFloat()))
|
|
272
|
+
mTxtCurrentTool.setEditorText(R.string.pe_label_brush)
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
override fun onShapePicked(shapeType: ShapeType) {
|
|
276
|
+
mPhotoEditor.setShape(mShapeBuilder.withShapeType(shapeType))
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
override fun onEmojiClick(emojiUnicode: String) {
|
|
280
|
+
mPhotoEditor.addEmoji(emojiUnicode)
|
|
281
|
+
mTxtCurrentTool.setEditorText(R.string.pe_label_emoji)
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
override fun onStickerClick(bitmap: Bitmap) {
|
|
285
|
+
mPhotoEditor.addImage(bitmap)
|
|
286
|
+
mTxtCurrentTool.setEditorText(R.string.pe_label_sticker)
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
private fun showSaveDialog() {
|
|
290
|
+
val builder = AlertDialog.Builder(this)
|
|
291
|
+
builder.setMessage(editorString(R.string.pe_msg_save_image))
|
|
292
|
+
builder.setPositiveButton(editorString(R.string.pe_label_save)) { _: DialogInterface?, _: Int -> saveImage() }
|
|
293
|
+
builder.setNegativeButton(editorString(R.string.pe_label_cancel)) { dialog: DialogInterface, _: Int -> dialog.dismiss() }
|
|
294
|
+
builder.setNeutralButton(editorString(R.string.pe_label_discard)) { _: DialogInterface?, _: Int -> cancelAndFinish() }
|
|
295
|
+
builder.create().show()
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
override fun onFilterSelected(photoFilter: PhotoFilter) {
|
|
299
|
+
mPhotoEditor.setFilterEffect(photoFilter)
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
override fun onToolSelected(toolType: ToolType) {
|
|
303
|
+
when (toolType) {
|
|
304
|
+
ToolType.SHAPE -> {
|
|
305
|
+
mPhotoEditor.setBrushDrawingMode(true)
|
|
306
|
+
mShapeBuilder = ShapeBuilder()
|
|
307
|
+
mPhotoEditor.setShape(mShapeBuilder)
|
|
308
|
+
mTxtCurrentTool.setEditorText(R.string.pe_label_shape)
|
|
309
|
+
showBottomSheetDialogFragment(mShapeBSFragment)
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
ToolType.TEXT -> {
|
|
313
|
+
val textEditorDialogFragment = TextEditorDialogFragment.show(this)
|
|
314
|
+
textEditorDialogFragment.setOnTextEditorListener(object :
|
|
315
|
+
TextEditorDialogFragment.TextEditorListener {
|
|
316
|
+
override fun onDone(inputText: String, colorCode: Int) {
|
|
317
|
+
val styleBuilder = TextStyleBuilder()
|
|
318
|
+
styleBuilder.withTextColor(colorCode)
|
|
319
|
+
mPhotoEditor.addText(inputText, styleBuilder)
|
|
320
|
+
mTxtCurrentTool.setEditorText(R.string.pe_label_text)
|
|
321
|
+
}
|
|
322
|
+
})
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
ToolType.ERASER -> {
|
|
326
|
+
mPhotoEditor.brushEraser()
|
|
327
|
+
mTxtCurrentTool.setEditorText(R.string.pe_label_eraser_mode)
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
ToolType.FILTER -> {
|
|
331
|
+
mTxtCurrentTool.setEditorText(R.string.pe_label_filter)
|
|
332
|
+
showFilter(true)
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
ToolType.EMOJI -> showBottomSheetDialogFragment(mEmojiBSFragment)
|
|
336
|
+
ToolType.STICKER -> showBottomSheetDialogFragment(mStickerBSFragment)
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
private fun showBottomSheetDialogFragment(fragment: BottomSheetDialogFragment?) {
|
|
341
|
+
if (fragment == null || fragment.isAdded) {
|
|
342
|
+
return
|
|
343
|
+
}
|
|
344
|
+
fragment.show(supportFragmentManager, fragment.tag)
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
private fun showFilter(isVisible: Boolean) {
|
|
348
|
+
mIsFilterVisible = isVisible
|
|
349
|
+
mConstraintSet.clone(mRootView)
|
|
350
|
+
|
|
351
|
+
val rvFilterId: Int = mRvFilters.id
|
|
352
|
+
|
|
353
|
+
if (isVisible) {
|
|
354
|
+
mConstraintSet.clear(rvFilterId, ConstraintSet.START)
|
|
355
|
+
mConstraintSet.connect(
|
|
356
|
+
rvFilterId, ConstraintSet.START,
|
|
357
|
+
ConstraintSet.PARENT_ID, ConstraintSet.START
|
|
358
|
+
)
|
|
359
|
+
mConstraintSet.connect(
|
|
360
|
+
rvFilterId, ConstraintSet.END,
|
|
361
|
+
ConstraintSet.PARENT_ID, ConstraintSet.END
|
|
362
|
+
)
|
|
363
|
+
} else {
|
|
364
|
+
mConstraintSet.connect(
|
|
365
|
+
rvFilterId, ConstraintSet.START,
|
|
366
|
+
ConstraintSet.PARENT_ID, ConstraintSet.END
|
|
367
|
+
)
|
|
368
|
+
mConstraintSet.clear(rvFilterId, ConstraintSet.END)
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
val changeBounds = ChangeBounds()
|
|
372
|
+
changeBounds.duration = 350
|
|
373
|
+
changeBounds.interpolator = AnticipateOvershootInterpolator(1.0f)
|
|
374
|
+
TransitionManager.beginDelayedTransition(mRootView, changeBounds)
|
|
375
|
+
|
|
376
|
+
mConstraintSet.applyTo(mRootView)
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
private fun cancelAndFinish() {
|
|
380
|
+
setResult(RESULT_CANCELED)
|
|
381
|
+
finish()
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
@Deprecated("Deprecated in Java")
|
|
385
|
+
override fun onBackPressed() {
|
|
386
|
+
if (mIsFilterVisible) {
|
|
387
|
+
showFilter(false)
|
|
388
|
+
mTxtCurrentTool.setEditorText(R.string.pe_app_name)
|
|
389
|
+
} else if (!mPhotoEditor.isCacheEmpty) {
|
|
390
|
+
showSaveDialog()
|
|
391
|
+
} else {
|
|
392
|
+
cancelAndFinish()
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
companion object {
|
|
397
|
+
private const val TAG = "EditImageActivity"
|
|
398
|
+
|
|
399
|
+
const val EXTRA_IMAGE_PATH = "image_path"
|
|
400
|
+
const val EXTRA_STICKERS = "stickers"
|
|
401
|
+
const val EXTRA_LANGUAGE = "language"
|
|
402
|
+
const val EXTRA_TRANSLATIONS = "translations"
|
|
403
|
+
const val RESULT_EXTRA_PATH = "edited_image_path"
|
|
404
|
+
const val RESULT_EXTRA_ERROR = "error_message"
|
|
405
|
+
const val RESULT_ERROR = 2
|
|
406
|
+
}
|
|
407
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
package com.photoeditor.editor
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.content.res.Configuration
|
|
5
|
+
import java.util.Locale
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Carries the requested editor language from the module to the activity.
|
|
9
|
+
*
|
|
10
|
+
* The tag cannot simply ride along in the intent. [android.app.Activity.attach]
|
|
11
|
+
* calls `attachBaseContext()` before it assigns `mIntent`, so `getIntent()` is
|
|
12
|
+
* still null at the only point where the locale can be applied to the context
|
|
13
|
+
* the layouts are inflated from. The activity reads the tag from here instead,
|
|
14
|
+
* and the intent extra exists only so the activity can notice that this field
|
|
15
|
+
* was lost to a process kill.
|
|
16
|
+
*/
|
|
17
|
+
internal object EditorLocale {
|
|
18
|
+
|
|
19
|
+
/** Set by the module immediately before launching the editor. */
|
|
20
|
+
@Volatile
|
|
21
|
+
var pendingTag: String? = null
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Builds the configuration the editor should render under, or null when no
|
|
25
|
+
* usable tag was given.
|
|
26
|
+
*
|
|
27
|
+
* Deliberately does not touch [Locale.setDefault]: that is process-wide
|
|
28
|
+
* state belonging to the host app, and the editor has no business changing
|
|
29
|
+
* it. The returned configuration is a full copy of [base]'s, so applying it
|
|
30
|
+
* keeps night mode, font scale and everything else the host already set.
|
|
31
|
+
*/
|
|
32
|
+
fun overrideConfiguration(base: Context, tag: String?): Configuration? {
|
|
33
|
+
val locale = tag?.takeIf { it.isNotBlank() }?.let(Locale::forLanguageTag)
|
|
34
|
+
if (locale == null || locale.language.isEmpty()) return null
|
|
35
|
+
|
|
36
|
+
return Configuration(base.resources.configuration).apply {
|
|
37
|
+
setLocale(locale)
|
|
38
|
+
setLayoutDirection(locale)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
package com.photoeditor.editor
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.os.Bundle
|
|
5
|
+
import android.widget.TextView
|
|
6
|
+
import androidx.annotation.StringRes
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Runtime string overrides supplied through the `translations` option.
|
|
10
|
+
*
|
|
11
|
+
* A `values-<lang>` folder in the host app is still the idiomatic way to
|
|
12
|
+
* translate the editor on Android, and nothing here replaces it. This exists so
|
|
13
|
+
* that one cross-platform map can drive both platforms, because iOS has no
|
|
14
|
+
* equivalent of dropping a resource folder into the app.
|
|
15
|
+
*
|
|
16
|
+
* Keys are resource entry names, so `pe_label_brush` overrides
|
|
17
|
+
* [com.photoeditor.R.string.pe_label_brush]. Keys with no override fall through
|
|
18
|
+
* to the normal resource lookup, which is what keeps `values-<lang>` working
|
|
19
|
+
* alongside this.
|
|
20
|
+
*/
|
|
21
|
+
internal object EditorStrings {
|
|
22
|
+
|
|
23
|
+
@Volatile
|
|
24
|
+
private var overrides: Map<String, String> = emptyMap()
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Replaces the current overrides. Called with the intent's extra on every
|
|
28
|
+
* launch, including null, so one session cannot inherit another's strings.
|
|
29
|
+
*/
|
|
30
|
+
fun setOverrides(bundle: Bundle?) {
|
|
31
|
+
overrides = bundle?.keySet().orEmpty()
|
|
32
|
+
.mapNotNull { key -> bundle?.getString(key)?.let { key to it } }
|
|
33
|
+
.toMap()
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
fun get(context: Context, @StringRes id: Int): String {
|
|
37
|
+
if (overrides.isEmpty()) return context.getString(id)
|
|
38
|
+
val name = runCatching { context.resources.getResourceEntryName(id) }.getOrNull()
|
|
39
|
+
return overrides[name] ?: context.getString(id)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Sets text through [EditorStrings] rather than straight from resources. */
|
|
44
|
+
internal fun TextView.setEditorText(@StringRes id: Int) {
|
|
45
|
+
text = EditorStrings.get(context, id)
|
|
46
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
package com.photoeditor.editor
|
|
2
|
+
|
|
3
|
+
import com.photoeditor.R
|
|
4
|
+
|
|
5
|
+
import android.annotation.SuppressLint
|
|
6
|
+
import android.app.Dialog
|
|
7
|
+
import android.content.Context
|
|
8
|
+
import android.view.LayoutInflater
|
|
9
|
+
import android.view.View
|
|
10
|
+
import android.view.ViewGroup
|
|
11
|
+
import android.widget.TextView
|
|
12
|
+
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
|
13
|
+
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
|
14
|
+
import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCallback
|
|
15
|
+
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
|
16
|
+
import androidx.recyclerview.widget.RecyclerView
|
|
17
|
+
import androidx.recyclerview.widget.GridLayoutManager
|
|
18
|
+
import java.lang.NumberFormatException
|
|
19
|
+
import java.util.ArrayList
|
|
20
|
+
|
|
21
|
+
class EmojiBSFragment : BottomSheetDialogFragment() {
|
|
22
|
+
private var mEmojiListener: EmojiListener? = null
|
|
23
|
+
private var emojisList: List<String> = emptyList()
|
|
24
|
+
|
|
25
|
+
interface EmojiListener {
|
|
26
|
+
fun onEmojiClick(emojiUnicode: String)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
private val mBottomSheetBehaviorCallback: BottomSheetCallback = object : BottomSheetCallback() {
|
|
30
|
+
override fun onStateChanged(bottomSheet: View, newState: Int) {
|
|
31
|
+
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
|
|
32
|
+
dismiss()
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
override fun onSlide(bottomSheet: View, slideOffset: Float) {}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@SuppressLint("RestrictedApi")
|
|
40
|
+
override fun setupDialog(dialog: Dialog, style: Int) {
|
|
41
|
+
super.setupDialog(dialog, style)
|
|
42
|
+
val contentView = View.inflate(context, R.layout.pe_fragment_bottom_sticker_emoji_dialog, null)
|
|
43
|
+
dialog.setContentView(contentView)
|
|
44
|
+
val params = (contentView.parent as View).layoutParams as CoordinatorLayout.LayoutParams
|
|
45
|
+
val behavior = params.behavior
|
|
46
|
+
if (behavior != null && behavior is BottomSheetBehavior<*>) {
|
|
47
|
+
behavior.setBottomSheetCallback(mBottomSheetBehaviorCallback)
|
|
48
|
+
}
|
|
49
|
+
(contentView.parent as View).setBackgroundColor(resources.getColor(android.R.color.transparent))
|
|
50
|
+
emojisList = getEmojis(requireContext())
|
|
51
|
+
val rvEmoji: RecyclerView = contentView.findViewById(R.id.rvEmoji)
|
|
52
|
+
|
|
53
|
+
contentView.findViewById<TextView>(R.id.txtClose).setEditorText(R.string.pe_label_close)
|
|
54
|
+
contentView.findViewById<TextView>(R.id.txtDone).setEditorText(R.string.pe_label_done)
|
|
55
|
+
val gridLayoutManager = GridLayoutManager(activity, 5)
|
|
56
|
+
rvEmoji.layoutManager = gridLayoutManager
|
|
57
|
+
val emojiAdapter = EmojiAdapter()
|
|
58
|
+
rvEmoji.adapter = emojiAdapter
|
|
59
|
+
rvEmoji.setHasFixedSize(true)
|
|
60
|
+
rvEmoji.setItemViewCacheSize(emojisList.size)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
fun setEmojiListener(emojiListener: EmojiListener?) {
|
|
64
|
+
mEmojiListener = emojiListener
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
inner class EmojiAdapter : RecyclerView.Adapter<EmojiAdapter.ViewHolder>() {
|
|
68
|
+
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
|
69
|
+
val view =
|
|
70
|
+
LayoutInflater.from(parent.context).inflate(R.layout.pe_row_emoji, parent, false)
|
|
71
|
+
return ViewHolder(view)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
|
75
|
+
holder.txtEmoji.text = emojisList[position]
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
override fun getItemCount(): Int {
|
|
79
|
+
return emojisList.size
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
|
83
|
+
val txtEmoji: TextView = itemView.findViewById(R.id.txtEmoji)
|
|
84
|
+
|
|
85
|
+
init {
|
|
86
|
+
itemView.setOnClickListener {
|
|
87
|
+
if (mEmojiListener != null) {
|
|
88
|
+
mEmojiListener!!.onEmojiClick(emojisList[layoutPosition])
|
|
89
|
+
}
|
|
90
|
+
dismiss()
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
companion object {
|
|
97
|
+
/**
|
|
98
|
+
* Provide the list of emoji in form of unicode string
|
|
99
|
+
*
|
|
100
|
+
* @param context context
|
|
101
|
+
* @return list of emoji unicode
|
|
102
|
+
*/
|
|
103
|
+
fun getEmojis(context: Context?): ArrayList<String> {
|
|
104
|
+
val convertedEmojiList = ArrayList<String>()
|
|
105
|
+
val emojiList = context!!.resources.getStringArray(R.array.photo_editor_emoji)
|
|
106
|
+
for (emojiUnicode in emojiList) {
|
|
107
|
+
convertedEmojiList.add(convertEmoji(emojiUnicode))
|
|
108
|
+
}
|
|
109
|
+
return convertedEmojiList
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
private fun convertEmoji(emoji: String): String {
|
|
113
|
+
return try {
|
|
114
|
+
val convertEmojiToInt = emoji.substring(2).toInt(16)
|
|
115
|
+
String(Character.toChars(convertEmojiToInt))
|
|
116
|
+
} catch (e: NumberFormatException) {
|
|
117
|
+
""
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
package com.photoeditor.editor
|
|
2
|
+
|
|
3
|
+
import com.photoeditor.R
|
|
4
|
+
|
|
5
|
+
import android.os.Bundle
|
|
6
|
+
import android.view.LayoutInflater
|
|
7
|
+
import android.view.View
|
|
8
|
+
import android.view.ViewGroup
|
|
9
|
+
import android.widget.SeekBar
|
|
10
|
+
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
|
11
|
+
import androidx.recyclerview.widget.RecyclerView
|
|
12
|
+
import androidx.recyclerview.widget.LinearLayoutManager
|
|
13
|
+
import com.photoeditor.editor.ColorPickerAdapter.OnColorPickerClickListener
|
|
14
|
+
import android.widget.TextView
|
|
15
|
+
|
|
16
|
+
class PropertiesBSFragment : BottomSheetDialogFragment(), SeekBar.OnSeekBarChangeListener {
|
|
17
|
+
private var mProperties: Properties? = null
|
|
18
|
+
|
|
19
|
+
interface Properties {
|
|
20
|
+
fun onColorChanged(colorCode: Int)
|
|
21
|
+
fun onOpacityChanged(opacity: Int)
|
|
22
|
+
fun onShapeSizeChanged(shapeSize: Int)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
override fun onCreateView(
|
|
26
|
+
inflater: LayoutInflater,
|
|
27
|
+
container: ViewGroup?,
|
|
28
|
+
savedInstanceState: Bundle?
|
|
29
|
+
): View? {
|
|
30
|
+
return inflater.inflate(R.layout.pe_fragment_bottom_properties_dialog, container, false)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
34
|
+
super.onViewCreated(view, savedInstanceState)
|
|
35
|
+
val rvColor: RecyclerView = view.findViewById(R.id.rvColors)
|
|
36
|
+
val sbOpacity = view.findViewById<SeekBar>(R.id.sbOpacity)
|
|
37
|
+
val sbBrushSize = view.findViewById<SeekBar>(R.id.sbSize)
|
|
38
|
+
|
|
39
|
+
view.findViewById<TextView>(R.id.txtOpacity).setEditorText(R.string.pe_label_opacity)
|
|
40
|
+
view.findViewById<TextView>(R.id.txtBrushSize).setEditorText(R.string.pe_label_brush)
|
|
41
|
+
sbOpacity.setOnSeekBarChangeListener(this)
|
|
42
|
+
sbBrushSize.setOnSeekBarChangeListener(this)
|
|
43
|
+
val layoutManager = LinearLayoutManager(activity, LinearLayoutManager.HORIZONTAL, false)
|
|
44
|
+
rvColor.layoutManager = layoutManager
|
|
45
|
+
rvColor.setHasFixedSize(true)
|
|
46
|
+
val colorPickerAdapter = activity?.let { ColorPickerAdapter(it) }
|
|
47
|
+
colorPickerAdapter?.setOnColorPickerClickListener(object : OnColorPickerClickListener {
|
|
48
|
+
override fun onColorPickerClickListener(colorCode: Int) {
|
|
49
|
+
if (mProperties != null) {
|
|
50
|
+
dismiss()
|
|
51
|
+
mProperties?.onColorChanged(colorCode)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
rvColor.adapter = colorPickerAdapter
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
fun setPropertiesChangeListener(properties: Properties?) {
|
|
59
|
+
mProperties = properties
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
override fun onProgressChanged(seekBar: SeekBar, i: Int, b: Boolean) {
|
|
63
|
+
when (seekBar.id) {
|
|
64
|
+
R.id.sbOpacity -> if (mProperties != null) {
|
|
65
|
+
mProperties?.onOpacityChanged(i)
|
|
66
|
+
}
|
|
67
|
+
R.id.sbSize -> if (mProperties != null) {
|
|
68
|
+
mProperties?.onShapeSizeChanged(i)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
override fun onStartTrackingTouch(seekBar: SeekBar) = Unit
|
|
74
|
+
|
|
75
|
+
override fun onStopTrackingTouch(seekBar: SeekBar) = Unit
|
|
76
|
+
}
|