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/PrettyKeyboard.jks
Normal file
140
app/build.gradle.kts
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
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")
|
||||||
|
}
|
||||||
|
|
||||||
|
val timestamp = SimpleDateFormat("MM_dd_HH_mm").format(Date())
|
||||||
|
android {
|
||||||
|
namespace = "com.pretty.keyboard.theme.keyboard"
|
||||||
|
compileSdk = 34
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
//com.pretty.keyboard.theme
|
||||||
|
applicationId = "com.pretty.keyboard.theme"
|
||||||
|
minSdk = 23
|
||||||
|
targetSdk = 34
|
||||||
|
versionCode = 1
|
||||||
|
versionName = "1.0.0"
|
||||||
|
setProperty(
|
||||||
|
"archivesBaseName",
|
||||||
|
"Pretty 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_1_8
|
||||||
|
targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = "1.8"
|
||||||
|
}
|
||||||
|
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")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
implementation(platform("com.google.firebase:firebase-bom:33.1.1"))
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
29
app/google-services.json
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"project_info": {
|
||||||
|
"project_number": "213295331810",
|
||||||
|
"project_id": "pretty-keyboard",
|
||||||
|
"storage_bucket": "pretty-keyboard.firebasestorage.app"
|
||||||
|
},
|
||||||
|
"client": [
|
||||||
|
{
|
||||||
|
"client_info": {
|
||||||
|
"mobilesdk_app_id": "1:213295331810:android:1eb97679de885932f6a1bb",
|
||||||
|
"android_client_info": {
|
||||||
|
"package_name": "com.pretty.keyboard.theme"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"oauth_client": [],
|
||||||
|
"api_key": [
|
||||||
|
{
|
||||||
|
"current_key": "AIzaSyCC5rhRP-M9VE1uHDwFR9sayQrAdJJKX_8"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"services": {
|
||||||
|
"appinvite_service": {
|
||||||
|
"other_platform_oauth_client": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"configuration_version": "1"
|
||||||
|
}
|
||||||
59
app/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|
|
||||||
|
-ignorewarnings
|
||||||
|
#----------------------------Part-----基本指令区----------------------------------
|
||||||
|
# 代码混淆压缩比,在0~7之间,默认为5,一般不做修改
|
||||||
|
-optimizationpasses 5
|
||||||
|
|
||||||
|
# 混合时不使用大小写混合,混合后的类名为小写
|
||||||
|
-dontusemixedcaseclassnames
|
||||||
|
|
||||||
|
# 指定不去忽略非公共库的类
|
||||||
|
-dontskipnonpubliclibraryclasses
|
||||||
|
|
||||||
|
# 这句话能够使我们的项目混淆后产生映射文件
|
||||||
|
# 包含有类名->混淆后类名的映射关系
|
||||||
|
-verbose
|
||||||
|
|
||||||
|
# 指定不去忽略非公共库的类成员
|
||||||
|
-dontskipnonpubliclibraryclassmembers
|
||||||
|
|
||||||
|
# 不做预校验,preverify是proguard的四个步骤之一,Android不需要preverify,去掉这一步能够加快混淆速度。
|
||||||
|
-dontpreverify
|
||||||
|
|
||||||
|
# 保留Annotation不混淆
|
||||||
|
-keepattributes *Annotation*,InnerClasses
|
||||||
|
|
||||||
|
# 避免混淆泛型
|
||||||
|
-keepattributes Signature
|
||||||
|
|
||||||
|
# 抛出异常时保留代码行号
|
||||||
|
-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-keep class com.omicronapplications.** { *; }
|
||||||
|
-keep class net.sf.sevenzipjbinding.** { *; }
|
||||||
|
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package com.pretty.keyboard.theme.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)
|
||||||
|
}
|
||||||
|
}
|
||||||
63
app/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<?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=".MyApp"
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:icon="@mipmap/logo"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:roundIcon="@mipmap/logo"
|
||||||
|
android:supportsRtl="true"
|
||||||
|
android:theme="@style/Theme.MyKeyBoard"
|
||||||
|
tools:targetApi="31">
|
||||||
|
<activity
|
||||||
|
android:name=".ui.WelActivity"
|
||||||
|
android:screenOrientation="portrait"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
<activity
|
||||||
|
android:name=".ui.SettingActivity"
|
||||||
|
android:screenOrientation="portrait"
|
||||||
|
android:exported="false" />
|
||||||
|
<activity
|
||||||
|
android:name=".ui.ApplySkinActivity"
|
||||||
|
android:screenOrientation="portrait"
|
||||||
|
android:exported="false" />
|
||||||
|
<activity
|
||||||
|
android:name=".ui.AllActivity"
|
||||||
|
android:screenOrientation="portrait"
|
||||||
|
android:exported="false" />
|
||||||
|
<activity
|
||||||
|
android:name=".ui.SuccessActivity"
|
||||||
|
android:screenOrientation="portrait"
|
||||||
|
android:exported="false" />
|
||||||
|
<activity
|
||||||
|
android:name=".ui.HomeActivity"
|
||||||
|
android:exported="true"
|
||||||
|
android:screenOrientation="portrait"
|
||||||
|
android:launchMode="singleTask">
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
<service
|
||||||
|
android:name=".view.InputService"
|
||||||
|
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/keyborad" />
|
||||||
|
</service>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
||||||
22461
app/src/main/assets/data.json
Normal file
119
app/src/main/java/com/pretty/keyboard/theme/keyboard/MyApp.kt
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
package com.pretty.keyboard.theme.keyboard
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import android.util.Log
|
||||||
|
import com.google.firebase.FirebaseApp
|
||||||
|
import com.pretty.keyboard.theme.keyboard.bean.DataClass
|
||||||
|
import com.pretty.keyboard.theme.keyboard.bean.Info
|
||||||
|
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 MyApp : Application() {
|
||||||
|
companion object {
|
||||||
|
lateinit var appInstance: MyApp
|
||||||
|
|
||||||
|
lateinit var list: MutableList<DataClass>
|
||||||
|
|
||||||
|
const val TAG = "+++++++++++++++++++++"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate() {
|
||||||
|
super.onCreate()
|
||||||
|
appInstance = this
|
||||||
|
dealFile()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun dealFile() {
|
||||||
|
val openFile = appInstance.assets.open("data.json")
|
||||||
|
val jsonString = getJsonString(openFile)
|
||||||
|
if (jsonString != null) {
|
||||||
|
resolveJsonString(jsonString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun resolveJsonString(string: String) {
|
||||||
|
val jsonData = JSONArray(string)
|
||||||
|
var dataList: MutableList<DataClass> = mutableListOf()
|
||||||
|
for (i in 0 until jsonData.length()) {
|
||||||
|
jsonData.getJSONObject(i).run {
|
||||||
|
val pName = getString("parent_name")
|
||||||
|
val listArray = getJSONArray("keyboard_list")
|
||||||
|
var infoList: MutableList<Info> = 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 {
|
||||||
|
|
||||||
|
}
|
||||||
|
infoList.add(
|
||||||
|
Info().apply {
|
||||||
|
setImgPath(imgPath)
|
||||||
|
setZipPath(zipPath)
|
||||||
|
setTitleName(title)
|
||||||
|
setImgGif(imgGif)
|
||||||
|
thumbUrl = thUrl
|
||||||
|
thumbGif = thGif
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
val dataClass = DataClass()
|
||||||
|
.apply {
|
||||||
|
parentName = pName
|
||||||
|
keyboardList = infoList
|
||||||
|
}
|
||||||
|
dataList.add(dataClass)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateDataList(dataList)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateDataList(mainList: MutableList<DataClass>) {
|
||||||
|
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,27 @@
|
|||||||
|
package com.pretty.keyboard.theme.keyboard.bean;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class DataClass {
|
||||||
|
private String parentName;
|
||||||
|
|
||||||
|
private List<Info> keyboardList;
|
||||||
|
|
||||||
|
public String getParentName() {
|
||||||
|
|
||||||
|
return parentName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Info> getKeyboardList() {
|
||||||
|
|
||||||
|
return keyboardList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParentName(String name) {
|
||||||
|
this.parentName = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKeyboardList(List<Info> keyboardList) {
|
||||||
|
this.keyboardList = keyboardList;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
package com.pretty.keyboard.theme.keyboard.bean;
|
||||||
|
|
||||||
|
public class Info {
|
||||||
|
private String titleName;
|
||||||
|
|
||||||
|
private String thumbUrl;
|
||||||
|
|
||||||
|
private String thumbGif;
|
||||||
|
|
||||||
|
private String zipPath;
|
||||||
|
|
||||||
|
private String imgPath;
|
||||||
|
private String imgGif;
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
package com.pretty.keyboard.theme.keyboard.callback
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
interface ApplySkinListener {
|
||||||
|
|
||||||
|
fun OnApplySkinListener(fileList: List<File?>?)
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
package com.pretty.keyboard.theme.keyboard.callback
|
||||||
|
|
||||||
|
interface ItemClickListener {
|
||||||
|
|
||||||
|
fun OnItemClickListener( )
|
||||||
|
}
|
||||||
@ -0,0 +1,166 @@
|
|||||||
|
package com.pretty.keyboard.theme.keyboard.dialogfragment
|
||||||
|
|
||||||
|
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.pretty.keyboard.theme.keyboard.MyApp
|
||||||
|
import com.pretty.keyboard.theme.keyboard.R
|
||||||
|
import com.pretty.keyboard.theme.keyboard.databinding.DialogLayoutActiveBinding
|
||||||
|
import com.pretty.keyboard.theme.keyboard.utils.InputUtils
|
||||||
|
|
||||||
|
|
||||||
|
class ActiveDialog(private var clickAction: (clickPos: Int) -> Unit) : DialogFragment() {
|
||||||
|
|
||||||
|
private lateinit var vb: DialogLayoutActiveBinding
|
||||||
|
|
||||||
|
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 = DialogLayoutActiveBinding.inflate(layoutInflater)
|
||||||
|
context = MyApp.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 = InputUtils.checkEnable(MyApp.appInstance)
|
||||||
|
val checkSetDefault = InputUtils.checkSetDefault(MyApp.appInstance)
|
||||||
|
if (checkEnable && checkSetDefault) {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val clickType_home = 0
|
||||||
|
const val clickType_lock = 1
|
||||||
|
const val clickType_both = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,109 @@
|
|||||||
|
package com.pretty.keyboard.theme.keyboard.listadapter;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.TypedValue;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.pretty.keyboard.theme.keyboard.R;
|
||||||
|
import com.pretty.keyboard.theme.keyboard.bean.DataClass;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class AllAdapter extends RecyclerView.Adapter<AllAdapter.ViewAllTabViewHolder> {
|
||||||
|
|
||||||
|
private Context mContext;
|
||||||
|
private List<DataClass> viewAllList;
|
||||||
|
|
||||||
|
private OnChangListener mOnChangListener;
|
||||||
|
|
||||||
|
private int selectedPos = 0;
|
||||||
|
|
||||||
|
private int oldSelectedPos = -1;
|
||||||
|
|
||||||
|
public AllAdapter(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 AllAdapter.ViewAllTabViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
View view = LayoutInflater.from(mContext).inflate(R.layout.item_all_layout, parent, false);
|
||||||
|
return new AllAdapter.ViewAllTabViewHolder(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull AllAdapter.ViewAllTabViewHolder holder, int pos) {
|
||||||
|
DataClass dataClass = viewAllList.get(pos);
|
||||||
|
|
||||||
|
holder.tabTitle.setText(dataClass.getParentName().toUpperCase());
|
||||||
|
if (pos == selectedPos) {
|
||||||
|
holder.tabTitle.setTextColor(mContext.getColor(R.color.white));
|
||||||
|
holder.tabTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP,17);
|
||||||
|
holder.tabIndicator.setVisibility(View.VISIBLE);
|
||||||
|
} else {
|
||||||
|
holder.tabTitle.setTextColor(mContext.getColor(R.color.view_all_text_color));
|
||||||
|
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<DataClass> 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,127 @@
|
|||||||
|
package com.pretty.keyboard.theme.keyboard.listadapter;
|
||||||
|
|
||||||
|
|
||||||
|
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.pretty.keyboard.theme.keyboard.R;
|
||||||
|
import com.pretty.keyboard.theme.keyboard.callback.ItemClickListener;
|
||||||
|
import com.pretty.keyboard.theme.keyboard.bean.Info;
|
||||||
|
import com.pretty.keyboard.theme.keyboard.ui.ApplySkinActivity;
|
||||||
|
import com.bumptech.glide.Glide;
|
||||||
|
import com.pretty.keyboard.theme.keyboard.utils.Common;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class MainAdapter extends RecyclerView.Adapter<MainAdapter.ForYouViewHolder> {
|
||||||
|
|
||||||
|
private Context mContext;
|
||||||
|
private List<Info> mList;
|
||||||
|
|
||||||
|
private ItemClickListener mCallBack;
|
||||||
|
|
||||||
|
public MainAdapter(Context context) {
|
||||||
|
mContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setForYouList(List<Info> list) {
|
||||||
|
this.mList = list;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setClickAction(ItemClickListener callback) {
|
||||||
|
mCallBack = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ForYouViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
|
||||||
|
View view = LayoutInflater.from(mContext).inflate(R.layout.item_home_layout, parent, false);
|
||||||
|
return new ForYouViewHolder(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull ForYouViewHolder holder, int position) {
|
||||||
|
Info info = mList.get(position);
|
||||||
|
String thumbGif = info.getThumbGif();
|
||||||
|
String thumb = info.getThumbUrl();
|
||||||
|
if (!thumbGif.isEmpty()) {
|
||||||
|
Common.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, ApplySkinActivity.class);
|
||||||
|
intentApply.putExtra(ApplySkinActivity.DISPLAY_URL_KEY, info.getImgPath());
|
||||||
|
intentApply.putExtra(ApplySkinActivity.ZIP_URL_KEY, info.getZipPath());
|
||||||
|
intentApply.putExtra(ApplySkinActivity.NAME_KEY, info.getTitleName());
|
||||||
|
intentApply.putExtra(ApplySkinActivity.GIF_KEY, info.getImgGif());
|
||||||
|
String intent_thumb;
|
||||||
|
if (!thumbGif.isEmpty()) {
|
||||||
|
intent_thumb = thumbGif;
|
||||||
|
} else {
|
||||||
|
intent_thumb = thumb;
|
||||||
|
}
|
||||||
|
intentApply.putExtra(ApplySkinActivity.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.item_image);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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,111 @@
|
|||||||
|
package com.pretty.keyboard.theme.keyboard.ui
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.widget.ImageView
|
||||||
|
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 androidx.viewpager.widget.ViewPager.OnPageChangeListener
|
||||||
|
import com.pretty.keyboard.theme.keyboard.MyApp
|
||||||
|
import com.pretty.keyboard.theme.keyboard.R
|
||||||
|
import com.pretty.keyboard.theme.keyboard.bean.DataClass
|
||||||
|
import com.pretty.keyboard.theme.keyboard.listadapter.AllAdapter
|
||||||
|
import com.pretty.keyboard.theme.keyboard.utils.Common
|
||||||
|
|
||||||
|
class AllActivity : AppCompatActivity() {
|
||||||
|
private lateinit var tabRecycler: RecyclerView
|
||||||
|
private lateinit var viewContent: ViewPager
|
||||||
|
lateinit var viewAllList:MutableList<DataClass>
|
||||||
|
private lateinit var tabAdapter: AllAdapter
|
||||||
|
|
||||||
|
private lateinit var imgBack: ImageView
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.activity_layout_view_all)
|
||||||
|
Common.initFullScreen(this)
|
||||||
|
findViewId()
|
||||||
|
setTabRecycler()
|
||||||
|
setContent()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findViewId(){
|
||||||
|
tabRecycler = findViewById(R.id.tab_recycler)
|
||||||
|
viewContent = findViewById(R.id.view_pager_content)
|
||||||
|
imgBack = findViewById(R.id.back)
|
||||||
|
imgBack.setOnClickListener {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setTabRecycler(){
|
||||||
|
val first = MyApp.list.filter {
|
||||||
|
it.parentName == "for you"
|
||||||
|
}
|
||||||
|
val otherList = MyApp.list.filter {
|
||||||
|
it.parentName != "for you"
|
||||||
|
}
|
||||||
|
val shuffled = otherList.shuffled()
|
||||||
|
|
||||||
|
viewAllList = mutableListOf<DataClass>().apply {
|
||||||
|
add(first[0])
|
||||||
|
addAll(shuffled)
|
||||||
|
}
|
||||||
|
tabAdapter = AllAdapter(
|
||||||
|
this@AllActivity
|
||||||
|
).apply {
|
||||||
|
tabTitleName(viewAllList)
|
||||||
|
setChangeListener (object : AllAdapter.OnChangListener{
|
||||||
|
override fun onChange(posit: Int) {
|
||||||
|
viewContent.setCurrentItem(posit,false)
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
tabRecycler.run {
|
||||||
|
adapter = tabAdapter
|
||||||
|
layoutManager = LinearLayoutManager(this@AllActivity,RecyclerView.HORIZONTAL,false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setContent(){
|
||||||
|
val fragList = mutableListOf<Fragment>()
|
||||||
|
for(index in 0 until viewAllList.size){
|
||||||
|
fragList.add(FragmentHome.newInstance(index))
|
||||||
|
}
|
||||||
|
|
||||||
|
viewContent.adapter = object :FragmentStatePagerAdapter(supportFragmentManager,
|
||||||
|
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 :OnPageChangeListener{
|
||||||
|
override fun onPageScrolled(
|
||||||
|
position: Int,
|
||||||
|
positionOffset: Float,
|
||||||
|
positionOffsetPixels: Int
|
||||||
|
) {
|
||||||
|
if(curViewPager != position){
|
||||||
|
tabAdapter.setSelectedPos(position)
|
||||||
|
tabRecycler.scrollToPosition(position)
|
||||||
|
curViewPager = position
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPageSelected(position: Int) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPageScrollStateChanged(state: Int) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,291 @@
|
|||||||
|
package com.pretty.keyboard.theme.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.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.pretty.keyboard.theme.keyboard.MyApp
|
||||||
|
import com.pretty.keyboard.theme.keyboard.R
|
||||||
|
import com.pretty.keyboard.theme.keyboard.callback.ApplySkinListener
|
||||||
|
import com.pretty.keyboard.theme.keyboard.callback.ItemClickListener
|
||||||
|
import com.pretty.keyboard.theme.keyboard.dialogfragment.ActiveDialog
|
||||||
|
import com.pretty.keyboard.theme.keyboard.listadapter.MainAdapter
|
||||||
|
import com.pretty.keyboard.theme.keyboard.utils.Common
|
||||||
|
import com.pretty.keyboard.theme.keyboard.utils.DownloadUtils
|
||||||
|
import com.pretty.keyboard.theme.keyboard.utils.InputUtils
|
||||||
|
import com.pretty.keyboard.theme.keyboard.utils.Save
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class ApplySkinActivity : 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"
|
||||||
|
}
|
||||||
|
|
||||||
|
private var dialog: ActiveDialog? = 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
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.activity_layout_apply)
|
||||||
|
Common.initFullScreen(this)
|
||||||
|
|
||||||
|
findViewId()
|
||||||
|
getExtraData()
|
||||||
|
displayData()
|
||||||
|
setApply()
|
||||||
|
onClick()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun getExtraData() {
|
||||||
|
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 = DownloadUtils.getServiceZipName(zipUrl)
|
||||||
|
unzipPath = DownloadUtils.getUnzipPath(serviceZipName)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
viewAllLayout.setOnClickListener {
|
||||||
|
startActivity(Intent(this, AllActivity::class.java))
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
val forYouList = MyApp.list.filter {
|
||||||
|
it.parentName == "for you"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
recommendedRecycler.run {
|
||||||
|
adapter = MainAdapter(
|
||||||
|
this@ApplySkinActivity
|
||||||
|
).apply {
|
||||||
|
val shuffled = forYouList[0].keyboardList.shuffled()
|
||||||
|
setForYouList(shuffled)
|
||||||
|
}.apply {
|
||||||
|
setClickAction(object : ItemClickListener {
|
||||||
|
override fun OnItemClickListener() {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
layoutManager = GridLayoutManager(this@ApplySkinActivity, 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 = InputUtils.checkEnable(this)
|
||||||
|
val checkSetDefault = InputUtils.checkSetDefault(this)
|
||||||
|
if (!checkEnable || !checkSetDefault) {
|
||||||
|
showDialog()
|
||||||
|
return@setOnClickListener
|
||||||
|
}
|
||||||
|
startDown()
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showDialog() {
|
||||||
|
dialog = dialog ?: ActiveDialog {
|
||||||
|
|
||||||
|
}
|
||||||
|
dialog?.show(supportFragmentManager, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startDown() {
|
||||||
|
loadingLayout.isVisible = true
|
||||||
|
applyBtn.isEnabled = false
|
||||||
|
|
||||||
|
val file = File(unzipPath)
|
||||||
|
if (file.exists()) {
|
||||||
|
val findFirstDirectory = DownloadUtils.findFirstDirectory(file)
|
||||||
|
|
||||||
|
Log.d(
|
||||||
|
MyApp.TAG,
|
||||||
|
"-----findFirstDirectory=$findFirstDirectory"
|
||||||
|
)
|
||||||
|
apply("${findFirstDirectory}/")
|
||||||
|
applyBtn.isEnabled = true
|
||||||
|
loadingLayout.isVisible = false
|
||||||
|
} else {
|
||||||
|
DownloadUtils.startDownloadZip(zipUrl, object : ApplySkinListener {
|
||||||
|
override fun OnApplySkinListener(fileList: List<File?>?) {
|
||||||
|
runOnUiThread {
|
||||||
|
applyBtn.isEnabled = true
|
||||||
|
loadingLayout.isVisible = false
|
||||||
|
}
|
||||||
|
if (fileList.isNullOrEmpty()) {
|
||||||
|
runOnUiThread {
|
||||||
|
Toast.makeText(
|
||||||
|
this@ApplySkinActivity,
|
||||||
|
getString(R.string.download_fail),
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fileList[0]?.path?.let {
|
||||||
|
runOnUiThread {
|
||||||
|
apply(it)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun apply(path: String) {
|
||||||
|
var skinParentPath = path
|
||||||
|
if (path.contains("res")) {
|
||||||
|
skinParentPath = path.substringBeforeLast("res")
|
||||||
|
}
|
||||||
|
Save.updateSkinPath(skinParentPath)
|
||||||
|
Toast.makeText(
|
||||||
|
this@ApplySkinActivity,
|
||||||
|
getString(R.string.theme_application_successful),
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
startActivity(Intent(this, SuccessActivity::class.java).apply {
|
||||||
|
putExtra(SuccessActivity.key_name, name)
|
||||||
|
})
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,61 @@
|
|||||||
|
package com.pretty.keyboard.theme.keyboard.ui
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.pretty.keyboard.theme.keyboard.R
|
||||||
|
import com.pretty.keyboard.theme.keyboard.listadapter.MainAdapter
|
||||||
|
|
||||||
|
private const val ARG_PARAM1 = "list_index"
|
||||||
|
|
||||||
|
class FragmentHome : Fragment() {
|
||||||
|
|
||||||
|
private var paramIndex: Int = 0
|
||||||
|
private lateinit var contentRecy:RecyclerView
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
arguments?.let {
|
||||||
|
paramIndex = it.getInt(ARG_PARAM1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun newInstance(index: Int) =
|
||||||
|
FragmentHome().apply {
|
||||||
|
arguments = Bundle().apply {
|
||||||
|
putInt(ARG_PARAM1, index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View? {
|
||||||
|
val viewMain = inflater.inflate(R.layout.fragment_layout_home, container, false)
|
||||||
|
contentRecy = viewMain.findViewById(R.id.content_recycler)
|
||||||
|
initContent()
|
||||||
|
return viewMain
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initContent(){
|
||||||
|
val allActivity = requireActivity() as AllActivity
|
||||||
|
val mainBean = allActivity.viewAllList[paramIndex]
|
||||||
|
contentRecy.run {
|
||||||
|
this.adapter = MainAdapter(
|
||||||
|
requireContext()
|
||||||
|
).apply {
|
||||||
|
val shufflList = mainBean.keyboardList.shuffled()
|
||||||
|
setForYouList(shufflList)
|
||||||
|
}
|
||||||
|
this.layoutManager = GridLayoutManager(requireContext(),2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,155 @@
|
|||||||
|
package com.pretty.keyboard.theme.keyboard.ui
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.cardview.widget.CardView
|
||||||
|
import androidx.core.view.GravityCompat
|
||||||
|
import androidx.drawerlayout.widget.DrawerLayout
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.pretty.keyboard.theme.keyboard.MyApp
|
||||||
|
import com.pretty.keyboard.theme.keyboard.R
|
||||||
|
import com.pretty.keyboard.theme.keyboard.bean.Info
|
||||||
|
import com.pretty.keyboard.theme.keyboard.dialogfragment.ActiveDialog
|
||||||
|
import com.pretty.keyboard.theme.keyboard.listadapter.MainAdapter
|
||||||
|
import com.pretty.keyboard.theme.keyboard.utils.Common
|
||||||
|
import com.pretty.keyboard.theme.keyboard.utils.Common.loadWepJif
|
||||||
|
import com.pretty.keyboard.theme.keyboard.utils.InputUtils
|
||||||
|
|
||||||
|
class HomeActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
private lateinit var forYouRecycler: RecyclerView
|
||||||
|
private lateinit var viewAllLayout: LinearLayout
|
||||||
|
|
||||||
|
private lateinit var menuView: ImageView
|
||||||
|
private lateinit var drawView: DrawerLayout
|
||||||
|
|
||||||
|
private lateinit var keySetting: LinearLayout
|
||||||
|
private lateinit var layoutRate: LinearLayout
|
||||||
|
private lateinit var layoutPrivacy: LinearLayout
|
||||||
|
|
||||||
|
private lateinit var cardView:CardView
|
||||||
|
private lateinit var banner:ImageView
|
||||||
|
|
||||||
|
private var dialog: ActiveDialog?= null
|
||||||
|
|
||||||
|
private var bannerInfo:Info ? = null
|
||||||
|
|
||||||
|
@SuppressLint("MissingInflatedId")
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.activity_layout_home)
|
||||||
|
Common.initFullScreen(this)
|
||||||
|
findViewId()
|
||||||
|
initDialog()
|
||||||
|
loadBanner()
|
||||||
|
setForYouData()
|
||||||
|
onClick()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findViewId() {
|
||||||
|
forYouRecycler = findViewById(R.id.for_you_recycler)
|
||||||
|
viewAllLayout = findViewById(R.id.layout_view_all)
|
||||||
|
menuView = findViewById(R.id.imageMenu)
|
||||||
|
drawView = findViewById(R.id.drawLayout)
|
||||||
|
keySetting = findViewById(R.id.layout_keyboard_setting)
|
||||||
|
layoutRate = findViewById(R.id.layout_rate)
|
||||||
|
layoutPrivacy = findViewById(R.id.layout_privacy)
|
||||||
|
cardView = findViewById(R.id.card_banner)
|
||||||
|
|
||||||
|
banner = findViewById(R.id.image_banner)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun initDialog(){
|
||||||
|
val checkEnable = InputUtils.checkEnable(MyApp.appInstance)
|
||||||
|
val checkSetDefault = InputUtils.checkSetDefault(MyApp.appInstance)
|
||||||
|
if(!checkEnable||!checkSetDefault){
|
||||||
|
dialog = dialog?: ActiveDialog {
|
||||||
|
|
||||||
|
}
|
||||||
|
dialog?.show(supportFragmentManager,"")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onClick() {
|
||||||
|
cardView.setOnClickListener {
|
||||||
|
if(bannerInfo == null){
|
||||||
|
|
||||||
|
return@setOnClickListener
|
||||||
|
}
|
||||||
|
val intentApply = Intent(this, ApplySkinActivity::class.java)
|
||||||
|
intentApply.putExtra(ApplySkinActivity.DISPLAY_URL_KEY, bannerInfo!!.imgPath)
|
||||||
|
intentApply.putExtra(ApplySkinActivity.ZIP_URL_KEY, bannerInfo!!.zipPath)
|
||||||
|
intentApply.putExtra(ApplySkinActivity.NAME_KEY, bannerInfo!!.titleName)
|
||||||
|
intentApply.putExtra(ApplySkinActivity.GIF_KEY, bannerInfo!!.imgGif)
|
||||||
|
if(!bannerInfo!!.thumbGif.isNullOrEmpty()){
|
||||||
|
intentApply.putExtra(ApplySkinActivity.THUMB_KEY,bannerInfo!!.thumbGif)
|
||||||
|
}else{
|
||||||
|
intentApply.putExtra(ApplySkinActivity.THUMB_KEY,bannerInfo!!.thumbUrl)
|
||||||
|
}
|
||||||
|
startActivity(intentApply)
|
||||||
|
}
|
||||||
|
viewAllLayout.setOnClickListener {
|
||||||
|
startActivity(Intent(this, AllActivity::class.java))
|
||||||
|
}
|
||||||
|
menuView.setOnClickListener {
|
||||||
|
drawView.openDrawer(GravityCompat.END)
|
||||||
|
}
|
||||||
|
|
||||||
|
layoutRate.setOnClickListener {
|
||||||
|
val intent = Intent(Intent.ACTION_VIEW)
|
||||||
|
intent.data = Uri.parse(getString(R.string.app_google_play)+packageName)
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
layoutPrivacy.setOnClickListener {
|
||||||
|
val intent = Intent(Intent.ACTION_VIEW)
|
||||||
|
intent.data = Uri.parse(getString(R.string.app_privacy_path))
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setForYouData() {
|
||||||
|
val forYouList = MyApp.list.filter {
|
||||||
|
it.parentName == "for you"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
forYouRecycler.run {
|
||||||
|
adapter = MainAdapter(
|
||||||
|
this@HomeActivity
|
||||||
|
).apply {
|
||||||
|
val keyboardList = forYouList[0].keyboardList.shuffled()
|
||||||
|
setForYouList(keyboardList)
|
||||||
|
}
|
||||||
|
layoutManager = GridLayoutManager(this@HomeActivity, 2)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadBanner(){
|
||||||
|
val dataClass = MyApp.list.shuffled()[0]
|
||||||
|
bannerInfo = dataClass.keyboardList.shuffled()[0]
|
||||||
|
|
||||||
|
val thumbGif = bannerInfo?.thumbGif
|
||||||
|
val thumb = bannerInfo?.thumbUrl
|
||||||
|
if (thumbGif != null) {
|
||||||
|
if (thumbGif.isNotEmpty()) {
|
||||||
|
loadWepJif(this, thumbGif, banner)
|
||||||
|
} else if(!thumb.isNullOrEmpty()){
|
||||||
|
Glide.with(this).load(thumb).into(banner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,118 @@
|
|||||||
|
package com.pretty.keyboard.theme.keyboard.ui
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.IntentFilter
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.provider.Settings
|
||||||
|
import android.view.inputmethod.InputMethodManager
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import com.pretty.keyboard.theme.keyboard.R
|
||||||
|
import com.pretty.keyboard.theme.keyboard.utils.Common
|
||||||
|
import com.pretty.keyboard.theme.keyboard.utils.InputUtils
|
||||||
|
|
||||||
|
class SettingActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
private lateinit var layoutStepOne: LinearLayout
|
||||||
|
private lateinit var imgBack: ImageView
|
||||||
|
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
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.dialog_layout_active)
|
||||||
|
Common.initFullScreen(this)
|
||||||
|
findViewId()
|
||||||
|
onViewStep()
|
||||||
|
getReceiver()
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("SuspiciousIndentation")
|
||||||
|
private fun findViewId() {
|
||||||
|
layoutStepOne = findViewById<LinearLayout>(R.id.linear_step_one)
|
||||||
|
layoutStepTwo = findViewById<LinearLayout>(R.id.linear_step_two)
|
||||||
|
imgBack = findViewById(R.id.back)
|
||||||
|
imgStepOkOne = findViewById(R.id.ok_one)
|
||||||
|
imgStepOkTwo = findViewById(R.id.ok_two)
|
||||||
|
stepOne= findViewById(R.id.text_step_one)
|
||||||
|
stepTwo= findViewById(R.id.text_step_two)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onViewStep(){
|
||||||
|
imgBack.setOnClickListener {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
layoutStepOne.setOnClickListener {
|
||||||
|
startActivity(Intent(Settings.ACTION_INPUT_METHOD_SETTINGS))
|
||||||
|
}
|
||||||
|
layoutStepTwo.setOnClickListener {
|
||||||
|
val inputMethodManager = this.getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
|
||||||
|
inputMethodManager.showInputMethodPicker()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
registerReceiver(myreceiver,intentFilter)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateUI(){
|
||||||
|
|
||||||
|
val checkEnable = InputUtils.checkEnable(this)
|
||||||
|
val checkSetDefault = InputUtils.checkSetDefault(this)
|
||||||
|
if(checkEnable){
|
||||||
|
layoutStepOne.isEnabled =false
|
||||||
|
layoutStepOne.isSelected = true
|
||||||
|
imgStepOkOne.isVisible = true
|
||||||
|
stepOne.setTextColor(getColor(R.color.step_true))
|
||||||
|
}else{
|
||||||
|
layoutStepOne.isEnabled =true
|
||||||
|
layoutStepOne.isSelected = false
|
||||||
|
imgStepOkOne.isVisible = false
|
||||||
|
stepOne.setTextColor(getColor(R.color.white))
|
||||||
|
}
|
||||||
|
|
||||||
|
if(checkSetDefault){
|
||||||
|
layoutStepTwo.isEnabled =false
|
||||||
|
layoutStepTwo.isSelected = true
|
||||||
|
imgStepOkTwo.isVisible = true
|
||||||
|
stepTwo.setTextColor(getColor(R.color.step_true))
|
||||||
|
}else{
|
||||||
|
layoutStepTwo.isEnabled =true
|
||||||
|
layoutStepTwo.isSelected = false
|
||||||
|
imgStepOkTwo.isVisible = false
|
||||||
|
stepTwo.setTextColor(getColor(R.color.white))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
if(myreceiver != null){
|
||||||
|
unregisterReceiver(myreceiver)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,120 @@
|
|||||||
|
package com.pretty.keyboard.theme.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.pretty.keyboard.theme.keyboard.databinding.ActivitySuccessBinding;
|
||||||
|
import com.pretty.keyboard.theme.keyboard.utils.Common;
|
||||||
|
import com.pretty.keyboard.theme.keyboard.utils.Save;
|
||||||
|
import com.pretty.keyboard.theme.keyboard.view.Codes;
|
||||||
|
|
||||||
|
import jp.wasabeef.glide.transformations.BlurTransformation;
|
||||||
|
|
||||||
|
|
||||||
|
public class SuccessActivity extends AppCompatActivity {
|
||||||
|
private ActivitySuccessBinding vb;
|
||||||
|
public static String key_name = "key_name";
|
||||||
|
private int mPreviousKeyboardHeight = -1;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
Common.INSTANCE.initFullScreen(this);
|
||||||
|
vb = ActivitySuccessBinding.inflate(getLayoutInflater());
|
||||||
|
setContentView(vb.getRoot());
|
||||||
|
Common.INSTANCE.initFullScreen(this);
|
||||||
|
onInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void onInit() {
|
||||||
|
|
||||||
|
String stringExtra = getIntent().getStringExtra(key_name);
|
||||||
|
vb.title.setText(stringExtra);
|
||||||
|
|
||||||
|
String curPath = Save.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/"+ Codes.previewBg;
|
||||||
|
|
||||||
|
Drawable bgDraw = Common.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);
|
||||||
|
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,63 @@
|
|||||||
|
package com.pretty.keyboard.theme.keyboard.ui
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.CountDownTimer
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.ProgressBar
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import com.pretty.keyboard.theme.keyboard.R
|
||||||
|
import com.pretty.keyboard.theme.keyboard.utils.Common
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
class WelActivity : 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.activity_layout_wel)
|
||||||
|
Common.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, HomeActivity::class.java))
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
timer.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,65 @@
|
|||||||
|
package com.pretty.keyboard.theme.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.view.View
|
||||||
|
import android.view.WindowManager
|
||||||
|
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 java.io.File
|
||||||
|
|
||||||
|
object Common {
|
||||||
|
fun initFullScreen(activity: Activity) {
|
||||||
|
val window = activity.window
|
||||||
|
val decorView = window.decorView
|
||||||
|
val rootView = decorView.rootView
|
||||||
|
|
||||||
|
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR)
|
||||||
|
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
|
||||||
|
// mView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
|
||||||
|
rootView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,197 @@
|
|||||||
|
package com.pretty.keyboard.theme.keyboard.utils;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.pretty.keyboard.theme.keyboard.MyApp;
|
||||||
|
import com.pretty.keyboard.theme.keyboard.callback.ApplySkinListener;
|
||||||
|
|
||||||
|
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 DownloadUtils {
|
||||||
|
|
||||||
|
public static void startDownloadZip(String zipPath, ApplySkinListener 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, ApplySkinListener callback) {
|
||||||
|
File zipfFile = new File(MyApp.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 MyApp.appInstance.getFilesDir().getPath() + "/" + replace;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void un7ZZipFile(File saveZipFile, ApplySkinListener 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
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
package com.pretty.keyboard.theme.keyboard.utils;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.provider.Settings;
|
||||||
|
import android.view.inputmethod.InputMethodInfo;
|
||||||
|
import android.view.inputmethod.InputMethodManager;
|
||||||
|
|
||||||
|
import com.pretty.keyboard.theme.keyboard.MyApp;
|
||||||
|
|
||||||
|
public class InputUtils {
|
||||||
|
private static Object systemService = MyApp.appInstance.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||||
|
private static InputMethodManager inputMethodManager = (InputMethodManager) systemService;
|
||||||
|
public static boolean checkSetDefault(Context con){
|
||||||
|
String defaultId = Settings.Secure.getString(con.getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
|
||||||
|
if(defaultId != null && defaultId.startsWith(con.getPackageName())){
|
||||||
|
return true;
|
||||||
|
}else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean checkEnable(Context con){
|
||||||
|
for (InputMethodInfo methodInfo : inputMethodManager.getEnabledInputMethodList()) {
|
||||||
|
if(methodInfo.getId().startsWith(con.getPackageName())){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
package com.pretty.keyboard.theme.keyboard.utils
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import com.pretty.keyboard.theme.keyboard.MyApp
|
||||||
|
|
||||||
|
object Save {
|
||||||
|
|
||||||
|
val SP_NAME = "keyboard_skin"
|
||||||
|
val SKIN_PATH = "skin_path"
|
||||||
|
val spSkin = MyApp.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,59 @@
|
|||||||
|
package com.pretty.keyboard.theme.keyboard.view
|
||||||
|
|
||||||
|
object Codes {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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,239 @@
|
|||||||
|
package com.pretty.keyboard.theme.keyboard.view;
|
||||||
|
|
||||||
|
|
||||||
|
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.SurfaceView;
|
||||||
|
|
||||||
|
import androidx.core.graphics.drawable.DrawableCompat;
|
||||||
|
|
||||||
|
import com.pretty.keyboard.theme.keyboard.R;
|
||||||
|
import com.pretty.keyboard.theme.keyboard.view.keyboard.CusKeyBoard;
|
||||||
|
import com.pretty.keyboard.theme.keyboard.view.keyboard.CusKeyBoardView;
|
||||||
|
|
||||||
|
|
||||||
|
public class CustomInputView 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 SkinParmeter skinParmeter;
|
||||||
|
|
||||||
|
public CustomInputView(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
mContext = context;
|
||||||
|
setAttribute(attrs, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomInputView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
mContext = context;
|
||||||
|
setAttribute(attrs, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomInputView(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() {
|
||||||
|
skinParmeter.updateSkinConfig();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initPaint() {
|
||||||
|
mPaint = new Paint();
|
||||||
|
mPaint.setAntiAlias(true);
|
||||||
|
mPaint.setTextAlign(Paint.Align.CENTER);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setAttribute(AttributeSet attrs, Context con) {
|
||||||
|
skinParmeter = new SkinParmeter(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 Codes.KEY_CODE_SHIFT:
|
||||||
|
drawAllShift(curKey, canvas);
|
||||||
|
break;
|
||||||
|
case Codes.KEY_CODE_NUMBER_SHIFT:
|
||||||
|
onDrawCurKey(curKey, canvas, "More", skinParmeter.getFunctionDraw(), null);
|
||||||
|
break;
|
||||||
|
case Codes.KEY_CODE_DELETE:
|
||||||
|
onDrawCurKey(curKey, canvas, "Delete", skinParmeter.getFunctionDraw(),null);
|
||||||
|
break;
|
||||||
|
case Codes.KEY_CODE_SYMBOL_SHIFT:
|
||||||
|
onDrawCurKey(curKey, canvas, "123", skinParmeter.getFunctionDraw(), null);
|
||||||
|
break;
|
||||||
|
case Codes.KEY_CODE_CHANGE_NUMBER:
|
||||||
|
onDrawCurKey(curKey, canvas, null, skinParmeter.getToDraw(), null);
|
||||||
|
break;
|
||||||
|
case Codes.KEY_CODE_BACK:
|
||||||
|
onDrawCurKey(curKey, canvas, "Back", skinParmeter.getToDraw(), null);
|
||||||
|
break;
|
||||||
|
case Codes.KEY_CODE_SPACE:
|
||||||
|
onDrawCurKey(curKey, canvas, null, skinParmeter.getSpaceDraw(), null);
|
||||||
|
break;
|
||||||
|
case Codes.KEY_CODE_COMPLETE:
|
||||||
|
onDrawCurKey(curKey, canvas, "Done", skinParmeter.getFunctionDraw(), null);
|
||||||
|
break;
|
||||||
|
case Codes.KEY_CODE_CANCEL:
|
||||||
|
onDrawCurKey(curKey, canvas, "Done", skinParmeter.getFunctionDraw(), null);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
|
||||||
|
onDrawCurKey(curKey, canvas, null, skinParmeter.getGeneralDraw(), null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawAllShift(CusKeyBoard.Key curKey, Canvas canvas) {
|
||||||
|
if (isLowerCase == 0) {
|
||||||
|
onDrawCurKey(curKey, canvas, "Shift", skinParmeter.getFunctionDraw(), null);
|
||||||
|
} else if (isLowerCase == 1) {
|
||||||
|
onDrawCurKey(curKey, canvas, "Shift", skinParmeter.getFunctionDraw(),null);
|
||||||
|
} else if(isLowerCase == 2){
|
||||||
|
onDrawCurKey(curKey, canvas, "Shift", skinParmeter.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(skinParmeter.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,288 @@
|
|||||||
|
package com.pretty.keyboard.theme.keyboard.view;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.inputmethodservice.InputMethodService;
|
||||||
|
|
||||||
|
import android.media.MediaPlayer;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.SurfaceView;
|
||||||
|
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.pretty.keyboard.theme.keyboard.MyApp;
|
||||||
|
import com.pretty.keyboard.theme.keyboard.R;
|
||||||
|
import com.pretty.keyboard.theme.keyboard.utils.Save;
|
||||||
|
import com.pretty.keyboard.theme.keyboard.view.keyboard.CusKeyBoard;
|
||||||
|
import com.pretty.keyboard.theme.keyboard.view.keyboard.CusKeyBoardView;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import kotlin.Unit;
|
||||||
|
import kotlin.jvm.functions.Function2;
|
||||||
|
|
||||||
|
public class InputService extends InputMethodService implements CusKeyBoardView.OnKeyboardActionListener {
|
||||||
|
|
||||||
|
|
||||||
|
private CustomInputView customInputView;
|
||||||
|
private CusKeyBoard mKeyBoard;
|
||||||
|
private View parentView;
|
||||||
|
|
||||||
|
|
||||||
|
private ImageView imBG;
|
||||||
|
private VideoView videoView;
|
||||||
|
|
||||||
|
private int a = R.xml.a;
|
||||||
|
private int b= R.xml.b;
|
||||||
|
private int c = R.xml.c;
|
||||||
|
|
||||||
|
@SuppressLint("InflateParams")
|
||||||
|
@Override
|
||||||
|
public View onCreateInputView() {
|
||||||
|
parentView = getLayoutInflater().inflate(R.layout.custome_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);
|
||||||
|
customInputView = parentView.findViewById(R.id.custom_input_view);
|
||||||
|
customInputView.setEnabled(true);
|
||||||
|
customInputView.setPreviewEnabled(false);
|
||||||
|
customInputView.setKeyboard(mKeyBoard);
|
||||||
|
customInputView.setOnKeyboardActionListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onWindowHidden() {
|
||||||
|
super.onWindowHidden();
|
||||||
|
if(videoView.isPlaying()){
|
||||||
|
videoView.pause();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onWindowShown() {
|
||||||
|
super.onWindowShown();
|
||||||
|
String skinPath = Save.INSTANCE.getSkinPath();
|
||||||
|
if(skinPath == null || skinPath.isEmpty()){
|
||||||
|
customInputView.updateUi();
|
||||||
|
}else {
|
||||||
|
KeyAction.INSTANCE.readBgOrVideo(this, new Function2<String, Drawable, Unit>() {
|
||||||
|
@Override
|
||||||
|
public Unit invoke(String s, Drawable drawable) {
|
||||||
|
if (s != null) {
|
||||||
|
// curMediaPlayer = mediaPlayer;
|
||||||
|
// curMediaPlayer.start();
|
||||||
|
customInputView.setBackground(null);
|
||||||
|
if(s.endsWith(".gif")){
|
||||||
|
imBG.setVisibility(View.VISIBLE);
|
||||||
|
videoView.setVisibility(View.GONE);
|
||||||
|
Glide.with(InputService.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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
|
||||||
|
// @Override
|
||||||
|
// public void onCompletion(MediaPlayer mp) {
|
||||||
|
// videoView.start();
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
customInputView.setBackground(drawable);
|
||||||
|
}
|
||||||
|
customInputView.updateUi();
|
||||||
|
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 Codes.KEY_CODE_DELETE:
|
||||||
|
curInputConnect.deleteSurroundingText(1, 0);
|
||||||
|
break;
|
||||||
|
case Codes.KEY_CODE_SHIFT:
|
||||||
|
switchShift();
|
||||||
|
break;
|
||||||
|
case Codes.KEY_CODE_NUMBER_SHIFT:
|
||||||
|
case Codes.KEY_CODE_SYMBOL_SHIFT:
|
||||||
|
switchMoreOrNumber();
|
||||||
|
break;
|
||||||
|
case Codes.KEY_CODE_CHANGE_NUMBER:
|
||||||
|
case Codes.KEY_CODE_BACK:
|
||||||
|
switchNormalOrNumber();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Codes.KEY_CODE_COMPLETE:
|
||||||
|
case Codes.KEY_CODE_CANCEL:
|
||||||
|
curInputConnect.performEditorAction(EditorInfo.IME_ACTION_DONE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
String codeToChar = KeyAction.INSTANCE.primaryCodeToChar(primaryCode);
|
||||||
|
curInputConnect.commitText(codeToChar, 1);
|
||||||
|
if (customInputView.isLowerCase() == 1) {
|
||||||
|
//自动转小写
|
||||||
|
customInputView.setLowerCase(0);
|
||||||
|
KeyAction.INSTANCE.keyToLowerCase(mKeyBoard);
|
||||||
|
customInputView.setKeyboard(mKeyBoard);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void switchMoreOrNumber() {
|
||||||
|
int mode = customInputView.getMode();
|
||||||
|
switch (mode) {
|
||||||
|
case 1:
|
||||||
|
mKeyBoard = new CusKeyBoard(this, c);
|
||||||
|
customInputView.setMode(2);
|
||||||
|
customInputView.setKeyboard(mKeyBoard);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
mKeyBoard = new CusKeyBoard(this, b);
|
||||||
|
customInputView.setMode(1);
|
||||||
|
customInputView.setKeyboard(mKeyBoard);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void switchNormalOrNumber() {
|
||||||
|
int mode = customInputView.getMode();
|
||||||
|
switch (mode) {
|
||||||
|
case 0:
|
||||||
|
mKeyBoard = new CusKeyBoard(this, b);
|
||||||
|
customInputView.setMode(1);
|
||||||
|
customInputView.setKeyboard(mKeyBoard);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
mKeyBoard = new CusKeyBoard(this, a);
|
||||||
|
customInputView.setMode(0);
|
||||||
|
customInputView.setKeyboard(mKeyBoard);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void switchShift() {
|
||||||
|
int lowerCase = customInputView.isLowerCase();
|
||||||
|
switch (lowerCase) {
|
||||||
|
case 0:
|
||||||
|
//当前小写转大写
|
||||||
|
customInputView.setLowerCase(1);
|
||||||
|
KeyAction.INSTANCE.keyToUpper(mKeyBoard);
|
||||||
|
customInputView.setKeyboard(mKeyBoard);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
//当前大写转锁定大写
|
||||||
|
customInputView.setLowerCase(2);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
//当前锁定大写转小写
|
||||||
|
customInputView.setLowerCase(0);
|
||||||
|
KeyAction.INSTANCE.keyToLowerCase(mKeyBoard);
|
||||||
|
customInputView.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,93 @@
|
|||||||
|
package com.pretty.keyboard.theme.keyboard.view
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.BitmapFactory
|
||||||
|
import android.graphics.drawable.BitmapDrawable
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
|
//import android.inputmethodservice.Keyboard
|
||||||
|
import android.media.MediaPlayer
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.SurfaceHolder
|
||||||
|
import android.view.SurfaceView
|
||||||
|
import com.pretty.keyboard.theme.keyboard.MyApp
|
||||||
|
import com.pretty.keyboard.theme.keyboard.utils.Save
|
||||||
|
import com.pretty.keyboard.theme.keyboard.view.keyboard.CusKeyBoard
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
object KeyAction {
|
||||||
|
|
||||||
|
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
|
||||||
|
) {
|
||||||
|
|
||||||
|
Save.getSkinPath()?.let { resPath ->
|
||||||
|
val videoPath = "${resPath}res/raw/${Codes.videoName}"
|
||||||
|
val videoPath2 = "${resPath}res/raw/${Codes.video}"
|
||||||
|
val backgroundPath = "${resPath}res/drawable-xxhdpi-v4/${Codes.bgName}"
|
||||||
|
val file = File(videoPath)
|
||||||
|
val file2 = File(videoPath2)
|
||||||
|
if (file.exists()||file2.exists()) {
|
||||||
|
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{
|
||||||
|
|
||||||
|
val bitmapDrawable = BitmapDrawable(context.resources, BitmapFactory.decodeFile(backgroundPath))
|
||||||
|
|
||||||
|
playAction.invoke(null,bitmapDrawable)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,152 @@
|
|||||||
|
package com.pretty.keyboard.theme.keyboard.view
|
||||||
|
|
||||||
|
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 android.view.SurfaceView
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import com.pretty.keyboard.theme.keyboard.MyApp
|
||||||
|
import com.pretty.keyboard.theme.keyboard.R
|
||||||
|
import com.pretty.keyboard.theme.keyboard.utils.Save
|
||||||
|
import org.xmlpull.v1.XmlPullParser
|
||||||
|
import java.io.File
|
||||||
|
import java.io.StringReader
|
||||||
|
|
||||||
|
class SkinParmeter(var context: Context) {
|
||||||
|
|
||||||
|
|
||||||
|
private var textSize = 13f
|
||||||
|
|
||||||
|
var functionDraw: Drawable = getDefaultDrawList(R.mipmap.key_normal,R.mipmap.key_pressed_on)
|
||||||
|
var generalDraw: Drawable = getDefaultDrawList(R.mipmap.key_normal,R.mipmap.key_pressed_on)
|
||||||
|
|
||||||
|
var toDraw: Drawable = getDefaultDrawList(R.mipmap.key_normal,R.mipmap.key_pressed_on)
|
||||||
|
var spaceDraw: Drawable = getDefaultDrawList(R.mipmap.key_normal,R.mipmap.key_pressed_on)
|
||||||
|
|
||||||
|
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() {
|
||||||
|
Save.getSkinPath()?.let { resPath ->
|
||||||
|
val pPath = "${resPath}res/drawable-xhdpi-v4/"
|
||||||
|
pPath.let {
|
||||||
|
readColors(resPath) {
|
||||||
|
for ((name, value) in it) {
|
||||||
|
if (name == Codes.keyTextColorName) {
|
||||||
|
keyTextColor = value
|
||||||
|
}
|
||||||
|
if (name == Codes.keyTextColorFunctionName) {
|
||||||
|
keyTextColorFunction = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
functionDraw = getDrawList(
|
||||||
|
it + Codes.functionNormalName,
|
||||||
|
it + Codes.functionPressName
|
||||||
|
)
|
||||||
|
generalDraw = getDrawList(it + Codes.normalName, it + Codes.pressName)
|
||||||
|
toDraw = getDrawList(it + Codes.toNormalName, it + Codes.toPressName)
|
||||||
|
spaceDraw =
|
||||||
|
getDrawList(it + Codes.spaceNormalName, it + Codes.spacePressName)
|
||||||
|
switchDraw =
|
||||||
|
getDrawList(it + Codes.imeSwitchName, it + Codes.imeSwitchName)
|
||||||
|
deleteDraw = getDrawList(
|
||||||
|
it + Codes.deleteNormalName,
|
||||||
|
it + Codes.deletePressName
|
||||||
|
)
|
||||||
|
backDraw = getDrawList(it + Codes.backName, it + Codes.backName)
|
||||||
|
searchDraw = getDrawList(it + Codes.searchName, it + Codes.searchName)
|
||||||
|
shiftDraw = getDrawList(
|
||||||
|
it + Codes.shiftNormalName,
|
||||||
|
it + Codes.shiftNormalName
|
||||||
|
)
|
||||||
|
shiftLockDraw =
|
||||||
|
getDrawList(it + Codes.shiftLockName, it + Codes.shiftLockName)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun getDefaultDrawList(normalDrawId: Int, pressDrawId: Int): StateListDrawable {
|
||||||
|
val normalDraw = ContextCompat.getDrawable(MyApp.appInstance,normalDrawId )
|
||||||
|
val pressDraw = ContextCompat.getDrawable(MyApp.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 == Codes.keyTextColorName
|
||||||
|
val b4 = attributeName == Codes.keyTextColorFunctionName
|
||||||
|
if (b3 || b4) {
|
||||||
|
resMaps[attributeName] = Color.parseColor(nextTextValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
curType = xmlPullParser.next()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
callBack.invoke(resMaps)
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,859 @@
|
|||||||
|
package com.pretty.keyboard.theme.keyboard.view.keyboard;
|
||||||
|
|
||||||
|
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.Log;
|
||||||
|
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.pretty.keyboard.theme.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
13
app/src/main/res/drawable/bg_active.xml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<gradient android:angle="270"
|
||||||
|
android:startColor="@color/main_color1"
|
||||||
|
android:centerColor="@color/main_color2"
|
||||||
|
android:endColor="@color/main_color3"/>
|
||||||
|
<corners
|
||||||
|
android:topLeftRadius="40dp"
|
||||||
|
android:topRightRadius="40dp" />
|
||||||
|
|
||||||
|
|
||||||
|
</shape>
|
||||||
7
app/src/main/res/drawable/bg_all.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>
|
||||||
7
app/src/main/res/drawable/bg_apply.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/pb_end_color" />
|
||||||
|
<corners android:radius="12dp" />
|
||||||
|
|
||||||
|
</shape>
|
||||||
7
app/src/main/res/drawable/bg_enable_apply.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>
|
||||||
15
app/src/main/res/drawable/bg_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>
|
||||||
5
app/src/main/res/drawable/cursor_color.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_color1" />
|
||||||
|
</shape>
|
||||||
9
app/src/main/res/drawable/im_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="#ffffff"/>
|
||||||
|
</vector>
|
||||||
10
app/src/main/res/drawable/layout_menu.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">
|
||||||
|
<gradient
|
||||||
|
android:angle="270"
|
||||||
|
android:endColor="@color/main_end"
|
||||||
|
android:startColor="@color/main_start" />
|
||||||
|
|
||||||
|
|
||||||
|
</shape>
|
||||||
27
app/src/main/res/drawable/pb.xml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?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" />
|
||||||
|
<gradient
|
||||||
|
android:angle="0"
|
||||||
|
android:endColor="@color/pb_end_color"
|
||||||
|
android:centerColor="@color/pb_center_color"
|
||||||
|
android:startColor="@color/pb_start_color" />
|
||||||
|
</shape>
|
||||||
|
</clip>
|
||||||
|
</item>
|
||||||
|
</layer-list>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
6
app/src/main/res/drawable/selector_acttive.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_apply" android:state_selected="false" />
|
||||||
|
<item android:drawable="@drawable/bg_enable_apply" />
|
||||||
|
</selector>
|
||||||
7
app/src/main/res/drawable/shape_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>
|
||||||
10
app/src/main/res/drawable/shape_main_bg.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">
|
||||||
|
<corners android:radius="10dp" />
|
||||||
|
<gradient
|
||||||
|
android:centerColor="@color/main_color2"
|
||||||
|
android:endColor="@color/main_color3"
|
||||||
|
android:startColor="@color/main_color1" />
|
||||||
|
|
||||||
|
</shape>
|
||||||
147
app/src/main/res/layout/activity_layout_apply.xml
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
<?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:background="@mipmap/bg_main"
|
||||||
|
tools:context=".ui.ApplySkinActivity">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/back"
|
||||||
|
android:layout_width="44dp"
|
||||||
|
android:layout_height="44dp"
|
||||||
|
android:paddingStart="5dp"
|
||||||
|
android:paddingTop="10dp"
|
||||||
|
android:layout_marginTop="30dp"
|
||||||
|
android:paddingBottom="10dp"
|
||||||
|
android:src="@mipmap/im_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/white"
|
||||||
|
android:textSize="20sp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/back"
|
||||||
|
app:layout_constraintLeft_toRightOf="@id/back"
|
||||||
|
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:cardElevation="0dp"
|
||||||
|
app:cardCornerRadius="12dp"
|
||||||
|
app:cardBackgroundColor="@color/transparent"
|
||||||
|
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"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
android:background="@drawable/bg_apply"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/card_viewData">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/im_download"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@mipmap/im_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" />
|
||||||
|
|
||||||
|
|
||||||
|
<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"
|
||||||
|
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/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:visibility="gone"
|
||||||
|
android:focusable="true"
|
||||||
|
android:clickable="true"
|
||||||
|
android:background="@color/bg_loading">
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:indeterminateTint="@color/white" />
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
216
app/src/main/res/layout/activity_layout_home.xml
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.drawerlayout.widget.DrawerLayout 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:id="@+id/drawLayout"
|
||||||
|
android:background="@mipmap/bg_main"
|
||||||
|
tools:context=".ui.HomeActivity">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_marginTop="30dp"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text_view_appName"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:text="@string/app_name"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="20sp"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="34dp"
|
||||||
|
android:layout_height="34dp"
|
||||||
|
android:padding="5dp"
|
||||||
|
android:id="@+id/imageMenu"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/text_view_appName"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/card_banner"
|
||||||
|
android:src="@mipmap/im_menu" />
|
||||||
|
|
||||||
|
|
||||||
|
<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"
|
||||||
|
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>
|
||||||
|
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="end"
|
||||||
|
android:layout_marginTop="30dp"
|
||||||
|
android:background="@drawable/layout_menu"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingEnd="16dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/imLogo"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:src="@mipmap/logo" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignTop="@id/imLogo"
|
||||||
|
android:layout_alignBottom="@id/imLogo"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_toEndOf="@id/imLogo"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/app_name"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/layout_keyboard_setting"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="56dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_below="@id/imLogo"
|
||||||
|
android:layout_marginTop="34dp"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:src="@mipmap/im_setting" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:text="@string/Keyboard_set"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_below="@id/layout_keyboard_setting"
|
||||||
|
android:background="@color/white" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/layout_rate"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="56dp"
|
||||||
|
android:layout_below="@id/layout_keyboard_setting"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:src="@mipmap/im_rate_us" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:text="@string/app_rate_us"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_below="@id/layout_rate"
|
||||||
|
android:background="@color/white" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/layout_privacy"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="56dp"
|
||||||
|
android:layout_below="@id/layout_rate"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:src="@mipmap/im_privacy" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:text="@string/app_privacy"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</RelativeLayout>
|
||||||
|
</androidx.drawerlayout.widget.DrawerLayout>
|
||||||
35
app/src/main/res/layout/activity_layout_view_all.xml
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?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"
|
||||||
|
android:background="@mipmap/bg_main"
|
||||||
|
tools:context=".ui.AllActivity">
|
||||||
|
<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="@mipmap/im_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>
|
||||||
44
app/src/main/res/layout/activity_layout_wel.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"
|
||||||
|
android:background="@mipmap/bg_main"
|
||||||
|
tools:context=".ui.WelActivity">
|
||||||
|
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/nova_progress"
|
||||||
|
style="?android:attr/progressBarStyleHorizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="10dp"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:layout_marginStart="33dp"
|
||||||
|
android:layout_marginEnd="33dp"
|
||||||
|
android:layout_marginBottom="40dp"
|
||||||
|
android:progress="3"
|
||||||
|
android:progressDrawable="@drawable/pb"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/image"
|
||||||
|
android:layout_width="106dp"
|
||||||
|
android:layout_height="106dp"
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:layout_marginTop="260dp"
|
||||||
|
android:src="@mipmap/logo" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/image"
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:textColor="@color/pb_end_color"
|
||||||
|
android:textSize="21sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:text="@string/app_name" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
64
app/src/main/res/layout/activity_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_et"
|
||||||
|
android:focusable="true"
|
||||||
|
android:focusableInTouchMode="true"
|
||||||
|
android:hint="@string/et_hint"
|
||||||
|
android:textColorHint="@color/apply_step_false"
|
||||||
|
android:paddingStart="15dp"
|
||||||
|
android:textCursorDrawable="@drawable/cursor_color"
|
||||||
|
android:textColor="@color/main_color1" />
|
||||||
|
</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="@mipmap/im_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>-->
|
||||||
42
app/src/main/res/layout/custome_layout_input_view.xml
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?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.pretty.keyboard.theme.keyboard.view.CustomInputView
|
||||||
|
android:id="@+id/custom_input_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:animateLayoutChanges="true"
|
||||||
|
android:background="@mipmap/bg_main"
|
||||||
|
android:focusable="true"
|
||||||
|
android:focusableInTouchMode="true"
|
||||||
|
android:keyBackground="@drawable/bg_key"
|
||||||
|
android:keyTextColor="@color/white"
|
||||||
|
android:keyTextSize="0sp"
|
||||||
|
android:labelTextSize="12sp"
|
||||||
|
android:paddingStart="5dp"
|
||||||
|
android:paddingTop="5dp"
|
||||||
|
android:paddingEnd="5dp"
|
||||||
|
android:paddingBottom="5dp" />
|
||||||
|
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
98
app/src/main/res/layout/dialog_layout_active.xml
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
<?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"
|
||||||
|
tools:context=".ui.SettingActivity">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:background="@drawable/bg_active"
|
||||||
|
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/im_close"
|
||||||
|
app:layout_constraintRight_toRightOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
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"
|
||||||
|
android:text="@string/open_str"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
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_acttive"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/text_open">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ok_one"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:src="@mipmap/im_ok"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text_step_one"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/step_1"
|
||||||
|
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_acttive"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/linear_step_one">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ok_two"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:src="@mipmap/im_ok"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text_step_two"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/step_2"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="15sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
</FrameLayout>
|
||||||
16
app/src/main/res/layout/fragment_layout_home.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=".ui.FragmentHome">
|
||||||
|
|
||||||
|
<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>
|
||||||
44
app/src/main/res/layout/item_all_layout.xml
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/item_layout"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_marginEnd="24dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text_tab_view"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:text="@string/app_name"
|
||||||
|
android:textSize="13sp"
|
||||||
|
android:textColor="@color/view_all_text_color" />
|
||||||
|
|
||||||
|
<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/white" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="16dp"
|
||||||
|
android:layout_height="4dp"
|
||||||
|
android:layout_marginStart="3dp"
|
||||||
|
android:layout_marginEnd="3dp"
|
||||||
|
android:background="@color/white" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="4dp"
|
||||||
|
android:layout_height="4dp"
|
||||||
|
android:background="@color/white" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
20
app/src/main/res/layout/item_home_layout.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/item_image"
|
||||||
|
android:scaleType="fitXY"/>
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
</FrameLayout>
|
||||||
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/bg_main.png
Normal file
|
After Width: | Height: | Size: 79 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/im_back.png
Normal file
|
After Width: | Height: | Size: 341 B |
BIN
app/src/main/res/mipmap-xxxhdpi/im_download.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/im_menu.png
Normal file
|
After Width: | Height: | Size: 259 B |
BIN
app/src/main/res/mipmap-xxxhdpi/im_ok.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/im_privacy.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/im_rate_us.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/im_setting.png
Normal file
|
After Width: | Height: | Size: 870 B |
BIN
app/src/main/res/mipmap-xxxhdpi/key_normal.png
Normal file
|
After Width: | Height: | Size: 481 B |
BIN
app/src/main/res/mipmap-xxxhdpi/key_pressed_on.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/logo.png
Normal file
|
After Width: | Height: | Size: 244 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/main_banner.png
Normal file
|
After Width: | Height: | Size: 132 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>
|
||||||
33
app/src/main/res/values/colors.xml
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?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_color">#66FFFFFF</color>
|
||||||
|
<color name="view_all_text_color">#80FFFFFF</color>
|
||||||
|
<color name="main_start">#FB5BAF</color>
|
||||||
|
<color name="main_end">#D15BFB</color>
|
||||||
|
<color name="apply_btn_bg_color">#ED4C97</color>
|
||||||
|
<color name="apply_step_false">#1A000000</color>
|
||||||
|
<color name="key_bg_press">#ffbbbbbb</color>
|
||||||
|
<color name="step_true">#666666</color>
|
||||||
|
<color name="status_bar">#FA93A8</color>
|
||||||
|
|
||||||
|
<color name="pb_bg">#898989</color>
|
||||||
|
<color name="pb_center_color">#c6affa</color>
|
||||||
|
<color name="pb_start_color">#b8c4fa</color>
|
||||||
|
<color name="pb_end_color">#Ae79fd</color>
|
||||||
|
|
||||||
|
<color name="dialog_start">#fa7691</color>
|
||||||
|
<color name="dialog_center">#f19dc7</color>
|
||||||
|
<color name="dialog_end">#f6e5f5</color>
|
||||||
|
<color name="transparent">#00000000</color>
|
||||||
|
<color name="bg_loading">#80000000</color>
|
||||||
|
<color name="main_color1">#c3b8fc</color>
|
||||||
|
<color name="main_color2">#Aec0f6</color>
|
||||||
|
<color name="main_color3">#efd4f8</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>
|
||||||
19
app/src/main/res/values/strings.xml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<resources>
|
||||||
|
<string name="app_name">Pretty Keyboard</string>
|
||||||
|
<string name="view_all">View All</string>
|
||||||
|
<string name="download_apply">Download & Apply</string>
|
||||||
|
<string name="apply">Apply</string>
|
||||||
|
<string name="app_rate_us">Rate us</string>
|
||||||
|
<string name="app_privacy">Privacy</string>
|
||||||
|
<string name="app_google_play">https://play.google.com/store/apps/details?id=</string>
|
||||||
|
<string name="app_privacy_path">https://marielathama.bitbucket.io/privacy.html</string>
|
||||||
|
<string name="recommended">Recommended</string>
|
||||||
|
<string name="Keyboard_set">Keyboard settings</string>
|
||||||
|
<string name="open_str">Activate Nova keyboard to enable MORE functions!</string>
|
||||||
|
<string name="step_1">Step 1:Select</string>
|
||||||
|
<string name="step_2">Step 2:Enable</string>
|
||||||
|
<string name="theme_application_successful">Theme application successful</string>
|
||||||
|
<string name="download_fail">Download failed, please try again</string>
|
||||||
|
<string name="text_promt">For normal use, please enter the setting to complete the setting steps.</string>
|
||||||
|
<string name="et_hint">Type a Message</string>
|
||||||
|
</resources>
|
||||||
38
app/src/main/res/values/themes.xml
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<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_500</item>
|
||||||
|
<item name="colorPrimaryVariant">@color/purple_700</item>
|
||||||
|
<item name="colorOnPrimary">@color/white</item>
|
||||||
|
<!-- Secondary brand color. -->
|
||||||
|
<item name="colorSecondary">@color/teal_200</item>
|
||||||
|
<item name="colorSecondaryVariant">@color/teal_700</item>
|
||||||
|
<item name="colorOnSecondary">@color/black</item>
|
||||||
|
<!-- Status bar color. -->
|
||||||
|
<item name="android:statusBarColor">@color/transparent</item>
|
||||||
|
<!-- Customize your theme here. -->
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<declare-styleable name="CustomInputView">
|
||||||
|
<attr format="integer" name="text_size_label"/>
|
||||||
|
<attr format="integer" name="text_size_key"/>
|
||||||
|
<attr format="color" name="text_color_key"/>
|
||||||
|
<attr format="color" name="background_color_key"/>
|
||||||
|
<attr format="color" name="icon_color_key"/>
|
||||||
|
<attr format="color" name="text_color_special"/>
|
||||||
|
<attr format="color" name="text_color_done"/>
|
||||||
|
<attr format="color" name="text_color_none"/>
|
||||||
|
<attr format="reference" name="drawable_delete"/>
|
||||||
|
<attr format="reference" name="drawable_capital"/>
|
||||||
|
<attr format="reference" name="drawable_capital_lock"/>
|
||||||
|
<attr format="reference" name="drawable_cancel"/>
|
||||||
|
<attr format="reference" name="drawable_space"/>
|
||||||
|
<attr format="reference" name="drawable_special"/>
|
||||||
|
<attr format="reference" name="drawable_done"/>
|
||||||
|
<attr format="reference" name="drawable_none"/>
|
||||||
|
</declare-styleable>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</resources>
|
||||||
75
app/src/main/res/values/value.xml
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<declare-styleable name="K_Keyboard_Key">
|
||||||
|
|
||||||
|
<attr name="android:codes"/>
|
||||||
|
|
||||||
|
<attr name="android:popupKeyboard"/>
|
||||||
|
|
||||||
|
<attr name="android:popupCharacters"/>
|
||||||
|
|
||||||
|
<attr name="android:keyEdgeFlags"/>
|
||||||
|
|
||||||
|
<attr name="android:isModifier"/>
|
||||||
|
|
||||||
|
<attr name="android:isSticky"/>
|
||||||
|
|
||||||
|
<attr name="android:isRepeatable"/>
|
||||||
|
|
||||||
|
<attr name="android:iconPreview"/>
|
||||||
|
|
||||||
|
<attr name="android:keyOutputText"/>
|
||||||
|
|
||||||
|
<attr name="android:keyLabel"/>
|
||||||
|
|
||||||
|
<attr name="android:keyIcon"/>
|
||||||
|
|
||||||
|
<attr name="android:keyboardMode"/>
|
||||||
|
</declare-styleable>
|
||||||
|
<declare-styleable name="Kil_Keyboard_Row">
|
||||||
|
|
||||||
|
<attr name="android:rowEdgeFlags"/>
|
||||||
|
|
||||||
|
<attr name="android:keyboardMode"/>
|
||||||
|
</declare-styleable>
|
||||||
|
<declare-styleable name="My_Keyboard_view">
|
||||||
|
|
||||||
|
<attr name="android:keyWidth"/>
|
||||||
|
|
||||||
|
<attr name="android:keyHeight"/>
|
||||||
|
|
||||||
|
<attr name="android:horizontalGap"/>
|
||||||
|
|
||||||
|
<attr name="android:verticalGap"/>
|
||||||
|
</declare-styleable>
|
||||||
|
<declare-styleable name="My_KeyboardView">
|
||||||
|
|
||||||
|
<attr name="android:keyBackground"/>
|
||||||
|
|
||||||
|
<attr name="android:keyTextSize"/>
|
||||||
|
|
||||||
|
<attr name="android:labelTextSize"/>
|
||||||
|
|
||||||
|
<attr name="android:keyTextColor"/>
|
||||||
|
|
||||||
|
<attr name="android:keyPreviewLayout"/>
|
||||||
|
|
||||||
|
<attr name="android:keyPreviewOffset"/>
|
||||||
|
|
||||||
|
<attr name="android:keyPreviewHeight"/>
|
||||||
|
|
||||||
|
<attr name="android:verticalCorrection"/>
|
||||||
|
|
||||||
|
<attr name="android:popupLayout"/>
|
||||||
|
|
||||||
|
<attr name="android:shadowColor"/>
|
||||||
|
|
||||||
|
<attr name="android:shadowRadius"/>
|
||||||
|
</declare-styleable>
|
||||||
|
<declare-styleable name="IM_KeyboardViewPreviewState">
|
||||||
|
|
||||||
|
<attr name="android:state_long_pressable"/>
|
||||||
|
</declare-styleable>
|
||||||
|
|
||||||
|
</resources>
|
||||||
142
app/src/main/res/xml/a.xml
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:horizontalGap="1%p"
|
||||||
|
android:keyWidth="9%p"
|
||||||
|
android:keyHeight="@dimen/key_height"
|
||||||
|
android:verticalGap="@dimen/keyboard_vertical_gap">
|
||||||
|
<Row>
|
||||||
|
<Key
|
||||||
|
android:codes="113"
|
||||||
|
android:keyLabel="q"
|
||||||
|
android:keyWidth="8.9%p"
|
||||||
|
android:keyEdgeFlags="left" />
|
||||||
|
<Key
|
||||||
|
android:codes="119"
|
||||||
|
android:keyLabel="w"
|
||||||
|
android:keyWidth="8.9%p"/>
|
||||||
|
<Key
|
||||||
|
android:codes="101"
|
||||||
|
android:keyLabel="e"
|
||||||
|
android:keyWidth="8.9%p" />
|
||||||
|
<Key
|
||||||
|
android:codes="114"
|
||||||
|
android:keyWidth="8.9%p"
|
||||||
|
android:keyLabel="r" />
|
||||||
|
<Key
|
||||||
|
android:codes="116"
|
||||||
|
android:keyLabel="t"
|
||||||
|
android:keyWidth="8.9%p"/>
|
||||||
|
<Key
|
||||||
|
android:codes="121"
|
||||||
|
android:keyLabel="y"
|
||||||
|
android:keyWidth="8.9%p"/>
|
||||||
|
<Key
|
||||||
|
android:codes="117"
|
||||||
|
android:keyLabel="u"
|
||||||
|
android:keyWidth="8.9%p"/>
|
||||||
|
<Key
|
||||||
|
android:codes="105"
|
||||||
|
android:keyLabel="i"
|
||||||
|
android:keyWidth="8.9%p"/>
|
||||||
|
<Key
|
||||||
|
android:codes="111"
|
||||||
|
android:keyLabel="o"
|
||||||
|
android:keyWidth="8.9%p"/>
|
||||||
|
<Key
|
||||||
|
android:codes="112"
|
||||||
|
android:keyLabel="p"
|
||||||
|
android:keyWidth="8.9%p"
|
||||||
|
android:keyEdgeFlags="right" />
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
<Row>
|
||||||
|
<Key
|
||||||
|
android:codes="97"
|
||||||
|
android:keyLabel="a"
|
||||||
|
android:horizontalGap="5.5%p"
|
||||||
|
android:keyEdgeFlags="left" />
|
||||||
|
<Key
|
||||||
|
android:codes="115"
|
||||||
|
android:keyLabel="s" />
|
||||||
|
<Key
|
||||||
|
android:codes="100"
|
||||||
|
android:keyLabel="d" />
|
||||||
|
<Key
|
||||||
|
android:codes="102"
|
||||||
|
android:keyLabel="f" />
|
||||||
|
<Key
|
||||||
|
android:codes="103"
|
||||||
|
android:keyLabel="g" />
|
||||||
|
<Key
|
||||||
|
android:codes="104"
|
||||||
|
android:keyLabel="h" />
|
||||||
|
<Key
|
||||||
|
android:codes="106"
|
||||||
|
android:keyLabel="j" />
|
||||||
|
<Key
|
||||||
|
android:codes="107"
|
||||||
|
android:keyLabel="k" />
|
||||||
|
<Key
|
||||||
|
android:codes="108"
|
||||||
|
android:keyLabel="l"
|
||||||
|
android:keyEdgeFlags="right" />
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
<Row>
|
||||||
|
<Key
|
||||||
|
android:codes="-1"
|
||||||
|
android:keyWidth="13.5%p"
|
||||||
|
android:isModifier="true"
|
||||||
|
android:isSticky="true"
|
||||||
|
android:keyEdgeFlags="left" />
|
||||||
|
<Key
|
||||||
|
android:codes="122"
|
||||||
|
android:keyLabel="z" />
|
||||||
|
<Key
|
||||||
|
android:codes="120"
|
||||||
|
android:keyLabel="x" />
|
||||||
|
<Key
|
||||||
|
android:codes="99"
|
||||||
|
android:keyLabel="c" />
|
||||||
|
<Key
|
||||||
|
android:codes="118"
|
||||||
|
android:keyLabel="v" />
|
||||||
|
<Key
|
||||||
|
android:codes="98"
|
||||||
|
android:keyLabel="b" />
|
||||||
|
<Key
|
||||||
|
android:codes="110"
|
||||||
|
android:keyLabel="n" />
|
||||||
|
<Key
|
||||||
|
android:codes="109"
|
||||||
|
android:keyLabel="m" />
|
||||||
|
<Key
|
||||||
|
android:codes="-5"
|
||||||
|
android:keyWidth="13.5%p"
|
||||||
|
android:isRepeatable="true" />
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
<Row android:rowEdgeFlags="bottom">
|
||||||
|
<Key
|
||||||
|
android:codes="-2"
|
||||||
|
android:keyLabel="\?123"
|
||||||
|
android:keyWidth="17%p" />
|
||||||
|
<Key
|
||||||
|
android:codes="46"
|
||||||
|
android:keyLabel="."
|
||||||
|
android:keyWidth="12%p" />
|
||||||
|
<Key
|
||||||
|
android:codes="32"
|
||||||
|
android:keyLabel="English"
|
||||||
|
android:keyWidth="36%p"
|
||||||
|
android:isRepeatable="false"/>
|
||||||
|
<Key
|
||||||
|
android:codes="63"
|
||||||
|
android:keyLabel="\?"
|
||||||
|
android:keyWidth="12%p" />
|
||||||
|
<Key
|
||||||
|
android:codes="-4"
|
||||||
|
android:keyWidth="17%p"
|
||||||
|
android:keyEdgeFlags="right" />
|
||||||
|
</Row>
|
||||||
|
</Keyboard>
|
||||||
147
app/src/main/res/xml/b.xml
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:horizontalGap="1%p"
|
||||||
|
android:keyWidth="9%p"
|
||||||
|
android:keyHeight="@dimen/key_height"
|
||||||
|
android:verticalGap="@dimen/keyboard_vertical_gap">
|
||||||
|
<Row>
|
||||||
|
<Key
|
||||||
|
android:codes="49"
|
||||||
|
android:keyLabel="1"
|
||||||
|
android:horizontalGap="1%p"
|
||||||
|
android:keyWidth="8.9%p"
|
||||||
|
android:keyEdgeFlags="left" />
|
||||||
|
<Key
|
||||||
|
android:codes="50"
|
||||||
|
android:keyLabel="2"
|
||||||
|
android:keyWidth="8.9%p" />
|
||||||
|
<Key
|
||||||
|
android:codes="51"
|
||||||
|
android:keyLabel="3"
|
||||||
|
android:keyWidth="8.9%p" />
|
||||||
|
<Key
|
||||||
|
android:codes="52"
|
||||||
|
android:keyLabel="4"
|
||||||
|
android:keyWidth="8.9%p" />
|
||||||
|
<Key
|
||||||
|
android:codes="53"
|
||||||
|
android:keyLabel="5"
|
||||||
|
android:keyWidth="8.9%p" />
|
||||||
|
<Key
|
||||||
|
android:codes="54"
|
||||||
|
android:keyLabel="6"
|
||||||
|
android:keyWidth="8.9%p"
|
||||||
|
/>
|
||||||
|
<Key
|
||||||
|
android:codes="55"
|
||||||
|
android:keyLabel="7"
|
||||||
|
android:keyWidth="8.9%p" />
|
||||||
|
<Key
|
||||||
|
android:codes="56"
|
||||||
|
android:keyLabel="8"
|
||||||
|
android:keyWidth="8.9%p" />
|
||||||
|
<Key
|
||||||
|
android:codes="57"
|
||||||
|
android:keyLabel="9"
|
||||||
|
android:keyWidth="8.9%p" />
|
||||||
|
<Key
|
||||||
|
android:codes="48"
|
||||||
|
android:keyLabel="0"
|
||||||
|
android:keyWidth="8.9%p"
|
||||||
|
android:keyEdgeFlags="right" />
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
<Row>
|
||||||
|
<Key
|
||||||
|
android:codes="33"
|
||||||
|
android:keyLabel="!"
|
||||||
|
android:horizontalGap="5.5%p"
|
||||||
|
android:keyEdgeFlags="left" />
|
||||||
|
<Key
|
||||||
|
android:codes="64"
|
||||||
|
android:keyLabel="\@" />
|
||||||
|
<Key
|
||||||
|
android:codes="35"
|
||||||
|
android:keyLabel="#" />
|
||||||
|
<Key
|
||||||
|
android:codes="36"
|
||||||
|
android:keyLabel="\$" />
|
||||||
|
<Key
|
||||||
|
android:codes="37"
|
||||||
|
android:keyLabel="%" />
|
||||||
|
<Key
|
||||||
|
android:codes="38"
|
||||||
|
android:keyLabel="&" />
|
||||||
|
<Key
|
||||||
|
android:codes="42"
|
||||||
|
android:keyLabel="*" />
|
||||||
|
<Key
|
||||||
|
android:codes="40"
|
||||||
|
android:keyLabel="(" />
|
||||||
|
<Key
|
||||||
|
android:codes="41"
|
||||||
|
android:keyLabel=")"
|
||||||
|
android:keyEdgeFlags="right" />
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
|
||||||
|
<Row>
|
||||||
|
<Key
|
||||||
|
android:codes="-103"
|
||||||
|
android:keyLabel="More"
|
||||||
|
android:keyWidth="13.5%p"
|
||||||
|
android:isModifier="true"
|
||||||
|
android:isSticky="true"
|
||||||
|
android:keyEdgeFlags="left" />
|
||||||
|
<Key
|
||||||
|
android:codes="39"
|
||||||
|
android:keyLabel="'" />
|
||||||
|
<Key
|
||||||
|
android:codes="47"
|
||||||
|
android:keyLabel="/" />
|
||||||
|
<Key
|
||||||
|
android:codes="45"
|
||||||
|
android:keyLabel="-" />
|
||||||
|
<Key
|
||||||
|
android:codes="95"
|
||||||
|
android:keyLabel="_" />
|
||||||
|
<Key
|
||||||
|
android:codes="58"
|
||||||
|
android:keyLabel=":" />
|
||||||
|
<Key
|
||||||
|
android:codes="59"
|
||||||
|
android:keyLabel=";" />
|
||||||
|
<Key
|
||||||
|
android:codes="44"
|
||||||
|
android:keyLabel="," />
|
||||||
|
<Key
|
||||||
|
android:codes="-5"
|
||||||
|
android:keyWidth="13.5%p"
|
||||||
|
android:isRepeatable="true" />
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
|
||||||
|
<Row android:rowEdgeFlags="bottom">
|
||||||
|
<Key
|
||||||
|
android:codes="-102"
|
||||||
|
android:keyWidth="17%p"
|
||||||
|
android:keyLabel="Back" />
|
||||||
|
<Key
|
||||||
|
android:codes="46"
|
||||||
|
android:keyWidth="12%p"
|
||||||
|
android:keyLabel="." />
|
||||||
|
<Key
|
||||||
|
android:codes="32"
|
||||||
|
android:isRepeatable="false"
|
||||||
|
android:keyWidth="36%p"
|
||||||
|
android:keyLabel="English" />
|
||||||
|
<Key
|
||||||
|
android:codes="63"
|
||||||
|
android:keyWidth="12%p"
|
||||||
|
android:keyLabel="\?" />
|
||||||
|
<Key
|
||||||
|
android:codes="-3"
|
||||||
|
android:keyWidth="17%p"
|
||||||
|
android:keyEdgeFlags="right" />
|
||||||
|
</Row>
|
||||||
|
</Keyboard>
|
||||||
147
app/src/main/res/xml/c.xml
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:horizontalGap="1%p"
|
||||||
|
android:keyWidth="9%p"
|
||||||
|
android:keyHeight="@dimen/key_height"
|
||||||
|
android:verticalGap="@dimen/keyboard_vertical_gap">
|
||||||
|
<Row>
|
||||||
|
<Key
|
||||||
|
android:codes="91"
|
||||||
|
android:keyLabel="["
|
||||||
|
android:horizontalGap="1%p"
|
||||||
|
android:keyWidth="8.9%p"
|
||||||
|
android:keyEdgeFlags="left" />
|
||||||
|
<Key
|
||||||
|
android:codes="93"
|
||||||
|
android:keyLabel="]"
|
||||||
|
android:keyWidth="8.9%p" />
|
||||||
|
<Key
|
||||||
|
android:codes="123"
|
||||||
|
android:keyLabel="{"
|
||||||
|
android:keyWidth="8.9%p" />
|
||||||
|
<Key
|
||||||
|
android:codes="125"
|
||||||
|
android:keyLabel="}"
|
||||||
|
android:keyWidth="8.9%p" />
|
||||||
|
<Key
|
||||||
|
android:codes="35"
|
||||||
|
android:keyLabel="#"
|
||||||
|
android:keyWidth="8.9%p" />
|
||||||
|
<Key
|
||||||
|
android:codes="37"
|
||||||
|
android:keyLabel="%"
|
||||||
|
android:keyWidth="8.9%p"
|
||||||
|
/>
|
||||||
|
<Key
|
||||||
|
android:codes="94"
|
||||||
|
android:keyLabel="^"
|
||||||
|
android:keyWidth="8.9%p" />
|
||||||
|
<Key
|
||||||
|
android:codes="96"
|
||||||
|
android:keyLabel="`"
|
||||||
|
android:keyWidth="8.9%p" />
|
||||||
|
<Key
|
||||||
|
android:codes="43"
|
||||||
|
android:keyLabel="+"
|
||||||
|
android:keyWidth="8.9%p" />
|
||||||
|
<Key
|
||||||
|
android:codes="61"
|
||||||
|
android:keyLabel="="
|
||||||
|
android:keyWidth="8.9%p"
|
||||||
|
android:keyEdgeFlags="right" />
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
<Row>
|
||||||
|
<Key
|
||||||
|
android:codes="126"
|
||||||
|
android:keyLabel="~"
|
||||||
|
android:horizontalGap="5.5%p"
|
||||||
|
android:keyEdgeFlags="left" />
|
||||||
|
<Key
|
||||||
|
android:codes="92"
|
||||||
|
android:keyLabel="\\" />
|
||||||
|
<Key
|
||||||
|
android:codes="124"
|
||||||
|
android:keyLabel="|" />
|
||||||
|
<Key
|
||||||
|
android:codes="60"
|
||||||
|
android:keyLabel="<" />
|
||||||
|
<Key
|
||||||
|
android:codes="62"
|
||||||
|
android:keyLabel=">" />
|
||||||
|
<Key
|
||||||
|
android:codes="165"
|
||||||
|
android:keyLabel="¥" />
|
||||||
|
<Key
|
||||||
|
android:codes="8364"
|
||||||
|
android:keyLabel="€" />
|
||||||
|
<Key
|
||||||
|
android:codes="163"
|
||||||
|
android:keyLabel="£" />
|
||||||
|
<Key
|
||||||
|
android:codes="8356"
|
||||||
|
android:keyLabel="₤"
|
||||||
|
android:keyEdgeFlags="right" />
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
|
||||||
|
<Row>
|
||||||
|
<Key
|
||||||
|
android:codes="-101"
|
||||||
|
android:keyLabel="123"
|
||||||
|
android:keyWidth="13.5%p"
|
||||||
|
android:isModifier="true"
|
||||||
|
android:isSticky="true"
|
||||||
|
android:keyEdgeFlags="left" />
|
||||||
|
<Key
|
||||||
|
android:codes="39"
|
||||||
|
android:keyLabel="'" />
|
||||||
|
<Key
|
||||||
|
android:codes="47"
|
||||||
|
android:keyLabel="/" />
|
||||||
|
<Key
|
||||||
|
android:codes="45"
|
||||||
|
android:keyLabel="-" />
|
||||||
|
<Key
|
||||||
|
android:codes="95"
|
||||||
|
android:keyLabel="_" />
|
||||||
|
<Key
|
||||||
|
android:codes="58"
|
||||||
|
android:keyLabel=":" />
|
||||||
|
<Key
|
||||||
|
android:codes="59"
|
||||||
|
android:keyLabel=";" />
|
||||||
|
<Key
|
||||||
|
android:codes="44"
|
||||||
|
android:keyLabel="," />
|
||||||
|
<Key
|
||||||
|
android:codes="-5"
|
||||||
|
android:keyWidth="13.5%p"
|
||||||
|
android:isRepeatable="true" />
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
|
||||||
|
<Row android:rowEdgeFlags="bottom">
|
||||||
|
<Key
|
||||||
|
android:codes="-102"
|
||||||
|
android:keyWidth="17%p"
|
||||||
|
android:keyLabel="Back" />
|
||||||
|
<Key
|
||||||
|
android:codes="46"
|
||||||
|
android:keyWidth="12%p"
|
||||||
|
android:keyLabel="." />
|
||||||
|
<Key
|
||||||
|
android:codes="32"
|
||||||
|
android:isRepeatable="false"
|
||||||
|
android:keyWidth="36%p"
|
||||||
|
android:keyLabel="English" />
|
||||||
|
<Key
|
||||||
|
android:codes="63"
|
||||||
|
android:keyWidth="12%p"
|
||||||
|
android:keyLabel="\?" />
|
||||||
|
<Key
|
||||||
|
android:codes="-3"
|
||||||
|
android:keyWidth="17%p"
|
||||||
|
android:keyEdgeFlags="right" />
|
||||||
|
</Row>
|
||||||
|
</Keyboard>
|
||||||
8
app/src/main/res/xml/keyborad.xml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<input-method xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<subtype
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:imeSubtypeLocale="en_US"
|
||||||
|
android:imeSubtypeMode="keyboard" />
|
||||||
|
|
||||||
|
</input-method>
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
package com.pretty.keyboard.theme.keyboard
|
||||||
|
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
import org.junit.Assert.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example local unit test, which will execute on the development machine (host).
|
||||||
|
*
|
||||||
|
* See [testing documentation](http://d.android.com/tools/testing).
|
||||||
|
*/
|
||||||
|
class ExampleUnitTest {
|
||||||
|
@Test
|
||||||
|
fun addition_isCorrect() {
|
||||||
|
assertEquals(4, 2 + 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
8
build.gradle.kts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
plugins {
|
||||||
|
id("com.android.application") version "8.0.1" apply false
|
||||||
|
id("org.jetbrains.kotlin.android") version "1.9.0" apply false
|
||||||
|
id("com.google.gms.google-services") version "4.3.15" apply false
|
||||||
|
id ("com.google.firebase.crashlytics") version "2.9.2" apply false
|
||||||
|
}
|
||||||
|
|
||||||
23
gradle.properties
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# Project-wide Gradle settings.
|
||||||
|
# IDE (e.g. Android Studio) users:
|
||||||
|
# Gradle settings configured through the IDE *will override*
|
||||||
|
# any settings specified in this file.
|
||||||
|
# For more details on how to configure your build environment visit
|
||||||
|
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||||
|
# Specifies the JVM arguments used for the daemon process.
|
||||||
|
# The setting is particularly useful for tweaking memory settings.
|
||||||
|
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
||||||
|
# When configured, Gradle will run in incubating parallel mode.
|
||||||
|
# This option should only be used with decoupled projects. More details, visit
|
||||||
|
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||||
|
# org.gradle.parallel=true
|
||||||
|
# AndroidX package structure to make it clearer which packages are bundled with the
|
||||||
|
# Android operating system, and which are packaged with your app's APK
|
||||||
|
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||||
|
android.useAndroidX=true
|
||||||
|
# Kotlin code style for this project: "official" or "obsolete":
|
||||||
|
kotlin.code.style=official
|
||||||
|
# Enables namespacing of each library's R class so that its R class includes only the
|
||||||
|
# resources declared in the library itself and none from the library's dependencies,
|
||||||
|
# thereby reducing the size of the R class for that library
|
||||||
|
android.nonTransitiveRClass=true
|
||||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
6
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#Thu Dec 21 17:14:29 CST 2023
|
||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
185
gradlew
vendored
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright 2015 the original author or authors.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
##
|
||||||
|
## Gradle start up script for UN*X
|
||||||
|
##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
PRG="$0"
|
||||||
|
# Need this for relative symlinks.
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG=`dirname "$PRG"`"/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
SAVED="`pwd`"
|
||||||
|
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||||
|
APP_HOME="`pwd -P`"
|
||||||
|
cd "$SAVED" >/dev/null
|
||||||
|
|
||||||
|
APP_NAME="Gradle"
|
||||||
|
APP_BASE_NAME=`basename "$0"`
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD="maximum"
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN* )
|
||||||
|
cygwin=true
|
||||||
|
;;
|
||||||
|
Darwin* )
|
||||||
|
darwin=true
|
||||||
|
;;
|
||||||
|
MINGW* )
|
||||||
|
msys=true
|
||||||
|
;;
|
||||||
|
NONSTOP* )
|
||||||
|
nonstop=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="java"
|
||||||
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||||
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
|
if [ $? -eq 0 ] ; then
|
||||||
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
|
MAX_FD="$MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
ulimit -n $MAX_FD
|
||||||
|
if [ $? -ne 0 ] ; then
|
||||||
|
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Darwin, add options to specify how the application appears in the dock
|
||||||
|
if $darwin; then
|
||||||
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
|
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||||
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
|
||||||
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
|
|
||||||
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||||
|
SEP=""
|
||||||
|
for dir in $ROOTDIRSRAW ; do
|
||||||
|
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||||
|
SEP="|"
|
||||||
|
done
|
||||||
|
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||||
|
# Add a user-defined pattern to the cygpath arguments
|
||||||
|
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||||
|
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||||
|
fi
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
i=0
|
||||||
|
for arg in "$@" ; do
|
||||||
|
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||||
|
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||||
|
|
||||||
|
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||||
|
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||||
|
else
|
||||||
|
eval `echo args$i`="\"$arg\""
|
||||||
|
fi
|
||||||
|
i=`expr $i + 1`
|
||||||
|
done
|
||||||
|
case $i in
|
||||||
|
0) set -- ;;
|
||||||
|
1) set -- "$args0" ;;
|
||||||
|
2) set -- "$args0" "$args1" ;;
|
||||||
|
3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
|
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
|
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
|
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
|
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
|
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
|
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Escape application args
|
||||||
|
save () {
|
||||||
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
|
echo " "
|
||||||
|
}
|
||||||
|
APP_ARGS=`save "$@"`
|
||||||
|
|
||||||
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
||||||
89
gradlew.bat
vendored
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
@rem
|
||||||
|
@rem Copyright 2015 the original author or authors.
|
||||||
|
@rem
|
||||||
|
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@rem you may not use this file except in compliance with the License.
|
||||||
|
@rem You may obtain a copy of the License at
|
||||||
|
@rem
|
||||||
|
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@rem
|
||||||
|
@rem Unless required by applicable law or agreed to in writing, software
|
||||||
|
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@rem See the License for the specific language governing permissions and
|
||||||
|
@rem limitations under the License.
|
||||||
|
@rem
|
||||||
|
|
||||||
|
@if "%DEBUG%" == "" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||||
|
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if "%ERRORLEVEL%" == "0" goto execute
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
||||||
6
keystore.properties
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
app_name=Pretty Keyboard
|
||||||
|
package_name=com.pretty.keyboard.theme
|
||||||
|
keystoreFile=app/PrettyKeyboard.jks
|
||||||
|
key_alias=PrettyKeyboardkey0
|
||||||
|
key_store_password=PrettyKeyboard
|
||||||
|
key_password=PrettyKeyboard
|
||||||
32
settings.gradle.kts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
pluginManagement {
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
gradlePluginPortal()
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dependencyResolutionManagement {
|
||||||
|
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
maven("https://jitpack.io")
|
||||||
|
|
||||||
|
// //Anythink(Core)
|
||||||
|
// maven("https://jfrog.anythinktech.com/artifactory/overseas_sdk")
|
||||||
|
// //Ironsource
|
||||||
|
// maven("https://android-sdk.is.com/")
|
||||||
|
// //Mintegral
|
||||||
|
// maven("https://dl-maven-android.mintegral.com/repository/mbridge_android_sdk_oversea")
|
||||||
|
// //Pangle
|
||||||
|
// maven ( "https://artifact.bytedance.com/repository/pangle")
|
||||||
|
//
|
||||||
|
// //TopOn集成测试工具
|
||||||
|
// maven ( "https://jfrog.anythinktech.com/artifactory/debugger")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rootProject.name = "Pretty Keyboard"
|
||||||
|
include(":app")
|
||||||
|
|
||||||