22人参与 • 2025-02-24 • Android
经常会遇到类似微信聊天图片点击放大缩小的效果,从点击位置的图片放大,再点击缩小回去原位置的效果,查找过网上代码,不过可参考比较少,这里将android官方代码进行略作修改有了以下代码。
效果如下:
item_zoom.xml
<?xml version="1.0" encoding="utf-8"?> <framelayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="wrap_content" android:layout_height="wrap_content"> <imagebutton android:id="@+id/thumb_button_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginright="1dp" android:contentdescription="@string/description_image_1" android:scaletype="centercrop" android:src="@drawable/ic_main_img" /> </framelayout>
activity_zoom_list.xml
<framelayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.recyclerview.widget.recyclerview android:id="@+id/rv_room" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" app:layoutmanager="androidx.recyclerview.widget.linearlayoutmanager" tools:itemcount="3" tools:listitem="@layout/item_zoom"/> <!-- this initially hidden imageview holds the zoomed version of the preceding images. without transformations applied, it fills the entire screen. to achieve the zoom animation, this view's bounds are animated from the bounds of the preceding thumbnail button to its final laid-out bounds. --> <imageview android:id="@+id/expanded_image" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="invisible" android:contentdescription="@string/description_zoom_touch_close" /> </framelayout>
zoomadapter.kt
class zoomadapter: recyclerview.adapter<zoomadapter.vh>() { var itemclick: ( (view) -> unit ) ?= null inner class vh(binding: itemzoombinding): recyclerview.viewholder(binding.root) override fun oncreateviewholder(parent: viewgroup, viewtype: int): vh { val layoutinflater = layoutinflater.from(parent.context) val binding = itemzoombinding.inflate(layoutinflater,parent,false) binding.thumbbutton1.setonclicklistener { itemclick?.invoke(it) } return vh(binding) } override fun onbindviewholder(holder: vh, position: int) { } override fun getitemcount(): int = 3 }
zoomactivity.kt
/** * 仿写微信应用中图片放大缩小效果 */ class zoomactivity: fragmentactivity() { // hold a reference to the current animator so that it can be canceled // midway. private var currentanimator: animator? = null // the system "short" animation time duration in milliseconds. this duration // is ideal for subtle animations or animations that occur frequently. private var shortanimationduration: int = 0 private val binding: activityzoomlistbinding by lazy { activityzoomlistbinding.inflate(layoutinflater) } private val adapter = zoomadapter() override fun oncreate(savedinstancestate: bundle?) { super.oncreate(savedinstancestate) setcontentview(binding.root) // retrieve and cache the system's default "short" animation time. shortanimationduration = resources.getinteger(android.r.integer.config_shortanimtime) initview() } private fun initview(){ binding.rvroom.adapter = adapter // hook up taps on the thumbnail views. adapter.itemclick = { zoomimagefromthumb(it, r.drawable.ic_main_img) } } private fun zoomimagefromthumb(thumbview: view, imageresid: int) { // if there's an animation in progress, cancel it immediately and // proceed with this one. currentanimator?.cancel() // load the high-resolution "zoomed-in" image. binding.expandedimage.setimageresource(imageresid) // calculate the starting and ending bounds for the zoomed-in image. val startboundsint = rect() val finalboundsint = rect() val globaloffset = point() // the start bounds are the global visible rectangle of the thumbnail, // and the final bounds are the global visible rectangle of the // container view. set the container view's offset as the origin for the // bounds, since that's the origin for the positioning animation // properties (x, y). thumbview.getglobalvisiblerect(startboundsint) binding.container.getglobalvisiblerect(finalboundsint, globaloffset) startboundsint.offset(-globaloffset.x, -globaloffset.y) finalboundsint.offset(-globaloffset.x, -globaloffset.y) val startbounds = rectf(startboundsint) val finalbounds = rectf(finalboundsint) // using the "center crop" technique, adjust the start bounds to be the // same aspect ratio as the final bounds. this prevents unwanted // stretching during the animation. calculate the start scaling factor. // the end scaling factor is always 1.0. val startscale: float if ((finalbounds.width() / finalbounds.height() > startbounds.width() / startbounds.height())) { // extend start bounds horizontally. startscale = startbounds.height() / finalbounds.height() val startwidth: float = startscale * finalbounds.width() val deltawidth: float = (startwidth - startbounds.width()) / 2 startbounds.left -= deltawidth.toint() startbounds.right += deltawidth.toint() } else { // extend start bounds vertically. startscale = startbounds.width() / finalbounds.width() val startheight: float = startscale * finalbounds.height() val deltaheight: float = (startheight - startbounds.height()) / 2f startbounds.top -= deltaheight.toint() startbounds.bottom += deltaheight.toint() } // hide the thumbnail and show the zoomed-in view. when the animation // begins, it positions the zoomed-in view in the place of the // thumbnail. thumbview.alpha = 0f animatezoomtolargeimage(startbounds, finalbounds, startscale) setdismisslargeimageanimation(thumbview, startbounds, startscale) } private fun animatezoomtolargeimage(startbounds: rectf, finalbounds: rectf, startscale: float) { binding.expandedimage.visibility = view.visible // set the pivot point for scale_x and scale_y transformations to the // top-left corner of the zoomed-in view. the default is the center of // the view. binding.expandedimage.pivotx = 0f binding.expandedimage.pivoty = 0f // construct and run the parallel animation of the four translation and // scale properties: x, y, scale_x, and scale_y. currentanimator = animatorset().apply { play( objectanimator.offloat( binding.expandedimage, view.x, startbounds.left, finalbounds.left) ).apply { with(objectanimator.offloat(binding.expandedimage, view.y, startbounds.top, finalbounds.top)) with(objectanimator.offloat(binding.expandedimage, view.scale_x, startscale, 1f)) with(objectanimator.offloat(binding.expandedimage, view.scale_y, startscale, 1f)) } duration = shortanimationduration.tolong() interpolator = decelerateinterpolator() addlistener(object : animatorlisteneradapter() { override fun onanimationend(animation: animator) { currentanimator = null } override fun onanimationcancel(animation: animator) { currentanimator = null } }) start() } } private fun setdismisslargeimageanimation(thumbview: view, startbounds: rectf, startscale: float) { // when the zoomed-in image is tapped, it zooms down to the original // bounds and shows the thumbnail instead of the expanded image. binding.expandedimage.setonclicklistener { currentanimator?.cancel() // animate the four positioning and sizing properties in parallel, // back to their original values. currentanimator = animatorset().apply { play(objectanimator.offloat(binding.expandedimage, view.x, startbounds.left)).apply { with(objectanimator.offloat(binding.expandedimage, view.y, startbounds.top)) with(objectanimator.offloat(binding.expandedimage, view.scale_x, startscale)) with(objectanimator.offloat(binding.expandedimage, view.scale_y, startscale)) } duration = shortanimationduration.tolong() interpolator = decelerateinterpolator() addlistener(object : animatorlisteneradapter() { override fun onanimationend(animation: animator) { thumbview.alpha = 1f binding.expandedimage.visibility = view.gone currentanimator = null } override fun onanimationcancel(animation: animator) { thumbview.alpha = 1f binding.expandedimage.visibility = view.gone currentanimator = null } }) start() } } } }
到此这篇关于android仿微信聊天图片的放大缩小效果的文章就介绍到这了,更多相关android微信聊天图片放大缩小内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论