人妖在线一区,国产日韩欧美一区二区综合在线,国产啪精品视频网站免费,欧美内射深插日本少妇

新聞動態(tài)

Dialog 按照順序彈窗的優(yōu)雅寫法

發(fā)布日期:2022-01-02 08:28 | 文章來源:腳本之家

我為 Compose 寫了一個波浪效果的進度加載庫,API 的設計上符合 Compose 的開發(fā)規(guī)范,使用非常簡便。

1. 使用方式

在 root 的 build.gradle 中引入 jitpack

allprojects {
	repositories {
		...
		maven { url 'https://jitpack.io' }
	}
}

在 module 的 build.gradle 中引入 ComposeWaveLoading 的最新版本

dependencies {
 implementation 'com.github.vitaviva:ComposeWaveLoading:$latest_version'
}

2. API 設計思想

Box {
 WaveLoading (
  progress = 0.5f // 0f ~ 1f
 ) {
  Image(
 painter = painterResource(id = R.drawable.logo_tiktok),
 contentDescription = ""
  )
 }
}

傳統(tǒng)的 UI 開發(fā)方式中,設計這樣一個波浪控件,一般會使用自定義 View 并將 Image 等作為屬性傳入。 而在 Compose 中,我們讓 WaveLoadingImage 以組合的方式使用,這樣的 API 更加靈活,WaveLoding 的內部可以是 Image,也可以是 Text 亦或是其他 Composable。波浪動畫不拘泥于某一特定 Composable, 任何 Composable 都可以以波浪動畫的形式展現(xiàn), 通過 Composable 的組合使用,擴大了 “能力” 的覆蓋范圍。

3. API 參數(shù)介紹

@Composable
fun WaveLoading(
 modifier: Modifier = Modifier,
 foreDrawType: DrawType = DrawType.DrawImage,
 backDrawType: DrawType = rememberDrawColor(color = Color.LightGray),
 @FloatRange(from = 0.0, to = 1.0) progress: Float = 0f,
 @FloatRange(from = 0.0, to = 1.0) amplitude: Float = defaultAmlitude,
 @FloatRange(from = 0.0, to = 1.0) velocity: Float = defaultVelocity,
 content: @Composable BoxScope.() -> Unit
) { ... }

參數(shù)說明如下:

參數(shù) 說明
progress 加載進度
foreDrawType 波浪圖的繪制類型: DrawColor 或者 DrawImage
backDrawType 波浪圖的背景繪制
amplitude 波浪的振幅, 0f ~ 1f 表示振幅在整個繪制區(qū)域的占比
velocity 波浪移動的速度
content 子Composalble

接下來重點介紹一下 DrawType。

DrawType

波浪的進度體現(xiàn)在前景(foreDrawType)和后景(backDrawType)的視覺差,我們可以為前景后景分別指定不同的 DrawType 改變波浪的樣式。

sealed interface DrawType {
 object None : DrawType
 object DrawImage : DrawType
 data class DrawColor(val color: Color) : DrawType
}

如上,DrawType 有三種類型:

  • None: 不進行繪制
  • DrawColor:使用單一顏色繪制
  • DrawImage:按照原樣繪制

以下面這個 Image 為例, 體會一下不同 DrawType 的組合效果

index backDrawType foreDrawType 說明
1 DrawImage DrawImage 背景灰度,前景原圖
2 DrawColor(Color.LightGray) DrawImage 背景單色,前景原圖
3 DrawColor(Color.LightGray) DrawColor(Color.Cyan) 背景單色,前景單色
4 None DrawColor(Color.Cyan) 無背景,前景單色

注意 backDrawType 設置為 DrawImage 時,會顯示為灰度圖。

4. 原理淺析

簡單介紹一下實現(xiàn)原理。為了便于理解,代碼經過簡化處理,完整代碼可以在 github 查看

這個庫的關鍵是可以將 WaveLoading {...} 內容取出,加以波浪動畫的形式顯示。所以需要將子 Composalbe 轉成 Bitmap 進行后續(xù)處理。

4.1 獲取 Bitmap

我在 Compose 中沒找到獲取位圖的辦法,所以用了一個 trick 的方式, 通過 Compose 與 Android 原生視圖良好的互操作性,先將子 Composalbe 顯示在 AndroidView 中,然后通過 native 的方式獲取 Bitmap:

@Composable
fun WaveLoading (...)
{
 Box {
 
  var _bitmap by remember {
mutableStateOf(Bitmap.createBitmap(1, 1, Bitmap.Config.RGB_565))
  }
  
  AndroidView(
factory = { context ->
 // Creates custom view
 object : AbstractComposeView(context) {
 
  @Composable
  override fun Content() {Box(Modifier.wrapContentSize(){
content()}
  }
 
 
  override fun dispatchDraw(canvas: Canvas?) {val bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)val canvas2 = Canvas(source)super.dispatchDraw(canvas2)_bitmap = bmp
  }
 
 }
}
 
  )
 
 
  WaveLoadingInternal(bitmap = _bitmap)
 
 }
}

AndroidView 是一個可以繪制 Composable 的原生控件,我們將 WaveLoading 的子 Composable 放在其 Content 中,然后在 dispatchDraw 中繪制時,將內容繪制到我們準備好的 Bitmap 中。

4.2 繪制波浪線

我們基于 Compose 的 Canvas 繪制波浪線,波浪線通過 Path 承載 定義 WaveAnim 用來進行波浪線的繪制

internal data class WaveAnim(
 val duration: Int,
 val offsetX: Float,
 val offsetY: Float,
 val scaleX: Float,
 val scaleY: Float,
) {
 
 private val _path = Path()
 
 //繪制波浪線
 internal fun buildWavePath(
  dp: Float,
  width: Float,
  height: Float,
  amplitude: Float,
  progress: Float
 ): Path {
 
  var wave = (scaleY * amplitude).roundToInt() //計算拉伸之后的波幅
 
  _path.reset()
  _path.moveTo(0f, height)
  _path.lineTo(0f, height * (1 - progress))
 
  // 通過正弦曲線繪制波浪
  if (wave > 0) {
 var x = dp
 while (x < width) {
  _path.lineTo(x,height * (1 - progress) - wave / 2f * Math.sin(4.0 * Math.PI * x / width)
.toFloat()
  )
  x += dp
 }
  }

  _path.lineTo(width, height * (1 - progress))
  _path.lineTo(width, height)
  _path.close()
  return _path
 }
 
}

如上,波浪線 Path 通過正弦函數(shù)繪制。

4.3 波浪填充

有了 Path ,我們還需要填充內容。填充的內容前文已經介紹過,或者是 DrawColor 或者 DrawImage。 繪制 Path 需要定義 Paint

 val forePaint = remember(foreDrawType, bitmap) {
  Paint().apply {
shader = BitmapShader(
 when (foreDrawType) {
  is DrawType.DrawColor -> bitmap.toColor(foreDrawType.color)
  is DrawType.DrawImage -> bitmap
  else -> alphaBitmap
 },
 Shader.TileMode.CLAMP,
 Shader.TileMode.CLAMP
)
  }
 } 

Paint 使用 Shader 著色器繪制 Bitmap, 當 DrawType 只繪制單色時, 對位圖做單值處理:

/**
 * 位圖單色化
 */
fun Bitmap.toColor(color: androidx.compose.ui.graphics.Color): Bitmap {
 val bmp = Bitmap.createBitmap(
  width, height, Bitmap.Config.ARGB_8888
 )
 val oldPx = IntArray(width * height) //用來存儲原圖每個像素點的顏色信息
 getPixels(oldPx, 0, width, 0, 0, width, height) //獲取原圖中的像素信息
 
 val newPx = oldPx.map {
  color.copy(Color.alpha(it) / 255f).toArgb()
 }.toTypedArray().toIntArray()
 bmp.setPixels(newPx, 0, width, 0, 0, width, height) //將處理后的像素信息賦給新圖
 return bmp
}

4.4 波浪動畫

最后通過 Compose 動畫讓波浪動起來

val transition = rememberInfiniteTransition()
 
 val waves = remember(Unit) {
  listOf(
WaveAnim(waveDuration, 0f, 0f, scaleX, scaleY),
WaveAnim((waveDuration * 0.75f).roundToInt(), 0f, 0f, scaleX, scaleY),
WaveAnim((waveDuration * 0.5f).roundToInt(), 0f, 0f, scaleX, scaleY)
  )
 }
 
 val animates :  List<State<Float>> = waves.map { transition.animateOf(duration = it.duration) }

為了讓波浪更有層次感,我們定義三個 WaveAnim 以 Set 的形式做動畫

最后,配合 WaveAnim 將波浪的 Path 繪制到 Canvas 即可

Canvas{
 
  drawIntoCanvas { canvas ->
 
//繪制后景
canvas.drawRect(0f, 0f, size.width, size.height, backPaint)
 
 
//繪制前景
waves.forEachIndexed { index, wave ->
 
 canvas.withSave {
 
  val maxWidth = 2 * scaleX * size.width / velocity.coerceAtLeast(0.1f)
  val maxHeight = scaleY * size.height

  canvas.drawPath (wave.buildWavePath(
width = maxWidth,
height = maxHeight,
amplitude = size.height * amplitude,
progress = progress), forePaint
  )
 }
 
}
  }
 }

需要源碼可以私信我,當天回復

到此這篇關于Dialog 按照順序彈窗的文章就介紹到這了,更多相關Dialog 按照順序彈窗內容請搜索本站以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持本站!

版權聲明:本站文章來源標注為YINGSOO的內容版權均為本站所有,歡迎引用、轉載,請保持原文完整并注明來源及原文鏈接。禁止復制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務器上建立鏡像,否則將依法追究法律責任。本站部分內容來源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來,僅供學習參考,不代表本站立場,如有內容涉嫌侵權,請聯(lián)系alex-e#qq.com處理。

相關文章

實時開通

自選配置、實時開通

免備案

全球線路精選!

全天候客戶服務

7x24全年不間斷在線

專屬顧問服務

1對1客戶咨詢顧問

在線
客服

在線客服:7*24小時在線

客服
熱線

400-630-3752
7*24小時客服服務熱線

關注
微信

關注官方微信
頂部