国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Android 實現(xiàn)單指滑動、雙指縮放照片

這篇具有很好參考價值的文章主要介紹了Android 實現(xiàn)單指滑動、雙指縮放照片。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

一、前景提示

最近接到一個查看大圖的需求,現(xiàn)在圖片展示還不夠大,要求還要能縮小能放大還能保存照片。直接開始Google實現(xiàn)方式。

二、實現(xiàn)功能

根據(jù)查詢到的結(jié)果分為兩種,一個是使用手勢監(jiān)聽來實現(xiàn),第二種監(jiān)聽觸摸事件來實現(xiàn)

  • 手勢監(jiān)聽-- ScaleGestureDetector Google提供的手勢監(jiān)聽類
  • 觸摸事件–OnTouchListener 自己監(jiān)聽觸摸事件自己實現(xiàn)放大縮小的邏輯

2.1 手勢監(jiān)聽

先寫布局文件

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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="match_parent"
  android:layout_height="match_parent"
  tools:context=".MainActivity">

  <androidx.appcompat.widget.AppCompatImageView
    android:id="@+id/iv_example"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:text="Hello World!"
    android:scaleType="fitCenter"
    android:src="@drawable/muffin_7870491_1920"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

再去實現(xiàn)手勢監(jiān)聽方法

class MainActivity : AppCompatActivity() {
    private lateinit var mScaleGestureDetector: ScaleGestureDetector
    private var mScaleFactor: Float = 1.0f
    private lateinit var mImageView: AppCompatImageView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        mImageView = findViewById(R.id.iv_example)
        mScaleGestureDetector = ScaleGestureDetector(this, ScaleGestureListener())
        mImageView.setOnTouchListener { _, event ->
            mScaleGestureDetector.onTouchEvent(event)
            true
        }
    }


    private inner class ScaleGestureListener : ScaleGestureDetector.SimpleOnScaleGestureListener() {
        override fun onScale(detector: ScaleGestureDetector): Boolean {
            mScaleFactor *= detector.scaleFactor
            // 限制縮放因子在0.1到10.0
            mScaleFactor = mScaleFactor.coerceIn(0.1f, 10.0f)
            mImageView.scaleX = mScaleFactor
            mImageView.scaleY = mScaleFactor
            return true
        }
    }
}

代碼很簡單直接使用ScaleGestureDetector去監(jiān)聽觸摸事件,手勢本質(zhì)也是Google內(nèi)部監(jiān)聽事件判斷再回調(diào)給我們使用。當(dāng)然我們這里不去查看源碼,只看實現(xiàn)過程。
在使用過程中發(fā)現(xiàn)這種縮放并不平滑,而且響應(yīng)有點慢,有延遲。猜想內(nèi)部是由很多其他的判斷吧。那我們只想簡單一點怎么搞呢,那就是自己去判斷縮放,還有實現(xiàn)單指滑動用手勢也不太好實現(xiàn)的樣子。所以我們試試第二種方式實現(xiàn)也就是觸摸事件。

2.2 觸摸事件

首先我們實現(xiàn)一下縮放,我們還是沿用上次使用onTouchListener來處理我們的觸摸事件,布局文件中需要把imageView的縮放屬性改為矩陣 android:scaleType=“matrix”

private var startMatrix = Matrix()
mImageView.setOnTouchListener { _, event ->
    when(event.action and MotionEvent.ACTION_MASK) {
        MotionEvent.ACTION_POINTER_DOWN -> {
            // 記錄雙指按下的位置和距離
            startDistance = getDistance(event)
            if (startDistance > 10f) {
                startMatrix.set(mImageView.imageMatrix)
                mode = 2
            }
            return@setOnTouchListener true
        }
    }
    true
}

沒有自己處理過觸摸事件的小伙伴可能會好奇MotionEvent.ACTION_MASK是什么,其實這個是為了處理多點觸摸事件加的一個flag和action做and操作,我們就能處理ACTION_POINTER_DOWN和ACTION_POINTER_UP這兩個多點觸摸事件。
看下代碼邏輯,我們先計算兩個手指的距離,如果距離大于10就證明是縮放操作,設(shè)置成我們自己定義的模式,再把imageView的矩陣保存,后續(xù)對照片移動,縮放都是通過變換矩陣來實現(xiàn)的。
至于計算兩個手指之間的距離用的勾股定理,來個示意圖,大家就明白了。
android 圖片手勢縮放,踩坑記錄,android,自定義View
計算如下。

 private fun getDistance(event: MotionEvent): Float {
        val dx = event.getX(0) - event.getX(1)
        val dy = event.getY(0) - event.getY(1)
        return sqrt(dx * dx + dy * dy)
    }

通過計算能得到直角邊和鄰邊,對他們使用勾股定理就能得到斜邊的值,也就是兩個手指之間的距離。
有做過觸摸事件監(jiān)聽的同學(xué)就應(yīng)該知道,我們下一步要監(jiān)聽移動事件了也就是MotionEvent.ACTION_MOVE。

mImageView.setOnTouchListener { _, event ->
    when (event.action and MotionEvent.ACTION_MASK) {
        MotionEvent.ACTION_POINTER_DOWN -> {
            // 記錄雙指按下的位置和距離
            startDistance = getDistance(event)
            if (startDistance > 10f) {
                startMatrix.set(mImageView.imageMatrix)
                mode = 2
            }
            return@setOnTouchListener true
        }
        MotionEvent.ACTION_MOVE -> {
            if (mode == 2) {
                // 雙指縮放
                val currentDistance = getDistance(event)
                if (currentDistance > 10f) {
                    val scale = currentDistance / startDistance
                    mImageView.imageMatrix = startMatrix.apply {
                        postScale(scale, scale, getMidX(event), getMidY(event))
                    }
                }
            }
            return@setOnTouchListener true
        }
        MotionEvent.ACTION_POINTER_UP -> {
            mode = 0
            return@setOnTouchListener true
        }

        else -> return@setOnTouchListener true

    }

}

這里在move事件中我們也需要對手指之間的距離進行計算,如果距離超過10,就開始計算縮放倍數(shù),通過postScale進行矩陣變換。
在MotionEvent.ACTION_POINTER_UP事件中對mode值進行復(fù)位操作,畢竟還有個單指拖動操作。
如果大家把上面的代碼運行過就會發(fā)現(xiàn)怎么圖片沒有居中顯示,這是因為我們的縮放屬性被改為矩陣也就是android:scaleType=“matrix”,那么想要圖片居中顯示怎么操作呢,只需要在觸摸時去改變縮放屬性,其他的時候不變即可。
我們把imageView恢復(fù)成android:scaleType=“fitCenter”,在onTouchListener中加入(放在when前即可)

mImageView.scaleType = ImageView.ScaleType.MATRIX

這樣一開始就可以保持圖片在中央了。
這樣縮放功能實現(xiàn)了,下面實現(xiàn)單指拖動功能,思路很簡單記錄第一次按下的位置,在移動過程中計算應(yīng)該需要偏移的距離,再記錄下當(dāng)前的位置,以便于下次計算。

private var lastX = 0f
private var lastY = 0f
mImageView.setOnTouchListener { _, event ->
    mImageView.scaleType = ImageView.ScaleType.MATRIX
    when (event.action and MotionEvent.ACTION_MASK) {
        MotionEvent.ACTION_DOWN -> {
            // 記錄單指按下的位置
            lastX = event.x
            lastY = event.y
            mode = 1
            startMatrix.set(mImageView.imageMatrix)
            return@setOnTouchListener true
        }
        MotionEvent.ACTION_POINTER_DOWN -> {
            // 記錄雙指按下的位置和距離
            startDistance = getDistance(event)
            if (startDistance > 10f) {
                startMatrix.set(mImageView.imageMatrix)
                mode = 2
            }
            return@setOnTouchListener true
        }
        MotionEvent.ACTION_MOVE -> {
            if (mode == 1) {
                // 單指拖動
                val dx = event.x - lastX
                val dy = event.y - lastY
                mImageView.imageMatrix = startMatrix.apply {
                    postTranslate(dx, dy)
                }
                lastX = event.x
                lastY = event.y
            } else if (mode == 2) {
                // 雙指縮放
                val currentDistance = getDistance(event)
                if (currentDistance > 10f) {
                    val scale = currentDistance / startDistance
                    mImageView.imageMatrix = startMatrix.apply {
                        postScale(scale, scale, getMidX(event), getMidY(event))
                    }
                }
            }
            return@setOnTouchListener true
        }
        MotionEvent.ACTION_UP, MotionEvent.ACTION_POINTER_UP -> {
            mode = 0
            return@setOnTouchListener true
        }

        else -> return@setOnTouchListener true

    }

}

代碼實現(xiàn)和思路一樣,我們還需要在MotionEvent.ACTION_UP中復(fù)位模式,調(diào)用postTranslate進行偏移。
這樣基本上功能我們都簡單實現(xiàn)了。下面我們就需要優(yōu)化了代碼,如果各位跟著實現(xiàn)了,就會發(fā)現(xiàn)縮放倍數(shù)太大了導(dǎo)致輕輕動一下就會放很大,還有別的都是需要我們優(yōu)化的。

三、功能優(yōu)化

3.1 優(yōu)化縮放倍數(shù)太大問題

其實這個問題和我們處理move事件有關(guān)系,熟悉Android事件機制都知道一個完整的事件流程就是down->move…move->up。知道了這個之后,再仔細看我們的代碼

val currentDistance = getDistance(event)
if (currentDistance > 10f) {
	val scale = currentDistance / startDistance
	mImageView.imageMatrix = startMatrix.apply {
		postScale(scale, scale, getMidX(event), getMidY(event))
	}
}

在move事件中我們這樣處理的,計算縮放倍數(shù)然后縮放,大體一看是沒有什么問題的。**但是,我們的move事件不止執(zhí)行一次,這就導(dǎo)致我們的縮放不止執(zhí)行一次,每次都是在原來的基礎(chǔ)上放大或者縮小。**所以輕輕移動倍數(shù)就會很多。
最簡單的辦法就是我們記錄一下move過程中累計的倍數(shù),如果到達最大值或者最小值就不讓放大或者縮小了。代碼如下。

if (scale > 1.0f) {
	sumScale += scale
} else {
	sumScale -= scale
}
if (sumScale >= maxScale || sumScale <= minScale) {
	return@setOnTouchListener true
}

簡單但是有效的方式。其中max和min,可以自己賦值。

3.2 保持原圖不縮小

實現(xiàn)起來也很簡單,需要先定義一個變量記錄當(dāng)前縮放之后的倍數(shù)。大家測試就會發(fā)現(xiàn),如果是放大操作那么倍數(shù)就會大于1如果是縮小倍數(shù)就會比1 小。我們就可以利用這點來處理我們的邏輯。

private var lastScaleFactor = 1f
if (scale * lastScaleFactor > 1.0f) {
	if (sumScale >= maxScale || sumScale <= minScale) {
		return@setOnTouchListener true
	}
	sumScale += scale
	mImageView.imageMatrix = startMatrix.apply {
		postScale(scale, scale, getMidX(event), getMidY(event))
		lastScaleFactor *= scale
	}
} else {
	sumScale -= scale
}

demo在這里點我點我
tips:demo好像不是放大不是很順暢,但是在項目里用Gilde加載后很流暢,猜測是照片大小問題。但是思路是一樣的問題不大。文章來源地址http://www.zghlxwxcb.cn/news/detail-679093.html

到了這里,關(guān)于Android 實現(xiàn)單指滑動、雙指縮放照片的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Android Studio實現(xiàn)滑動圖片驗證碼

    Android Studio實現(xiàn)滑動圖片驗證碼

    源代碼鏈接 效果: MainActivity SlideImageView activity_main.xml

    2024年02月13日
    瀏覽(29)
  • 【Android】Bitmap圖片旋轉(zhuǎn)、縮放、翻轉(zhuǎn)等變換(90/100)

    【Android】Bitmap圖片旋轉(zhuǎn)、縮放、翻轉(zhuǎn)等變換(90/100)

    自定義BitmapChangeView: 工具類: 布局引用: 應(yīng)用如下: 推薦理由 postman在國內(nèi)使用已經(jīng)越來越困難: 1、登錄問題嚴(yán)重 2、Mock功能服務(wù)基本沒法使用 3、版本更新功能已很匱乏 4、某些外力因素導(dǎo)致postman以后能否使用風(fēng)險較大 出于以上考慮因此筆者自己開發(fā)了一款api調(diào)試開發(fā)工

    2024年02月16日
    瀏覽(21)
  • Android進階:ListView性能優(yōu)化異步加載圖片 使滑動效果流暢

    ListView? 是一種可以顯示一系列項目并能進行滾動顯示的 View,每一行的Item可能包含復(fù)雜的結(jié)構(gòu),可能會從網(wǎng)絡(luò)上獲取icon等的一些圖標(biāo)信息,就現(xiàn)在的網(wǎng)絡(luò)速度要想保持ListView運行的很好滾動流暢是做不到的 所以這里就需要把這些信息利用多線程實現(xiàn)異步加載 實現(xiàn)這樣功能的

    2024年02月16日
    瀏覽(26)
  • Android Studio App開發(fā)之使用相機拍攝照片和從相冊中選取圖片(附源碼 超詳細必看)

    Android Studio App開發(fā)之使用相機拍攝照片和從相冊中選取圖片(附源碼 超詳細必看)

    運行有問題或需要源碼請點贊關(guān)注收藏后評論區(qū)留言~~~ 對于手機拍照的App開發(fā)而言,有兩種實現(xiàn)方式 1:通過 camera工具聯(lián)合表面視圖SurfaceView自行規(guī)劃編碼細節(jié) 2:借助系統(tǒng)相機自動拍照,考慮到多數(shù)場景對圖片并沒有特殊要求,所以使用系統(tǒng)相機更加方便快捷? 效果如下 點

    2024年02月11日
    瀏覽(17)
  • Android 實現(xiàn)滑動數(shù)字選擇器

    Android 實現(xiàn)滑動數(shù)字選擇器

    Android 滑動數(shù)字選擇器是一種用戶界面控件,它允許用戶從一系列數(shù)字中選擇一個值。用戶可以通過滑動手勢或點擊手勢來選擇數(shù)字。以下是一些關(guān)于 Android 滑動數(shù)字選擇器的信息和鏈接: Android NumberPicker:這是 Android 框架提供的原生數(shù)字選擇器控件。它可以通過 XML 或代碼創(chuàng)

    2024年02月07日
    瀏覽(19)
  • Android View實現(xiàn)滑動的方式

    實現(xiàn)View的滑動有三種方式 通過View本身提供的scrollTo/scrollBy方法實現(xiàn)滑動 通過動畫給View施加平移效果來實現(xiàn)滑動 通過改變View LayoutParams使得View重新布局從而實現(xiàn)滑動 scrollTo:通過傳遞的參數(shù)實現(xiàn)絕對滑動 scrollBy:通過傳遞的參數(shù)實現(xiàn)相對滑動 scrollTo和scrollBy只能改變View內(nèi)容

    2024年02月16日
    瀏覽(27)
  • Android——禁止ViewPager的左右滑動功能實現(xiàn)

    Android——禁止ViewPager的左右滑動功能實現(xiàn) 在Android開發(fā)中,ViewPager是一種常用的滑動控件,用于實現(xiàn)頁面的左右切換效果。然而,在某些場景中,我們可能需要禁止ViewPager的左右滑動功能,只允許通過其他方式進行頁面切換。本文將介紹如何在Android中實現(xiàn)禁止ViewPager左右滑動

    2024年02月06日
    瀏覽(24)
  • Android中矩陣Matrix實現(xiàn)平移,旋轉(zhuǎn),縮放和翻轉(zhuǎn)的用法詳細介紹

    Android中矩陣Matrix實現(xiàn)平移,旋轉(zhuǎn),縮放和翻轉(zhuǎn)的用法詳細介紹

    一,矩陣Matrix的數(shù)學(xué)原理 矩陣的數(shù)學(xué)原理涉及到矩陣的運算和變換,是高等代數(shù)學(xué)中的重要概念。在圖形變換中,矩陣起到關(guān)鍵作用,通過矩陣的變換可以改變圖形的位置、形狀和大小。矩陣的運算是數(shù)值分析領(lǐng)域的重要問題,對矩陣進行分解和簡化可以簡化計算過程。對于

    2024年01月22日
    瀏覽(38)
  • Flutter 雙指縮放和雙指移動共存手勢檢測系列之--1方案

    Flutter 雙指縮放和雙指移動共存手勢檢測系列之--1方案

    本文所采用Flutter 版本為 3.10.6, 也許后續(xù)版本官方會對手勢做進一步豐富完善,以解決本文涉及到的解決方案。 本文涉及項目手勢需求 :雙指向外或內(nèi)觸屏伸縮,對圖片進行縮放;雙指在屏幕上同向觸屏移動,移動圖片。 Flutter 使用中采用 GestureDetector 進行移動或是手勢判

    2024年02月02日
    瀏覽(22)
  • vue 拖動、縮放容器組件,支持移動端雙指縮放和PC端鼠標(biāo)滾輪縮放

    本組件基于CSS的transform實現(xiàn)。移動端監(jiān)聽touch事件(單指移動,雙指移動+縮放),PC端監(jiān)聽mouse事件(移動)和滾動事件wheel(縮放),更新transform的translateX/translateY/scale值,從而實現(xiàn)縮放、移動。由于transform不會產(chǎn)生重排,因此不節(jié)流也可以有很好的性能,用戶體驗就像德芙

    2024年02月03日
    瀏覽(94)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包