欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android?上實現(xiàn)DragonBones換裝功能

 更新時間:2022年06月29日 08:50:08   作者:??SugarTurboS?Team???  
這篇文章主要介紹了Android?上實現(xiàn)DragonBones換裝功能,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,感興趣的小伙伴可以參考一下

前言

最近在預(yù)研一款換裝的小游戲,通過在積分樂園中兌換服裝,就可以在不同場景中展示穿上新服裝的角色。對于這類有主題形象的動畫,自然就想到了骨骼動畫,通過網(wǎng)格自由變形和蒙皮技術(shù)就能在視覺上呈現(xiàn)所需要的動畫效果,并且骨骼動畫也支持皮膚替換,或者插槽的圖片替換,對于換裝的需求比較友好。因此決定使用骨骼動畫來實現(xiàn)換裝小游戲的Demo,以下就是在Android平臺上實現(xiàn)DragonBones換裝的過程。

技術(shù)選型

對于DragonBones在Android端的渲染顯示,有多個方案可以選擇,例如:白鷺引擎或者Cocos2d游戲引擎。最終選擇使用korge來進(jìn)行渲染,為什么拋棄Cocos2d這個廣泛使用的游戲引擎來渲染呢?主要理由是:

  • Cocos2d 游戲引擎加載比較耗時,其首次加載時間無法接受;
  • Cocos2d 編譯出來的底層依賴需要單獨裁剪,裁剪后的libcocos.so依然較大;
  • Cocos2d 對于游戲動畫的渲染,其渲染的載體是Activity,也就是編譯出來的CocosActivity,這個是無法滿足業(yè)務(wù)需要的。因此需要自定義游戲容器,并且需要改動畫加載的容器載體和加載路徑。簡單點來說,可以從任意路徑來加載游戲資源(例如網(wǎng)絡(luò)或者本地,不僅僅是assets目錄),并且可以在自定義View中進(jìn)行渲染。解決思路可以參考:Android實戰(zhàn)之Cocos游戲容器搭建

最終,還是在官方的Github上發(fā)現(xiàn)這條Issue,從而找到了Android上渲染DragonBones的方式。Korge的介紹是這樣的

Modern Multiplatform Game Engine for Kotlin.

Korge的基本用法

1)創(chuàng)建 DragonBones Scene

class DisplayChangeImgScene : BaseDbScene() {
    companion object {
 ? ? ? ?private const val SKE_JSON = "mecha_1004d_show/mecha_1004d_show_ske.json"
 ? ? ? ?private const val TEX_JSON = "mecha_1004d_show/mecha_1004d_show_tex.json"
 ? ? ? ?private const val TEX_PNG = "mecha_1004d_show/mecha_1004d_show_tex.png"
 ?  }
 ? ?private val factory = KorgeDbFactory()
 ? ?override suspend fun Container.createSceneArmatureDisplay(): KorgeDbArmatureDisplay {
 ? ? ? ?val skeDeferred = asyncImmediately { res[SKE_JSON].readString() }
 ? ? ? ?val texDeferred = asyncImmediately { res[TEX_JSON].readString() }
 ? ? ? ?val imgDeferred = asyncImmediately { res[TEX_PNG].readBitmap().mipmaps() }
?
 ? ? ? ?val skeJsonData = skeDeferred.await()
 ? ? ? ?val texJsonData = texDeferred.await()
 ? ? ? ?factory.parseDragonBonesData(Json.parse(skeJsonData)!!)
 ? ? ? ?factory.parseTextureAtlasData(Json.parse(texJsonData)!!, imgDeferred.await())
?
 ? ? ? ?val armatureDisplay = factory.buildArmatureDisplay("mecha_1004d")!!.position(500, 700)
 ? ? ? ?armatureDisplay.animation.play("idle")
?
 ? ? ? ?return armatureDisplay
 ?  }
}

2)使用KorgeAndroidView加載 Scene Module

class MainActivity : AppCompatActivity() {
 ? ?private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }?
 ? ?private val slotDisplayModule by sceneModule<DisplayChangeImgScene>()?
 ? ?override fun onCreate(savedInstanceState: Bundle?) {
 ? ? ? ?super.onCreate(savedInstanceState)
 ? ? ? ?setContentView(binding.root)
 ? ? ? ?binding.root.addView(KorgeAndroidView(this).apply { 
 ? ? ? ? ? ?loadModule(slotDisplayModule)
 ? ? ?  })
 ?  }
}

3)sceneModule 函數(shù)

@MainThread
inline fun <reified DS : BaseDbScene> Activity.sceneModule(
 ? ?windowWidth: Int = resources.displayMetrics.widthPixels,
 ? ?windowHeight: Int = resources.displayMetrics.heightPixels
): Lazy<Module> {
 ? ?return SceneModuleLazy(DS::class, windowWidth, windowHeight)
}
class SceneModuleLazy<DS : BaseDbScene>(
 ? ?private val dbSceneClass: KClass<DS>,
 ? ?private val width: Int,
 ? ?private val height: Int
) : Lazy<Module> {
 ? ?private var cached: Module? = null?
 ? ?override val value: Module
 ? ? ? ?get() {
 ? ? ? ? ? ?return cached ?: object : Module() {
 ? ? ? ? ? ? ? ?override val mainScene = dbSceneClass
 ? ? ? ? ? ? ? ?override suspend fun AsyncInjector.configure() {
 ? ? ? ? ? ? ? ? ? ?mapPrototype(dbSceneClass) {
 ? ? ? ? ? ? ? ? ? ? ? ?val sceneInstance = Class.forName(dbSceneClass.qualifiedName!!).newInstance()
 ? ? ? ? ? ? ? ? ? ? ? ?sceneInstance as DS
 ? ? ? ? ? ? ? ? ?  }
 ? ? ? ? ? ? ?  }
 ? ? ? ? ? ? ? ?override val fullscreen = true?
 ? ? ? ? ? ? ? ?override val size: SizeInt
 ? ? ? ? ? ? ? ? ? ?get() = SizeInt(width, height)
 ? ? ? ? ? ? ? ?override val windowSize: SizeInt
 ? ? ? ? ? ? ? ? ? ?get() = SizeInt(width, height)
 ? ? ? ? ?  }
 ? ? ?  }?
 ? ?override fun isInitialized(): Boolean = cached != null
}

上面就是最簡單的Demo,通過加載DragonBones的配置數(shù)據(jù)即可顯示骨骼動畫。

實現(xiàn)換裝的多種實現(xiàn)

靜態(tài)換裝 vs 動態(tài)換裝

靜態(tài)換裝

如果換裝的素材是固定的,可以預(yù)先放置在插槽里,通過切換插槽的displayIndex實現(xiàn)換裝。

在骨骼動畫設(shè)計時,每個slot可對應(yīng)多個display,例如:

{
 ?"name": "weapon_hand_l",
 ?"display": [
 ?  {
 ? ? ?"name": "weapon_1004_l",
 ? ? ?"transform": {
 ? ? ? ?"x": 91.22,
 ? ? ? ?"y": -30.21
 ? ?  }
 ?  },
 ?  {
 ? ? ?"name": "weapon_1004b_l",
 ? ? ?"transform": {
 ? ? ? ?"x": 122.94,
 ? ? ? ?"y": -44.14
 ? ?  }
 ?  },
 ?  {
 ? ? ?"name": "weapon_1004c_l",
 ? ? ?"transform": {
 ? ? ? ?"x": 130.95,
 ? ? ? ?"y": -56.95
 ? ?  }
 ?  },
 ?  {
 ? ? ?"name": "weapon_1004d_l",
 ? ? ?"transform": {
 ? ? ? ?"x": 134.67,
 ? ? ? ?"y": -55.25
 ? ?  }
 ?  },
 ?  {
 ? ? ?"name": "weapon_1004e_l",
 ? ? ?"transform": {
 ? ? ? ?"x": 155.62,
 ? ? ? ?"y": -59.2
 ? ?  }
 ?  }
  ]
}

在代碼中,可直接切換display進(jìn)行換裝,即:

 ? ?private var leftWeaponIndex = 0
 ? ?private val leftDisplayList = listOf(
 ? ? ? ?"weapon_1004_l", "weapon_1004b_l", "weapon_1004c_l", "weapon_1004d_l", "weapon_1004e_l"
 ?  )
 ? ?override suspend fun Container.createSceneArmatureDisplay(): KorgeDbArmatureDisplay {
 ? ? ? ?val skeDeferred = asyncImmediately { Json.parse(res["mecha_1004d_show/mecha_1004d_show_ske.json"].readString())!! }
 ? ? ? ?val texDeferred = asyncImmediately { res["mecha_1004d_show/mecha_1004d_show_tex.json"].readString() }
 ? ? ? ?val imgDeferred = asyncImmediately { res["mecha_1004d_show/mecha_1004d_show_tex.png"].readBitmap().mipmaps() }
 ? ? ? ?factory.parseDragonBonesData(skeDeferred.await())
 ? ? ? ?factory.parseTextureAtlasData(Json.parse(texDeferred.await())!!, imgDeferred.await())?
 ? ? ? ?val armatureDisplay = factory.buildArmatureDisplay("mecha_1004d")!!.position(500, 700)
 ? ? ? ?armatureDisplay.animation.play("idle")
?
 ? ? ? ?val slot = armatureDisplay.armature.getSlot("weapon_hand_l")!!
 ? ? ? ?mouse {
 ? ? ? ? ? ?upAnywhere {
 ? ? ? ? ? ? ? ?leftWeaponIndex++;
 ? ? ? ? ? ? ? ?leftWeaponIndex %= leftDisplayList.size
?
 ? ? ? ? ? ? ? ?factory.replaceSlotDisplay(
 ? ? ? ? ? ? ? ? ? ?dragonBonesName = "mecha_1004d_show",
 ? ? ? ? ? ? ? ? ? ?armatureName = "mecha_1004d",
 ? ? ? ? ? ? ? ? ? ?slotName = "weapon_hand_l",
 ? ? ? ? ? ? ? ? ? ?displayName = leftDisplayList[leftWeaponIndex],
 ? ? ? ? ? ? ? ? ? ?slot = slot
 ? ? ? ? ? ? ?  )
 ? ? ? ? ?  }
 ? ? ?  }?
 ? ? ? ?return armatureDisplay
 ?  }

動態(tài)換裝

如果換裝的素材是不固定的,需要動態(tài)獲取資源,或者通過一張外部圖片來實現(xiàn)換裝效果,可以通過修改slot的顯示紋理即可實現(xiàn)。

```
// 換裝原理是:通過factory.parseTextureAtlasData來解析紋理數(shù)據(jù),紋理為外部圖片,紋理配置為Mock數(shù)據(jù)
private fun changeSlotDisplay(slot: Slot, replaceBitmap: Bitmap) {
 ? ?// 使用 HashCode 來作為 骨架名稱 和 骨骼名稱
 ? ?val replaceArmatureName = replaceBitmap.hashCode().toString()
 ? ?// 需要替換的插槽所包含的顯示對象
 ? ?val replaceDisplayName = slot._displayFrames.first { it.rawDisplayData != null }.rawDisplayData!!.name
 ? ?// 通過factory解析紋理數(shù)據(jù)
 ? ?val mockTexModel = mockTexModel(replaceArmatureName, replaceDisplayName, replaceBitmap.width, replaceBitmap.height)
 ? ?val textureAtlasData = Json.parse(gson.toJson(mockTexModel))!!
 ? ?factory.parseTextureAtlasData(textureAtlasData, replaceBitmap.mipmaps())
?
 ? ?// 替換 Display 的紋理,替換的圖片和原圖大小、位置一致
 ? ?val replaceTextureData = getReplaceDisplayTextureData(replaceArmatureName, replaceDisplayName)
 ? ?slot.replaceTextureData(replaceTextureData)
?
 ? ?slot._displayFrame?.displayData?.transform?.let {
 ? ? ? ?// 修改 display 相對于 slot 的位置、初始縮放等配置
 ?  }
}
private fun getReplaceDisplayTextureData(replaceArmatureName: String, replaceDisplayName: String): TextureData {
 ? ?val data = factory.getTextureAtlasData(replaceArmatureName)
 ? ?data!!.fastForEach { textureAtlasData ->
 ? ? ? ?val textureData = textureAtlasData.getTexture(replaceDisplayName)
 ? ? ? ?if (textureData != null) {
 ? ? ? ? ? ?return textureData
 ? ? ?  }
 ?  }
 ? ?throw Exception("getNewDisplayTextureData null")
}
private fun mockTexModel(armatureName: String, displayName: String, imgW: Int, imgH: Int): DragonBonesTexModel {
 ? ?val originTexModel = gson.fromJson(texJsonData, DragonBonesTexModel::class.java)
?
 ? ?val subTexture: DragonBonesTexModel.SubTexture = run loop@{
 ? ? ? ?originTexModel.subTexture.forEach { subTexture ->
 ? ? ? ? ? ?if (subTexture.name == displayName) {
 ? ? ? ? ? ? ? ?return@loop subTexture.apply {
 ? ? ? ? ? ? ? ? ? ?this.x = 0
 ? ? ? ? ? ? ? ? ? ?this.y = 0
 ? ? ? ? ? ? ?  }
 ? ? ? ? ?  }
 ? ? ?  }
 ? ? ? ?throw Exception("Can not find replace display!")
 ?  }
 ? ?return DragonBonesTexModel(
 ? ? ? ?name = armatureName,
 ? ? ? ?width = imgW,
 ? ? ? ?height = imgH,
 ? ? ? ?subTexture = listOf(subTexture)
 ?  )
}
```

包含動畫 vs 不包含動畫

如果換裝的部位不包含動畫,則可以使用圖片做為換裝素材,具體實現(xiàn)方法如上。 如果換裝的部位包含動畫,則可以使用子骨架做為換裝的素材,API調(diào)用方法和換圖片是一樣的,只不過換進(jìn)去的是子骨架的顯示對象,在引擎層面,圖片和子骨架的顯示對象都是顯示對象,所以處理起來是一樣的,唯一不同的是子骨架不需要考慮軸點,也不能重新設(shè)置軸點,因為他自身有動畫數(shù)據(jù)相當(dāng)于已經(jīng)包含軸點信息。

先將原始骨骼動畫文件中,該slot的display信息定義為空。例如:

{
 ?"name": "1036",
 ?"display": [
 ?  {
 ? ? ?"name": "blank"
 ?  }
  ]
},
{
 ?"name": "1082",
 ?"display": [
 ?  {
 ? ? ?"name": "blank"
 ?  }
  ]
},

在子骨架中定義 slot 的 display 信息。例如:

 ? ? ? ? ? "slot": [
 ? ? ? ? ? ? ?  {
 ? ? ? ? ? ? ? ? ? ?"name": "1019",
 ? ? ? ? ? ? ? ? ? ?"parent": "root"
 ? ? ? ? ? ? ?  }
 ? ? ? ? ?  ],
 ? ? ? ? ? ?"skin": [
 ? ? ? ? ? ? ?  {
 ? ? ? ? ? ? ? ? ? ?"name": "",
 ? ? ? ? ? ? ? ? ? ?"slot": [
 ? ? ? ? ? ? ? ? ? ? ?  {
 ? ? ? ? ? ? ? ? ? ? ? ? ? ?"name": "1019",
 ? ? ? ? ? ? ? ? ? ? ? ? ? ?"display": [
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  {
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"type": "mesh",
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"name": "glove/2080500b",
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"width": 159,
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"height": 323,
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"vertices": [
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?104.98,
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?-1078.6,
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?108.08,
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?-1094.03
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  ],
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"uvs": [
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0.45257,
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0.1035,
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0.4721,
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0.15156,
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0.4234,
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0.05575
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  ],
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"triangles": [
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?7,
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?11,
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?18,
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?20
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  ],
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"weights": [
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?2,
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?3,
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0.92
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  ],
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"slotPose": [
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?1,
?
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0,
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  ],
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"bonePose": [
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?6,
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0.193207,
?
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?139.903737,
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?-897.076346
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  ],
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"edges": [
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?19,
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?18,
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?18,
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?20,
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?19
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  ],
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"userEdges": [
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?16,
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?11,
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?7
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  ]
 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  }
 ? ? ? ? ? ? ? ? ? ? ? ? ?  ]
 ? ? ? ? ? ? ? ? ? ? ?  }
 ? ? ? ? ? ? ? ? ?  ]
 ? ? ? ? ? ? ?  }
 ? ? ? ? ?  ],

使用子骨架的顯示對象進(jìn)行替換,以下是使用直接替換 skin 的方式,和替換 display 的原理相同。

private suspend fun replaceDragonBonesDisplay(armatureDisplay: KorgeDbArmatureDisplay) {
 ? ?val path = "you_xin/suit1/replace/"
 ? ?val dragonBonesJSONPath = path + "xx_ske.json"
 ? ?val textureAtlasJSONPath = path + "xx_tex.json"
 ? ?val textureAtlasPath = path + "xx_tex.png"
 ? ?// 加載子骨架數(shù)據(jù)
 ? ?factory.parseDragonBonesData(Json.parse(res[dragonBonesJSONPath].readString())!!)
 ? ?factory.parseTextureAtlasData(
 ? ? ? ?Json.parse(res[textureAtlasJSONPath].readString())!!,
 ? ? ? ?res[textureAtlasPath].readBitmap().mipmaps()
 ?  )
 ? ?// 獲取解析后的骨骼數(shù)據(jù)
 ? ?val replaceArmatureData = factory.getArmatureData("xx")
 ? ?// 通過 replaceSkin 的方式修改 slot display
 ? ?factory.replaceSkin(armatureDisplay.armature, replaceArmatureData!!.defaultSkin!!)
}

局部換裝 vs 全局換裝

之前說的都是局部換裝,替換的是紋理集中的一塊子紋理,如果希望一次性替換整個紋理集也是支持的。但是紋理集的配置文件不能換(如果配置文件也要換的話,就直接重新構(gòu)建骨架就好) 也就是說游戲中可以有一套紋理集配置文件對應(yīng)多個紋理集圖片,實現(xiàn)配置文件不變的情況下?lián)Q整個紋理集。利用這個技術(shù)可以實現(xiàn)例如格斗游戲中同樣的角色穿不同顏色的衣服的效果。

全局換裝之Skin修改

DragonBones支持多套皮膚的切換,如果皮膚時固定的,可預(yù)先配置在骨骼動畫文件中,需要時直接切換即可。

private fun changeDragonBonesSkin(armatureDisplay: KorgeDbArmatureDisplay) {
 ? ?val replaceSkin = factory.getArmatureData("xxx")?.getSkin("xxx") ?: return
 ? ?factory.replaceSkin(armatureDisplay.armature, replaceSkin)
}

全局換裝之紋理修改

如果皮膚并未固定的,需要動態(tài)配置或者網(wǎng)絡(luò)下發(fā),那么可以使用紋理替換的方式。

private suspend fun changeDragonBonesSkin() {
 ? ?val texDeferred = asyncImmediately { res["body/texture_01.png"].readBitmap().mipmaps() }
 ? ?factory.updateTextureAtlases(texDeferred.await(), "body")
}

總結(jié)

對于一款換裝小游戲來講,使用Spine或者是DragonBones的差異不大,其設(shè)計思路基本相同,而且Korge同樣也是支持Spine的渲染。從技術(shù)實現(xiàn)上,換裝的功能并不難實現(xiàn),只是需要考慮的細(xì)節(jié)方面還有很多,例如:

  • 服裝商城的在線配置和管理,并且有些服裝還可能自帶動畫
  • 某些服裝可能涉及多個插槽,例如:一套裙子,有一部分的層級在身體前面,另一部分的層級在身體后面,那就意味需要兩個插槽才能實現(xiàn)
  • 如果該人物形象在多個界面或者應(yīng)用中出現(xiàn),動畫效果不同,但是身上的服裝相同,需要考慮處理換裝后服裝同步的問題

到此這篇關(guān)于Android 上實現(xiàn)DragonBones換裝功能的文章就介紹到這了,更多相關(guān)Android  DragonBones換裝內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Android 自定義View的使用介紹

    Android 自定義View的使用介紹

    本篇文章小編為大家介紹,Android 自定義View的使用。需要的朋友參考下
    2013-04-04
  • android 加載本地聯(lián)系人實現(xiàn)方法

    android 加載本地聯(lián)系人實現(xiàn)方法

    在android開發(fā)過程中,有些功能需要訪問本地聯(lián)系人列表,本人搜集整理了一番,拿出來和大家分享一下,希望可以幫助你們
    2012-12-12
  • Android如何給按鈕添加點擊音效

    Android如何給按鈕添加點擊音效

    這篇文章主要為大家詳細(xì)介紹了Android如何給按鈕添加點擊音效,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • Android頁面中引導(dǎo)蒙層的使用方法詳解

    Android頁面中引導(dǎo)蒙層的使用方法詳解

    這篇文章主要為大家詳細(xì)介紹了Android頁面中的引導(dǎo)蒙層使用方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-03-03
  • Android activity動畫不生效原因及解決方案總結(jié)

    Android activity動畫不生效原因及解決方案總結(jié)

    android activity動畫是一個比較簡單的功能。但是使用時總會由于各種小問題導(dǎo)致動畫失效,筆者根據(jù)自己經(jīng)驗,整理了各種可能導(dǎo)致的原因,期望能對你有所幫助
    2021-11-11
  • 一篇文章就能了解Rxjava

    一篇文章就能了解Rxjava

    最近偶然接觸到了rxjava。關(guān)于rxjava,褒貶不一,有人說好用,有人說難用,不過它到底是什么?它有什么用?接下來,本文通過部分代碼及分析,向大家介紹rxjava及其相關(guān)內(nèi)容。
    2017-10-10
  • Android如何實現(xiàn)設(shè)備的異顯功能詳解

    Android如何實現(xiàn)設(shè)備的異顯功能詳解

    這篇文章主要給大家介紹了關(guān)于Android如何實現(xiàn)設(shè)備的異顯功能的相關(guān)資料,這篇文章通過示例代碼介紹的非常詳細(xì),對各位Android開發(fā)者們具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2022-02-02
  • 淺談Android invalidate 分析

    淺談Android invalidate 分析

    本篇文章主要介紹了淺談Android invalidate 分析,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-04-04
  • android實現(xiàn)拍照或從相冊選取圖片

    android實現(xiàn)拍照或從相冊選取圖片

    這篇文章主要為大家詳細(xì)介紹了android實現(xiàn)拍照或從相冊選取圖片,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-03-03
  • android實現(xiàn)簡單進(jìn)度條ProgressBar效果

    android實現(xiàn)簡單進(jìn)度條ProgressBar效果

    這篇文章主要為大家詳細(xì)介紹了android實現(xiàn)簡單進(jìn)度條ProgressBar效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-07-07

最新評論