imageviewer
2.1.23
썸네일 보기에서 원본 보기로 원활하게 전환되는 시각적 효과를 제공하며 일반 사진, 긴 사진, 애니메이션 사진을 우아하게 탐색할 수 있습니다.
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
}
}
}
이제 간단한 통합이 완료되었습니다.
(아래 3가지 방법으로 구현하세요. 맞춤형 디스플레이 및 기능 추가 가능)
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) {}
}
재산 | 기능 설명 |
---|---|
OFFSCREEN_PAGE_LIMIT | 시청자가 미리 로드한 항목 수 |
VIEWER_ORIENTATION | 뷰어 슬라이딩 방향 |
VIEWER_BACKGROUND_COLOR | 큰 이미지를 미리 볼 때 배경색(기본값은 순수 검정색) |
DURATION_TRANSITION | 전환 애니메이션 기간 |
DURATION_BG | 전환 애니메이션 배경 변경 기간 |
SWIPE_DISMISS | 드래그 앤 드롭 반환 지원 여부 |
SWIPE_TOUCH_SLOP | 드래그 터치 감지 임계값 |
DISMISS_FRACTION | 경계 임계값으로 돌아가려면 드래그하세요. |
TRANSITION_OFFSET_Y | 투명한 상태 표시줄 아래 전환 애니메이션의 시작 위치를 수정했습니다. |
interface Photo {
fun id(): Long // 每条图片数据的唯一标示. 主要用于分页数据加载. 定位过渡动画的对应关系
fun itemType(): @ItemType.Type Int // 是否启用SubsamplingScaleImageView实现图片区块加载或ExoVideoView实现Video加载
}
ViewModelProvider(activity).get(ImageViewerActionViewModel::class.java)
통해 viewer
개체 참조를 얻은 다음 setCurrentItem(pos: Int)
사용하여 큰 이미지의 위치를 지정된 위치로 전환하여 탐색을 dismiss()
큰 이미지 remove(item: List<Photo>)
그 안의 요소 삭제
SimpleViewerCustomizer
구현할 수 있습니다.Transformer
올바르게 구성해야 합니다. getView
반환 값이 null이 아닌지 확인해야 합니다.Config.TRANSITION_OFFSET_Y
데모를 실행할 수 있습니다. 데모를 실행할 수 있습니다. 데모 코드가 리팩터링되었습니다.
다들 보셨을 텐데요, Star
[왕차이]를 눌러주시면 어떨까요?
내 오픈 소스 라이브러리가 개발 시간을 많이 절약하는 데 도움이 되었다고 생각하신다면 아래 QR 코드를 스캔하여 저에게 보상해 주세요. 귀하의 격려는 프로젝트를 유지하는 가장 큰 동기입니다