diff options
author | Allan Wang <me@allanwang.ca> | 2017-08-01 10:48:37 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-08-01 10:48:37 -0700 |
commit | 7d894be6de118357ec908d2d171b6152ce67307d (patch) | |
tree | f34f0676e78433f7f58d6a5bad800430f8e767a0 /mediapicker/src/main/kotlin/ca/allanwang/kau/mediapicker/MediaPickerCore.kt | |
parent | 48213d0b427c478865c75fee912ff1ae8bbaffb5 (diff) | |
download | kau-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.kt | 182 |
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 |