aboutsummaryrefslogtreecommitdiff
path: root/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerCore.kt
diff options
context:
space:
mode:
authorAllan Wang <me@allanwang.ca>2017-08-01 10:48:37 -0700
committerGitHub <noreply@github.com>2017-08-01 10:48:37 -0700
commit7d894be6de118357ec908d2d171b6152ce67307d (patch)
treef34f0676e78433f7f58d6a5bad800430f8e767a0 /mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerCore.kt
parent48213d0b427c478865c75fee912ff1ae8bbaffb5 (diff)
downloadkau-7d894be6de118357ec908d2d171b6152ce67307d.tar.gz
kau-7d894be6de118357ec908d2d171b6152ce67307d.tar.bz2
kau-7d894be6de118357ec908d2d171b6152ce67307d.zip
Imagepicker -> mediapicker (#16)3.2.1
* Readme * Fix kau direction bits * Truly support transparent ripples * Update changelog * Test rect as base * Replace fab transition with generic fade scale transition * Add scalexy func * Add scaleXY * Add arguments to fadeScaleTransition * Clean up ink indicator * Create setOnSingleTapListener * Fix lint and add rndColor * Create kotterknife resettables * Add readme and missing objec * Create lazy resettable registered * Update core docs * Opt for separate class for resettable registry * Clean up resettable registry * Rename functions * Add ripple callback listener * Adjust kprefactivity desc color * Add more transitions * Add delete keys option * Add instrumentation tests * switch id * Revert automatic instrumental tests * Generify imagepickercore and prepare video alternative * Create working video picker * Address possible null issue * Update searchview * Make layouts public * Add changelog test * Update logo link * Add custom color gif * Rename imagepicker to mediapicker * Clean up * Fix remaining merge conflicts * Update readme * Update readme
Diffstat (limited to 'mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerCore.kt')
-rw-r--r--mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerCore.kt182
1 files changed, 182 insertions, 0 deletions
diff --git a/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerCore.kt b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerCore.kt
new file mode 100644
index 0000000..255cec4
--- /dev/null
+++ b/mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerCore.kt
@@ -0,0 +1,182 @@
+package ca.allanwang.kau.mediapicker
+
+import android.Manifest
+import android.app.Activity
+import android.content.Context
+import android.content.Intent
+import android.database.Cursor
+import android.graphics.Color
+import android.graphics.drawable.Drawable
+import android.os.Bundle
+import android.provider.MediaStore
+import android.support.v4.app.LoaderManager
+import android.support.v4.content.CursorLoader
+import android.support.v4.content.Loader
+import android.support.v7.app.AppCompatActivity
+import android.support.v7.widget.GridLayoutManager
+import android.support.v7.widget.RecyclerView
+import ca.allanwang.kau.animators.FadeScaleAnimatorAdd
+import ca.allanwang.kau.animators.KauAnimator
+import ca.allanwang.kau.permissions.kauRequestPermissions
+import ca.allanwang.kau.utils.dimenPixelSize
+import ca.allanwang.kau.utils.toast
+import com.mikepenz.fastadapter.IItem
+import com.mikepenz.fastadapter.commons.adapters.FastItemAdapter
+import com.mikepenz.google_material_typeface_library.GoogleMaterial
+import com.mikepenz.iconics.IconicsDrawable
+
+/**
+ * Created by Allan Wang on 2017-07-23.
+ *
+ * Container for the main logic behind the both pickers
+ */
+abstract class MediaPickerCore<T : IItem<*, *>>(val mediaType: MediaType) : AppCompatActivity(), LoaderManager.LoaderCallbacks<Cursor> {
+
+ companion object {
+ /**
+ * Given the dimensions of our device and a minimum image size,
+ * Computer the optimal column count for our grid layout
+ *
+ * @return column count
+ */
+ fun computeColumnCount(context: Context): Int {
+ val minImageSizePx = context.dimenPixelSize(R.dimen.kau_image_minimum_size)
+ val screenWidthPx = context.resources.displayMetrics.widthPixels
+ return screenWidthPx / minImageSizePx
+ }
+
+ /**
+ * Compute our resulting image size
+ */
+ fun computeViewSize(context: Context): Int {
+ val screenWidthPx = context.resources.displayMetrics.widthPixels
+ return screenWidthPx / computeColumnCount(context)
+ }
+
+ /**
+ * Create error tile for a given item
+ */
+ fun getErrorDrawable(context: Context): Drawable {
+ val sizePx = MediaPickerCore.computeViewSize(context)
+ return IconicsDrawable(context, GoogleMaterial.Icon.gmd_error)
+ .sizePx(sizePx)
+ .backgroundColor(accentColor)
+ .paddingPx(sizePx / 3)
+ .color(Color.WHITE)
+ }
+
+ var accentColor: Int = 0xff666666.toInt()
+
+ /**
+ * Helper method to retrieve the media from our media picker
+ * This is used for both single and multiple photo picks
+ */
+ fun onMediaPickerResult(resultCode: Int, data: Intent?): List<MediaModel> {
+ if (resultCode != Activity.RESULT_OK || data == null || !data.hasExtra(MEDIA_PICKER_RESULT))
+ return emptyList()
+ return data.getParcelableArrayListExtra(MEDIA_PICKER_RESULT)
+ }
+
+ /**
+ * Number of loaded items we should cache
+ * This is arbitrary
+ */
+ const val CACHE_SIZE = 80
+ }
+
+ val adapter: FastItemAdapter<T> = FastItemAdapter()
+
+ /**
+ * Further improve preloading by extending the layout space
+ */
+ val extraSpace: Int by lazy { resources.displayMetrics.heightPixels }
+
+ fun initializeRecycler(recycler: RecyclerView) {
+ recycler.apply {
+ val manager = object : GridLayoutManager(context, computeColumnCount(context)) {
+ override fun getExtraLayoutSpace(state: RecyclerView.State?): Int {
+ return if (mediaType != MediaType.VIDEO) extraSpace else super.getExtraLayoutSpace(state)
+ }
+ }
+ setItemViewCacheSize(CACHE_SIZE)
+ isDrawingCacheEnabled = true
+ layoutManager = manager
+ adapter = this@MediaPickerCore.adapter
+ setHasFixedSize(true)
+ itemAnimator = KauAnimator(FadeScaleAnimatorAdd(0.8f))
+ }
+ }
+
+ //Sort by descending date
+ var sortQuery = MediaStore.MediaColumns.DATE_MODIFIED + " DESC"
+
+ override fun onCreateLoader(id: Int, args: Bundle?): Loader<Cursor> {
+ return CursorLoader(this, mediaType.contentUri, MediaModel.projection, null, null, sortQuery)
+ }
+
+ /**
+ * Request read permissions and load all external items
+ * The result will be filtered through {@link #onLoadFinished(Loader, Cursor)}
+ * Call this to make sure that we request permissions each time
+ * The adapter will be cleared on each successful call
+ */
+ open fun loadItems() {
+ kauRequestPermissions(Manifest.permission.READ_EXTERNAL_STORAGE) {
+ granted, _ ->
+ if (granted) {
+ supportLoaderManager.initLoader(LOADER_ID, null, this)
+ onStatusChange(true)
+ } else {
+ toast(R.string.kau_permission_denied)
+ onStatusChange(false)
+ }
+ }
+ }
+
+ override fun onLoadFinished(loader: Loader<Cursor>?, data: Cursor?) {
+ reset()
+ if (data == null || !data.moveToFirst()) {
+ toast(R.string.kau_no_items_found)
+ onStatusChange(false)
+ return
+ }
+ val items = mutableListOf<T>()
+ do {
+ val model = MediaModel(data)
+ if (!shouldLoad(model)) continue
+ items.add(converter(model))
+ } while (data.moveToNext())
+ addItems(items)
+ }
+
+ abstract fun converter(model: MediaModel): T
+
+ override fun onLoaderReset(loader: Loader<Cursor>?) = reset()
+
+ /**
+ * Called at the end of [onLoadFinished]
+ * when the adapter should add the items
+ */
+ open fun addItems(items: List<T>) {
+ adapter.add(items)
+ }
+
+ /**
+ * Clears the adapter to prepare for a new load
+ */
+ open fun reset() {
+ adapter.clear()
+ }
+
+ /**
+ * Optional filter to decide which items get displayed
+ * Defaults to checking their sizes to filter out
+ * very small items such as lurking drawables/icons
+ *
+ * Returns true if model should be displayed, false otherwise
+ */
+ open fun shouldLoad(model: MediaModel): Boolean = model.size > 10000L
+
+ open fun onStatusChange(loaded: Boolean) {}
+
+} \ No newline at end of file