V1.0.0(1)
18
.gitignore
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/caches
|
||||
/.idea/libraries
|
||||
/.idea/modules.xml
|
||||
/.idea/workspace.xml
|
||||
/.idea/navEditor.xml
|
||||
/.idea/assetWizardSettings.xml
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
.idea/
|
||||
.safedk/
|
||||
app/debug/
|
||||
1
app/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
||||
BIN
app/BubbleKeyboard.jks
Normal file
149
app/build.gradle.kts
Normal file
@ -0,0 +1,149 @@
|
||||
import java.util.Date
|
||||
import java.text.SimpleDateFormat
|
||||
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
id("org.jetbrains.kotlin.android")
|
||||
// id("com.google.gms.google-services")
|
||||
// id("com.google.firebase.crashlytics")
|
||||
kotlin("kapt")
|
||||
id ("kotlin-android")
|
||||
|
||||
|
||||
}
|
||||
|
||||
val timestamp = SimpleDateFormat("MM_dd_HH_mm").format(Date())
|
||||
android {
|
||||
namespace = "com.keyboard.bubble.skin.keyboard"
|
||||
compileSdk = 34
|
||||
|
||||
defaultConfig {
|
||||
//com.keyboard.bubble.skin
|
||||
applicationId = "com.keyboard.bubble.skin"
|
||||
minSdk = 23
|
||||
targetSdk = 34
|
||||
versionCode = 1
|
||||
versionName = "1.0.0"
|
||||
setProperty(
|
||||
"archivesBaseName",
|
||||
"Bubble Keyboard_V" + versionName + "(${versionCode})_$timestamp"
|
||||
)
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
isMinifyEnabled = true
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "17"
|
||||
}
|
||||
buildFeatures {
|
||||
buildConfig = true
|
||||
viewBinding = true
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation("androidx.core:core-ktx:1.9.0")
|
||||
implementation("androidx.appcompat:appcompat:1.6.1")
|
||||
implementation("com.google.android.material:material:1.10.0")
|
||||
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
||||
testImplementation("junit:junit:4.13.2")
|
||||
androidTestImplementation("androidx.test.ext:junit:1.1.5")
|
||||
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
|
||||
|
||||
|
||||
implementation("com.squareup.okhttp3:okhttp:4.12.0")
|
||||
implementation("com.github.bumptech.glide:glide:4.16.0")
|
||||
implementation ("jp.wasabeef:glide-transformations:4.3.0")
|
||||
//Glide支持webp动图的库
|
||||
implementation("com.github.zjupure:webpdecoder:2.0.4.12.0")
|
||||
implementation("com.github.omicronapps:7-Zip-JBinding-4Android:Release-16.02-2.02")
|
||||
|
||||
val room_version = "2.6.1"
|
||||
implementation ("androidx.room:room-runtime:$room_version")
|
||||
kapt("androidx.room:room-compiler:$room_version")
|
||||
implementation ("androidx.room:room-ktx:$room_version")
|
||||
implementation ("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")
|
||||
implementation ("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.0")
|
||||
|
||||
// implementation(platform("com.google.firebase:firebase-bom:33.7.0"))
|
||||
// implementation("com.google.firebase:firebase-crashlytics")
|
||||
// implementation("com.google.firebase:firebase-analytics")
|
||||
// implementation("com.google.firebase:firebase-config")
|
||||
|
||||
|
||||
//-----------------------------------------------TopOn(pangle、IronSource、mintegral、unityads、liftoff(vungle)、Bigo)
|
||||
//Anythink (Necessary)
|
||||
// implementation("com.anythink.sdk:core-tpn:6.3.68")
|
||||
// implementation("com.anythink.sdk:nativead-tpn:6.3.68")
|
||||
// implementation("com.anythink.sdk:banner-tpn:6.3.68")
|
||||
// implementation("com.anythink.sdk:interstitial-tpn:6.3.68")
|
||||
// implementation("com.anythink.sdk:rewardedvideo-tpn:6.3.68")
|
||||
// implementation("com.anythink.sdk:splash-tpn:6.3.68")
|
||||
//
|
||||
// //Androidx (Necessary)
|
||||
// implementation("androidx.appcompat:appcompat:1.1.0")
|
||||
// implementation("androidx.browser:browser:1.4.0")
|
||||
//
|
||||
// //Vungle
|
||||
// implementation("com.anythink.sdk:adapter-tpn-vungle:6.3.68")
|
||||
// implementation("com.vungle:vungle-ads:7.3.2")
|
||||
// implementation("com.google.android.gms:play-services-basement:18.1.0")
|
||||
// implementation("com.google.android.gms:play-services-ads-identifier:18.0.1")
|
||||
//
|
||||
// //UnityAds
|
||||
// implementation("com.anythink.sdk:adapter-tpn-unityads:6.3.68")
|
||||
// implementation("com.unity3d.ads:unity-ads:4.9.3")
|
||||
//
|
||||
// //Ironsource
|
||||
// implementation("com.anythink.sdk:adapter-tpn-ironsource:6.3.68")
|
||||
// implementation("com.ironsource.sdk:mediationsdk:8.1.0")
|
||||
// implementation("com.google.android.gms:play-services-appset:16.0.2")
|
||||
// implementation("com.google.android.gms:play-services-ads-identifier:18.0.1")
|
||||
// implementation("com.google.android.gms:play-services-basement:18.1.0")
|
||||
//
|
||||
// //Bigo
|
||||
// implementation("com.anythink.sdk:adapter-tpn-bigo:6.3.68")
|
||||
// implementation("com.bigossp:bigo-ads:4.7.4")
|
||||
//
|
||||
// //Pangle
|
||||
// implementation("com.anythink.sdk:adapter-tpn-pangle-nonchina:6.3.68.1")
|
||||
// implementation( "com.pangle.global:ads-sdk:6.0.0.3")
|
||||
// implementation( "com.google.android.gms:play-services-ads-identifier:18.0.1")
|
||||
//
|
||||
// //Mintegral
|
||||
// implementation("com.anythink.sdk:adapter-tpn-mintegral-nonchina:6.3.68")
|
||||
// implementation("com.mbridge.msdk.oversea:reward:16.7.51")
|
||||
// implementation("com.mbridge.msdk.oversea:newinterstitial:16.7.51")
|
||||
// implementation("com.mbridge.msdk.oversea:mbnative:16.7.51")
|
||||
// implementation("com.mbridge.msdk.oversea:mbnativeadvanced:16.7.51")
|
||||
// implementation("com.mbridge.msdk.oversea:mbsplash:16.7.51")
|
||||
// implementation("com.mbridge.msdk.oversea:mbbanner:16.7.51")
|
||||
// implementation("com.mbridge.msdk.oversea:mbbid:16.7.51")
|
||||
// implementation("androidx.recyclerview:recyclerview:1.1.0")
|
||||
//
|
||||
// //Tramini
|
||||
// implementation("com.anythink.sdk:tramini-plugin-tpn:6.3.68")
|
||||
//
|
||||
// // Debugger UI Tools
|
||||
// implementation ("com.anythink.sdk:debugger-ui:1.0.7")
|
||||
|
||||
//----------------------------------------------TopOn
|
||||
|
||||
|
||||
}
|
||||
45
app/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
|
||||
|
||||
# 保持 Room 的核心类不被混淆
|
||||
-keep class androidx.room.** { *; }
|
||||
-keep class androidx.sqlite.db.** { *; }
|
||||
|
||||
# 保持 Room 数据库类的基本结构
|
||||
-keep class * extends androidx.room.RoomDatabase { *; }
|
||||
|
||||
# 保持 Room DAO 接口
|
||||
-keep @androidx.room.Dao interface * { *; }
|
||||
-keep @androidx.room.Dao class * { *; }
|
||||
|
||||
# 保持 Room 实体类
|
||||
-keep @androidx.room.Entity class * { *; }
|
||||
|
||||
# 保持 Room 的注解类
|
||||
-keep @androidx.room.Database class * { *; }
|
||||
|
||||
|
||||
|
||||
-keep class com.omicronapplications.** { *; }
|
||||
-keep class net.sf.sevenzipjbinding.** { *; }
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
package com.keyboard.bubble.skin.keyboard
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ExampleInstrumentedTest {
|
||||
@Test
|
||||
fun useAppContext() {
|
||||
// Context of the app under test.
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
assertEquals("com.ba.ali.apps.keyboard", appContext.packageName)
|
||||
}
|
||||
}
|
||||
60
app/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:name=".App"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/icon"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/icon"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.MyKeyBoard"
|
||||
tools:targetApi="31">
|
||||
|
||||
<activity
|
||||
android:name=".ui.WelcomeActivity"
|
||||
android:exported="true"
|
||||
android:screenOrientation="portrait">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".ui.SetkeyboardActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
<!-- <activity-->
|
||||
<!-- android:name=".ui.PreviewActivity"-->
|
||||
<!-- android:exported="false"-->
|
||||
<!-- android:screenOrientation="portrait" />-->
|
||||
<activity
|
||||
android:name=".ui.SuccessPreViewActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name=".ui.MainActivity"
|
||||
android:exported="true"
|
||||
android:launchMode="singleTask"
|
||||
android:screenOrientation="portrait"/>
|
||||
|
||||
<service
|
||||
android:name=".customerview.MyInputMethodService"
|
||||
android:exported="true"
|
||||
android:permission="android.permission.BIND_INPUT_METHOD">
|
||||
<intent-filter>
|
||||
<action android:name="android.view.InputMethod" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.view.im"
|
||||
android:resource="@xml/my_keyborad" />
|
||||
</service>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
BIN
app/src/main/assets/my_font.ttf
Normal file
22462
app/src/main/assets/res.json
Normal file
123
app/src/main/java/com/keyboard/bubble/skin/keyboard/App.kt
Normal file
@ -0,0 +1,123 @@
|
||||
package com.keyboard.bubble.skin.keyboard
|
||||
|
||||
import android.app.Application
|
||||
import android.graphics.Typeface
|
||||
import com.keyboard.bubble.skin.keyboard.bean.ParentBean
|
||||
import com.keyboard.bubble.skin.keyboard.bean.ChildBean
|
||||
//import com.pretty.keyboard.theme.keyboard.helper.ObjectBox
|
||||
import org.json.JSONArray
|
||||
import java.io.BufferedReader
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.io.InputStreamReader
|
||||
import java.io.StringWriter
|
||||
|
||||
class App : Application() {
|
||||
companion object {
|
||||
lateinit var appInstance: App
|
||||
|
||||
lateinit var list: MutableList<ParentBean>
|
||||
|
||||
const val TAG = "-----------------"
|
||||
var defaultFont: Typeface? = null
|
||||
const val DB_VERSION = 1
|
||||
const val DB_NAME = "db_name"
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
appInstance = this
|
||||
// ObjectBox.init(this)
|
||||
defaultFont = Typeface.createFromAsset(assets, "my_font.ttf")
|
||||
dealFile()
|
||||
|
||||
}
|
||||
|
||||
private fun dealFile() {
|
||||
val openFile = appInstance.assets.open("res.json")
|
||||
val jsonString = getJsonString(openFile)
|
||||
if (jsonString != null) {
|
||||
resolveJsonString(jsonString)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun resolveJsonString(string: String) {
|
||||
val jsonData = JSONArray(string)
|
||||
var dataList: MutableList<ParentBean> = mutableListOf()
|
||||
for (i in 0 until jsonData.length()) {
|
||||
jsonData.getJSONObject(i).run {
|
||||
val pName = getString("parent_name")
|
||||
val listArray = getJSONArray("keyboard_list")
|
||||
var childBeanList: MutableList<ChildBean> = mutableListOf()
|
||||
for (listIndex in 0 until listArray.length()) {
|
||||
listArray.getJSONObject(listIndex).also {
|
||||
val title = it.getString("title")
|
||||
val thUrl = it.getString("thumbUrl")
|
||||
val thGif = it.getString("thumbUrlGif")
|
||||
var zipPath = ""
|
||||
var imgPath = ""
|
||||
var imgGif = ""
|
||||
var imgPreviewGif = ""
|
||||
if (it.has("detail")) {
|
||||
val contentObject =
|
||||
it.getJSONObject("detail").getJSONObject("themeContent")
|
||||
zipPath = contentObject.getString("androidRawZipUrl")
|
||||
imgPath = contentObject.getString("img")
|
||||
imgGif = contentObject.getString("imgGif")
|
||||
imgPreviewGif = contentObject.getString("imgPreviewGif")
|
||||
} else {
|
||||
|
||||
}
|
||||
childBeanList.add(
|
||||
ChildBean().apply {
|
||||
setImgPath(imgPath)
|
||||
setZipPath(zipPath)
|
||||
setTitleName(title)
|
||||
setImgGif(imgGif)
|
||||
thumbUrl = thUrl
|
||||
thumbGif = thGif
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
val dataParentBean = ParentBean()
|
||||
.apply {
|
||||
parentName = pName
|
||||
keyboardList = childBeanList
|
||||
}
|
||||
dataList.add(dataParentBean)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
updateDataList(dataList)
|
||||
|
||||
}
|
||||
|
||||
private fun updateDataList(mainList: MutableList<ParentBean>) {
|
||||
list = mainList
|
||||
|
||||
}
|
||||
private fun getJsonString(fileInputStream: InputStream): String? {
|
||||
return try {
|
||||
// FileInputStream fileInputStream = new FileInputStream(path);
|
||||
val charArray = CharArray(fileInputStream.available())
|
||||
var readCount = 0
|
||||
val streamReader = InputStreamReader(fileInputStream)
|
||||
val bufferedReader = BufferedReader(streamReader)
|
||||
val stringWriter = StringWriter()
|
||||
while (bufferedReader.read(charArray).also { readCount = it } != -1) {
|
||||
stringWriter.write(charArray, 0, readCount)
|
||||
}
|
||||
stringWriter.toString()
|
||||
} catch (e: IOException) {
|
||||
""
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,108 @@
|
||||
package com.keyboard.bubble.skin.keyboard.bean;
|
||||
|
||||
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.PrimaryKey;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Entity(tableName = "ChildBean")
|
||||
public class ChildBean implements Serializable {
|
||||
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
private long id;
|
||||
private String titleName;
|
||||
|
||||
private String thumbUrl;
|
||||
|
||||
private String thumbGif;
|
||||
|
||||
private String zipPath;
|
||||
|
||||
private String imgPath;
|
||||
private String imgGif;
|
||||
|
||||
|
||||
private boolean download;
|
||||
|
||||
private boolean like;
|
||||
|
||||
|
||||
public boolean isDownload() {
|
||||
return download;
|
||||
}
|
||||
|
||||
public void setDownload(boolean download) {
|
||||
this.download = download;
|
||||
}
|
||||
|
||||
public boolean isLike() {
|
||||
return like;
|
||||
}
|
||||
|
||||
public void setLike(boolean like) {
|
||||
this.like = like;
|
||||
}
|
||||
|
||||
public void setImgGif(String imgGif) {
|
||||
this.imgGif = imgGif;
|
||||
}
|
||||
|
||||
public String getTitleName() {
|
||||
|
||||
return titleName;
|
||||
}
|
||||
|
||||
public String getThumbUrl() {
|
||||
|
||||
return thumbUrl;
|
||||
}
|
||||
|
||||
public String getThumbGif() {
|
||||
|
||||
return thumbGif;
|
||||
}
|
||||
|
||||
public String getZipPath() {
|
||||
|
||||
return zipPath;
|
||||
}
|
||||
|
||||
public String getImgPath() {
|
||||
|
||||
return imgPath;
|
||||
}
|
||||
|
||||
public void setTitleName(String name) {
|
||||
this.titleName = name;
|
||||
}
|
||||
|
||||
public void setThumbUrl(String thumbUrl) {
|
||||
this.thumbUrl = thumbUrl;
|
||||
}
|
||||
|
||||
public void setThumbGif(String thumbGif) {
|
||||
this.thumbGif = thumbGif;
|
||||
}
|
||||
|
||||
public void setZipPath(String path) {
|
||||
this.zipPath = path;
|
||||
}
|
||||
|
||||
public void setImgPath(String imgPath) {
|
||||
this.imgPath = imgPath;
|
||||
}
|
||||
|
||||
public String getImgGif() {
|
||||
return imgGif;
|
||||
}
|
||||
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package com.keyboard.bubble.skin.keyboard.bean;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ParentBean {
|
||||
private String parentName;
|
||||
|
||||
private List<ChildBean> keyboardList;
|
||||
|
||||
public String getParentName() {
|
||||
|
||||
return parentName;
|
||||
}
|
||||
|
||||
public List<ChildBean> getKeyboardList() {
|
||||
|
||||
return keyboardList;
|
||||
}
|
||||
|
||||
public void setParentName(String name) {
|
||||
this.parentName = name;
|
||||
}
|
||||
|
||||
public void setKeyboardList(List<ChildBean> keyboardList) {
|
||||
this.keyboardList = keyboardList;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,98 @@
|
||||
package com.keyboard.bubble.skin.keyboard.customerview
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.util.Log
|
||||
import com.keyboard.bubble.skin.keyboard.App
|
||||
import com.keyboard.bubble.skin.keyboard.resourcecode.CusKeyBoard
|
||||
import com.keyboard.bubble.skin.keyboard.utils.ConstValue
|
||||
import com.keyboard.bubble.skin.keyboard.utils.SharedManager
|
||||
import java.io.File
|
||||
|
||||
object KeyFunction {
|
||||
|
||||
fun keyToUpper(mKeyBoard: CusKeyBoard) {
|
||||
for (key in mKeyBoard.keys) {
|
||||
if (key.label != null) {
|
||||
if (key.label.length == 1) {
|
||||
val charLabel = key.label.toString()[0]
|
||||
val toUpperCase = charLabel.toUpperCase()
|
||||
key.codes[0] = toUpperCase.toInt()
|
||||
key.label = toUpperCase.toString()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun keyToLowerCase(mKeyBoard: CusKeyBoard) {
|
||||
for (key in mKeyBoard.keys) {
|
||||
if (key.label != null) {
|
||||
if (key.label.length == 1) {
|
||||
val charLabel = key.label.toString()[0]
|
||||
val toLowerCase = charLabel.toLowerCase()
|
||||
key.codes[0] = toLowerCase.toInt()
|
||||
key.label = toLowerCase.toString()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun primaryCodeToChar(primCode: Int): String {
|
||||
val toString = primCode.toChar().toString()
|
||||
|
||||
return toString
|
||||
}
|
||||
|
||||
@SuppressLint("SuspiciousIndentation")
|
||||
fun readBgOrVideo(
|
||||
context: Context,
|
||||
playAction: (gif: String?,bgDraw:Drawable?) -> Unit
|
||||
) {
|
||||
|
||||
SharedManager.getSkinPath()?.let { resPath ->
|
||||
val videoPath = "${resPath}res/raw/${ConstValue.videoName}"
|
||||
val videoPath2 = "${resPath}res/raw/${ConstValue.video}"
|
||||
val backgroundPath = "${resPath}res/drawable-xxhdpi-v4/${ConstValue.bgName}"
|
||||
val file = File(videoPath)
|
||||
val file2 = File(videoPath2)
|
||||
val file3 = File(backgroundPath)
|
||||
if (file.exists()||file2.exists()) {
|
||||
Log.d(App.TAG, "--------11111111= resPath=${resPath}")
|
||||
val path:String = if(file.exists()){
|
||||
videoPath
|
||||
}else{
|
||||
videoPath2
|
||||
}
|
||||
|
||||
|
||||
|
||||
val bitmapDrawable = BitmapDrawable(context.resources, BitmapFactory.decodeFile(path))
|
||||
|
||||
playAction.invoke(path,null)
|
||||
|
||||
// playAction.invoke(mediaPlayer,null);
|
||||
}else{
|
||||
Log.d(App.TAG, "--------11111111= file3.exists()"+file3.exists()+"---resPath="+resPath)
|
||||
if(file3.exists()){
|
||||
val bitmapDrawable = BitmapDrawable(context.resources, BitmapFactory.decodeFile(backgroundPath))
|
||||
playAction.invoke(null,bitmapDrawable)
|
||||
}else{
|
||||
playAction.invoke(null,null)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,285 @@
|
||||
package com.keyboard.bubble.skin.keyboard.customerview;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.inputmethodservice.InputMethodService;
|
||||
|
||||
import android.media.MediaPlayer;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.VideoView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.integration.webp.decoder.WebpDrawable;
|
||||
import com.bumptech.glide.load.DataSource;
|
||||
import com.bumptech.glide.load.engine.GlideException;
|
||||
import com.bumptech.glide.request.RequestListener;
|
||||
import com.bumptech.glide.request.target.Target;
|
||||
import com.keyboard.bubble.skin.keyboard.App;
|
||||
import com.keyboard.bubble.skin.keyboard.R;
|
||||
import com.keyboard.bubble.skin.keyboard.utils.ConstValue;
|
||||
import com.keyboard.bubble.skin.keyboard.utils.MyUtils;
|
||||
import com.keyboard.bubble.skin.keyboard.utils.SharedManager;
|
||||
import com.keyboard.bubble.skin.keyboard.resourcecode.CusKeyBoard;
|
||||
import com.keyboard.bubble.skin.keyboard.resourcecode.CusKeyBoardView;
|
||||
|
||||
|
||||
import kotlin.Unit;
|
||||
import kotlin.jvm.functions.Function2;
|
||||
|
||||
public class MyInputMethodService extends InputMethodService implements CusKeyBoardView.OnKeyboardActionListener {
|
||||
|
||||
|
||||
private MyInputView myInputView;
|
||||
private CusKeyBoard mKeyBoard;
|
||||
private View parentView;
|
||||
|
||||
|
||||
private ImageView imBG;
|
||||
private VideoView videoView;
|
||||
|
||||
private int a = R.xml.xml1;
|
||||
private int b= R.xml.xml2;
|
||||
private int c = R.xml.xml3;
|
||||
|
||||
private int curImeAction = EditorInfo.IME_ACTION_UNSPECIFIED;
|
||||
@SuppressLint("InflateParams")
|
||||
@Override
|
||||
public View onCreateInputView() {
|
||||
parentView = getLayoutInflater().inflate(R.layout.layout_input_view, null);
|
||||
findView();
|
||||
return parentView;
|
||||
}
|
||||
|
||||
private void findView() {
|
||||
|
||||
imBG = parentView.findViewById(R.id.gif_bg);
|
||||
videoView = parentView.findViewById(R.id.video_view);
|
||||
mKeyBoard = new CusKeyBoard(this, a);
|
||||
myInputView = parentView.findViewById(R.id.custom_input_view);
|
||||
myInputView.setEnabled(true);
|
||||
myInputView.setPreviewEnabled(false);
|
||||
myInputView.setKeyboard(mKeyBoard);
|
||||
myInputView.setOnKeyboardActionListener(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onWindowHidden() {
|
||||
super.onWindowHidden();
|
||||
if(videoView.isPlaying()){
|
||||
videoView.pause();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowShown() {
|
||||
super.onWindowShown();
|
||||
EditorInfo currentInputEditorInfo = getCurrentInputEditorInfo();
|
||||
curImeAction = MyUtils.INSTANCE.getTextForImeAction(currentInputEditorInfo.imeOptions);
|
||||
String skinPath = SharedManager.INSTANCE.getSkinPath();
|
||||
|
||||
if(skinPath == null || skinPath.isEmpty()){
|
||||
Log.d(App.TAG, "---------skinPath= bull");
|
||||
myInputView.updateUi(curImeAction);
|
||||
}else {
|
||||
Log.d(App.TAG, "---------skinPath= 1111");
|
||||
KeyFunction.INSTANCE.readBgOrVideo(this, new Function2<String, Drawable, Unit>() {
|
||||
@Override
|
||||
public Unit invoke(String s, Drawable drawable) {
|
||||
Log.d(App.TAG, "---------s= "+s+"---------drawable="+drawable);
|
||||
if (s != null) {
|
||||
myInputView.setBackground(null);
|
||||
if(s.endsWith(".gif")){
|
||||
imBG.setVisibility(View.VISIBLE);
|
||||
videoView.setVisibility(View.GONE);
|
||||
Glide.with(MyInputMethodService.this)
|
||||
.load(s)
|
||||
.addListener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
||||
if (resource instanceof WebpDrawable) {
|
||||
((WebpDrawable) resource).setLoopCount(WebpDrawable.LOOP_FOREVER);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}).into(imBG) ;
|
||||
}else if(s.endsWith(".mp4")){
|
||||
imBG.setVisibility(View.GONE);
|
||||
videoView.setVisibility(View.VISIBLE);
|
||||
videoView.setVideoPath(s);
|
||||
videoView.start();
|
||||
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
|
||||
@Override
|
||||
public void onPrepared(MediaPlayer mp) {
|
||||
mp.setLooping(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} else {
|
||||
myInputView.setBackground(drawable);
|
||||
}
|
||||
myInputView.updateUi(curImeAction);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
videoView.stopPlayback();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPress(int primaryCode) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRelease(int primaryCode) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKey(int primaryCode, int[] keyCodes) {
|
||||
|
||||
InputConnection curInputConnect = getCurrentInputConnection();
|
||||
switch (primaryCode) {
|
||||
case ConstValue.KEY_CODE_DELETE:
|
||||
curInputConnect.deleteSurroundingText(1, 0);
|
||||
break;
|
||||
case ConstValue.KEY_CODE_SHIFT:
|
||||
switchShift();
|
||||
break;
|
||||
case ConstValue.KEY_CODE_NUMBER_SHIFT:
|
||||
case ConstValue.KEY_CODE_SYMBOL_SHIFT:
|
||||
switchMoreOrNumber();
|
||||
break;
|
||||
case ConstValue.KEY_CODE_CHANGE_NUMBER:
|
||||
case ConstValue.KEY_CODE_BACK:
|
||||
switchNormalOrNumber();
|
||||
break;
|
||||
|
||||
case ConstValue.KEY_CODE_COMPLETE:
|
||||
case ConstValue.KEY_CODE_CANCEL:
|
||||
curInputConnect.performEditorAction(curImeAction);
|
||||
// curInputConnect.performEditorAction(EditorInfo.IME_ACTION_DONE);
|
||||
break;
|
||||
default:
|
||||
String codeToChar = KeyFunction.INSTANCE.primaryCodeToChar(primaryCode);
|
||||
curInputConnect.commitText(codeToChar, 1);
|
||||
if (myInputView.isLowerCase() == 1) {
|
||||
//自动转小写
|
||||
myInputView.setLowerCase(0);
|
||||
KeyFunction.INSTANCE.keyToLowerCase(mKeyBoard);
|
||||
myInputView.setKeyboard(mKeyBoard);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void switchMoreOrNumber() {
|
||||
int mode = myInputView.getMode();
|
||||
switch (mode) {
|
||||
case 1:
|
||||
mKeyBoard = new CusKeyBoard(this, c);
|
||||
myInputView.setMode(2);
|
||||
myInputView.setKeyboard(mKeyBoard);
|
||||
break;
|
||||
case 2:
|
||||
mKeyBoard = new CusKeyBoard(this, b);
|
||||
myInputView.setMode(1);
|
||||
myInputView.setKeyboard(mKeyBoard);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void switchNormalOrNumber() {
|
||||
int mode = myInputView.getMode();
|
||||
switch (mode) {
|
||||
case 0:
|
||||
mKeyBoard = new CusKeyBoard(this, b);
|
||||
myInputView.setMode(1);
|
||||
myInputView.setKeyboard(mKeyBoard);
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
mKeyBoard = new CusKeyBoard(this, a);
|
||||
myInputView.setMode(0);
|
||||
myInputView.setKeyboard(mKeyBoard);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void switchShift() {
|
||||
int lowerCase = myInputView.isLowerCase();
|
||||
switch (lowerCase) {
|
||||
case 0:
|
||||
//当前小写转大写
|
||||
myInputView.setLowerCase(1);
|
||||
KeyFunction.INSTANCE.keyToUpper(mKeyBoard);
|
||||
myInputView.setKeyboard(mKeyBoard);
|
||||
break;
|
||||
case 1:
|
||||
//当前大写转锁定大写
|
||||
myInputView.setLowerCase(2);
|
||||
break;
|
||||
case 2:
|
||||
//当前锁定大写转小写
|
||||
myInputView.setLowerCase(0);
|
||||
KeyFunction.INSTANCE.keyToLowerCase(mKeyBoard);
|
||||
myInputView.setKeyboard(mKeyBoard);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onText(CharSequence text) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swipeLeft() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swipeRight() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swipeDown() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swipeUp() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,243 @@
|
||||
package com.keyboard.bubble.skin.keyboard.customerview;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
|
||||
import androidx.core.graphics.drawable.DrawableCompat;
|
||||
|
||||
import com.keyboard.bubble.skin.keyboard.R;
|
||||
import com.keyboard.bubble.skin.keyboard.resourcecode.CusKeyBoard;
|
||||
import com.keyboard.bubble.skin.keyboard.resourcecode.CusKeyBoardView;
|
||||
import com.keyboard.bubble.skin.keyboard.utils.ConstValue;
|
||||
import com.keyboard.bubble.skin.keyboard.utils.SkinManager;
|
||||
|
||||
|
||||
public class MyInputView extends CusKeyBoardView {
|
||||
|
||||
private Paint mPaint;
|
||||
private Context mContext;
|
||||
|
||||
private float mRation = 0.5f;
|
||||
|
||||
|
||||
//0 小写 1 大写 2 大写锁定
|
||||
private int isLowerCase = 0;
|
||||
//0 默认键盘 1 字母键盘 2 符号键盘
|
||||
private int mMode = 0;
|
||||
|
||||
private SkinManager skinManager;
|
||||
private int curImeAction = EditorInfo.IME_ACTION_UNSPECIFIED;
|
||||
public MyInputView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mContext = context;
|
||||
setAttribute(attrs, context);
|
||||
}
|
||||
|
||||
public MyInputView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mContext = context;
|
||||
setAttribute(attrs, context);
|
||||
}
|
||||
|
||||
public MyInputView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
mContext = context;
|
||||
setAttribute(attrs, context);
|
||||
}
|
||||
|
||||
|
||||
public void setMode(int mType) {
|
||||
this.mMode = mType;
|
||||
}
|
||||
|
||||
public int getMode() {
|
||||
return mMode;
|
||||
}
|
||||
|
||||
public int isLowerCase() {
|
||||
return isLowerCase;
|
||||
}
|
||||
|
||||
public void setLowerCase(int lowerCase) {
|
||||
isLowerCase = lowerCase;
|
||||
}
|
||||
|
||||
public void updateUi(int ime) {
|
||||
curImeAction = ime;
|
||||
skinManager.updateSkinConfig();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
private void initPaint() {
|
||||
mPaint = new Paint();
|
||||
mPaint.setAntiAlias(true);
|
||||
mPaint.setTextAlign(Paint.Align.CENTER);
|
||||
|
||||
}
|
||||
|
||||
private void setAttribute(AttributeSet attrs, Context con) {
|
||||
skinManager = new SkinManager(con);
|
||||
initPaint();
|
||||
TypedArray mTypedArray = con.obtainStyledAttributes(attrs, R.styleable.CustomInputView);
|
||||
|
||||
int color = mTypedArray.getColor(R.styleable.CustomInputView_text_color_done, 1);
|
||||
|
||||
Drawable drawable = mTypedArray.getDrawable(R.styleable.CustomInputView_drawable_cancel);
|
||||
|
||||
int textSize = mTypedArray.getInt(R.styleable.CustomInputView_text_size_key, 12);
|
||||
|
||||
mTypedArray.recycle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
|
||||
for (CusKeyBoard.Key curKey : getKeyboard().getKeys()) {
|
||||
int code = curKey.codes[0];
|
||||
realDraw(curKey, canvas, code);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
private void realDraw(CusKeyBoard.Key curKey, Canvas canvas, int code) {
|
||||
switch (code) {
|
||||
case ConstValue.KEY_CODE_SHIFT:
|
||||
drawAllShift(curKey, canvas);
|
||||
break;
|
||||
case ConstValue.KEY_CODE_NUMBER_SHIFT:
|
||||
onDrawCurKey(curKey, canvas, "More", skinManager.getFunctionDraw(), null);
|
||||
break;
|
||||
case ConstValue.KEY_CODE_DELETE:
|
||||
onDrawCurKey(curKey, canvas, "Delete", skinManager.getFunctionDraw(),null);
|
||||
break;
|
||||
case ConstValue.KEY_CODE_SYMBOL_SHIFT:
|
||||
onDrawCurKey(curKey, canvas, "123", skinManager.getFunctionDraw(), null);
|
||||
break;
|
||||
case ConstValue.KEY_CODE_CHANGE_NUMBER:
|
||||
onDrawCurKey(curKey, canvas, null, skinManager.getToDraw(), null);
|
||||
break;
|
||||
case ConstValue.KEY_CODE_BACK:
|
||||
onDrawCurKey(curKey, canvas, "Back", skinManager.getToDraw(), null);
|
||||
break;
|
||||
case ConstValue.KEY_CODE_SPACE:
|
||||
onDrawCurKey(curKey, canvas, null, skinManager.getSpaceDraw(), null);
|
||||
break;
|
||||
case ConstValue.KEY_CODE_COMPLETE, ConstValue.KEY_CODE_CANCEL:
|
||||
if(curImeAction == EditorInfo.IME_ACTION_SEARCH){
|
||||
onDrawCurKey(curKey, canvas, "Search", skinManager.getFunctionDraw(), null);
|
||||
}else {
|
||||
onDrawCurKey(curKey, canvas, "Done", skinManager.getFunctionDraw(), null);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
onDrawCurKey(curKey, canvas, null, skinManager.getGeneralDraw(), null);
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void drawAllShift(CusKeyBoard.Key curKey, Canvas canvas) {
|
||||
if (isLowerCase == 0) {
|
||||
onDrawCurKey(curKey, canvas, "Shift", skinManager.getFunctionDraw(), null);
|
||||
} else if (isLowerCase == 1) {
|
||||
onDrawCurKey(curKey, canvas, "Shift", skinManager.getFunctionDraw(),null);
|
||||
} else if(isLowerCase == 2){
|
||||
onDrawCurKey(curKey, canvas, "Shift", skinManager.getFunctionDraw(), null);
|
||||
}
|
||||
}
|
||||
|
||||
private void onDrawCurKey(CusKeyBoard.Key curKey, Canvas curCanvas, String label, Drawable bgDrawable, Drawable iconDraw) {
|
||||
|
||||
if (bgDrawable != null) {
|
||||
onDrawKeyBackground(curKey, curCanvas, bgDrawable);
|
||||
}
|
||||
if (iconDraw != null) {
|
||||
onDrawKeyIcon(curKey, curCanvas, iconDraw);
|
||||
}
|
||||
onDrawKeyText(curKey, curCanvas, label);
|
||||
}
|
||||
|
||||
private void onDrawKeyText(CusKeyBoard.Key curKey, Canvas curCanvas, String label) {
|
||||
mPaint.setColor(skinManager.getKeyTextColor());
|
||||
mPaint.setTextSize(mContext.getResources().getDimension(R.dimen.text_size));
|
||||
float v = curKey.width / 2f;
|
||||
float v1 = curKey.height / 2f;
|
||||
float v2 = (mPaint.getTextSize() - mPaint.descent()) / 2f;
|
||||
|
||||
|
||||
if (curKey.label != null) {
|
||||
curCanvas.drawText((String) curKey.label, curKey.x + getPaddingLeft() + v, curKey.y + getPaddingRight() + v1 + v2, mPaint);
|
||||
} else if (label != null) {
|
||||
curCanvas.drawText(label, curKey.x + getPaddingLeft() + v, curKey.y + getPaddingRight() + v1 + v2, mPaint);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void onDrawKeyBackground(CusKeyBoard.Key curKey, Canvas curCanvas, Drawable curDrawable) {
|
||||
if (curKey.codes[0] != 0) {
|
||||
curDrawable.setState(curKey.getCurrentDrawableState());
|
||||
}
|
||||
Rect rect = new Rect((curKey.x + this.getPaddingLeft()), (curKey.y + this.getPaddingTop()), (curKey.x + this.getPaddingLeft() + curKey.width), (curKey.y + this.getPaddingTop() + curKey.height));
|
||||
curDrawable.setBounds(rect);
|
||||
|
||||
curDrawable.draw(curCanvas);
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void onDrawKeyIcon(CusKeyBoard.Key curKey, Canvas curCanvas, Drawable curDrawable) {
|
||||
|
||||
Drawable wrap = DrawableCompat.wrap(curDrawable);
|
||||
|
||||
curKey.icon = curDrawable;
|
||||
float iconW = (float) curKey.icon.getIntrinsicWidth();
|
||||
float iconH = (float) curKey.icon.getIntrinsicHeight();
|
||||
|
||||
float wDivRation = iconW / curKey.width;
|
||||
float hDivRation = iconH / curKey.height;
|
||||
|
||||
curKey.icon.draw(curCanvas);
|
||||
|
||||
if (wDivRation > hDivRation) {
|
||||
float minRatio = 0;
|
||||
if (wDivRation <= mRation) {
|
||||
minRatio = wDivRation;
|
||||
} else {
|
||||
minRatio = mRation;
|
||||
}
|
||||
iconH = (iconH / wDivRation) * minRatio;
|
||||
iconW = (iconW / wDivRation) * minRatio;
|
||||
} else {
|
||||
float minRatio = 0;
|
||||
if (hDivRation <= mRation) {
|
||||
minRatio = hDivRation;
|
||||
} else {
|
||||
minRatio = mRation;
|
||||
}
|
||||
iconH = (iconH / hDivRation) * minRatio;
|
||||
iconW = (iconW / hDivRation) * minRatio;
|
||||
}
|
||||
float subW = (curKey.width - iconW) / 2f;
|
||||
float subH = (curKey.height - iconH) / 2f;
|
||||
int xLeft = (int) (curKey.x + getPaddingLeft() + subW);
|
||||
int yTop = (int) (curKey.y + getPaddingTop() + subH);
|
||||
int xRight = (int) (xLeft + iconW);
|
||||
int yBottom = (int) (yTop + iconH);
|
||||
curKey.icon.setBounds(xLeft, yTop, xRight, yBottom);
|
||||
curKey.icon.draw(curCanvas);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
package com.keyboard.bubble.skin.keyboard.db
|
||||
|
||||
import com.keyboard.bubble.skin.keyboard.bean.ChildBean
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
object DbOpManager {
|
||||
|
||||
|
||||
suspend fun addLike(data: ChildBean) {
|
||||
data.isLike = true
|
||||
withContext(Dispatchers.IO) {
|
||||
MyDb.myDb.ThemesDao().insertData(data)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
suspend fun addDownload(data: ChildBean) {
|
||||
data.isDownload = true
|
||||
withContext(Dispatchers.IO) {
|
||||
MyDb.myDb.ThemesDao().insertData(data)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
suspend fun removeLike(data: ChildBean) {
|
||||
withContext(Dispatchers.IO) {
|
||||
val queryIsLike = MyDb.myDb.ThemesDao().queryIsLike(data.titleName)
|
||||
if (queryIsLike != null) {
|
||||
if (!queryIsLike.isDownload) {
|
||||
MyDb.myDb.ThemesDao().delete(queryIsLike)
|
||||
} else {
|
||||
queryIsLike.isLike = false
|
||||
MyDb.myDb.ThemesDao().updateLike(queryIsLike)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
suspend fun getIsLike(name: String, action: (isLike: Boolean) -> Unit) {
|
||||
withContext(Dispatchers.IO) {
|
||||
val query = MyDb.myDb.ThemesDao().queryIsLike(name)
|
||||
withContext(Dispatchers.Main) {
|
||||
action.invoke(query != null)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package com.keyboard.bubble.skin.keyboard.db
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Delete
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import androidx.room.Update
|
||||
import com.keyboard.bubble.skin.keyboard.bean.ChildBean
|
||||
|
||||
@Dao
|
||||
interface MyDao {
|
||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||
suspend fun insertData(data: ChildBean): Long
|
||||
|
||||
@Query("select * from ChildBean where `like` = :isLike")
|
||||
fun queryAllLike(isLike: Boolean = true): LiveData<List<ChildBean?>?>
|
||||
|
||||
@Query("select * from ChildBean where `download` = :idDownload")
|
||||
fun queryAllDownload(idDownload: Boolean = true): LiveData<List<ChildBean?>?>
|
||||
|
||||
@Query("select * from ChildBean where titleName = :title And `like` = :isLike")
|
||||
suspend fun queryIsLike(title: String, isLike: Boolean = true): ChildBean?
|
||||
|
||||
|
||||
@Delete
|
||||
suspend fun delete(data: ChildBean)
|
||||
|
||||
@Update
|
||||
suspend fun updateLike(data: ChildBean)
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
package com.keyboard.bubble.skin.keyboard.db
|
||||
|
||||
import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
import com.keyboard.bubble.skin.keyboard.App
|
||||
import com.keyboard.bubble.skin.keyboard.bean.ChildBean
|
||||
|
||||
|
||||
@Database(
|
||||
entities = [ChildBean::class],
|
||||
version = App.DB_VERSION,
|
||||
exportSchema = false
|
||||
)
|
||||
abstract class MyDb : RoomDatabase() {
|
||||
|
||||
abstract fun ThemesDao(): MyDao
|
||||
|
||||
|
||||
|
||||
companion object {
|
||||
val myDb: MyDb by lazy {
|
||||
Room.databaseBuilder(
|
||||
App.appInstance, MyDb::class.java,
|
||||
App.DB_NAME
|
||||
).build()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,162 @@
|
||||
package com.keyboard.bubble.skin.keyboard.fagment
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import com.keyboard.bubble.skin.keyboard.App
|
||||
import com.keyboard.bubble.skin.keyboard.R
|
||||
import com.keyboard.bubble.skin.keyboard.databinding.LayoutActiveBinding
|
||||
import com.keyboard.bubble.skin.keyboard.utils.MyUtils
|
||||
|
||||
|
||||
class EnablePage(private var clickAction: () -> Unit) : DialogFragment() {
|
||||
|
||||
private lateinit var vb: LayoutActiveBinding
|
||||
|
||||
private lateinit var layoutStepOne: LinearLayout
|
||||
private lateinit var layoutStepTwo: LinearLayout
|
||||
private lateinit var imgStepOkOne: ImageView
|
||||
private lateinit var imgStepOkTwo: ImageView
|
||||
private lateinit var intentFilter: IntentFilter
|
||||
private var myreceiver: BroadcastReceiver? = null
|
||||
|
||||
private lateinit var stepOne: TextView
|
||||
private lateinit var stepTwo: TextView
|
||||
|
||||
private lateinit var context: Context
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
vb = LayoutActiveBinding.inflate(layoutInflater)
|
||||
context = App.appInstance
|
||||
|
||||
|
||||
findViewId()
|
||||
onViewStep()
|
||||
getReceiver()
|
||||
return vb.root
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
dialog?.run {
|
||||
setCanceledOnTouchOutside(true)
|
||||
window?.run {
|
||||
setGravity(Gravity.BOTTOM)
|
||||
setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||
|
||||
attributes = attributes.apply {
|
||||
width = WindowManager.LayoutParams.MATCH_PARENT
|
||||
height = WindowManager.LayoutParams.WRAP_CONTENT
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private fun findViewId() {
|
||||
|
||||
layoutStepOne = vb.linearStepOne
|
||||
layoutStepTwo = vb.linearStepTwo
|
||||
imgStepOkOne = vb.okOne
|
||||
imgStepOkTwo = vb.okTwo
|
||||
stepOne = vb.textStepOne
|
||||
stepTwo = vb.textStepTwo
|
||||
}
|
||||
|
||||
private fun onViewStep() {
|
||||
|
||||
layoutStepOne.setOnClickListener {
|
||||
startActivity(Intent(Settings.ACTION_INPUT_METHOD_SETTINGS))
|
||||
}
|
||||
layoutStepTwo.setOnClickListener {
|
||||
val inputMethodManager =
|
||||
context.getSystemService(AppCompatActivity.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
inputMethodManager.showInputMethodPicker()
|
||||
}
|
||||
vb.imClose.setOnClickListener {
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
updateUI()
|
||||
}
|
||||
|
||||
private fun getReceiver() {
|
||||
myreceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
updateUI()
|
||||
}
|
||||
}
|
||||
intentFilter = IntentFilter(Intent.ACTION_INPUT_METHOD_CHANGED)
|
||||
|
||||
context.registerReceiver(myreceiver, intentFilter)
|
||||
}
|
||||
|
||||
private fun updateUI() {
|
||||
|
||||
val checkEnable = MyUtils.checkEnable(App.appInstance)
|
||||
val checkSetDefault = MyUtils.checkSetDefault(App.appInstance)
|
||||
if (checkEnable && checkSetDefault) {
|
||||
clickAction.invoke()
|
||||
dismiss()
|
||||
return
|
||||
}
|
||||
if (checkEnable) {
|
||||
layoutStepOne.isEnabled = false
|
||||
layoutStepOne.isSelected = true
|
||||
imgStepOkOne.isVisible = true
|
||||
stepOne.setTextColor(context.getColor(R.color.step_true))
|
||||
} else {
|
||||
layoutStepOne.isEnabled = true
|
||||
layoutStepOne.isSelected = false
|
||||
imgStepOkOne.isVisible = false
|
||||
stepOne.setTextColor(context.getColor(R.color.white))
|
||||
}
|
||||
|
||||
if (checkSetDefault) {
|
||||
layoutStepTwo.isEnabled = false
|
||||
layoutStepTwo.isSelected = true
|
||||
imgStepOkTwo.isVisible = true
|
||||
stepTwo.setTextColor(context.getColor(R.color.step_true))
|
||||
} else {
|
||||
layoutStepTwo.isEnabled = true
|
||||
layoutStepTwo.isSelected = false
|
||||
imgStepOkTwo.isVisible = false
|
||||
stepTwo.setTextColor(context.getColor(R.color.white))
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
if (myreceiver != null) {
|
||||
context.unregisterReceiver(myreceiver)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
package com.keyboard.bubble.skin.keyboard.fagment
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import com.keyboard.bubble.skin.keyboard.App
|
||||
import com.keyboard.bubble.skin.keyboard.bean.ChildBean
|
||||
import com.keyboard.bubble.skin.keyboard.databinding.LayoutLikeFragmentBinding
|
||||
import com.keyboard.bubble.skin.keyboard.db.DbOpManager
|
||||
import com.keyboard.bubble.skin.keyboard.db.MyDb
|
||||
import com.keyboard.bubble.skin.keyboard.myada.AdapterLike
|
||||
import com.keyboard.bubble.skin.keyboard.mylistener.CancelLikeCallback
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class LikePage : Fragment() {
|
||||
private lateinit var vb: LayoutLikeFragmentBinding
|
||||
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun newInstance() =
|
||||
LikePage()
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
vb = LayoutLikeFragmentBinding.inflate(layoutInflater)
|
||||
|
||||
init()
|
||||
|
||||
return vb.root
|
||||
}
|
||||
|
||||
|
||||
private fun init() {
|
||||
val mainAdapter = AdapterLike(
|
||||
requireContext()
|
||||
).apply {
|
||||
setRemoveLike(object : CancelLikeCallback {
|
||||
override fun OnRemoveLike(data: ChildBean) {
|
||||
lifecycleScope.launch {
|
||||
DbOpManager.removeLike(data)
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
vb.likeRecycler.run {
|
||||
adapter = mainAdapter
|
||||
layoutManager = GridLayoutManager(requireContext(), 2)
|
||||
}
|
||||
|
||||
MyDb.myDb.ThemesDao().queryAllLike(true).observe(requireActivity()) {
|
||||
Log.d(App.TAG, "---------it=${it?.size}")
|
||||
if(it.isNullOrEmpty()){
|
||||
vb.likeRecycler.isVisible = false
|
||||
vb.emptyTitle.isVisible = true
|
||||
}else{
|
||||
vb.likeRecycler.isVisible = true
|
||||
vb.emptyTitle.isVisible = false
|
||||
mainAdapter.setForYouList(it)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
package com.keyboard.bubble.skin.keyboard.fagment
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.keyboard.bubble.skin.keyboard.App
|
||||
import com.keyboard.bubble.skin.keyboard.R
|
||||
import com.keyboard.bubble.skin.keyboard.myada.AdapterMain
|
||||
|
||||
|
||||
class MainPage : Fragment() {
|
||||
|
||||
private var paramIndex: Int = 0
|
||||
private lateinit var contentRecy: RecyclerView
|
||||
val ARG_PARAM1 = "KEY"
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
arguments?.let {
|
||||
paramIndex = it.getInt(ARG_PARAM1)
|
||||
}
|
||||
}
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun newInstance(index: Int) =
|
||||
MainPage().apply {
|
||||
arguments = Bundle().apply {
|
||||
putInt(ARG_PARAM1, index)
|
||||
}
|
||||
}
|
||||
}
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
val viewMain = inflater.inflate(R.layout.layout_main_fragment, container, false)
|
||||
contentRecy = viewMain.findViewById(R.id.content_recycler)
|
||||
initContent()
|
||||
return viewMain
|
||||
}
|
||||
|
||||
private fun initContent(){
|
||||
val mainBean = App.list[paramIndex]
|
||||
contentRecy.run {
|
||||
this.adapter = AdapterMain(
|
||||
requireContext()
|
||||
).apply {
|
||||
val shufflList = mainBean.keyboardList.shuffled()
|
||||
setForYouList(shufflList)
|
||||
}
|
||||
this.layoutManager = GridLayoutManager(requireContext(), 2)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,109 @@
|
||||
package com.keyboard.bubble.skin.keyboard.fagment
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentStatePagerAdapter
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import com.keyboard.bubble.skin.keyboard.App
|
||||
import com.keyboard.bubble.skin.keyboard.bean.ParentBean
|
||||
import com.keyboard.bubble.skin.keyboard.databinding.LayoutThemeFragmentBinding
|
||||
import com.keyboard.bubble.skin.keyboard.myada.AdapterTab
|
||||
|
||||
class ViewPage : Fragment() {
|
||||
|
||||
|
||||
private lateinit var vb: LayoutThemeFragmentBinding
|
||||
|
||||
|
||||
private lateinit var viewContent: ViewPager
|
||||
lateinit var viewAllList: MutableList<ParentBean>
|
||||
private lateinit var adapterTab: AdapterTab
|
||||
|
||||
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun newInstance() =
|
||||
ViewPage()
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
vb = LayoutThemeFragmentBinding.inflate(layoutInflater)
|
||||
viewContent = vb.viewPager
|
||||
setTabRecycler()
|
||||
setContent()
|
||||
return vb.root
|
||||
}
|
||||
|
||||
|
||||
private fun setTabRecycler() {
|
||||
viewAllList = App.list
|
||||
adapterTab = AdapterTab(
|
||||
requireContext()
|
||||
).apply {
|
||||
tabTitleName(viewAllList)
|
||||
setChangeListener(object : AdapterTab.OnChangListener {
|
||||
override fun onChange(posit: Int) {
|
||||
viewContent.setCurrentItem(posit, false)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
vb.tabRecycler.run {
|
||||
adapter = adapterTab
|
||||
layoutManager = LinearLayoutManager(requireContext(), RecyclerView.HORIZONTAL, false)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setContent() {
|
||||
val fragList = mutableListOf<Fragment>()
|
||||
for (index in 0 until viewAllList.size) {
|
||||
fragList.add(MainPage.newInstance(index))
|
||||
}
|
||||
|
||||
viewContent.adapter = object : FragmentStatePagerAdapter(
|
||||
childFragmentManager,
|
||||
BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT
|
||||
) {
|
||||
override fun getCount(): Int = fragList.size
|
||||
|
||||
override fun getItem(position: Int): Fragment = fragList[position]
|
||||
|
||||
}
|
||||
var curViewPager = 0
|
||||
viewContent.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
|
||||
override fun onPageScrolled(
|
||||
position: Int,
|
||||
positionOffset: Float,
|
||||
positionOffsetPixels: Int
|
||||
) {
|
||||
if (curViewPager != position) {
|
||||
adapterTab.setSelectedPos(position)
|
||||
// tabRecycler.scrollToPosition(position)
|
||||
curViewPager = position
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onPageSelected(position: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun onPageScrollStateChanged(state: Int) {
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,124 @@
|
||||
package com.keyboard.bubble.skin.keyboard.myada;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.cardview.widget.CardView;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.keyboard.bubble.skin.keyboard.R;
|
||||
import com.keyboard.bubble.skin.keyboard.bean.ChildBean;
|
||||
import com.keyboard.bubble.skin.keyboard.utils.MyUtils;
|
||||
import com.keyboard.bubble.skin.keyboard.mylistener.CancelLikeCallback;
|
||||
import com.keyboard.bubble.skin.keyboard.ui.SetkeyboardActivity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class AdapterLike extends RecyclerView.Adapter<AdapterLike.ForYouViewHolder> {
|
||||
|
||||
private Context mContext;
|
||||
private List<ChildBean> mList = new ArrayList<>();
|
||||
|
||||
private CancelLikeCallback mCallBack;
|
||||
|
||||
public AdapterLike(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public void setForYouList(List<ChildBean> list) {
|
||||
this.mList = list;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
|
||||
public void setRemoveLike(CancelLikeCallback callback) {
|
||||
mCallBack = callback;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ForYouViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
|
||||
View view = LayoutInflater.from(mContext).inflate(R.layout.item_like, parent, false);
|
||||
return new ForYouViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ForYouViewHolder holder, int position) {
|
||||
ChildBean childBean = mList.get(position);
|
||||
String thumbGif = childBean.getThumbGif();
|
||||
String thumb = childBean.getThumbUrl();
|
||||
if (!thumbGif.isEmpty()) {
|
||||
MyUtils.INSTANCE.loadWepJif(mContext, thumbGif, holder.itemImg);
|
||||
} else {
|
||||
Glide.with(mContext).load(thumb).into(holder.itemImg);
|
||||
}
|
||||
holder.itemFavorite.setSelected(true);
|
||||
holder.layoutFavorite.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
holder.itemFavorite.setSelected(false);
|
||||
int adapterPosition = holder.getAdapterPosition();
|
||||
notifyItemRemoved(adapterPosition);
|
||||
if (mCallBack != null) {
|
||||
mCallBack.OnRemoveLike(childBean);
|
||||
}
|
||||
}
|
||||
});
|
||||
holder.cardView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intentApply = new Intent(mContext, SetkeyboardActivity.class);
|
||||
intentApply.putExtra(SetkeyboardActivity.SOURCE_KEY, childBean);
|
||||
intentApply.putExtra(SetkeyboardActivity.DISPLAY_URL_KEY, childBean.getImgPath());
|
||||
intentApply.putExtra(SetkeyboardActivity.ZIP_URL_KEY, childBean.getZipPath());
|
||||
intentApply.putExtra(SetkeyboardActivity.NAME_KEY, childBean.getTitleName());
|
||||
intentApply.putExtra(SetkeyboardActivity.GIF_KEY, childBean.getImgGif());
|
||||
String intent_thumb;
|
||||
if (!thumbGif.isEmpty()) {
|
||||
intent_thumb = thumbGif;
|
||||
} else {
|
||||
intent_thumb = thumb;
|
||||
}
|
||||
intentApply.putExtra(SetkeyboardActivity.THUMB_KEY, intent_thumb);
|
||||
mContext.startActivity(intentApply);
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mList.size();
|
||||
}
|
||||
|
||||
public static class ForYouViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
private CardView cardView;
|
||||
private FrameLayout layoutFavorite;
|
||||
private ImageView itemImg, itemFavorite;
|
||||
|
||||
public ForYouViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
cardView = itemView.findViewById(R.id.card_view);
|
||||
layoutFavorite = itemView.findViewById(R.id.layout_favorite);
|
||||
itemImg = itemView.findViewById(R.id.im);
|
||||
itemFavorite = itemView.findViewById(R.id.im_favorite);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,129 @@
|
||||
package com.keyboard.bubble.skin.keyboard.myada;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.cardview.widget.CardView;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.keyboard.bubble.skin.keyboard.R;
|
||||
import com.keyboard.bubble.skin.keyboard.bean.ChildBean;
|
||||
import com.keyboard.bubble.skin.keyboard.mylistener.ItemClickCallback;
|
||||
import com.keyboard.bubble.skin.keyboard.ui.SetkeyboardActivity;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.keyboard.bubble.skin.keyboard.utils.MyUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class AdapterMain extends RecyclerView.Adapter<AdapterMain.ForYouViewHolder> {
|
||||
|
||||
private Context mContext;
|
||||
private List<ChildBean> mList = new ArrayList<>();
|
||||
|
||||
private ItemClickCallback mCallBack;
|
||||
|
||||
public AdapterMain(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public void setForYouList(List<ChildBean> list) {
|
||||
this.mList = list;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
|
||||
public void setClickAction(ItemClickCallback callback) {
|
||||
mCallBack = callback;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ForYouViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
|
||||
View view = LayoutInflater.from(mContext).inflate(R.layout.item_main, parent, false);
|
||||
return new ForYouViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ForYouViewHolder holder, int position) {
|
||||
ChildBean childBean = mList.get(position);
|
||||
String thumbGif = childBean.getThumbGif();
|
||||
String thumb = childBean.getThumbUrl();
|
||||
if (!thumbGif.isEmpty()) {
|
||||
MyUtils.INSTANCE.loadWepJif(mContext, thumbGif, holder.itemImg);
|
||||
} else {
|
||||
Glide.with(mContext).load(thumb).into(holder.itemImg);
|
||||
}
|
||||
|
||||
holder.cardView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intentApply = new Intent(mContext, SetkeyboardActivity.class);
|
||||
intentApply.putExtra(SetkeyboardActivity.SOURCE_KEY, childBean);
|
||||
intentApply.putExtra(SetkeyboardActivity.DISPLAY_URL_KEY, childBean.getImgPath());
|
||||
intentApply.putExtra(SetkeyboardActivity.ZIP_URL_KEY, childBean.getZipPath());
|
||||
intentApply.putExtra(SetkeyboardActivity.NAME_KEY, childBean.getTitleName());
|
||||
intentApply.putExtra(SetkeyboardActivity.GIF_KEY, childBean.getImgGif());
|
||||
String intent_thumb;
|
||||
if (!thumbGif.isEmpty()) {
|
||||
intent_thumb = thumbGif;
|
||||
} else {
|
||||
intent_thumb = thumb;
|
||||
}
|
||||
intentApply.putExtra(SetkeyboardActivity.THUMB_KEY, intent_thumb);
|
||||
mContext.startActivity(intentApply);
|
||||
if (mCallBack != null) {
|
||||
mCallBack.OnItemClickListener();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mList.size();
|
||||
}
|
||||
|
||||
public static class ForYouViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
private CardView cardView;
|
||||
private ImageView itemImg;
|
||||
|
||||
public ForYouViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
cardView = itemView.findViewById(R.id.card_view);
|
||||
itemImg = itemView.findViewById(R.id.imPreview);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// private void loadWepJif(String webpGifUrl,ImageView view){
|
||||
// Glide.with(mContext).load(webpGifUrl).addListener(new RequestListener<Drawable>() {
|
||||
// @Override
|
||||
// public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
||||
// if(resource instanceof WebpDrawable){
|
||||
// WebpDrawable webpDrawable = (WebpDrawable) resource;
|
||||
// webpDrawable.setLoopCount(LOOP_FOREVER);
|
||||
// }
|
||||
//
|
||||
// return false;
|
||||
// }
|
||||
// }).into(view);
|
||||
// }
|
||||
}
|
||||
@ -0,0 +1,108 @@
|
||||
package com.keyboard.bubble.skin.keyboard.myada;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.keyboard.bubble.skin.keyboard.R;
|
||||
import com.keyboard.bubble.skin.keyboard.bean.ParentBean;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class AdapterTab extends RecyclerView.Adapter<AdapterTab.ViewAllTabViewHolder> {
|
||||
|
||||
private Context mContext;
|
||||
private List<ParentBean> viewAllList;
|
||||
|
||||
private OnChangListener mOnChangListener;
|
||||
|
||||
private int selectedPos = 0;
|
||||
|
||||
private int oldSelectedPos = -1;
|
||||
|
||||
public AdapterTab(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public void setSelectedPos(int selectedPosition) {
|
||||
oldSelectedPos = selectedPos;
|
||||
selectedPos = selectedPosition;
|
||||
notifyItemChanged(oldSelectedPos);
|
||||
notifyItemChanged(selectedPos);
|
||||
}
|
||||
|
||||
|
||||
public void setChangeListener(OnChangListener onChangListener){
|
||||
mOnChangListener = onChangListener;
|
||||
}
|
||||
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public AdapterTab.ViewAllTabViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(mContext).inflate(R.layout.item_preview, parent, false);
|
||||
return new AdapterTab.ViewAllTabViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull AdapterTab.ViewAllTabViewHolder holder, int pos) {
|
||||
ParentBean aParentBean = viewAllList.get(pos);
|
||||
|
||||
holder.tabTitle.setText(aParentBean.getParentName().toUpperCase());
|
||||
if (pos == selectedPos) {
|
||||
holder.tabTitle.setSelected(true);
|
||||
// holder.tabTitle.setBackground(ContextCompat.getDrawable(App.appInstance,R.drawable.selected_tab_bg));
|
||||
// holder.tabTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP,17);
|
||||
// holder.tabIndicator.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
holder.tabTitle.setSelected(false);
|
||||
// holder.tabTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP,14);
|
||||
// holder.tabIndicator.setVisibility(View.GONE);
|
||||
}
|
||||
holder.itemLayout.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
oldSelectedPos = selectedPos;
|
||||
selectedPos = holder.getAdapterPosition();
|
||||
|
||||
notifyItemChanged(oldSelectedPos);
|
||||
notifyItemChanged(selectedPos);
|
||||
mOnChangListener.onChange(selectedPos);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return viewAllList.size();
|
||||
}
|
||||
public void tabTitleName(List<ParentBean> list) {
|
||||
viewAllList = list;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
static class ViewAllTabViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
|
||||
private TextView tabTitle;
|
||||
// private LinearLayout tabIndicator;
|
||||
private RelativeLayout itemLayout;
|
||||
|
||||
public ViewAllTabViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
tabTitle = itemView.findViewById(R.id.text_tab_view);
|
||||
// tabIndicator = itemView.findViewById(R.id.layout_indicator);
|
||||
itemLayout = itemView.findViewById(R.id.item_layout);
|
||||
}
|
||||
}
|
||||
|
||||
public interface OnChangListener{
|
||||
void onChange(int posit);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
package com.keyboard.bubble.skin.keyboard.mylistener
|
||||
|
||||
import com.keyboard.bubble.skin.keyboard.bean.ChildBean
|
||||
|
||||
interface CancelLikeCallback {
|
||||
|
||||
fun OnRemoveLike(data: ChildBean)
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
package com.keyboard.bubble.skin.keyboard.mylistener
|
||||
|
||||
interface ItemClickCallback {
|
||||
|
||||
fun OnItemClickListener( )
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
package com.keyboard.bubble.skin.keyboard.mylistener
|
||||
|
||||
import java.io.File
|
||||
|
||||
interface SetCallback {
|
||||
|
||||
fun OnApplySkinListener(fileList: List<File?>?)
|
||||
}
|
||||
@ -0,0 +1,858 @@
|
||||
package com.keyboard.bubble.skin.keyboard.resourcecode;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.TypedValue;
|
||||
import android.util.Xml;
|
||||
|
||||
import androidx.annotation.XmlRes;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
|
||||
import com.keyboard.bubble.skin.keyboard.R;
|
||||
|
||||
public class CusKeyBoard {
|
||||
|
||||
static final String TAG = "------------Keyboard-----------";
|
||||
|
||||
// Keyboard XML Tags
|
||||
private static final String TAG_KEYBOARD = "Keyboard";
|
||||
private static final String TAG_ROW = "Row";
|
||||
private static final String TAG_KEY = "Key";
|
||||
|
||||
public static final int EDGE_LEFT = 0x01;
|
||||
public static final int EDGE_RIGHT = 0x02;
|
||||
public static final int EDGE_TOP = 0x04;
|
||||
public static final int EDGE_BOTTOM = 0x08;
|
||||
|
||||
public static final int KEYCODE_SHIFT = -1;
|
||||
public static final int KEYCODE_MODE_CHANGE = -2;
|
||||
public static final int KEYCODE_CANCEL = -3;
|
||||
public static final int KEYCODE_DONE = -4;
|
||||
public static final int KEYCODE_DELETE = -5;
|
||||
public static final int KEYCODE_ALT = -6;
|
||||
|
||||
/** Keyboard label **/
|
||||
private CharSequence mLabel;
|
||||
|
||||
/** Horizontal gap default for all rows */
|
||||
private int mDefaultHorizontalGap;
|
||||
|
||||
/** Default key width */
|
||||
private int mDefaultWidth;
|
||||
|
||||
/** Default key height */
|
||||
private int mDefaultHeight;
|
||||
|
||||
/** Default gap between rows */
|
||||
private int mDefaultVerticalGap;
|
||||
|
||||
/** Is the keyboard in the shifted state */
|
||||
private boolean mShifted;
|
||||
|
||||
/** Key instance for the shift key, if present */
|
||||
private CusKeyBoard.Key[] mShiftKeys = { null, null };
|
||||
|
||||
/** Key index for the shift key, if present */
|
||||
private int[] mShiftKeyIndices = {-1, -1};
|
||||
|
||||
/** Current key width, while loading the keyboard */
|
||||
private int mKeyWidth;
|
||||
|
||||
/** Current key height, while loading the keyboard */
|
||||
private int mKeyHeight;
|
||||
|
||||
/** Total height of the keyboard, including the padding and keys */
|
||||
private int mTotalHeight;
|
||||
|
||||
/**
|
||||
* Total width of the keyboard, including left side gaps and keys, but not any gaps on the
|
||||
* right side.
|
||||
*/
|
||||
private int mTotalWidth;
|
||||
|
||||
/** List of keys in this keyboard */
|
||||
private List<CusKeyBoard.Key> mKeys;
|
||||
|
||||
/** List of modifier keys such as Shift & Alt, if any */
|
||||
private List<CusKeyBoard.Key> mModifierKeys;
|
||||
|
||||
/** Width of the screen available to fit the keyboard */
|
||||
private int mDisplayWidth;
|
||||
|
||||
/** Height of the screen */
|
||||
private int mDisplayHeight;
|
||||
|
||||
/** Keyboard mode, or zero, if none. */
|
||||
private int mKeyboardMode;
|
||||
|
||||
// Variables for pre-computing nearest keys.
|
||||
|
||||
private static final int GRID_WIDTH = 10;
|
||||
private static final int GRID_HEIGHT = 5;
|
||||
private static final int GRID_SIZE = GRID_WIDTH * GRID_HEIGHT;
|
||||
private int mCellWidth;
|
||||
private int mCellHeight;
|
||||
private int[][] mGridNeighbors;
|
||||
private int mProximityThreshold;
|
||||
/** Number of key widths from current touch point to search for nearest keys. */
|
||||
private static float SEARCH_DISTANCE = 1.8f;
|
||||
|
||||
private ArrayList<CusKeyBoard.Row> rows = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Container for keys in the keyboard. All keys in a row are at the same Y-coordinate.
|
||||
* Some of the key size defaults can be overridden per row from what the {@link CusKeyBoard}
|
||||
* defines.
|
||||
* @attr ref android.R.styleable#King_Keyboard_keyWidth
|
||||
* @attr ref android.R.styleable#King_Keyboard_keyHeight
|
||||
* @attr ref android.R.styleable#King_Keyboard_horizontalGap
|
||||
* @attr ref android.R.styleable#King_Keyboard_verticalGap
|
||||
* @attr ref android.R.styleable#King_Keyboard_Row_rowEdgeFlags
|
||||
* @attr ref android.R.styleable#King_Keyboard_Row_keyboardMode
|
||||
*/
|
||||
public static class Row {
|
||||
/** Default width of a key in this row. */
|
||||
public int defaultWidth;
|
||||
/** Default height of a key in this row. */
|
||||
public int defaultHeight;
|
||||
/** Default horizontal gap between keys in this row. */
|
||||
public int defaultHorizontalGap;
|
||||
/** Vertical gap following this row. */
|
||||
public int verticalGap;
|
||||
|
||||
ArrayList<CusKeyBoard.Key> mKeys = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Edge flags for this row of keys. Possible values that can be assigned are
|
||||
* {@link CusKeyBoard#EDGE_TOP EDGE_TOP} and {@link CusKeyBoard#EDGE_BOTTOM EDGE_BOTTOM}
|
||||
*/
|
||||
public int rowEdgeFlags;
|
||||
|
||||
/** The keyboard mode for this row */
|
||||
public int mode;
|
||||
|
||||
private CusKeyBoard parent;
|
||||
|
||||
public Row(CusKeyBoard parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public Row(Resources res, CusKeyBoard parent, XmlResourceParser parser) {
|
||||
this.parent = parent;
|
||||
TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser),
|
||||
R.styleable.My_Keyboard_view);
|
||||
defaultWidth = getDimensionOrFraction(a,
|
||||
R.styleable.My_Keyboard_view_android_keyWidth,
|
||||
parent.mDisplayWidth, parent.mDefaultWidth);
|
||||
defaultHeight = getDimensionOrFraction(a,
|
||||
R.styleable.My_Keyboard_view_android_keyHeight,
|
||||
parent.mDisplayHeight, parent.mDefaultHeight);
|
||||
defaultHorizontalGap = getDimensionOrFraction(a,
|
||||
R.styleable.My_Keyboard_view_android_horizontalGap,
|
||||
parent.mDisplayWidth, parent.mDefaultHorizontalGap);
|
||||
verticalGap = getDimensionOrFraction(a,
|
||||
R.styleable.My_Keyboard_view_android_verticalGap,
|
||||
parent.mDisplayHeight, parent.mDefaultVerticalGap);
|
||||
a.recycle();
|
||||
a = res.obtainAttributes(Xml.asAttributeSet(parser),
|
||||
R.styleable.Kil_Keyboard_Row);
|
||||
rowEdgeFlags = a.getInt(R.styleable.Kil_Keyboard_Row_android_rowEdgeFlags, 0);
|
||||
mode = a.getResourceId(R.styleable.Kil_Keyboard_Row_android_keyboardMode,
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class for describing the position and characteristics of a single key in the keyboard.
|
||||
*
|
||||
* @attr ref android.R.styleable#King_Keyboard_keyWidth
|
||||
* @attr ref android.R.styleable#King_Keyboard_keyHeight
|
||||
* @attr ref android.R.styleable#King_Keyboard_horizontalGap
|
||||
* @attr ref android.R.styleable#King_Keyboard_Key_codes
|
||||
* @attr ref android.R.styleable#King_Keyboard_Key_keyIcon
|
||||
* @attr ref android.R.styleable#King_Keyboard_Key_keyLabel
|
||||
* @attr ref android.R.styleable#King_Keyboard_Key_iconPreview
|
||||
* @attr ref android.R.styleable#King_Keyboard_Key_isSticky
|
||||
* @attr ref android.R.styleable#King_Keyboard_Key_isRepeatable
|
||||
* @attr ref android.R.styleable#King_Keyboard_Key_isModifier
|
||||
* @attr ref android.R.styleable#King_Keyboard_Key_popupKeyboard
|
||||
* @attr ref android.R.styleable#King_Keyboard_Key_popupCharacters
|
||||
* @attr ref android.R.styleable#King_Keyboard_Key_keyOutputText
|
||||
* @attr ref android.R.styleable#King_Keyboard_Key_keyEdgeFlags
|
||||
*/
|
||||
public static class Key {
|
||||
/**
|
||||
* All the key codes (unicode or custom code) that this key could generate, zero'th
|
||||
* being the most important.
|
||||
*/
|
||||
public int[] codes;
|
||||
|
||||
/** Label to display */
|
||||
public CharSequence label;
|
||||
|
||||
/** Icon to display instead of a label. Icon takes precedence over a label */
|
||||
public Drawable icon;
|
||||
/** Preview version of the icon, for the preview popup */
|
||||
public Drawable iconPreview;
|
||||
/** Width of the key, not including the gap */
|
||||
public int width;
|
||||
/** Height of the key, not including the gap */
|
||||
public int height;
|
||||
/** The horizontal gap before this key */
|
||||
public int gap;
|
||||
/** Whether this key is sticky, i.e., a toggle key */
|
||||
public boolean sticky;
|
||||
/** X coordinate of the key in the keyboard layout */
|
||||
public int x;
|
||||
/** Y coordinate of the key in the keyboard layout */
|
||||
public int y;
|
||||
/** The current pressed state of this key */
|
||||
public boolean pressed;
|
||||
/** If this is a sticky key, is it on? */
|
||||
public boolean on;
|
||||
/** Text to output when pressed. This can be multiple characters, like ".com" */
|
||||
public CharSequence text;
|
||||
/** Popup characters */
|
||||
public CharSequence popupCharacters;
|
||||
|
||||
/**
|
||||
* Flags that specify the anchoring to edges of the keyboard for detecting touch events
|
||||
* that are just out of the boundary of the key. This is a bit mask of
|
||||
* {@link CusKeyBoard#EDGE_LEFT}, {@link CusKeyBoard#EDGE_RIGHT}, {@link CusKeyBoard#EDGE_TOP} and
|
||||
* {@link CusKeyBoard#EDGE_BOTTOM}.
|
||||
*/
|
||||
public int edgeFlags;
|
||||
/** Whether this is a modifier key, such as Shift or Alt */
|
||||
public boolean modifier;
|
||||
/** The keyboard that this key belongs to */
|
||||
private CusKeyBoard keyboard;
|
||||
/**
|
||||
* If this key pops up a mini keyboard, this is the resource id for the XML layout for that
|
||||
* keyboard.
|
||||
*/
|
||||
public int popupResId;
|
||||
/** Whether this key repeats itself when held down */
|
||||
public boolean repeatable;
|
||||
|
||||
|
||||
private final static int[] KEY_STATE_NORMAL_ON = {
|
||||
android.R.attr.state_checkable,
|
||||
android.R.attr.state_checked
|
||||
};
|
||||
|
||||
private final static int[] KEY_STATE_PRESSED_ON = {
|
||||
android.R.attr.state_pressed,
|
||||
android.R.attr.state_checkable,
|
||||
android.R.attr.state_checked
|
||||
};
|
||||
|
||||
private final static int[] KEY_STATE_NORMAL_OFF = {
|
||||
android.R.attr.state_checkable
|
||||
};
|
||||
|
||||
private final static int[] KEY_STATE_PRESSED_OFF = {
|
||||
android.R.attr.state_pressed,
|
||||
android.R.attr.state_checkable
|
||||
};
|
||||
|
||||
private final static int[] KEY_STATE_NORMAL = {
|
||||
};
|
||||
|
||||
private final static int[] KEY_STATE_PRESSED = {
|
||||
android.R.attr.state_pressed
|
||||
};
|
||||
|
||||
/** Create an empty key with no attributes. */
|
||||
public Key(CusKeyBoard.Row parent) {
|
||||
keyboard = parent.parent;
|
||||
height = parent.defaultHeight;
|
||||
width = parent.defaultWidth;
|
||||
gap = parent.defaultHorizontalGap;
|
||||
edgeFlags = parent.rowEdgeFlags;
|
||||
}
|
||||
|
||||
/** Create a key with the given top-left coordinate and extract its attributes from
|
||||
* the XML parser.
|
||||
* @param res resources associated with the caller's context
|
||||
* @param parent the row that this key belongs to. The row must already be attached to
|
||||
* a {@link CusKeyBoard}.
|
||||
* @param x the x coordinate of the top-left
|
||||
* @param y the y coordinate of the top-left
|
||||
* @param parser the XML parser containing the attributes for this key
|
||||
*/
|
||||
public Key(Resources res, CusKeyBoard.Row parent, int x, int y, XmlResourceParser parser) {
|
||||
this(parent);
|
||||
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
|
||||
TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser),
|
||||
R.styleable.My_Keyboard_view);
|
||||
|
||||
width = getDimensionOrFraction(a,
|
||||
R.styleable.My_Keyboard_view_android_keyWidth,
|
||||
keyboard.mDisplayWidth, parent.defaultWidth);
|
||||
height = getDimensionOrFraction(a,
|
||||
R.styleable.My_Keyboard_view_android_keyHeight,
|
||||
keyboard.mDisplayHeight, parent.defaultHeight);
|
||||
gap = getDimensionOrFraction(a,
|
||||
R.styleable.My_Keyboard_view_android_horizontalGap,
|
||||
keyboard.mDisplayWidth, parent.defaultHorizontalGap);
|
||||
a.recycle();
|
||||
a = res.obtainAttributes(Xml.asAttributeSet(parser),
|
||||
R.styleable.K_Keyboard_Key);
|
||||
this.x += gap;
|
||||
TypedValue codesValue = new TypedValue();
|
||||
a.getValue(R.styleable.K_Keyboard_Key_android_codes,
|
||||
codesValue);
|
||||
if (codesValue.type == TypedValue.TYPE_INT_DEC
|
||||
|| codesValue.type == TypedValue.TYPE_INT_HEX) {
|
||||
codes = new int[] { codesValue.data };
|
||||
} else if (codesValue.type == TypedValue.TYPE_STRING) {
|
||||
codes = parseCSV(codesValue.string.toString());
|
||||
}
|
||||
|
||||
iconPreview = a.getDrawable(R.styleable.K_Keyboard_Key_android_iconPreview);
|
||||
if (iconPreview != null) {
|
||||
iconPreview.setBounds(0, 0, iconPreview.getIntrinsicWidth(),
|
||||
iconPreview.getIntrinsicHeight());
|
||||
}
|
||||
popupCharacters = a.getText(
|
||||
R.styleable.K_Keyboard_Key_android_popupCharacters);
|
||||
popupResId = a.getResourceId(
|
||||
R.styleable.K_Keyboard_Key_android_popupKeyboard, 0);
|
||||
repeatable = a.getBoolean(
|
||||
R.styleable.K_Keyboard_Key_android_isRepeatable, false);
|
||||
modifier = a.getBoolean(
|
||||
R.styleable.K_Keyboard_Key_android_isModifier, false);
|
||||
sticky = a.getBoolean(
|
||||
R.styleable.K_Keyboard_Key_android_isSticky, false);
|
||||
edgeFlags = a.getInt(R.styleable.K_Keyboard_Key_android_keyEdgeFlags, 0);
|
||||
edgeFlags |= parent.rowEdgeFlags;
|
||||
|
||||
icon = a.getDrawable(
|
||||
R.styleable.K_Keyboard_Key_android_keyIcon);
|
||||
if (icon != null) {
|
||||
icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
|
||||
}
|
||||
label = a.getText(R.styleable.K_Keyboard_Key_android_keyLabel);
|
||||
text = a.getText(R.styleable.K_Keyboard_Key_android_keyOutputText);
|
||||
|
||||
if (codes == null && !TextUtils.isEmpty(label)) {
|
||||
codes = new int[] { label.charAt(0) };
|
||||
}
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Informs the key that it has been pressed, in case it needs to change its appearance or
|
||||
* state.
|
||||
* @see #onReleased(boolean)
|
||||
*/
|
||||
public void onPressed() {
|
||||
pressed = !pressed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the pressed state of the key.
|
||||
*
|
||||
* <p>Toggled state of the key will be flipped when all the following conditions are
|
||||
* fulfilled:</p>
|
||||
*
|
||||
* <ul>
|
||||
* <li>This is a sticky key, that is, {@link #sticky} is {@code true}.
|
||||
* <li>The parameter {@code inside} is {@code true}.
|
||||
* <li>{@link android.os.Build.VERSION#SDK_INT} is greater than
|
||||
* {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}.
|
||||
* </ul>
|
||||
*
|
||||
* @param inside whether the finger was released inside the key. Works only on Android M and
|
||||
* later. See the method document for details.
|
||||
* @see #onPressed()
|
||||
*/
|
||||
public void onReleased(boolean inside) {
|
||||
pressed = !pressed;
|
||||
if (sticky && inside) {
|
||||
on = !on;
|
||||
}
|
||||
}
|
||||
|
||||
int[] parseCSV(String value) {
|
||||
int count = 0;
|
||||
int lastIndex = 0;
|
||||
if (value.length() > 0) {
|
||||
count++;
|
||||
while ((lastIndex = value.indexOf(",", lastIndex + 1)) > 0) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
int[] values = new int[count];
|
||||
count = 0;
|
||||
StringTokenizer st = new StringTokenizer(value, ",");
|
||||
while (st.hasMoreTokens()) {
|
||||
try {
|
||||
values[count++] = Integer.parseInt(st.nextToken());
|
||||
} catch (NumberFormatException nfe) {
|
||||
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects if a point falls inside this key.
|
||||
* @param x the x-coordinate of the point
|
||||
* @param y the y-coordinate of the point
|
||||
* @return whether or not the point falls inside the key. If the key is attached to an edge,
|
||||
* it will assume that all points between the key and the edge are considered to be inside
|
||||
* the key.
|
||||
*/
|
||||
public boolean isInside(int x, int y) {
|
||||
boolean leftEdge = (edgeFlags & EDGE_LEFT) > 0;
|
||||
boolean rightEdge = (edgeFlags & EDGE_RIGHT) > 0;
|
||||
boolean topEdge = (edgeFlags & EDGE_TOP) > 0;
|
||||
boolean bottomEdge = (edgeFlags & EDGE_BOTTOM) > 0;
|
||||
if ((x >= this.x || (leftEdge && x <= this.x + this.width))
|
||||
&& (x < this.x + this.width || (rightEdge && x >= this.x))
|
||||
&& (y >= this.y || (topEdge && y <= this.y + this.height))
|
||||
&& (y < this.y + this.height || (bottomEdge && y >= this.y))) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the square of the distance between the center of the key and the given point.
|
||||
* @param x the x-coordinate of the point
|
||||
* @param y the y-coordinate of the point
|
||||
* @return the square of the distance of the point from the center of the key
|
||||
*/
|
||||
public int squaredDistanceFrom(int x, int y) {
|
||||
int xDist = this.x + width / 2 - x;
|
||||
int yDist = this.y + height / 2 - y;
|
||||
return xDist * xDist + yDist * yDist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the drawable state for the key, based on the current state and type of the key.
|
||||
* @return the drawable state of the key.
|
||||
* @see android.graphics.drawable.StateListDrawable#setState(int[])
|
||||
*/
|
||||
public int[] getCurrentDrawableState() {
|
||||
int[] states = KEY_STATE_NORMAL;
|
||||
|
||||
if (on) {
|
||||
if (pressed) {
|
||||
states = KEY_STATE_PRESSED_ON;
|
||||
} else {
|
||||
states = KEY_STATE_NORMAL_ON;
|
||||
}
|
||||
} else {
|
||||
if (sticky) {
|
||||
if (pressed) {
|
||||
states = KEY_STATE_PRESSED_OFF;
|
||||
} else {
|
||||
states = KEY_STATE_NORMAL_OFF;
|
||||
}
|
||||
} else {
|
||||
if (pressed) {
|
||||
states = KEY_STATE_PRESSED;
|
||||
}
|
||||
}
|
||||
}
|
||||
return states;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a keyboard from the given xml key layout file.
|
||||
* @param context the application or service context
|
||||
* @param xmlLayoutResId the resource file that contains the keyboard layout and keys.
|
||||
*/
|
||||
public CusKeyBoard(Context context, int xmlLayoutResId) {
|
||||
this(context, xmlLayoutResId, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a keyboard from the given xml key layout file. Weeds out rows
|
||||
* that have a keyboard mode defined but don't match the specified mode.
|
||||
* @param context the application or service context
|
||||
* @param xmlLayoutResId the resource file that contains the keyboard layout and keys.
|
||||
* @param modeId keyboard mode identifier
|
||||
* @param width sets width of keyboard
|
||||
* @param height sets height of keyboard
|
||||
*/
|
||||
public CusKeyBoard(Context context, @XmlRes int xmlLayoutResId, int modeId, int width,
|
||||
int height) {
|
||||
mDisplayWidth = width;
|
||||
mDisplayHeight = height;
|
||||
|
||||
mDefaultHorizontalGap = 0;
|
||||
mDefaultWidth = mDisplayWidth / 10;
|
||||
mDefaultVerticalGap = 0;
|
||||
mDefaultHeight = mDefaultWidth;
|
||||
mKeys = new ArrayList<>();
|
||||
mModifierKeys = new ArrayList<>();
|
||||
mKeyboardMode = modeId;
|
||||
loadKeyboard(context, context.getResources().getXml(xmlLayoutResId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a keyboard from the given xml key layout file. Weeds out rows
|
||||
* that have a keyboard mode defined but don't match the specified mode.
|
||||
* @param context the application or service context
|
||||
* @param xmlLayoutResId the resource file that contains the keyboard layout and keys.
|
||||
* @param modeId keyboard mode identifier
|
||||
*/
|
||||
public CusKeyBoard(Context context, @XmlRes int xmlLayoutResId, int modeId) {
|
||||
DisplayMetrics dm = context.getResources().getDisplayMetrics();
|
||||
mDisplayWidth = dm.widthPixels;
|
||||
mDisplayHeight = dm.heightPixels;
|
||||
//Log.v(TAG, "keyboard's display metrics:" + dm);
|
||||
|
||||
mDefaultHorizontalGap = 0;
|
||||
mDefaultWidth = mDisplayWidth / 10;
|
||||
mDefaultVerticalGap = 0;
|
||||
mDefaultHeight = mDefaultWidth;
|
||||
mKeys = new ArrayList<>();
|
||||
mModifierKeys = new ArrayList<>();
|
||||
mKeyboardMode = modeId;
|
||||
loadKeyboard(context, context.getResources().getXml(xmlLayoutResId));
|
||||
}
|
||||
|
||||
public CusKeyBoard(Context context, int layoutTemplateResId,
|
||||
CharSequence characters, int columns, int horizontalPadding) {
|
||||
this(context, layoutTemplateResId);
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int column = 0;
|
||||
mTotalWidth = 0;
|
||||
|
||||
CusKeyBoard.Row row = new CusKeyBoard.Row(this);
|
||||
row.defaultHeight = mDefaultHeight;
|
||||
row.defaultWidth = mDefaultWidth;
|
||||
row.defaultHorizontalGap = mDefaultHorizontalGap;
|
||||
row.verticalGap = mDefaultVerticalGap;
|
||||
row.rowEdgeFlags = EDGE_TOP | EDGE_BOTTOM;
|
||||
final int maxColumns = columns == -1 ? Integer.MAX_VALUE : columns;
|
||||
for (int i = 0; i < characters.length(); i++) {
|
||||
char c = characters.charAt(i);
|
||||
if (column >= maxColumns
|
||||
|| x + mDefaultWidth + horizontalPadding > mDisplayWidth) {
|
||||
x = 0;
|
||||
y += mDefaultVerticalGap + mDefaultHeight;
|
||||
column = 0;
|
||||
}
|
||||
final CusKeyBoard.Key key = new CusKeyBoard.Key(row);
|
||||
key.x = x;
|
||||
key.y = y;
|
||||
key.label = String.valueOf(c);
|
||||
key.codes = new int[] { c };
|
||||
column++;
|
||||
x += key.width + key.gap;
|
||||
mKeys.add(key);
|
||||
row.mKeys.add(key);
|
||||
if (x > mTotalWidth) {
|
||||
mTotalWidth = x;
|
||||
}
|
||||
}
|
||||
mTotalHeight = y + mDefaultHeight;
|
||||
rows.add(row);
|
||||
}
|
||||
|
||||
final void resize(int newWidth, int newHeight) {
|
||||
int numRows = rows.size();
|
||||
for (int rowIndex = 0; rowIndex < numRows; ++rowIndex) {
|
||||
CusKeyBoard.Row row = rows.get(rowIndex);
|
||||
int numKeys = row.mKeys.size();
|
||||
int totalGap = 0;
|
||||
int totalWidth = 0;
|
||||
for (int keyIndex = 0; keyIndex < numKeys; ++keyIndex) {
|
||||
CusKeyBoard.Key key = row.mKeys.get(keyIndex);
|
||||
if (keyIndex > 0) {
|
||||
totalGap += key.gap;
|
||||
}
|
||||
totalWidth += key.width;
|
||||
}
|
||||
if (totalGap + totalWidth > newWidth) {
|
||||
int x = 0;
|
||||
float scaleFactor = (float)(newWidth - totalGap) / totalWidth;
|
||||
for (int keyIndex = 0; keyIndex < numKeys; ++keyIndex) {
|
||||
CusKeyBoard.Key key = row.mKeys.get(keyIndex);
|
||||
key.width *= scaleFactor;
|
||||
key.x = x;
|
||||
x += key.width + key.gap;
|
||||
}
|
||||
}
|
||||
}
|
||||
mTotalWidth = newWidth;
|
||||
// TODO: This does not adjust the vertical placement according to the new size.
|
||||
// The main problem in the previous code was horizontal placement/size, but we should
|
||||
// also recalculate the vertical sizes/positions when we get this resize call.
|
||||
}
|
||||
|
||||
public List<CusKeyBoard.Key> getKeys() {
|
||||
return mKeys;
|
||||
}
|
||||
|
||||
public List<CusKeyBoard.Key> getModifierKeys() {
|
||||
return mModifierKeys;
|
||||
}
|
||||
|
||||
protected int getHorizontalGap() {
|
||||
return mDefaultHorizontalGap;
|
||||
}
|
||||
|
||||
protected void setHorizontalGap(int gap) {
|
||||
mDefaultHorizontalGap = gap;
|
||||
}
|
||||
|
||||
protected int getVerticalGap() {
|
||||
return mDefaultVerticalGap;
|
||||
}
|
||||
|
||||
protected void setVerticalGap(int gap) {
|
||||
mDefaultVerticalGap = gap;
|
||||
}
|
||||
|
||||
protected int getKeyHeight() {
|
||||
return mDefaultHeight;
|
||||
}
|
||||
|
||||
protected void setKeyHeight(int height) {
|
||||
mDefaultHeight = height;
|
||||
}
|
||||
|
||||
protected int getKeyWidth() {
|
||||
return mDefaultWidth;
|
||||
}
|
||||
|
||||
protected void setKeyWidth(int width) {
|
||||
mDefaultWidth = width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total height of the keyboard
|
||||
* @return the total height of the keyboard
|
||||
*/
|
||||
public int getHeight() {
|
||||
return mTotalHeight;
|
||||
}
|
||||
|
||||
public int getMinWidth() {
|
||||
return mTotalWidth;
|
||||
}
|
||||
|
||||
public boolean setShifted(boolean shiftState) {
|
||||
for (CusKeyBoard.Key shiftKey : mShiftKeys) {
|
||||
if (shiftKey != null) {
|
||||
shiftKey.on = shiftState;
|
||||
}
|
||||
}
|
||||
if (mShifted != shiftState) {
|
||||
mShifted = shiftState;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isShifted() {
|
||||
return mShifted;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public int[] getShiftKeyIndices() {
|
||||
return mShiftKeyIndices;
|
||||
}
|
||||
|
||||
public int getShiftKeyIndex() {
|
||||
return mShiftKeyIndices[0];
|
||||
}
|
||||
|
||||
private void computeNearestNeighbors() {
|
||||
// Round-up so we don't have any pixels outside the grid
|
||||
mCellWidth = (getMinWidth() + GRID_WIDTH - 1) / GRID_WIDTH;
|
||||
mCellHeight = (getHeight() + GRID_HEIGHT - 1) / GRID_HEIGHT;
|
||||
mGridNeighbors = new int[GRID_SIZE][];
|
||||
int[] indices = new int[mKeys.size()];
|
||||
final int gridWidth = GRID_WIDTH * mCellWidth;
|
||||
final int gridHeight = GRID_HEIGHT * mCellHeight;
|
||||
for (int x = 0; x < gridWidth; x += mCellWidth) {
|
||||
for (int y = 0; y < gridHeight; y += mCellHeight) {
|
||||
int count = 0;
|
||||
for (int i = 0; i < mKeys.size(); i++) {
|
||||
final CusKeyBoard.Key key = mKeys.get(i);
|
||||
if (key.squaredDistanceFrom(x, y) < mProximityThreshold ||
|
||||
key.squaredDistanceFrom(x + mCellWidth - 1, y) < mProximityThreshold ||
|
||||
key.squaredDistanceFrom(x + mCellWidth - 1, y + mCellHeight - 1)
|
||||
< mProximityThreshold ||
|
||||
key.squaredDistanceFrom(x, y + mCellHeight - 1) < mProximityThreshold) {
|
||||
indices[count++] = i;
|
||||
}
|
||||
}
|
||||
int [] cell = new int[count];
|
||||
System.arraycopy(indices, 0, cell, 0, count);
|
||||
mGridNeighbors[(y / mCellHeight) * GRID_WIDTH + (x / mCellWidth)] = cell;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the indices of the keys that are closest to the given point.
|
||||
* @param x the x-coordinate of the point
|
||||
* @param y the y-coordinate of the point
|
||||
* @return the array of integer indices for the nearest keys to the given point. If the given
|
||||
* point is out of range, then an array of size zero is returned.
|
||||
*/
|
||||
public int[] getNearestKeys(int x, int y) {
|
||||
if (mGridNeighbors == null) computeNearestNeighbors();
|
||||
if (x >= 0 && x < getMinWidth() && y >= 0 && y < getHeight()) {
|
||||
int index = (y / mCellHeight) * GRID_WIDTH + (x / mCellWidth);
|
||||
if (index < GRID_SIZE) {
|
||||
return mGridNeighbors[index];
|
||||
}
|
||||
}
|
||||
return new int[0];
|
||||
}
|
||||
|
||||
protected CusKeyBoard.Row createRowFromXml(Resources res, XmlResourceParser parser) {
|
||||
return new CusKeyBoard.Row(res, this, parser);
|
||||
}
|
||||
|
||||
protected CusKeyBoard.Key createKeyFromXml(Resources res, CusKeyBoard.Row parent, int x, int y,
|
||||
XmlResourceParser parser) {
|
||||
return new CusKeyBoard.Key(res, parent, x, y, parser);
|
||||
}
|
||||
|
||||
private void loadKeyboard(Context context, XmlResourceParser parser) {
|
||||
boolean inKey = false;
|
||||
boolean inRow = false;
|
||||
boolean leftMostKey = false;
|
||||
int row = 0;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
CusKeyBoard.Key key = null;
|
||||
CusKeyBoard.Row currentRow = null;
|
||||
Resources res = context.getResources();
|
||||
boolean skipRow = false;
|
||||
|
||||
try {
|
||||
int event;
|
||||
while ((event = parser.next()) != XmlResourceParser.END_DOCUMENT) {
|
||||
if (event == XmlResourceParser.START_TAG) {
|
||||
String tag = parser.getName();
|
||||
if (TAG_ROW.equals(tag)) {
|
||||
inRow = true;
|
||||
x = 0;
|
||||
currentRow = createRowFromXml(res, parser);
|
||||
rows.add(currentRow);
|
||||
skipRow = currentRow.mode != 0 && currentRow.mode != mKeyboardMode;
|
||||
if (skipRow) {
|
||||
skipToEndOfRow(parser);
|
||||
inRow = false;
|
||||
}
|
||||
} else if (TAG_KEY.equals(tag)) {
|
||||
inKey = true;
|
||||
key = createKeyFromXml(res, currentRow, x, y, parser);
|
||||
mKeys.add(key);
|
||||
if (key.codes[0] == KEYCODE_SHIFT) {
|
||||
// Find available shift key slot and put this shift key in it
|
||||
for (int i = 0; i < mShiftKeys.length; i++) {
|
||||
if (mShiftKeys[i] == null) {
|
||||
mShiftKeys[i] = key;
|
||||
mShiftKeyIndices[i] = mKeys.size()-1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mModifierKeys.add(key);
|
||||
} else if (key.codes[0] == KEYCODE_ALT) {
|
||||
mModifierKeys.add(key);
|
||||
}
|
||||
currentRow.mKeys.add(key);
|
||||
} else if (TAG_KEYBOARD.equals(tag)) {
|
||||
parseKeyboardAttributes(res, parser);
|
||||
}
|
||||
} else if (event == XmlResourceParser.END_TAG) {
|
||||
if (inKey) {
|
||||
inKey = false;
|
||||
x += key.gap + key.width;
|
||||
if (x > mTotalWidth) {
|
||||
mTotalWidth = x;
|
||||
}
|
||||
} else if (inRow) {
|
||||
inRow = false;
|
||||
y += currentRow.verticalGap;
|
||||
y += currentRow.defaultHeight;
|
||||
row++;
|
||||
} else {
|
||||
// TODO: error or extend?
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
e.printStackTrace();
|
||||
}
|
||||
mTotalHeight = y - mDefaultVerticalGap;
|
||||
}
|
||||
|
||||
private void skipToEndOfRow(XmlResourceParser parser)
|
||||
throws XmlPullParserException, IOException {
|
||||
int event;
|
||||
while ((event = parser.next()) != XmlResourceParser.END_DOCUMENT) {
|
||||
if (event == XmlResourceParser.END_TAG
|
||||
&& parser.getName().equals(TAG_ROW)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void parseKeyboardAttributes(Resources res, XmlResourceParser parser) {
|
||||
TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser),
|
||||
R.styleable.My_Keyboard_view);
|
||||
|
||||
mDefaultWidth = getDimensionOrFraction(a,
|
||||
R.styleable.My_Keyboard_view_android_keyWidth,
|
||||
mDisplayWidth, mDisplayWidth / 10);
|
||||
mDefaultHeight = getDimensionOrFraction(a,
|
||||
R.styleable.My_Keyboard_view_android_keyHeight,
|
||||
mDisplayHeight, 50);
|
||||
mDefaultHorizontalGap = getDimensionOrFraction(a,
|
||||
R.styleable.My_Keyboard_view_android_horizontalGap,
|
||||
mDisplayWidth, 0);
|
||||
mDefaultVerticalGap = getDimensionOrFraction(a,
|
||||
R.styleable.My_Keyboard_view_android_verticalGap,
|
||||
mDisplayHeight, 0);
|
||||
mProximityThreshold = (int) (mDefaultWidth * SEARCH_DISTANCE);
|
||||
mProximityThreshold = mProximityThreshold * mProximityThreshold; // Square it for comparison
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
static int getDimensionOrFraction(TypedArray a, int index, int base, int defValue) {
|
||||
TypedValue value = a.peekValue(index);
|
||||
if (value == null) return defValue;
|
||||
if (value.type == TypedValue.TYPE_DIMENSION) {
|
||||
return a.getDimensionPixelOffset(index, defValue);
|
||||
} else if (value.type == TypedValue.TYPE_FRACTION) {
|
||||
// Round it to avoid values like 47.9999 from getting truncated
|
||||
return Math.round(a.getFraction(index, base, base, defValue));
|
||||
}
|
||||
return defValue;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,110 @@
|
||||
package com.keyboard.bubble.skin.keyboard.ui;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
import androidx.viewpager2.widget.ViewPager2;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import com.keyboard.bubble.skin.keyboard.R;
|
||||
import com.keyboard.bubble.skin.keyboard.databinding.ActivityMainBinding;
|
||||
import com.keyboard.bubble.skin.keyboard.fagment.LikePage;
|
||||
import com.keyboard.bubble.skin.keyboard.fagment.ViewPage;
|
||||
import com.keyboard.bubble.skin.keyboard.utils.MyUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
private ActivityMainBinding vb;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
vb = ActivityMainBinding.inflate(getLayoutInflater());
|
||||
MyUtils.INSTANCE.initFullScreen(this,true);
|
||||
setContentView(vb.getRoot());
|
||||
init();
|
||||
|
||||
}
|
||||
|
||||
private void init() {
|
||||
List<Fragment> listFragment = new ArrayList<>();
|
||||
listFragment.add(ViewPage.newInstance());
|
||||
listFragment.add(LikePage.newInstance());
|
||||
|
||||
for (int i = 0; i < listFragment.size(); i++) {
|
||||
TabLayout.Tab tab = vb.tabLayout.newTab();
|
||||
|
||||
View inflate = LayoutInflater.from(this).inflate(R.layout.item_cutomer_view, null, false);
|
||||
ImageView icon = inflate.findViewById(R.id.im_icon);
|
||||
// TextView textView = inflate.findViewById(R.id.textView);
|
||||
if (i == 0) {
|
||||
// textView.setSelected(true);
|
||||
// textView.setText(getString(R.string.tv_home));
|
||||
icon.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.selector_tab_theme));
|
||||
} else if(i ==1){
|
||||
// textView.setSelected(false);
|
||||
// textView.setText(getString(R.string.tv_like));
|
||||
icon.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.selector_like));
|
||||
}
|
||||
tab.setCustomView(inflate);
|
||||
vb.tabLayout.addTab(tab);
|
||||
}
|
||||
|
||||
|
||||
vb.viewpager.setUserInputEnabled(false);
|
||||
vb.viewpager.setAdapter(new FragmentStateAdapter(this) {
|
||||
@NonNull
|
||||
@Override
|
||||
public Fragment createFragment(int position) {
|
||||
return listFragment.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return listFragment.size();
|
||||
}
|
||||
});
|
||||
bing();
|
||||
}
|
||||
|
||||
|
||||
private void bing() {
|
||||
vb.tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
|
||||
@Override
|
||||
public void onTabSelected(TabLayout.Tab tab) {
|
||||
ImageView icon = Objects.requireNonNull(tab.getCustomView()).findViewById(R.id.im_icon);
|
||||
icon.setSelected(true);
|
||||
vb.viewpager.setCurrentItem(tab.getPosition());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabUnselected(TabLayout.Tab tab) {
|
||||
ImageView icon = Objects.requireNonNull(tab.getCustomView()).findViewById(R.id.im_icon);
|
||||
icon.setSelected(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabReselected(TabLayout.Tab tab) {
|
||||
|
||||
}
|
||||
});
|
||||
vb.viewpager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
super.onPageSelected(position);
|
||||
Objects.requireNonNull(vb.tabLayout.getTabAt(position)).select();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,329 @@
|
||||
package com.keyboard.bubble.skin.keyboard.ui
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.integration.webp.decoder.WebpDrawable
|
||||
import com.bumptech.glide.load.DataSource
|
||||
import com.bumptech.glide.load.engine.GlideException
|
||||
import com.bumptech.glide.request.RequestListener
|
||||
import com.bumptech.glide.request.target.Target
|
||||
import com.keyboard.bubble.skin.keyboard.App
|
||||
import com.keyboard.bubble.skin.keyboard.R
|
||||
import com.keyboard.bubble.skin.keyboard.bean.ChildBean
|
||||
import com.keyboard.bubble.skin.keyboard.db.DbOpManager
|
||||
import com.keyboard.bubble.skin.keyboard.fagment.EnablePage
|
||||
import com.keyboard.bubble.skin.keyboard.myada.AdapterMain
|
||||
import com.keyboard.bubble.skin.keyboard.mylistener.ItemClickCallback
|
||||
import com.keyboard.bubble.skin.keyboard.mylistener.SetCallback
|
||||
import com.keyboard.bubble.skin.keyboard.utils.DownloadSkinManager
|
||||
import com.keyboard.bubble.skin.keyboard.utils.MyUtils
|
||||
import com.keyboard.bubble.skin.keyboard.utils.SharedManager
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.File
|
||||
|
||||
|
||||
class SetkeyboardActivity : AppCompatActivity() {
|
||||
companion object {
|
||||
@JvmField
|
||||
var DISPLAY_URL_KEY: String = "display_url_key"
|
||||
|
||||
@JvmField
|
||||
val ZIP_URL_KEY = "zip_url_key"
|
||||
|
||||
|
||||
@JvmField
|
||||
val NAME_KEY = "name_key"
|
||||
|
||||
@JvmField
|
||||
val GIF_KEY = "gif_key"
|
||||
|
||||
@JvmField
|
||||
val THUMB_KEY = "thumb_key"
|
||||
|
||||
@JvmField
|
||||
val SOURCE_KEY = "data_key"
|
||||
}
|
||||
|
||||
private var dialog: EnablePage? = null
|
||||
private lateinit var displayUrl: String
|
||||
private lateinit var gifUrl: String
|
||||
private lateinit var zipUrl: String
|
||||
private lateinit var name: String
|
||||
private lateinit var applyBtn: LinearLayout
|
||||
private lateinit var imgData: ImageView
|
||||
private lateinit var imgBack: ImageView
|
||||
private lateinit var textName: TextView
|
||||
|
||||
private lateinit var recommendedRecycler: RecyclerView
|
||||
// private lateinit var viewAllLayout: LinearLayout
|
||||
|
||||
private lateinit var loadingLayout: FrameLayout
|
||||
|
||||
private lateinit var unzipPath: String
|
||||
|
||||
private lateinit var tvDownload: TextView
|
||||
private lateinit var imDownload: ImageView
|
||||
|
||||
private lateinit var thumb: String
|
||||
|
||||
private lateinit var imgLike: ImageView
|
||||
|
||||
private lateinit var data: ChildBean
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.layout_apply)
|
||||
MyUtils.initFullScreen(this)
|
||||
|
||||
findViewId()
|
||||
getExtraData()
|
||||
displayData()
|
||||
setApply()
|
||||
onClick()
|
||||
}
|
||||
|
||||
|
||||
private fun getExtraData() {
|
||||
data = intent.getSerializableExtra(SOURCE_KEY) as ChildBean
|
||||
|
||||
displayUrl = intent.getStringExtra(DISPLAY_URL_KEY).toString()
|
||||
zipUrl = intent.getStringExtra(ZIP_URL_KEY).toString()
|
||||
name = intent.getStringExtra(NAME_KEY).toString()
|
||||
gifUrl = intent.getStringExtra(GIF_KEY).toString()
|
||||
thumb = intent.getStringExtra(THUMB_KEY).toString()
|
||||
|
||||
val serviceZipName = DownloadSkinManager.getServiceZipName(zipUrl)
|
||||
unzipPath = DownloadSkinManager.getUnzipPath(serviceZipName)
|
||||
|
||||
|
||||
lifecycleScope.launch {
|
||||
DbOpManager.getIsLike(name) {
|
||||
imgLike.isSelected = it
|
||||
}
|
||||
}
|
||||
|
||||
if (File(unzipPath).exists()) {
|
||||
imDownload.isVisible = false
|
||||
tvDownload.text = getString(R.string.apply)
|
||||
} else {
|
||||
imDownload.isVisible = true
|
||||
tvDownload.text = getString(R.string.download_apply)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun findViewId() {
|
||||
applyBtn = findViewById(R.id.layoutDownloadApply)
|
||||
imgData = findViewById(R.id.image_data)
|
||||
imgBack = findViewById(R.id.back)
|
||||
textName = findViewById(R.id.textview_data_name)
|
||||
recommendedRecycler = findViewById(R.id.recommended_recycler)
|
||||
// viewAllLayout = findViewById(R.id.layout_view_all)
|
||||
|
||||
imgLike = findViewById(R.id.im_like)
|
||||
loadingLayout = findViewById(R.id.loading)
|
||||
imDownload = findViewById(R.id.im_download)
|
||||
tvDownload = findViewById(R.id.tv_download)
|
||||
}
|
||||
|
||||
private fun displayData() {
|
||||
textName.text = name
|
||||
if (gifUrl.isNotEmpty()) {
|
||||
loadImgGif()
|
||||
} else {
|
||||
Glide.with(this)
|
||||
.load(displayUrl)
|
||||
.thumbnail(Glide.with(this).load(thumb))
|
||||
.into(imgData)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun onClick() {
|
||||
imgBack.setOnClickListener {
|
||||
finish()
|
||||
}
|
||||
|
||||
imgLike.setOnClickListener {
|
||||
imgLike.isSelected = !imgLike.isSelected
|
||||
|
||||
lifecycleScope.launch {
|
||||
if (imgLike.isSelected) {
|
||||
DbOpManager.addLike(data)
|
||||
} else {
|
||||
DbOpManager.removeLike(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
val forYouList = App.list.filter {
|
||||
it.parentName == "for you"
|
||||
|
||||
}
|
||||
|
||||
recommendedRecycler.run {
|
||||
adapter = AdapterMain(
|
||||
this@SetkeyboardActivity
|
||||
).apply {
|
||||
val shuffled = forYouList[0].keyboardList.shuffled()
|
||||
setForYouList(shuffled)
|
||||
}.apply {
|
||||
setClickAction(object : ItemClickCallback {
|
||||
override fun OnItemClickListener() {
|
||||
finish()
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
layoutManager = GridLayoutManager(this@SetkeyboardActivity, 2)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private fun loadImgGif() {
|
||||
Glide.with(this)
|
||||
.load(gifUrl)
|
||||
.thumbnail(Glide.with(this).load(thumb))
|
||||
.addListener(object : RequestListener<Drawable> {
|
||||
override fun onLoadFailed(
|
||||
e: GlideException?,
|
||||
model: Any?,
|
||||
target: Target<Drawable>,
|
||||
isFirstResource: Boolean
|
||||
): Boolean {
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onResourceReady(
|
||||
resource: Drawable,
|
||||
model: Any,
|
||||
target: Target<Drawable>?,
|
||||
dataSource: DataSource,
|
||||
isFirstResource: Boolean
|
||||
): Boolean {
|
||||
if (resource is WebpDrawable) {
|
||||
resource.loopCount = WebpDrawable.LOOP_FOREVER
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
}).into(imgData)
|
||||
}
|
||||
|
||||
private fun setApply() {
|
||||
applyBtn.setOnClickListener {
|
||||
val checkEnable = MyUtils.checkEnable(this)
|
||||
val checkSetDefault = MyUtils.checkSetDefault(this)
|
||||
if (!checkEnable || !checkSetDefault) {
|
||||
showDialog()
|
||||
return@setOnClickListener
|
||||
}
|
||||
startDown()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private fun showDialog() {
|
||||
dialog = dialog ?: EnablePage {
|
||||
startDown()
|
||||
}
|
||||
dialog?.show(supportFragmentManager, "")
|
||||
}
|
||||
|
||||
private fun startDown() {
|
||||
loadingLayout.isVisible = true
|
||||
applyBtn.isEnabled = false
|
||||
|
||||
val file = File(unzipPath)
|
||||
if (file.exists()) {
|
||||
val findFirstDirectory = DownloadSkinManager.findFirstDirectory(file)
|
||||
|
||||
Log.d(
|
||||
App.TAG,
|
||||
"-----findFirstDirectory=$findFirstDirectory"
|
||||
)
|
||||
apply("${findFirstDirectory}/")
|
||||
applyBtn.isEnabled = true
|
||||
loadingLayout.isVisible = false
|
||||
} else {
|
||||
DownloadSkinManager.startDownloadZip(zipUrl, object : SetCallback {
|
||||
override fun OnApplySkinListener(fileList: List<File?>?) {
|
||||
runOnUiThread {
|
||||
applyBtn.isEnabled = true
|
||||
loadingLayout.isVisible = false
|
||||
}
|
||||
if (fileList.isNullOrEmpty()) {
|
||||
runOnUiThread {
|
||||
Toast.makeText(
|
||||
this@SetkeyboardActivity,
|
||||
getString(R.string.download_fail),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
} else {
|
||||
lifecycleScope.launch {
|
||||
DbOpManager.addDownload(data)
|
||||
}
|
||||
if (file.exists()) {
|
||||
val findFirstDirectory = DownloadSkinManager.findFirstDirectory(file)
|
||||
Log.d(
|
||||
App.TAG,
|
||||
"----apply------------it=$findFirstDirectory"
|
||||
)
|
||||
runOnUiThread {
|
||||
apply("${findFirstDirectory}/")
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun apply(path: String) {
|
||||
var skinParentPath = path
|
||||
if (path.contains("res")) {
|
||||
skinParentPath = path.substringBeforeLast("res")
|
||||
}
|
||||
// val configFilePath = skinParentPath + "assets/keyboard.conf"
|
||||
// val file = File(configFilePath)
|
||||
|
||||
SharedManager.updateSkinPath(skinParentPath)
|
||||
Toast.makeText(
|
||||
this@SetkeyboardActivity,
|
||||
getString(R.string.theme_application_successful),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
startActivity(Intent(this, SuccessPreViewActivity::class.java).apply {
|
||||
putExtra(SuccessPreViewActivity.key_name, name)
|
||||
})
|
||||
finish()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,132 @@
|
||||
package com.keyboard.bubble.skin.keyboard.ui;
|
||||
|
||||
import static com.bumptech.glide.request.RequestOptions.bitmapTransform;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.DataSource;
|
||||
import com.bumptech.glide.load.engine.GlideException;
|
||||
import com.bumptech.glide.request.RequestListener;
|
||||
import com.bumptech.glide.request.target.Target;
|
||||
import com.keyboard.bubble.skin.keyboard.databinding.LayoutSuccessBinding;
|
||||
import com.keyboard.bubble.skin.keyboard.utils.MyUtils;
|
||||
import com.keyboard.bubble.skin.keyboard.utils.ConstValue;
|
||||
import com.keyboard.bubble.skin.keyboard.utils.SharedManager;
|
||||
|
||||
import jp.wasabeef.glide.transformations.BlurTransformation;
|
||||
|
||||
|
||||
public class SuccessPreViewActivity extends AppCompatActivity {
|
||||
private LayoutSuccessBinding vb;
|
||||
public static String key_name = "key_name";
|
||||
private int mPreviousKeyboardHeight = -1;
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
MyUtils.INSTANCE.initFullScreen(this,true);
|
||||
vb = LayoutSuccessBinding.inflate(getLayoutInflater());
|
||||
setContentView(vb.getRoot());
|
||||
|
||||
onInit();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void onInit() {
|
||||
|
||||
String stringExtra = getIntent().getStringExtra(key_name);
|
||||
vb.title.setText(stringExtra);
|
||||
|
||||
String curPath = SharedManager.INSTANCE.getSkinPath();
|
||||
|
||||
vb.idBack.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
if (curPath == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String bgPath = curPath+"res/drawable-xxhdpi-v4/"+ ConstValue.previewBg;
|
||||
|
||||
Drawable bgDraw = MyUtils.INSTANCE.getBgDrawable(this, bgPath);
|
||||
if (bgDraw != null) {
|
||||
|
||||
Glide.with(this)
|
||||
.load(bgDraw)
|
||||
.apply(bitmapTransform(new BlurTransformation(15, 3))) // 设置模糊半径和模糊采样
|
||||
.listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
||||
vb.relayout.setBackground(resource);
|
||||
// new Thread(new Runnable() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// String s = getCacheDir() + "/test.jpg";
|
||||
// File file = new File(s);
|
||||
// try {
|
||||
// DownloadSkinManager.saveDrawableToFile(resource,file);
|
||||
// } catch (IOException e) {
|
||||
//
|
||||
// }
|
||||
// }
|
||||
// }).start();
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.preload();
|
||||
|
||||
}
|
||||
keyboardheight();
|
||||
vb.et.requestFocus();
|
||||
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void keyboardheight() {
|
||||
final View rootView = getWindow().getDecorView();
|
||||
rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
|
||||
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
Rect r = new Rect();
|
||||
rootView.getWindowVisibleDisplayFrame(r);
|
||||
int screenHeight = rootView.getRootView().getHeight();
|
||||
int keypadHeight = screenHeight - r.bottom;
|
||||
|
||||
if (keypadHeight != mPreviousKeyboardHeight) {
|
||||
if (mPreviousKeyboardHeight < keypadHeight) {
|
||||
mPreviousKeyboardHeight = keypadHeight;
|
||||
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) vb.et.getLayoutParams();
|
||||
params.bottomMargin = mPreviousKeyboardHeight;
|
||||
vb.et.setLayoutParams(params);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
package com.keyboard.bubble.skin.keyboard.ui
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.os.CountDownTimer
|
||||
import android.widget.ProgressBar
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.keyboard.bubble.skin.keyboard.R
|
||||
import com.keyboard.bubble.skin.keyboard.utils.MyUtils
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class WelcomeActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var progressBar: ProgressBar
|
||||
private var countTime = 1000L
|
||||
private lateinit var timer: CountDownTimer
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.layout_launch)
|
||||
MyUtils.initFullScreen(this)
|
||||
init()
|
||||
findView()
|
||||
}
|
||||
|
||||
private fun init() {
|
||||
|
||||
timer = object : CountDownTimer(countTime, 100) {
|
||||
override fun onTick(millisUntilFinished: Long) {
|
||||
val percentage: Float = 100 - millisUntilFinished.toFloat() / countTime * 100
|
||||
val round = percentage.roundToInt()
|
||||
progressBar.progress = round
|
||||
}
|
||||
|
||||
override fun onFinish() {
|
||||
progressBar.progress = 100
|
||||
toHome()
|
||||
}
|
||||
|
||||
}
|
||||
timer.start()
|
||||
|
||||
}
|
||||
|
||||
|
||||
private fun findView() {
|
||||
progressBar = findViewById<ProgressBar>(R.id.nova_progress)
|
||||
}
|
||||
|
||||
|
||||
private fun toHome() {
|
||||
startActivity(Intent(this, MainActivity::class.java))
|
||||
finish()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
timer.cancel()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
package com.keyboard.bubble.skin.keyboard.utils
|
||||
|
||||
object ConstValue {
|
||||
|
||||
|
||||
|
||||
const val KEY_CODE_DELETE = -5
|
||||
|
||||
|
||||
//同一个按键
|
||||
const val KEY_CODE_SHIFT = -1
|
||||
const val KEY_CODE_NUMBER_SHIFT = -103
|
||||
const val KEY_CODE_SYMBOL_SHIFT = -101
|
||||
|
||||
//同一个按键
|
||||
const val KEY_CODE_CHANGE_NUMBER = -2
|
||||
const val KEY_CODE_BACK = -102
|
||||
|
||||
|
||||
const val KEY_CODE_COMPLETE = -4
|
||||
const val KEY_CODE_CANCEL = -3
|
||||
|
||||
const val KEY_CODE_SPACE = 32
|
||||
|
||||
|
||||
const val functionNormalName = "btn_keyboard_key_functional_normal.9.png"
|
||||
const val functionPressName = "btn_keyboard_key_functional_pressed.9.png"
|
||||
|
||||
const val normalName = "btn_keyboard_key_normal_normal.9.png"
|
||||
const val pressName = "btn_keyboard_key_normal_pressed.9.png"
|
||||
|
||||
const val toNormalName="btn_keyboard_key_toggle_normal_on.9.png"
|
||||
const val toPressName="btn_keyboard_key_toggle_pressed_on.9.png"
|
||||
|
||||
const val spaceNormalName = "btn_keyboard_spacekey_normal_normal.9.png"
|
||||
const val spacePressName = "btn_keyboard_spacekey_normal_pressed.9.png"
|
||||
|
||||
const val imeSwitchName ="ic_ime_switcher.png"
|
||||
|
||||
const val deleteNormalName = "sym_keyboard_delete_normal.png"
|
||||
const val deletePressName = "sym_keyboard_delete_pressed.png"
|
||||
|
||||
const val backName ="sym_keyboard_return_normal.png"
|
||||
|
||||
const val searchName ="sym_keyboard_search.png"
|
||||
|
||||
const val shiftNormalName ="sym_keyboard_shift.png"
|
||||
const val shiftLockName ="sym_keyboard_shift_locked.png"
|
||||
|
||||
const val keyTextColorName ="key_text_color_normal"
|
||||
const val keyTextColorFunctionName ="key_text_color_functional"
|
||||
|
||||
const val videoName ="keyboard_background_video.mp4"
|
||||
const val bgName ="keyboard_background.jpg"
|
||||
|
||||
const val previewBg="keyboard_preview_screenshot.jpg"
|
||||
|
||||
const val video ="keyboard_background_video.gif"
|
||||
}
|
||||
@ -0,0 +1,233 @@
|
||||
package com.keyboard.bubble.skin.keyboard.utils;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import com.keyboard.bubble.skin.keyboard.App;
|
||||
import com.keyboard.bubble.skin.keyboard.mylistener.SetCallback;
|
||||
|
||||
import net.sf.sevenzipjbinding.ArchiveFormat;
|
||||
import net.sf.sevenzipjbinding.IArchiveOpenCallback;
|
||||
import net.sf.sevenzipjbinding.IInArchive;
|
||||
import net.sf.sevenzipjbinding.SevenZip;
|
||||
import net.sf.sevenzipjbinding.SevenZipException;
|
||||
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
|
||||
import net.sf.sevenzipjbinding.impl.RandomAccessFileOutStream;
|
||||
import net.sf.sevenzipjbinding.simple.ISimpleInArchive;
|
||||
import net.sf.sevenzipjbinding.simple.ISimpleInArchiveItem;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import okhttp3.Call;
|
||||
import okhttp3.Callback;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class DownloadSkinManager {
|
||||
|
||||
public static void startDownloadZip(String zipPath, SetCallback callback) {
|
||||
OkHttpClient clientZip = new OkHttpClient().newBuilder().
|
||||
connectTimeout(20, TimeUnit.SECONDS)
|
||||
.writeTimeout(10, TimeUnit.SECONDS)
|
||||
.readTimeout(10, TimeUnit.SECONDS).build();
|
||||
Request.Builder builder = new Request.Builder();
|
||||
Request request = builder.get().url(zipPath).build();
|
||||
|
||||
clientZip.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(Call call, IOException e) {
|
||||
callback.OnApplySkinListener(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(Call call, Response response) {
|
||||
|
||||
InputStream inputStream = response.body().byteStream();
|
||||
long l = response.body().contentLength();
|
||||
MediaType mediaType = response.body().contentType();
|
||||
|
||||
saveZipFile(inputStream, getServiceZipName(zipPath), callback);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public static String getServiceZipName(String zipPath) {
|
||||
String pointStr = "/";
|
||||
int lastIndexOf = zipPath.lastIndexOf(pointStr);
|
||||
String zipName = zipPath.substring(lastIndexOf + pointStr.length());
|
||||
|
||||
|
||||
return zipName;
|
||||
}
|
||||
|
||||
private static String getunZipFolderName(String zipPath) {
|
||||
String pointStr = ".";
|
||||
int lastIndexOf = zipPath.lastIndexOf(pointStr);
|
||||
String zipName = zipPath.substring(0, lastIndexOf);
|
||||
|
||||
|
||||
return zipName;
|
||||
}
|
||||
|
||||
private static void saveZipFile(InputStream inputStream, String zipFileName, SetCallback callback) {
|
||||
File zipfFile = new File(App.appInstance.getFilesDir(), zipFileName);
|
||||
byte[] bytes = new byte[4096];
|
||||
int readLength = 0;
|
||||
InputStream is = inputStream;
|
||||
FileOutputStream fileOs = null;
|
||||
try {
|
||||
fileOs = new FileOutputStream(zipfFile);
|
||||
|
||||
while ((readLength = is.read(bytes)) != -1) {
|
||||
fileOs.write(bytes, 0, readLength);
|
||||
}
|
||||
fileOs.flush();
|
||||
|
||||
} catch (Exception exception) {
|
||||
|
||||
} finally {
|
||||
try {
|
||||
if (is != null) {
|
||||
is.close();
|
||||
}
|
||||
if (fileOs != null) {
|
||||
fileOs.close();
|
||||
}
|
||||
} catch (IOException ioException) {
|
||||
|
||||
}
|
||||
un7ZZipFile(zipfFile, callback);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static String getUnzipPath(String zipName){
|
||||
String folderName = getunZipFolderName(zipName);
|
||||
String replace = folderName.replace(".", "");
|
||||
return App.appInstance.getFilesDir().getPath() + "/" + replace;
|
||||
}
|
||||
|
||||
private static void un7ZZipFile(File saveZipFile, SetCallback callback) {
|
||||
List<File> fileList = new ArrayList<>();
|
||||
|
||||
String unzipFolderPath = getUnzipPath(saveZipFile.getName());
|
||||
|
||||
try {
|
||||
RandomAccessFileInStream inStream = new RandomAccessFileInStream(new RandomAccessFile(saveZipFile, "r"));
|
||||
IInArchive open = SevenZip.openInArchive(ArchiveFormat.SEVEN_ZIP, inStream, new IArchiveOpenCallback() {
|
||||
@Override
|
||||
public void setTotal(Long files, Long bytes) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCompleted(Long files, Long bytes) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
ISimpleInArchive simple = open.getSimpleInterface();
|
||||
for (ISimpleInArchiveItem archiveItem : simple.getArchiveItems()) {
|
||||
RandomAccessFileOutStream outStream = null;
|
||||
try {
|
||||
File itemFile;
|
||||
if (archiveItem.isFolder()) {
|
||||
File itemFolder = new File(unzipFolderPath, archiveItem.getPath());
|
||||
boolean mkdirs = itemFolder.mkdirs();
|
||||
continue;
|
||||
} else {
|
||||
itemFile = new File(unzipFolderPath, archiveItem.getPath());
|
||||
if (!itemFile.getParentFile().exists()) {
|
||||
boolean mkdirs = itemFile.getParentFile().mkdirs();
|
||||
}
|
||||
}
|
||||
outStream = new RandomAccessFileOutStream(new RandomAccessFile(itemFile, "rw"));
|
||||
archiveItem.extractSlow(outStream);
|
||||
fileList.add(itemFile);
|
||||
} finally {
|
||||
if (outStream != null) {
|
||||
outStream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inStream.close();
|
||||
open.close();
|
||||
|
||||
} catch (FileNotFoundException | SevenZipException exception) {
|
||||
|
||||
} catch (IOException ioException) {
|
||||
|
||||
} finally {
|
||||
if (saveZipFile.exists()) {
|
||||
|
||||
saveZipFile.delete();
|
||||
|
||||
}
|
||||
callback.OnApplySkinListener(fileList);
|
||||
}
|
||||
}
|
||||
|
||||
public static File findFirstDirectory(File dir) {
|
||||
if (dir.isDirectory()) {
|
||||
File[] files = dir.listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
if (file.isDirectory()) {
|
||||
return file; // 返回第一个文件目录
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null; // 如果没有找到文件目录,则返回null
|
||||
}
|
||||
|
||||
|
||||
private static Bitmap drawableToBitmap(Drawable drawable) {
|
||||
if (drawable instanceof BitmapDrawable) {
|
||||
return ((BitmapDrawable) drawable).getBitmap();
|
||||
}
|
||||
|
||||
// 如果不是 BitmapDrawable,则创建一个空的 Bitmap 对象
|
||||
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
|
||||
drawable.getIntrinsicHeight(),
|
||||
Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
|
||||
drawable.draw(canvas);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
// 将 Bitmap 保存到文件
|
||||
private static void saveBitmapToFile(Bitmap bitmap, File file) throws IOException {
|
||||
if(!file.exists()){
|
||||
file.createNewFile();
|
||||
}
|
||||
FileOutputStream out = new FileOutputStream(file);
|
||||
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out); // 保存为 PNG 格式
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
|
||||
// 示例:将 Drawable 写入文件
|
||||
public static void saveDrawableToFile(Drawable drawable, File file) throws IOException {
|
||||
Bitmap bitmap = drawableToBitmap(drawable);
|
||||
saveBitmapToFile(bitmap, file);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package com.keyboard.bubble.skin.keyboard.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.keyboard.bubble.skin.keyboard.App;
|
||||
import com.keyboard.bubble.skin.keyboard.R;
|
||||
|
||||
|
||||
public class MyTextView extends androidx.appcompat.widget.AppCompatTextView {
|
||||
|
||||
|
||||
public MyTextView(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
initAttrs(context,attrs);
|
||||
}
|
||||
|
||||
|
||||
private void initAttrs(Context context, AttributeSet attrs){
|
||||
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyTV);
|
||||
boolean aBoolean = typedArray.getBoolean(R.styleable.MyTV_apply_font,false);
|
||||
if(aBoolean){
|
||||
initFont(this);
|
||||
}
|
||||
|
||||
typedArray.recycle();
|
||||
}
|
||||
|
||||
public static void initFont(TextView tv) {
|
||||
tv.setTypeface(App.Companion.getDefaultFont());
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,102 @@
|
||||
package com.keyboard.bubble.skin.keyboard.utils
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.provider.Settings
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.ImageView
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.integration.webp.decoder.WebpDrawable
|
||||
import com.bumptech.glide.load.DataSource
|
||||
import com.bumptech.glide.load.engine.GlideException
|
||||
import com.bumptech.glide.request.RequestListener
|
||||
import com.bumptech.glide.request.target.Target
|
||||
import com.keyboard.bubble.skin.keyboard.App
|
||||
import java.io.File
|
||||
|
||||
object MyUtils {
|
||||
fun initFullScreen(activity: Activity, dark: Boolean? = true) {
|
||||
val window = activity.window
|
||||
val decorView = window.decorView
|
||||
val rootView = decorView.rootView
|
||||
//
|
||||
if (dark == null) return
|
||||
|
||||
if (dark) {
|
||||
decorView.setSystemUiVisibility(
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
|
||||
)
|
||||
} else {
|
||||
decorView.setSystemUiVisibility(
|
||||
(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
|
||||
)
|
||||
}
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
|
||||
}
|
||||
|
||||
|
||||
fun loadWepJif(mContext: Context, webpGifUrl: String, view: ImageView) {
|
||||
Glide.with(mContext).load(webpGifUrl).addListener(object : RequestListener<Drawable> {
|
||||
override fun onLoadFailed(
|
||||
e: GlideException?,
|
||||
model: Any?,
|
||||
target: Target<Drawable>,
|
||||
isFirstResource: Boolean
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onResourceReady(
|
||||
resource: Drawable,
|
||||
model: Any,
|
||||
target: Target<Drawable>,
|
||||
dataSource: DataSource,
|
||||
isFirstResource: Boolean
|
||||
): Boolean {
|
||||
if (resource is WebpDrawable) {
|
||||
resource.loopCount = WebpDrawable.LOOP_FOREVER
|
||||
}
|
||||
return false
|
||||
}
|
||||
}).into(view)
|
||||
}
|
||||
|
||||
|
||||
fun getBgDrawable(con: Context, filePath: String): Drawable? {
|
||||
if (!File(filePath).exists()) {
|
||||
return null
|
||||
}
|
||||
return BitmapDrawable(con.resources, BitmapFactory.decodeFile(filePath))
|
||||
}
|
||||
|
||||
|
||||
private val systemService =
|
||||
App.appInstance.getSystemService(Context.INPUT_METHOD_SERVICE)
|
||||
private val inputMethodManager = systemService as InputMethodManager
|
||||
fun checkSetDefault(con: Context): Boolean {
|
||||
val defaultId =
|
||||
Settings.Secure.getString(con.contentResolver, Settings.Secure.DEFAULT_INPUT_METHOD)
|
||||
return defaultId != null && defaultId.startsWith(con.packageName)
|
||||
}
|
||||
|
||||
fun checkEnable(con: Context): Boolean {
|
||||
for (methodInfo in inputMethodManager.enabledInputMethodList) {
|
||||
if (methodInfo.id.startsWith(con.packageName)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun getTextForImeAction(imeOptions: Int): Int {
|
||||
return imeOptions and EditorInfo.IME_MASK_ACTION
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package com.keyboard.bubble.skin.keyboard.utils
|
||||
|
||||
import android.content.Context
|
||||
import com.keyboard.bubble.skin.keyboard.App
|
||||
|
||||
object SharedManager {
|
||||
|
||||
val SP_NAME = "keyboard_skin"
|
||||
val SKIN_PATH = "skin_path"
|
||||
val spSkin = App.appInstance.getSharedPreferences(SP_NAME,Context.MODE_PRIVATE)
|
||||
|
||||
fun updateSkinPath(skinPath:String){
|
||||
spSkin.edit().putString(SKIN_PATH,skinPath).apply()
|
||||
}
|
||||
|
||||
fun getSkinPath( ):String?{
|
||||
return spSkin.getString(SKIN_PATH,null)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,150 @@
|
||||
package com.keyboard.bubble.skin.keyboard.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.graphics.drawable.StateListDrawable
|
||||
import android.util.Xml
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.keyboard.bubble.skin.keyboard.App
|
||||
import com.keyboard.bubble.skin.keyboard.R
|
||||
import org.xmlpull.v1.XmlPullParser
|
||||
import java.io.File
|
||||
import java.io.StringReader
|
||||
|
||||
class SkinManager(var context: Context) {
|
||||
|
||||
|
||||
private var textSize = 13f
|
||||
|
||||
var functionDraw: Drawable = getDefaultDrawList(R.drawable.de_normalkey,R.drawable.de_pressedkey)
|
||||
var generalDraw: Drawable = getDefaultDrawList(R.drawable.de_normalkey,R.drawable.de_pressedkey)
|
||||
|
||||
var toDraw: Drawable = getDefaultDrawList(R.drawable.de_normalkey,R.drawable.de_pressedkey)
|
||||
var spaceDraw: Drawable = getDefaultDrawList(R.drawable.de_normalkey,R.drawable.de_pressedkey)
|
||||
|
||||
var switchDraw: Drawable? = null
|
||||
var deleteDraw: Drawable? = null
|
||||
var backDraw: Drawable? = null
|
||||
var searchDraw: Drawable? = null
|
||||
|
||||
var shiftDraw: Drawable? = null
|
||||
var shiftLockDraw: Drawable? = null
|
||||
|
||||
var keyTextColor: Int = ContextCompat.getColor(context, R.color.black)
|
||||
var keyTextColorFunction: Int = ContextCompat.getColor(context, R.color.black)
|
||||
fun updateSkinConfig() {
|
||||
SharedManager.getSkinPath()?.let { resPath ->
|
||||
val pPath = "${resPath}res/drawable-xhdpi-v4/"
|
||||
pPath.let {
|
||||
readColors(resPath) {
|
||||
for ((name, value) in it) {
|
||||
if (name == ConstValue.keyTextColorName) {
|
||||
keyTextColor = value
|
||||
}
|
||||
if (name == ConstValue.keyTextColorFunctionName) {
|
||||
keyTextColorFunction = value
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
functionDraw = getDrawList(
|
||||
it + ConstValue.functionNormalName,
|
||||
it + ConstValue.functionPressName
|
||||
)
|
||||
generalDraw = getDrawList(it + ConstValue.normalName, it + ConstValue.pressName)
|
||||
toDraw = getDrawList(it + ConstValue.toNormalName, it + ConstValue.toPressName)
|
||||
spaceDraw =
|
||||
getDrawList(it + ConstValue.spaceNormalName, it + ConstValue.spacePressName)
|
||||
switchDraw =
|
||||
getDrawList(it + ConstValue.imeSwitchName, it + ConstValue.imeSwitchName)
|
||||
deleteDraw = getDrawList(
|
||||
it + ConstValue.deleteNormalName,
|
||||
it + ConstValue.deletePressName
|
||||
)
|
||||
backDraw = getDrawList(it + ConstValue.backName, it + ConstValue.backName)
|
||||
searchDraw = getDrawList(it + ConstValue.searchName, it + ConstValue.searchName)
|
||||
shiftDraw = getDrawList(
|
||||
it + ConstValue.shiftNormalName,
|
||||
it + ConstValue.shiftNormalName
|
||||
)
|
||||
shiftLockDraw =
|
||||
getDrawList(it + ConstValue.shiftLockName, it + ConstValue.shiftLockName)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun getDefaultDrawList(normalDrawId: Int, pressDrawId: Int): StateListDrawable {
|
||||
val normalDraw = ContextCompat.getDrawable(App.appInstance,normalDrawId )
|
||||
val pressDraw = ContextCompat.getDrawable(App.appInstance,pressDrawId )
|
||||
val stateListDrawable = StateListDrawable().apply {
|
||||
addState(
|
||||
intArrayOf(android.R.attr.state_pressed),
|
||||
pressDraw
|
||||
)
|
||||
addState(intArrayOf(), normalDraw)
|
||||
}
|
||||
|
||||
return stateListDrawable
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private fun getDrawList(normalPath: String, pressPath: String): StateListDrawable {
|
||||
val pressDraw = BitmapFactory.decodeFile(pressPath)
|
||||
val normalDraw = BitmapFactory.decodeFile(normalPath)
|
||||
val stateListDrawable = StateListDrawable().apply {
|
||||
addState(
|
||||
intArrayOf(android.R.attr.state_pressed),
|
||||
BitmapDrawable(context.resources, pressDraw)
|
||||
)
|
||||
addState(intArrayOf(), BitmapDrawable(context.resources, normalDraw))
|
||||
}
|
||||
|
||||
return stateListDrawable
|
||||
|
||||
|
||||
}
|
||||
|
||||
private fun readColors(resPath: String, callBack: (Map<String, Int>) -> Unit) {
|
||||
val resMaps = mutableMapOf<String, Int>()
|
||||
|
||||
val pPath = "${resPath}res/colors.xml"
|
||||
val file = File(pPath)
|
||||
if (file.exists()) {
|
||||
val xmlPullParser = Xml.newPullParser().apply {
|
||||
setInput(StringReader(file.readText()))
|
||||
setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false)
|
||||
|
||||
}
|
||||
var curType = xmlPullParser.eventType
|
||||
while (curType != XmlPullParser.END_DOCUMENT) {
|
||||
val b = curType == XmlPullParser.START_TAG
|
||||
val b1 = xmlPullParser.name == "color"
|
||||
val b2 = xmlPullParser.name == "item"
|
||||
if (b && (b1 || b2)) {
|
||||
val attributeName = xmlPullParser.getAttributeValue(null, "name")
|
||||
val nextTextValue = xmlPullParser.nextText()
|
||||
val b3 = attributeName == ConstValue.keyTextColorName
|
||||
val b4 = attributeName == ConstValue.keyTextColorFunctionName
|
||||
if (b3 || b4) {
|
||||
resMaps[attributeName] = Color.parseColor(nextTextValue)
|
||||
}
|
||||
}
|
||||
curType = xmlPullParser.next()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
callBack.invoke(resMaps)
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
6
app/src/main/res/color/selector_text_color.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="@color/main_color" android:state_selected="true"/>
|
||||
<item android:color="#cccccc" android:state_selected="false"/>
|
||||
|
||||
</selector>
|
||||
15
app/src/main/res/drawable/background_key.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_pressed="false">
|
||||
<shape android:shape="rectangle">
|
||||
<corners android:radius="4dp"/>
|
||||
<solid android:color="@color/white"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item android:state_pressed="true">
|
||||
<shape android:shape="rectangle">
|
||||
<corners android:radius="4dp"/>
|
||||
<solid android:color="@color/key_bg_press"/>
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
||||
7
app/src/main/res/drawable/bg_all_shape.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<corners android:radius="80dp"/>
|
||||
<solid android:color="@color/apply_step_false"/>
|
||||
|
||||
</shape>
|
||||
5
app/src/main/res/drawable/bg_cursor.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<size android:width="2dp" />
|
||||
<solid android:color="@color/main_color" />
|
||||
</shape>
|
||||
10
app/src/main/res/drawable/bg_enable.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/white"/>
|
||||
<corners
|
||||
android:topLeftRadius="40dp"
|
||||
android:topRightRadius="40dp" />
|
||||
|
||||
|
||||
</shape>
|
||||
7
app/src/main/res/drawable/bg_enable_shape.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/apply_step_false" />
|
||||
<corners android:radius="12dp" />
|
||||
|
||||
</shape>
|
||||
7
app/src/main/res/drawable/bg_set.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/btn_color" />
|
||||
<corners android:radius="12dp" />
|
||||
|
||||
</shape>
|
||||
9
app/src/main/res/drawable/black_back.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="64dp"
|
||||
android:height="64dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:pathData="M395.2,513.6l323.1,-312.4c19.1,-18.4 19.1,-48.3 0,-66.7 -19.1,-18.4 -49.9,-18.4 -69,0L291.8,480.3c-19.1,18.4 -19.1,48.3 0,66.7l357.6,345.7c9.5,9.2 22,13.8 34.5,13.8 12.5,0 25,-4.6 34.5,-13.8 19.1,-18.4 19.1,-48.2 0,-66.7L395.2,513.6z"
|
||||
android:fillColor="@color/black"/>
|
||||
</vector>
|
||||
9
app/src/main/res/drawable/black_close.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="16dp"
|
||||
android:height="16dp"
|
||||
android:viewportWidth="16"
|
||||
android:viewportHeight="16">
|
||||
<path
|
||||
android:pathData="M8.72,8L14.21,2.51C14.412,2.307 14.412,1.992 14.21,1.79C14.007,1.587 13.692,1.587 13.49,1.79L8,7.28L2.51,1.79C2.307,1.587 1.992,1.587 1.79,1.79C1.587,1.992 1.587,2.307 1.79,2.51L7.28,8L1.79,13.49C1.587,13.692 1.587,14.007 1.79,14.21C1.88,14.3 2.015,14.367 2.15,14.367C2.285,14.367 2.42,14.322 2.51,14.21L8,8.72L13.49,14.21C13.58,14.3 13.715,14.367 13.85,14.367C13.985,14.367 14.12,14.322 14.21,14.21C14.412,14.007 14.412,13.692 14.21,13.49L8.72,8Z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
||||
BIN
app/src/main/res/drawable/de_normalkey.png
Normal file
|
After Width: | Height: | Size: 481 B |
BIN
app/src/main/res/drawable/de_pressedkey.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
app/src/main/res/drawable/icon_download.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
app/src/main/res/drawable/icon_ok.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
6
app/src/main/res/drawable/item_like.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
<solid android:color="@color/white"/>
|
||||
|
||||
</shape>
|
||||
9
app/src/main/res/drawable/like_normal.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="64dp"
|
||||
android:height="64dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:pathData="M716.8,60.2c-81.3,0 -153.6,36.1 -204.8,96.4 -51.2,-60.2 -123.5,-96.4 -204.8,-96.4C153.6,60.2 30.1,192.8 30.1,358.4c0,45.2 6,87.3 21.1,126.5 0,0 12,36.1 21.1,57.2C189.7,798.1 512,963.8 512,963.8s322.3,-165.6 439.7,-424.7c0,0 15.1,-33.1 21.1,-57.2 12,-39.2 21.1,-81.3 21.1,-126.5C993.9,192.8 870.4,60.2 716.8,60.2zM915.6,466.8c-6,15.1 -15.1,42.2 -18.1,48.2 -87.3,192.8 -307.2,334.3 -385.5,379.5 -78.3,-45.2 -298.2,-186.7 -385.5,-379.5 -6,-15.1 -15.1,-36.1 -18.1,-51.2 -12,-33.1 -18.1,-72.3 -18.1,-105.4C90.4,225.9 189.7,120.5 307.2,120.5c60.2,0 117.5,27.1 159.6,75.3L512,247l45.2,-51.2C599.3,147.6 656.6,120.5 716.8,120.5c120.5,0 216.8,105.4 216.8,234.9 0,36.1 -6,72.3 -18.1,111.4z"
|
||||
android:fillColor="@color/black"/>
|
||||
</vector>
|
||||
9
app/src/main/res/drawable/like_selected.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="64dp"
|
||||
android:height="64dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:pathData="M667.8,117.3C832.9,117.3 938.7,249.7 938.7,427.9c0,138.3 -125.1,290.5 -371.6,461.6a96.8,96.8 0,0 1,-110.2 0C210.4,718.4 85.3,566.1 85.3,427.9 85.3,249.7 191.1,117.3 356.2,117.3c59.6,0 100.1,20.8 155.8,68.1C567.7,138.2 608.2,117.3 667.8,117.3z"
|
||||
android:fillColor="@color/like_color"/>
|
||||
</vector>
|
||||
23
app/src/main/res/drawable/pb_drawable.xml
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:id="@android:id/background">
|
||||
<shape>
|
||||
<corners android:radius="10dp" />
|
||||
<solid android:color="@color/pb_bg" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:id="@android:id/progress">
|
||||
<clip>
|
||||
<shape>
|
||||
<corners android:radius="10dp" />
|
||||
<solid android:color="@color/main_color"/>
|
||||
</shape>
|
||||
</clip>
|
||||
</item>
|
||||
</layer-list>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
7
app/src/main/res/drawable/selected_tab_bg.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<corners android:radius="6dp"/>
|
||||
<solid android:color="@color/sub_main_color"/>
|
||||
|
||||
</shape>
|
||||
7
app/src/main/res/drawable/selected_tab_bg_false.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<corners android:radius="6dp"/>
|
||||
<solid android:color="@color/gray"/>
|
||||
|
||||
</shape>
|
||||
6
app/src/main/res/drawable/selector_collection.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/like_normal" android:state_selected="false"/>
|
||||
<item android:drawable="@drawable/like_selected" android:state_selected="true" />
|
||||
|
||||
</selector>
|
||||
6
app/src/main/res/drawable/selector_enable.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:drawable="@drawable/bg_set" android:state_selected="false" />
|
||||
<item android:drawable="@drawable/bg_enable_shape" />
|
||||
</selector>
|
||||
6
app/src/main/res/drawable/selector_like.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/tab_like" android:state_selected="false"/>
|
||||
<item android:drawable="@drawable/tab_like_selected" android:state_selected="true" />
|
||||
|
||||
</selector>
|
||||
6
app/src/main/res/drawable/selector_tab.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/selected_tab_bg_false" android:state_selected="false"/>
|
||||
<item android:drawable="@drawable/selected_tab_bg" android:state_selected="true" />
|
||||
|
||||
</selector>
|
||||
6
app/src/main/res/drawable/selector_tab_theme.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/theme" android:state_selected="false"/>
|
||||
<item android:drawable="@drawable/theme_selected" android:state_selected="true" />
|
||||
|
||||
</selector>
|
||||
7
app/src/main/res/drawable/shape_success_et.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<corners android:radius="10dp"/>
|
||||
<solid android:color="@color/white"/>
|
||||
|
||||
</shape>
|
||||
12
app/src/main/res/drawable/tab_like.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="64dp"
|
||||
android:height="64dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:pathData="M513.3,950.8h-0c-20.3,-0 -39.2,-8.3 -53.3,-23.2L150.1,598.4c-3.3,-3.5 -6.5,-7.2 -9.2,-10.4 -47.8,-55.8 -73.3,-128.3 -71.7,-204.1 1.6,-76.1 30.4,-147.6 81,-201.3 53,-56.2 123.6,-87.1 199.1,-87.1 60,0 117,19.4 164.8,56.2 53.5,-39.5 119,-58.1 184.6,-52.4 66.4,5.8 128.8,36.3 175.7,85.9l0.1,0.1c102.9,109.5 108.3,285.8 12.5,401.8 -4.2,5.5 -8.4,10 -12.5,14.3l-0.1,0.1 -307.7,326.3c-14.1,15 -33,23.2 -53.3,23.2zM349.2,167.8c-55.3,0 -107.3,22.9 -146.4,64.4 -78.4,83.2 -81.5,221.7 -6.9,308.8 2.4,2.8 4.8,5.6 7,7.9L512.7,877.9c0.4,0.4 0.6,0.5 0.6,0.5 0,0 0.3,-0.1 0.6,-0.5l307.7,-326.3c3.3,-3.5 5.9,-6.3 7.9,-9l1.1,-1.3c73.4,-88.4 69.5,-223.1 -9,-306.6 -71.3,-75.3 -182.6,-85.8 -264.8,-24.8 -26.1,19.4 -61,19 -86.8,-0.9 -35.1,-27.1 -76.9,-41.3 -120.8,-41.3z"
|
||||
android:fillColor="#cccccc"/>
|
||||
<path
|
||||
android:pathData="M249,502.9c-11.9,0 -22.8,-7.9 -26.1,-19.9 -15.2,-55.2 -8.1,-113.1 20.2,-162.9 28.3,-49.8 74.3,-85.7 129.5,-100.9 14.4,-4 29.3,4.5 33.3,18.9 4,14.4 -4.5,29.3 -18.9,33.3 -85.2,23.5 -135.4,112 -111.9,197.2 4,14.4 -4.5,29.3 -18.9,33.3 -2.4,0.7 -4.8,1 -7.2,1z"
|
||||
android:fillColor="#cccccc"/>
|
||||
</vector>
|
||||
12
app/src/main/res/drawable/tab_like_selected.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="64dp"
|
||||
android:height="64dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:pathData="M513.3,950.8h-0c-20.3,-0 -39.2,-8.3 -53.3,-23.2L150.1,598.4c-3.3,-3.5 -6.5,-7.2 -9.2,-10.4 -47.8,-55.8 -73.3,-128.3 -71.7,-204.1 1.6,-76.1 30.4,-147.6 81,-201.3 53,-56.2 123.6,-87.1 199.1,-87.1 60,0 117,19.4 164.8,56.2 53.5,-39.5 119,-58.1 184.6,-52.4 66.4,5.8 128.8,36.3 175.7,85.9l0.1,0.1c102.9,109.5 108.3,285.8 12.5,401.8 -4.2,5.5 -8.4,10 -12.5,14.3l-0.1,0.1 -307.7,326.3c-14.1,15 -33,23.2 -53.3,23.2zM349.2,167.8c-55.3,0 -107.3,22.9 -146.4,64.4 -78.4,83.2 -81.5,221.7 -6.9,308.8 2.4,2.8 4.8,5.6 7,7.9L512.7,877.9c0.4,0.4 0.6,0.5 0.6,0.5 0,0 0.3,-0.1 0.6,-0.5l307.7,-326.3c3.3,-3.5 5.9,-6.3 7.9,-9l1.1,-1.3c73.4,-88.4 69.5,-223.1 -9,-306.6 -71.3,-75.3 -182.6,-85.8 -264.8,-24.8 -26.1,19.4 -61,19 -86.8,-0.9 -35.1,-27.1 -76.9,-41.3 -120.8,-41.3z"
|
||||
android:fillColor="@color/main_color"/>
|
||||
<path
|
||||
android:pathData="M249,502.9c-11.9,0 -22.8,-7.9 -26.1,-19.9 -15.2,-55.2 -8.1,-113.1 20.2,-162.9 28.3,-49.8 74.3,-85.7 129.5,-100.9 14.4,-4 29.3,4.5 33.3,18.9 4,14.4 -4.5,29.3 -18.9,33.3 -85.2,23.5 -135.4,112 -111.9,197.2 4,14.4 -4.5,29.3 -18.9,33.3 -2.4,0.7 -4.8,1 -7.2,1z"
|
||||
android:fillColor="@color/main_color"/>
|
||||
</vector>
|
||||
12
app/src/main/res/drawable/theme.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="64dp"
|
||||
android:height="64dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:pathData="M736.8,64.7L287.2,64.7C175,64.7 83.8,155.9 83.8,268.1L83.8,756c0,112.1 91.2,203.4 203.4,203.4h449.7c112.1,0 203.4,-91.2 203.4,-203.4L940.3,268.1C940.2,155.9 849,64.7 736.8,64.7zM886.3,755.9c0,82.4 -67,149.5 -149.5,149.5L287.2,905.4c-82.4,0 -149.5,-67 -149.5,-149.5L137.7,268.1c0,-82.4 67,-149.5 149.5,-149.5h449.7c82.4,0 149.5,67 149.5,149.5v487.8z"
|
||||
android:fillColor="#cccccc"/>
|
||||
<path
|
||||
android:pathData="M645.2,344.6c-9.7,-9.7 -23.7,-13.8 -37.3,-10.9 -6.5,1.4 -12.4,4.1 -17.5,8.2 -21.1,16.9 -47.6,26.2 -74.6,26.2h-0.8c-0.8,0 -1.6,-0.1 -2.4,-0.1h-1.2c-0.8,0 -1.6,0.1 -2.4,0.1h-0.8c-27,0 -53.6,-9.3 -74.7,-26.2 -5.1,-4.1 -11,-6.8 -17.5,-8.2 -13.7,-2.9 -27.6,1.2 -37.3,10.9l-66.8,66.8c-7.5,7.5 -11.8,17.8 -11.9,28.4v2.6c0.6,11 5.6,21.4 13.9,28.7 13.8,12 28.9,22.8 44.8,32.1 2.9,1.7 4.6,4.7 4.6,7.9v121.8c0,21.2 14.4,39.6 35.1,44.8 35.6,9 72.4,13.5 109.3,13.5h4c38.8,0.3 76.9,-4.2 113.8,-13.5 20.6,-5.2 35.1,-23.6 35.1,-44.8L660.6,511.1c0,-3.3 1.7,-6.3 4.6,-7.9 15.9,-9.2 30.9,-20 44.8,-32.1 8.2,-7.1 13.2,-17.4 13.9,-28.2 0.1,-1.1 0.1,-2.2 0.1,-3.3 -0.2,-10.5 -4.5,-20.7 -11.9,-28.1l-66.9,-66.9zM641.5,462.4c-17.3,10.1 -28.1,28.8 -28.1,48.7v121c-32.8,8.2 -66.7,12.3 -101.7,11.9 -34.3,0.4 -68.5,-3.7 -101.3,-11.9v-121c0,-20 -10.8,-38.6 -28.1,-48.7 -11.3,-6.6 -22.2,-14.1 -32.3,-22.5l58,-58c28.7,21.5 64.1,33.3 100,33.3 1.2,0 2.4,-0.1 3.5,-0.1h0.4c1.2,0.1 2.4,0.1 3.5,0.1 36,0 71.3,-11.8 100,-33.3l58,58c-9.7,8.4 -20.5,15.9 -31.9,22.5z"
|
||||
android:fillColor="#cccccc"/>
|
||||
</vector>
|
||||
12
app/src/main/res/drawable/theme_selected.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="64dp"
|
||||
android:height="64dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:pathData="M736.8,64.7L287.2,64.7C175,64.7 83.8,155.9 83.8,268.1L83.8,756c0,112.1 91.2,203.4 203.4,203.4h449.7c112.1,0 203.4,-91.2 203.4,-203.4L940.3,268.1C940.2,155.9 849,64.7 736.8,64.7zM886.3,755.9c0,82.4 -67,149.5 -149.5,149.5L287.2,905.4c-82.4,0 -149.5,-67 -149.5,-149.5L137.7,268.1c0,-82.4 67,-149.5 149.5,-149.5h449.7c82.4,0 149.5,67 149.5,149.5v487.8z"
|
||||
android:fillColor="@color/main_color"/>
|
||||
<path
|
||||
android:pathData="M645.2,344.6c-9.7,-9.7 -23.7,-13.8 -37.3,-10.9 -6.5,1.4 -12.4,4.1 -17.5,8.2 -21.1,16.9 -47.6,26.2 -74.6,26.2h-0.8c-0.8,0 -1.6,-0.1 -2.4,-0.1h-1.2c-0.8,0 -1.6,0.1 -2.4,0.1h-0.8c-27,0 -53.6,-9.3 -74.7,-26.2 -5.1,-4.1 -11,-6.8 -17.5,-8.2 -13.7,-2.9 -27.6,1.2 -37.3,10.9l-66.8,66.8c-7.5,7.5 -11.8,17.8 -11.9,28.4v2.6c0.6,11 5.6,21.4 13.9,28.7 13.8,12 28.9,22.8 44.8,32.1 2.9,1.7 4.6,4.7 4.6,7.9v121.8c0,21.2 14.4,39.6 35.1,44.8 35.6,9 72.4,13.5 109.3,13.5h4c38.8,0.3 76.9,-4.2 113.8,-13.5 20.6,-5.2 35.1,-23.6 35.1,-44.8L660.6,511.1c0,-3.3 1.7,-6.3 4.6,-7.9 15.9,-9.2 30.9,-20 44.8,-32.1 8.2,-7.1 13.2,-17.4 13.9,-28.2 0.1,-1.1 0.1,-2.2 0.1,-3.3 -0.2,-10.5 -4.5,-20.7 -11.9,-28.1l-66.9,-66.9zM641.5,462.4c-17.3,10.1 -28.1,28.8 -28.1,48.7v121c-32.8,8.2 -66.7,12.3 -101.7,11.9 -34.3,0.4 -68.5,-3.7 -101.3,-11.9v-121c0,-20 -10.8,-38.6 -28.1,-48.7 -11.3,-6.6 -22.2,-14.1 -32.3,-22.5l58,-58c28.7,21.5 64.1,33.3 100,33.3 1.2,0 2.4,-0.1 3.5,-0.1h0.4c1.2,0.1 2.4,0.1 3.5,0.1 36,0 71.3,-11.8 100,-33.3l58,58c-9.7,8.4 -20.5,15.9 -31.9,22.5z"
|
||||
android:fillColor="@color/main_color"/>
|
||||
</vector>
|
||||
BIN
app/src/main/res/drawable/white_back.png
Normal file
|
After Width: | Height: | Size: 341 B |
25
app/src/main/res/layout/activity_main.xml
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout 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"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="34dp"
|
||||
tools:context=".ui.MainActivity">
|
||||
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/viewpager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_above="@id/tab_layout" />
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/tab_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
app:tabIndicatorHeight="0dp" />
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
26
app/src/main/res/layout/item_cutomer_view.xml
Normal file
@ -0,0 +1,26 @@
|
||||
<?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"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/im_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp" />
|
||||
|
||||
<com.keyboard.bubble.skin.keyboard.utils.MyTextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/app_name"
|
||||
android:id="@+id/textView"
|
||||
app:apply_font="true"
|
||||
android:visibility="gone"
|
||||
android:textColor="@color/selector_text_color"
|
||||
android:layout_marginTop="5dp"
|
||||
android:textSize="12sp" />
|
||||
|
||||
</LinearLayout>
|
||||
50
app/src/main/res/layout/item_like.xml
Normal file
@ -0,0 +1,50 @@
|
||||
<?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"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/card_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="120dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginBottom="12dp"
|
||||
app:cardElevation="0dp"
|
||||
app:cardCornerRadius="12dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/im"
|
||||
android:scaleType="fitXY"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/layout_favorite"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginTop="5dp"
|
||||
android:elevation="2dp"
|
||||
android:background="@drawable/item_like"
|
||||
android:layout_marginEnd="10dp"
|
||||
app:cardCornerRadius="100dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/im_favorite"
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginStart="2dp"
|
||||
android:layout_marginTop="2dp"
|
||||
android:layout_marginEnd="2dp"
|
||||
android:layout_marginBottom="2dp"
|
||||
android:padding="2dp"
|
||||
android:src="@drawable/selector_collection" />
|
||||
</FrameLayout>
|
||||
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
</FrameLayout>
|
||||
20
app/src/main/res/layout/item_main.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="match_parent"
|
||||
app:cardCornerRadius="12dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:id="@+id/card_view"
|
||||
android:layout_height="120dp">
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/imPreview"
|
||||
android:scaleType="fitXY"/>
|
||||
</androidx.cardview.widget.CardView>
|
||||
</FrameLayout>
|
||||
50
app/src/main/res/layout/item_preview.xml
Normal file
@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/item_layout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginEnd="24dp">
|
||||
|
||||
<com.keyboard.bubble.skin.keyboard.utils.MyTextView
|
||||
android:id="@+id/text_tab_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="30dp"
|
||||
android:layout_centerInParent="true"
|
||||
android:text="@string/app_name"
|
||||
app:apply_font="true"
|
||||
android:gravity="center"
|
||||
android:background="@drawable/selector_tab"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:textSize="13sp"
|
||||
android:textColor="@color/black" />
|
||||
|
||||
<!-- <LinearLayout-->
|
||||
<!-- android:id="@+id/layout_indicator"-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:layout_alignParentBottom="true"-->
|
||||
<!-- android:layout_centerHorizontal="true"-->
|
||||
<!-- android:visibility="gone"-->
|
||||
<!-- android:orientation="horizontal">-->
|
||||
|
||||
<!-- <View-->
|
||||
<!-- android:layout_width="4dp"-->
|
||||
<!-- android:layout_height="4dp"-->
|
||||
<!-- android:background="@color/main_color" />-->
|
||||
|
||||
<!-- <View-->
|
||||
<!-- android:layout_width="16dp"-->
|
||||
<!-- android:layout_height="4dp"-->
|
||||
<!-- android:layout_marginStart="3dp"-->
|
||||
<!-- android:layout_marginEnd="3dp"-->
|
||||
<!-- android:background="@color/main_color" />-->
|
||||
|
||||
<!-- <View-->
|
||||
<!-- android:layout_width="4dp"-->
|
||||
<!-- android:layout_height="4dp"-->
|
||||
<!-- android:background="@color/main_color" />-->
|
||||
<!-- </LinearLayout>-->
|
||||
|
||||
</RelativeLayout>
|
||||
100
app/src/main/res/layout/layout_active.xml
Normal file
@ -0,0 +1,100 @@
|
||||
<?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="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:background="@drawable/bg_enable"
|
||||
android:paddingBottom="20dp"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="55dp"
|
||||
android:layout_height="45dp"
|
||||
android:padding="12dp"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:id="@+id/im_close"
|
||||
android:layout_marginTop="10dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:src="@drawable/black_close"
|
||||
app:layout_constraintRight_toRightOf="parent" />
|
||||
|
||||
<com.keyboard.bubble.skin.keyboard.utils.MyTextView
|
||||
android:id="@+id/text_open"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="50dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginEnd="50dp"
|
||||
android:gravity="center"
|
||||
app:apply_font="true"
|
||||
android:text="@string/open_str"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintTop_toBottomOf="@id/im_close" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linear_step_one"
|
||||
android:layout_width="280dp"
|
||||
android:layout_height="52dp"
|
||||
android:layout_marginTop="32dp"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
android:background="@drawable/selector_enable"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_open">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ok_one"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:src="@drawable/icon_ok"
|
||||
android:visibility="gone" />
|
||||
|
||||
<com.keyboard.bubble.skin.keyboard.utils.MyTextView
|
||||
android:id="@+id/text_step_one"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/step_1"
|
||||
app:apply_font="true"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="15sp" />
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linear_step_two"
|
||||
android:layout_width="280dp"
|
||||
android:layout_height="52dp"
|
||||
android:layout_marginTop="20dp"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
android:background="@drawable/selector_enable"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintTop_toBottomOf="@id/linear_step_one">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ok_two"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:src="@drawable/icon_ok"
|
||||
android:visibility="gone" />
|
||||
|
||||
<com.keyboard.bubble.skin.keyboard.utils.MyTextView
|
||||
android:id="@+id/text_step_two"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/step_2"
|
||||
app:apply_font="true"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="15sp" />
|
||||
</LinearLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</FrameLayout>
|
||||
137
app/src/main/res/layout/layout_apply.xml
Normal file
@ -0,0 +1,137 @@
|
||||
<?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=".ui.SetkeyboardActivity">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/back"
|
||||
android:layout_width="44dp"
|
||||
android:layout_height="44dp"
|
||||
android:layout_marginTop="35dp"
|
||||
android:paddingStart="5dp"
|
||||
android:paddingTop="10dp"
|
||||
android:paddingBottom="10dp"
|
||||
android:src="@drawable/black_back"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textview_data_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:text="@string/app_name"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/back"
|
||||
app:layout_constraintLeft_toRightOf="@id/back"
|
||||
app:layout_constraintTop_toTopOf="@id/back" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/im_like"
|
||||
android:layout_width="44dp"
|
||||
android:layout_height="44dp"
|
||||
android:layout_marginEnd="30dp"
|
||||
android:padding="12dp"
|
||||
android:src="@drawable/selector_collection"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/back" />
|
||||
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/card_viewData"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="204dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
app:cardBackgroundColor="@color/transparent"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="0dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/back">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_data"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="fitXY" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layoutDownloadApply"
|
||||
android:layout_width="260dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="28dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:background="@drawable/bg_set"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/card_viewData">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/im_download"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:src="@drawable/icon_download" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_download"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:text="@string/download_apply"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_for_you"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="25dp"
|
||||
android:text="@string/recommended"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/layoutDownloadApply" />
|
||||
|
||||
|
||||
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recommended_recycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="17dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_for_you" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/loading"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/bg_loading"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:visibility="gone">
|
||||
|
||||
<ProgressBar
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:indeterminateTint="@color/white" />
|
||||
</FrameLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
41
app/src/main/res/layout/layout_input_view.xml
Normal file
@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/rl_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/gif_bg"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_alignTop="@id/custom_input_view"
|
||||
android:layout_alignBottom="@id/custom_input_view" />
|
||||
|
||||
<VideoView
|
||||
android:id="@+id/video_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_alignTop="@id/custom_input_view"
|
||||
android:layout_alignBottom="@id/custom_input_view" />
|
||||
|
||||
|
||||
<com.keyboard.bubble.skin.keyboard.customerview.MyInputView
|
||||
android:id="@+id/custom_input_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:animateLayoutChanges="true"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:keyBackground="@drawable/background_key"
|
||||
android:keyTextColor="@color/white"
|
||||
android:keyTextSize="0sp"
|
||||
android:labelTextSize="12sp"
|
||||
android:paddingStart="5dp"
|
||||
android:paddingTop="5dp"
|
||||
android:paddingEnd="5dp"
|
||||
android:paddingBottom="5dp" />
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
44
app/src/main/res/layout/layout_launch.xml
Normal file
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout 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=".ui.WelcomeActivity">
|
||||
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/nova_progress"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="240dp"
|
||||
android:layout_height="5dp"
|
||||
android:layout_below="@id/tv"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginStart="33dp"
|
||||
android:layout_marginTop="28dp"
|
||||
android:layout_marginEnd="33dp"
|
||||
android:layout_marginBottom="40dp"
|
||||
android:progress="3"
|
||||
android:progressDrawable="@drawable/pb_drawable" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image"
|
||||
android:layout_width="106dp"
|
||||
android:layout_height="106dp"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="260dp"
|
||||
android:src="@mipmap/icon" />
|
||||
|
||||
<com.keyboard.bubble.skin.keyboard.utils.MyTextView
|
||||
android:id="@+id/tv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/image"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="5dp"
|
||||
android:text="@string/app_name"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="21sp"
|
||||
app:apply_font="true" />
|
||||
|
||||
</RelativeLayout>
|
||||
47
app/src/main/res/layout/layout_like_fragment.xml
Normal file
@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout 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=".fagment.MainPage">
|
||||
|
||||
<com.keyboard.bubble.skin.keyboard.utils.MyTextView
|
||||
android:id="@+id/top_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="15dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/tv_like"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
app:apply_font="true" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/like_recycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/top_title"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginEnd="15dp" />
|
||||
|
||||
|
||||
<com.keyboard.bubble.skin.keyboard.utils.MyTextView
|
||||
android:id="@+id/empty_title"
|
||||
android:layout_width="260dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:layout_marginStart="25dp"
|
||||
android:layout_marginTop="15dp"
|
||||
android:visibility="gone"
|
||||
android:layout_marginEnd="25dp"
|
||||
android:gravity="center"
|
||||
android:lineSpacingExtra="2dp"
|
||||
android:text="@string/no_like"
|
||||
android:textColor="@color/view_all_text_color"
|
||||
android:textSize="16sp"
|
||||
app:apply_font="true" />
|
||||
|
||||
</RelativeLayout>
|
||||
90
app/src/main/res/layout/layout_main_activity.xml
Normal file
@ -0,0 +1,90 @@
|
||||
<?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"
|
||||
|
||||
android:paddingTop="30dp"
|
||||
tools:context=".ui.MainActivity">
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_view_appName"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:text="@string/app_name"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/card_banner"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="194dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_view_appName">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_banner"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="fitXY" />
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_for_you"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="25dp"
|
||||
android:text="@string/recommended"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/card_banner" />
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_view_all"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:background="@drawable/bg_all_shape"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingEnd="10dp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/text_for_you"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/text_for_you">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/view_all"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/for_you_recycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="17dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_for_you" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
||||
16
app/src/main/res/layout/layout_main_fragment.xml
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".fagment.MainPage">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/content_recycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="17dp"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
</FrameLayout>
|
||||
64
app/src/main/res/layout/layout_success.xml
Normal file
@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout 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="wrap_content">
|
||||
<RelativeLayout
|
||||
android:id="@+id/relayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/bg_loading" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_marginTop="50dp"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:background="@drawable/shape_success_et"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:hint="@string/et_hint"
|
||||
android:textColorHint="@color/apply_step_false"
|
||||
android:paddingStart="15dp"
|
||||
android:textCursorDrawable="@drawable/bg_cursor"
|
||||
android:textColor="@color/black" />
|
||||
</RelativeLayout>
|
||||
<ImageView
|
||||
android:id="@+id/id_back"
|
||||
android:layout_width="44dp"
|
||||
android:layout_height="44dp"
|
||||
android:paddingStart="5dp"
|
||||
android:paddingTop="10dp"
|
||||
android:layout_marginTop="35dp"
|
||||
android:paddingBottom="10dp"
|
||||
android:src="@drawable/white_back" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignTop="@id/id_back"
|
||||
android:layout_alignBottom="@id/id_back"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:maxLines="1"
|
||||
android:paddingStart="5dp"
|
||||
android:paddingEnd="5dp"
|
||||
android:text="@string/app_name"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="18sp" />
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<!--</ScrollView>-->
|
||||
47
app/src/main/res/layout/layout_theme_fragment.xml
Normal file
@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingEnd="10dp"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
tools:context=".fagment.MainPage">
|
||||
<com.keyboard.bubble.skin.keyboard.utils.MyTextView
|
||||
android:layout_width="wrap_content"
|
||||
app:apply_font="true"
|
||||
android:textSize="24sp"
|
||||
android:id="@+id/title"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/app_name"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/black"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<!-- <com.themes.fancy.keyboard.keyboard.utils.MyTextView-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- app:apply_font="true"-->
|
||||
<!-- android:textSize="17sp"-->
|
||||
<!-- android:id="@+id/sub_title"-->
|
||||
<!-- android:text="@string/welcome"-->
|
||||
<!-- android:textStyle="bold"-->
|
||||
<!-- android:layout_below="@id/top_title"-->
|
||||
<!-- android:textColor="@color/text_sub_color"-->
|
||||
<!-- android:layout_height="wrap_content"/>-->
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/tab_recycler"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_below="@id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
android:id="@+id/view_pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_below="@id/tab_recycler"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</RelativeLayout>
|
||||
33
app/src/main/res/layout/layout_view_all.xml
Normal file
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout 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"
|
||||
android:orientation="vertical">
|
||||
<ImageView
|
||||
android:id="@+id/back"
|
||||
android:layout_width="44dp"
|
||||
android:layout_height="44dp"
|
||||
android:paddingStart="5dp"
|
||||
android:paddingTop="10dp"
|
||||
android:paddingBottom="10dp"
|
||||
android:layout_marginTop="32dp"
|
||||
android:src="@drawable/white_back"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/tab_recycler"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
android:id="@+id/view_pager_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
BIN
app/src/main/res/mipmap-hdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 982 B |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/icon.png
Normal file
|
After Width: | Height: | Size: 56 KiB |
16
app/src/main/res/values-night/themes.xml
Normal file
@ -0,0 +1,16 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Theme.MyKeyBoard" parent="Theme.MaterialComponents.DayNight.NoActionBar">
|
||||
<!-- Primary brand color. -->
|
||||
<item name="colorPrimary">@color/purple_200</item>
|
||||
<item name="colorPrimaryVariant">@color/purple_700</item>
|
||||
<item name="colorOnPrimary">@color/black</item>
|
||||
<!-- Secondary brand color. -->
|
||||
<item name="colorSecondary">@color/teal_200</item>
|
||||
<item name="colorSecondaryVariant">@color/teal_200</item>
|
||||
<item name="colorOnSecondary">@color/black</item>
|
||||
<!-- Status bar color. -->
|
||||
<item name="android:statusBarColor">@color/transparent</item>
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
</resources>
|
||||
6
app/src/main/res/values/attrs.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<declare-styleable name="MyTV">
|
||||
<attr name="apply_font" format="boolean"/>
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
31
app/src/main/res/values/colors.xml
Normal file
@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="purple_200">#FFBB86FC</color>
|
||||
<color name="purple_500">#FF6200EE</color>
|
||||
<color name="purple_700">#FF3700B3</color>
|
||||
<color name="teal_200">#FF03DAC5</color>
|
||||
<color name="teal_700">#FF018786</color>
|
||||
<color name="black">#FF000000</color>
|
||||
<color name="white">#FFFFFFFF</color>
|
||||
|
||||
<color name="view_all_text_color">#80000000</color>
|
||||
|
||||
<color name="apply_step_false">#1A000000</color>
|
||||
<color name="key_bg_press">#ffbbbbbb</color>
|
||||
<color name="step_true">#666666</color>
|
||||
|
||||
|
||||
<color name="pb_bg">#CCC8C8</color>
|
||||
|
||||
<color name="transparent">#00000000</color>
|
||||
<color name="bg_loading">#80000000</color>
|
||||
|
||||
|
||||
<color name="sub_main_color">#FFF3c1</color>
|
||||
<color name="gray">#CCCBC6</color>
|
||||
<color name="main_color">#FFe16c</color>
|
||||
<color name="main_color_cf">#141413</color>
|
||||
<color name="text_sub_color">#575656</color>
|
||||
<color name="like_color">#F44336</color>
|
||||
<color name="btn_color">#4e67ff</color>
|
||||
</resources>
|
||||
7
app/src/main/res/values/dimen.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<dimen name="text_size">15sp</dimen>
|
||||
<dimen name="key_height">48dp</dimen>
|
||||
<dimen name="keyboard_vertical_gap">5dp</dimen>
|
||||
</resources>
|
||||