Skip to content

Commit

Permalink
working sample on both simple loading and transition.
Browse files Browse the repository at this point in the history
  • Loading branch information
luca committed Dec 15, 2019
1 parent 4897ff7 commit cec598c
Show file tree
Hide file tree
Showing 21 changed files with 617 additions and 147 deletions.
2 changes: 1 addition & 1 deletion lib/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,5 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_ver"
implementation 'androidx.core:core-ktx:1.1.0'

implementation "com.github.KirkBushman:subsampling-scale-image-view:$ssiv_ver"
api "com.github.KirkBushman:subsampling-scale-image-view:$ssiv_ver"
}
22 changes: 18 additions & 4 deletions lib/src/main/java/com/kirkbushman/largeimageview/ImageLoader.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,25 @@ import android.view.View

interface ImageLoader {

fun getThumbnailView(context: Context): View
/**
* Receive from the user the view that binds to thumbnailView
*/
fun getThumbnailView(context: Context): View?

/**
* Load the image to the View provided, the method is up to the user
*/
fun loadThumbnail(view: View, url: String)

fun preloadSource(url: String)
/**
* Receive from the user the view that binds to errorView
*/
fun getErrorView(context: Context): View?

// fun onImageDownloaded(onLoaded: () -> Unit)
// fun onImageErrored(onErrored: () -> Unit)
/**
* Start preloading the large image as a java File,
* the method used is up to the user, use the callback to report if the image is available
* or the fetching went wrong.
*/
fun preloadSource(url: String, callback: ImageReadyCallback)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.kirkbushman.largeimageview

import java.io.File

interface ImageReadyCallback {

/**
* The large image preloaded is ready, as a java File Object
*/
fun onImageReady(file: File, forceImageShow: Boolean = false)

/**
* The process did return an error.
*/
fun onImageErrored()
}
184 changes: 157 additions & 27 deletions lib/src/main/java/com/kirkbushman/largeimageview/LargeImageView.kt
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
package com.kirkbushman.largeimageview

import android.content.Context
import android.net.Uri
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.annotation.UiThread
import com.davemorrissey.labs.subscaleview.ImageSource
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
import java.io.File

@Suppress("unused", "MemberVisibilityCanBePrivate")
class LargeImageView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {

private var loader: ImageLoader? = null
class LargeImageView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : FrameLayout(context, attrs, defStyleAttr) {

private var thumbnailUrl: String? = null
private var sourceUrl: String? = null

private var thumbnailView: View? = null
private var errorView: View? = null
private var sourceView: SubsamplingScaleImageView? = null

private var loader: ImageLoader? = null
private var viewsShownListener: OnViewsShownListener? = null

private var showImageWhenAvailable = true

init {
Expand All @@ -33,10 +35,14 @@ class LargeImageView @JvmOverloads constructor(
typedArray.recycle()
}

fun setImageLoader(loader: ImageLoader) {
fun setImageLoader(loader: ImageLoader?) {
this.loader = loader
}

fun getSsiv(): SubsamplingScaleImageView? {
return sourceView
}

fun getShowImageWhenAvailable(): Boolean {
return showImageWhenAvailable
}
Expand All @@ -45,47 +51,171 @@ class LargeImageView @JvmOverloads constructor(
this.showImageWhenAvailable = showImageWhenAvailable
}

fun setThumbnail(thumbnailUrl: String) {
setImage(thumbnailUrl, null)
}

fun setImage(sourceUrl: String) {
setImage(null, sourceUrl)
fun setOnViewShownListener(viewsShownListener: OnViewsShownListener?) {
this.viewsShownListener = viewsShownListener
}

fun setImage(thumbnailUrl: String?, sourceUrl: String?) {
this.thumbnailUrl = thumbnailUrl
this.sourceUrl = sourceUrl

loadImage()
startLoading()
}

private fun loadImage() {
fun triggerShowImage() {

if (loader == null) {
if (showImageWhenAvailable) {
return
}

thumbnailUrl?.let { thumbUrl ->
showImage()
}

private fun startLoading() {

clearViews()

loader?.let { loader ->

// show the thumbnail in the meantime,
// while the large image is loading in the background.
thumbnailUrl?.let { thumbUrl ->

thumbnailView = loader.getThumbnailView(context)
thumbnailView?.let { thumbView ->

loader.loadThumbnail(thumbView, thumbUrl)

showThumbnail()
}
}

// start loading in the background the real image.
sourceUrl?.let { url ->

sourceView = SubsamplingScaleImageView(context)
sourceView?.let { view ->

loader.preloadSource(url, object : ImageReadyCallback {

// if the image is ready set it in the SSIV
//
// if showImageWhenAvailable is set to true,
// show the main image right away
//
// otherwise wait for triggerShowImage() to get called.
//
override fun onImageReady(file: File, forceImageShow: Boolean) {

view.setImage(ImageSource.uri(Uri.fromFile(file)))

if (showImageWhenAvailable || forceImageShow) {
showImage()
}
}

// if something went wrong, show the error view.
override fun onImageErrored() {
errorView = loader.getErrorView(context)
errorView?.let { _ ->

showErrorView()
}
}
})
}
}
}
}

fun clearViews() {
if (childCount > 0) {
removeAllViews()
}

thumbnailView = null
errorView = null
sourceView = null
}

thumbnailView = loader!!.getThumbnailView(context)
thumbnailView?.let { thumbView ->
@UiThread
private fun showThumbnail() {

loader!!.loadThumbnail(thumbView, thumbUrl)
if (thumbnailView != null) {
if (findViewById<View>(thumbnailView!!.id) == null) {

addView(thumbnailView,
addView(
thumbnailView,
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT)
ViewGroup.LayoutParams.MATCH_PARENT
)
}

viewsShownListener?.onThumbnailViewShown(thumbnailView!!)
}

sourceUrl?.let { url ->
if (thumbnailView?.visibility != View.VISIBLE) {
thumbnailView?.visibility = View.VISIBLE
}
}

sourceView = SubsamplingScaleImageView(context)
sourceView?.let { view ->
@UiThread
private fun showErrorView() {

loader!!.preloadSource(url)
if (errorView != null) {
if (findViewById<View>(errorView!!.id) == null) {

addView(
errorView,
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
}

viewsShownListener?.onErrorViewShown(errorView!!)
}

if (errorView?.visibility != View.VISIBLE) {
errorView?.visibility = View.VISIBLE
}

if (childCount > 0) {

postDelayed({

sourceView?.visibility = View.GONE
thumbnailView?.visibility = View.GONE
}, 1000)
}
}

@UiThread
private fun showImage() {

if (sourceView != null) {
if (findViewById<View>(sourceView!!.id) == null) {

addView(
sourceView,
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
}

viewsShownListener?.onImageViewShown(sourceView!!)
}

if (sourceView?.visibility != View.VISIBLE) {
sourceView?.visibility = View.VISIBLE
}

if (childCount > 0) {

postDelayed({

errorView?.visibility = View.GONE
thumbnailView?.visibility = View.GONE
}, 1000)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.kirkbushman.largeimageview

import android.view.View
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView

interface OnViewsShownListener {

/**
* Called after the thumbnail view is attached as children and shown
*/
fun onThumbnailViewShown(view: View)

/**
* Called after the image view is attached as children and shown
*/
fun onImageViewShown(view: SubsamplingScaleImageView)

/**
* Called after the error view is attached as children and shown
*/
fun onErrorViewShown(view: View)
}
15 changes: 10 additions & 5 deletions sampleapp/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
xmlns:tools="http://schemas.android.com/tools"
package="com.kirkbushman.largeimageview.sampleapp">

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
Expand All @@ -19,14 +22,16 @@
</intent-filter>
</activity>

<activity android:name=".BasicActivity"
<activity android:name=".activities.BasicActivity"
android:parentActivityName=".MainActivity" />

<activity android:name=".AnimFirstActivity"
android:parentActivityName=".MainActivity" />
<activity android:name=".activities.AnimFirstActivity"
android:parentActivityName=".MainActivity"
android:theme="@style/TransitionTheme" />

<activity android:name=".AnimSecondActivity"
android:parentActivityName=".AnimFirstActivity" />
<activity android:name=".activities.AnimSecondActivity"
android:parentActivityName=".activities.AnimFirstActivity"
android:theme="@style/TransitionTheme" />


</application>
Expand Down

This file was deleted.

This file was deleted.

Loading

0 comments on commit cec598c

Please sign in to comment.