Ini memberikan efek visual transisi mulus dari tampilan thumbnail ke tampilan asli, dan memungkinkan Anda menelusuri gambar biasa, gambar panjang, dan gambar animasi dengan elegan.
implementation 'com.github.iielse:imageviewer:x.y.z'
fun show() { //
val dataList: List<Photo> = // 将要展示的图片集合列表
val clickedData: Photo = // 被点击的其中的那个图片元素信息
val builder = ImageViewerBuilder(
context = view.context,
dataProvider = SimpleDataProvider(clickedData, dataList), // 一次性全量加载 // 实现DataProvider接口支持分页加载
imageLoader = SimpleImageLoader(), // 可使用demo固定写法 // 实现对数据源的加载.支持自定义加载数据类型,加载方案
transformer = SimpleTransformer(), // 可使用demo固定写法 // 以photoId为标示,设置过渡动画的'配对'.
)
builder.show()
}
// 基本是固定写法. Glide 可以换成别的. demo代码中有video的写法.
class SimpleImageLoader : ImageLoader {
/** 根据自身photo数据加载图片.可以使用其它图片加载框架. */
override fun load(view: ImageView, data: Photo, viewHolder: RecyclerView.ViewHolder) {
val it = (data as? MyData?)?.url ?: return
Glide.with(view).load(it)
.placeholder(view.drawable)
.into(view)
}
/**
* 根据自身photo数据加载超大图.subsamplingView数据源需要先将内容完整下载到本地.
*/
override fun load(subsamplingView: SubsamplingScaleImageView, data: Photo, viewHolder: RecyclerView.ViewHolder) {
val it = (data as? MyData?)?.url ?: return
subsamplingDownloadRequest(it)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe { findLoadingView(viewHolder)?.visibility = View.VISIBLE }
.doFinally { findLoadingView(viewHolder)?.visibility = View.GONE }
.doOnNext { subsamplingView.setImage(ImageSource.uri(Uri.fromFile(it))) }
.doOnError { toast(it.message) }
.subscribe().bindLifecycle(subsamplingView)
}
private fun subsamplingDownloadRequest(url: String): Observable<File> {
return Observable.create {
try {
it.onNext(Glide.with(appContext).downloadOnly().load(url).submit().get())
it.onComplete()
} catch (e: java.lang.Exception) {
if (!it.isDisposed) it.onError(e)
}
}
}
private fun findLoadingView(viewHolder: RecyclerView.ViewHolder): View? {
return viewHolder.itemView.findViewById<ProgressBar>(R.id.loadingView)
}
......
}
// 基本是可以作为固定写法.
class SimpleTransformer : Transformer {
override fun getView(key: Long): ImageView? = provide(key)
companion object {
private val transition = HashMap<ImageView, Long>()
fun put(photoId: Long, imageView: ImageView) {
require(isMainThread())
if (!imageView.isAttachedToWindow) return
imageView.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
override fun onViewAttachedToWindow(p0: View?) = Unit
override fun onViewDetachedFromWindow(p0: View?) {
transition.remove(imageView)
imageView.removeOnAttachStateChangeListener(this)
}
})
transition[imageView] = photoId
}
private fun provide(photoId: Long): ImageView? {
transition.keys.forEach {
if (transition[it] == photoId)
return it
}
return null
}
}
}
Pada titik ini integrasi sederhana telah selesai.
(Terapkan 3 metode berikut. Tampilan dan fungsi yang disesuaikan dapat ditambahkan)
builder.setVHCustomizer(MyCustomViewHolderUI())
.builder.setOverlayCustomizer(MyCustomIndicatorUI())
builder.setViewerCallback(MyViewerStateChangedListener())
// 一般监听翻页onPageSelected可以控制 video播放的状态
// viewer 各状态监听回调
interface ViewerCallback : ImageViewerAdapterListener {
// 当点击缩略图变化大图的瞬间
override fun onInit(viewHolder: RecyclerView.ViewHolder) {}
// 当图片被拖动时
override fun onDrag(viewHolder: RecyclerView.ViewHolder, view: View, fraction: Float) {}
// 当图片被拖动但不至于退出浏览
override fun onRestore(viewHolder: RecyclerView.ViewHolder, view: View, fraction: Float) {}
// 当图片被拖动执行退出浏览
override fun onRelease(viewHolder: RecyclerView.ViewHolder, view: View) {}
// 翻页中状态变化
fun onPageScrollStateChanged(state: Int) {}
// 翻页中
fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
// 当某大图页面被选中
fun onPageSelected(position: Int, viewHolder: RecyclerView.ViewHolder) {}
}
milik | Deskripsi fungsi |
---|---|
OFFSCREEN_PAGE_LIMIT | Jumlah item yang dimuat sebelumnya oleh pemirsa |
PENAMPIL_ORIENTASI | arah geser penampil |
LIHAT_BACKGROUND_COLOR | Warna latar belakang saat melihat pratinjau gambar besar (standarnya adalah hitam murni) |
DURATION_TRANSISI | Durasi animasi transisi |
DURATION_BG | Durasi perubahan latar belakang animasi transisi |
SWIPE_DISMISS | Apakah akan mendukung pengembalian seret dan lepas |
SWIPE_TOUCH_SLOP | Tarik ambang batas penginderaan sentuhan |
DISMISS_FRACTION | Seret untuk kembali ke ambang batas |
TRANSISI_OFFSET_Y | Memperbaiki posisi awal animasi transisi di bawah bilah status transparan |
interface Photo {
fun id(): Long // 每条图片数据的唯一标示. 主要用于分页数据加载. 定位过渡动画的对应关系
fun itemType(): @ItemType.Type Int // 是否启用SubsamplingScaleImageView实现图片区块加载或ExoVideoView实现Video加载
}
Dapatkan referensi objek viewer
melalui ViewModelProvider(activity).get(ImageViewerActionViewModel::class.java)
. Anda kemudian dapat menggunakan setCurrentItem(pos: Int)
untuk mengalihkan posisi gambar besar ke posisi dismiss()
ditentukan; gambar besar; remove(item: List<Photo>)
hapus elemen di dalamnya
SimpleViewerCustomizer
Transformer
perlu dikonfigurasi dengan benar. Penting untuk memastikan bahwa nilai kembalian getView
tidak nol.Config.TRANSITION_OFFSET_Y
demo dapat berjalan. demo dapat berjalan. demo dapat berjalan.
Anda semua pernah melihat ini, mengapa Anda tidak mengklik Star
[Wang Chai]
Jika menurut Anda perpustakaan sumber terbuka saya telah membantu Anda menghemat banyak waktu pengembangan, Anda dapat memindai kode QR di bawah untuk memberi saya imbalan. Dorongan Anda adalah motivasi terbesar saya untuk mempertahankan proyek ini