前言
需求是是实现一个可滑动与缩放得功能,说实话控件很多,但是开发者需要具备一定的定制能力,所以简单的功能就不要借助轮子,尽量的自己动手完成,会有一定的成就感和自我提升,以下其实也是拿来主义,最好是重写touch事件,
这里记录一下,希望对大家有所帮助
示例
布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="@dimen/top_bar_height"
android:background="@drawable/top_bar_background">
<TextView
android:layout_width="wrap_content"
android:id="@+id/complete"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="@dimen/margin_20dp"
android:text="@string/finish"
android:textColor="@color/orange"
android:textSize="@dimen/textsize_16sp" />
<ImageView
android:id="@+id/info_back_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginRight="@dimen/margin_10dp"
android:scaleType="centerInside"
android:src="@drawable/set_back_w" />
</RelativeLayout>
<View
android:id="@+id/transparent_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@color/transparent" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="220dp"
android:background="@color/setting_text_clore">
<TextView
android:id="@+id/tip_detector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="@dimen/margin_30dp"
android:text="@string/fusison_detector_tip"
android:textColor="@color/white"
android:textSize="@dimen/textsize_16sp" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_35dp"
android:layout_below="@+id/tip_detector"
android:layout_centerHorizontal="true">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:src="@drawable/gesture_drag_n" />
<View
android:layout_width="@dimen/margin_80dp"
android:layout_height="wrap_content" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:src="@drawable/gesture_zoom_n" />
</LinearLayout>
</RelativeLayout>
</LinearLayout>
定义
class FusionGestureDetectorsPopup(ctx: Context, var fusionX: Int, var fusionY: Int, var fusionScale: Float) : PopupWindow(ctx), View.OnTouchListener {
companion object {
private val TAG = "FusionGesture"
private val MinScale = 2f;//min缩放系数
private val MaxScale = 8f;//max缩放系数
private val MaxFusion = 1024 * 4
private val ZERO = 0F
private val ONE = 1
private val TWO = 2
private val TEN = 10
private val HUNDRED = 100
}
private var lastX = ZERO;
private var lastY = ZERO;
private var lastScale = ZERO
private lateinit var mContentView: View
private var mFusionGestureDetectorsListener: FusionGestureDetectorsListener? = null
interface FusionGestureDetectorsListener {
fun onScale(scale: Int)
fun onMove(x: Int, y: Int)
}
/*
* 注释:
* @author maqi
* created at 2022/11/9 17:45
* https://juejin.cn/post/6988524761148031007
* */
private val mScaleDetector = ScaleGestureDetector(ctx, object : ScaleGestureDetector.SimpleOnScaleGestureListener() {
override fun onScaleBegin(detector: ScaleGestureDetector?): Boolean {
Log.d(TAG, "onScaleBegin")
return super.onScaleBegin(detector)
}
override fun onScaleEnd(detector: ScaleGestureDetector?) {
Log.d(TAG, "onScaleEnd ")
lastScale = ZERO
super.onScaleEnd(detector)
}
override fun onScale(detector: ScaleGestureDetector?): Boolean {
var thizScale = detector!!.scaleFactor
Log.d(TAG, "onScale 1 " + thizScale)
if (lastScale != ZERO) {
val deltaScale = thizScale - lastScale
Log.d(TAG, "onScale 2 " + deltaScale)
fusionScale += deltaScale
if (fusionScale < MinScale) {
fusionScale = MinScale
}
if (fusionScale > MaxScale) {
fusionScale = MaxScale
}
Log.d(TAG, "onScale 3 " + fusionScale)
mFusionGestureDetectorsListener?.onScale((fusionScale * HUNDRED).toInt())
}
lastScale = thizScale
return super.onScale(detector)
}
});
private val mMoveDetector = MoveGestureDetector(ctx, object : MoveGestureDetector.SimpleOnMoveGestureListener() {
override fun onMove(detector: MoveGestureDetector?): Boolean {
val d = detector!!.getFocusDelta()
val thizX = d.x
val thizY = d.y
Log.d(TAG, "onMove x : " + d.x + " y :" + d.y)
if (lastX != ZERO && lastY != ZERO) {
val deltaX = (thizX - lastX).toInt()
val deltY = (thizY - lastY).toInt()
//屏蔽快速移动
if (Math.abs(deltaX) < TEN* TWO && Math.abs(deltY) < TEN* TWO) {
fusionX -= deltaX
fusionY += deltY
}
//限制范围
if (fusionY < -MaxFusion) {
fusionY = -MaxFusion
}
if (fusionX < -MaxFusion) {
fusionX = -MaxFusion
}
if (fusionY > MaxFusion) {
fusionY = MaxFusion
}
if (fusionX > MaxFusion) {
fusionX = MaxFusion
}
mFusionGestureDetectorsListener?.onMove( fusionX,fusionY)
}
lastX = thizX
lastY = thizY
return super.onMove(detector)
}
override fun onMoveBegin(detector: MoveGestureDetector?): Boolean {
Log.d(TAG, "onMoveBegin")
return super.onMoveBegin(detector)
}
override fun onMoveEnd(detector: MoveGestureDetector?) {
lastX = ZERO
lastY = ZERO
super.onMoveEnd(detector)
}
});
init {
initView(ctx)
contentView = mContentView
width = ScreenUtils.getScreenWidth(ctx)
height = ScreenUtils.getScreenHeight(ctx)
isFocusable = true
isOutsideTouchable = true
animationStyle = R.style.dialog_animation_horizontal_style
val dw = ColorDrawable(ctx.resources.getColor(R.color.transparent))
setBackgroundDrawable(dw)
}
private fun initView(ctx: Context) {
mContentView = LayoutInflater.from(ctx).inflate(R.layout.view_fusion_detector_sence, null)
mContentView.findViewById<View>(R.id.complete).setOnClickListener { dismiss() }
mContentView.findViewById<View>(R.id.info_back_tv).setOnClickListener { dismiss() }
val transparentContainer = mContentView.findViewById<View>(R.id.transparent_container)
transparentContainer.setOnTouchListener(this)
}
override fun onTouch(v: View?, event: MotionEvent?): Boolean {
if (event!!.pointerCount == ONE) {
mMoveDetector.onTouchEvent(event)
} else if (event!!.pointerCount == TWO) {
mScaleDetector.onTouchEvent(event)
}
return true;//true:消费掉事件,不继续分发
}
fun setFusionGestureDetectorsListener(fusionGestureDetectorsListener: FusionGestureDetectorsListener) {
mFusionGestureDetectorsListener = fusionGestureDetectorsListener
}
}
使用
if (null == fusionGestureDetectorsPopup) {
fusionGestureDetectorsPopup = FusionGestureDetectorsPopup(requireContext(), fusionY, fusionX, fusionScale / 100f)
fusionGestureDetectorsPopup?.setFusionGestureDetectorsListener(object : FusionGestureDetectorsPopup.FusionGestureDetectorsListener {
override fun onScale(scale: Int) {
}
override fun onMove(x: Int, y: Int) {
}
})
}
if (isfusion) {
fusionGestureDetectorsPopup?.showAtLocation(fusion, Gravity.CENTER, 0, 0)
} else {
fusionGestureDetectorsPopup?.dismiss()
}
引用
https://github.com/Almeros/android-gesture-detectors
https://juejin.cn/post/6988524761148031007#heading-9
PS:android-gesture-detectors提供充分的扩展能力,请自行查阅参考