diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 4895369..9ff3b48 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -25,6 +25,19 @@
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/com/timber/soft/newkeyboard/AppInputMethodService.kt b/app/src/main/java/com/timber/soft/newkeyboard/AppInputMethodService.kt
index c605886..369cfc0 100644
--- a/app/src/main/java/com/timber/soft/newkeyboard/AppInputMethodService.kt
+++ b/app/src/main/java/com/timber/soft/newkeyboard/AppInputMethodService.kt
@@ -1,37 +1,100 @@
package com.timber.soft.newkeyboard
import android.inputmethodservice.InputMethodService
+import android.inputmethodservice.Keyboard
import android.inputmethodservice.KeyboardView.OnKeyboardActionListener
+import android.os.Build
+import android.os.SystemClock
+import android.view.KeyboardShortcutGroup
import android.view.View
+import android.view.inputmethod.EditorInfo
+import androidx.annotation.RequiresApi
+import com.timber.soft.newkeyboard.databinding.ViewInputBinding
+import com.timber.soft.newkeyboard.tools.AppVal
class AppInputMethodService : InputMethodService(), OnKeyboardActionListener {
+ private lateinit var binding: ViewInputBinding
+ private val views =
+ intArrayOf(R.xml.keyboard_letter, R.xml.keyboard_number, R.xml.keyboard_symbol)
+ private var mouble = false
+ private var laTime = -3L
+
+ private fun keyCase(toBig: Boolean, keyboard: Keyboard) {
+ for (key in keyboard.keys) {
+ if (!key.label.isNullOrEmpty()) {
+ if (key.label.length == 1) {
+ var strin: Char = if (toBig) {
+ key.label.toString()[0].uppercaseChar()
+ } else {
+ key.label.toString()[0].lowercaseChar()
+ }
+ key.run {
+ label = strin.toString()
+ codes[0] = strin.code
+ }
+ }
+ }
+ }
+ }
+
+ private fun changeXml(mode: Int) {
+ binding.myCustomInput.run {
+ when (mode) {
+ 0 -> {
+ xmlMode = AppVal.xml0
+ keyboard = Keyboard(context, views[0])
+ }
+
+ 2 -> {
+ xmlMode = AppVal.xml2
+ keyboard = Keyboard(context, views[2])
+
+ }
+
+ 1 -> {
+ xmlMode = AppVal.xml1
+ keyboard = Keyboard(context, views[1])
+ }
+ }
+ }
+ }
/**
* 构建键盘视图
*/
override fun onCreateInputView(): View {
- return super.onCreateInputView()
- TODO("Not yet implemented")
+ binding = ViewInputBinding.inflate(layoutInflater, null, false)
+ binding.myCustomInput.setOnKeyboardActionListener(this)
+ binding.myCustomInput.run {
+ keyboard = Keyboard(this@AppInputMethodService, views[0])
+ isEnabled = true
+ }
+ return binding.root
}
-
/**
* 向用户展示键盘时候调用
*/
+ @RequiresApi(Build.VERSION_CODES.M)
override fun onWindowShown() {
super.onWindowShown()
- TODO("Not yet implemented")
+ binding.myCustomInput.upUi(this@AppInputMethodService)
}
-
/**
* Called when the user presses a key.
*
* 监听特定的按钮
*/
override fun onPress(primaryCode: Int) {
- TODO("Not yet implemented")
+ mouble = false
+ if (primaryCode == Keyboard.KEYCODE_SHIFT) {
+ if (300 > SystemClock.elapsedRealtime() - laTime) {
+ mouble = true
+ }
+ laTime = SystemClock.elapsedRealtime()
+ }
}
/**
@@ -40,7 +103,80 @@ class AppInputMethodService : InputMethodService(), OnKeyboardActionListener {
* 监听用户点击的键盘按键
*/
override fun onKey(primaryCode: Int, keyCodes: IntArray?) {
- TODO("Not yet implemented")
+
+ when (primaryCode) {
+ Keyboard.KEYCODE_SHIFT -> {
+ binding.myCustomInput.run {
+ val myKeyboard = keyboard
+ when (shiftStatus) {
+ AppVal.Shift_S -> {
+ shiftStatus = if (mouble) {
+ AppVal.Shift_B_lo
+ } else {
+ AppVal.Shift_B
+ }
+ keyCase(true, myKeyboard)
+ keyboard = myKeyboard
+ }
+
+ AppVal.Shift_B_lo -> {
+ shiftStatus = AppVal.Shift_S
+ keyCase(false, myKeyboard)
+ keyboard = myKeyboard
+ }
+
+ AppVal.Shift_B -> {
+ shiftStatus = if (mouble) {
+ AppVal.Shift_B_lo
+ } else {
+ keyCase(false, myKeyboard)
+ AppVal.Shift_S
+ }
+ keyboard = myKeyboard
+ }
+ }
+ }
+
+ }
+
+ Keyboard.KEYCODE_DONE -> {
+ currentInputConnection.performEditorAction(EditorInfo.IME_ACTION_DONE)
+ }
+
+ Keyboard.KEYCODE_MODE_CHANGE -> {
+ binding.myCustomInput.run {
+ if (xmlMode == AppVal.xml0) {
+ changeXml(1)
+ } else {
+ changeXml(0)
+ }
+ }
+ }
+
+ AppVal.SHIFT_NUMBER -> {
+ changeXml(2)
+ }
+
+ Keyboard.KEYCODE_DELETE -> {
+ currentInputConnection.deleteSurroundingText(1, 0)
+ }
+
+ AppVal.SHIFT_SYMBOL -> {
+ changeXml(1)
+ }
+
+ else -> {
+ currentInputConnection.commitText(primaryCode.toChar().toString(), 1)
+ binding.myCustomInput.keyboard = binding.myCustomInput.apply {
+ if (shiftStatus == AppVal.Shift_B) {
+ shiftStatus = AppVal.Shift_S
+ keyCase(false, binding.myCustomInput.keyboard)
+ }
+ }.keyboard
+ }
+
+ }
+
}
diff --git a/app/src/main/java/com/timber/soft/newkeyboard/activity/ApplyActivity.kt b/app/src/main/java/com/timber/soft/newkeyboard/activity/ApplyActivity.kt
index 4689c2e..830f511 100644
--- a/app/src/main/java/com/timber/soft/newkeyboard/activity/ApplyActivity.kt
+++ b/app/src/main/java/com/timber/soft/newkeyboard/activity/ApplyActivity.kt
@@ -67,7 +67,7 @@ class ApplyActivity : AppCompatActivity() {
private fun isChoose(): Boolean {
Settings.Secure.getString(contentResolver, Settings.Secure.DEFAULT_INPUT_METHOD).let { id ->
return id.startsWith(packageName)
- } ?: return false
+ }
}
private fun isEnable(): Boolean {
diff --git a/app/src/main/java/com/timber/soft/newkeyboard/activity/DetailsActivity.kt b/app/src/main/java/com/timber/soft/newkeyboard/activity/DetailsActivity.kt
index 5b48378..fe32099 100644
--- a/app/src/main/java/com/timber/soft/newkeyboard/activity/DetailsActivity.kt
+++ b/app/src/main/java/com/timber/soft/newkeyboard/activity/DetailsActivity.kt
@@ -22,6 +22,7 @@ import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.target.Target
import com.timber.soft.newkeyboard.R
import com.timber.soft.newkeyboard.databinding.ActivityDetailsBinding
+import com.timber.soft.newkeyboard.listener.ApplyListener
import com.timber.soft.newkeyboard.model.DataModel
import com.timber.soft.newkeyboard.tools.AppVal
import com.timber.soft.newkeyboard.tools.StatusBarTools
@@ -36,13 +37,14 @@ import java.io.FileOutputStream
import java.io.InputStream
import java.io.RandomAccessFile
-class DetailsActivity : AppCompatActivity() {
+class DetailsActivity : AppCompatActivity(), ApplyListener {
private lateinit var binding: ActivityDetailsBinding
private lateinit var inputManager: InputMethodManager
private lateinit var previewUrl: String
private lateinit var zipPath: String
private lateinit var dataModel: DataModel
+ private lateinit var sp: SharedPreferences
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -117,68 +119,59 @@ class DetailsActivity : AppCompatActivity() {
e.printStackTrace()
}
+ // 初始化键值对
+ sp = getSharedPreferences(
+ AppVal.SHARE_NAME, Context.MODE_PRIVATE
+ )
}
private fun applyTheme() {
// 检查是否启动键盘并设置
if (!isEnable() || !isChoose()) {
+ Toast.makeText(this, getString(R.string.text_promote), Toast.LENGTH_SHORT).show()
val intent = Intent(this, ApplyActivity::class.java)
startActivity(intent)
return
}
+
binding.themeProgressbar.visibility = View.VISIBLE
val file = File(zipPath)
// 判断缓存中是否存在文件
if (file.exists()) {
val allThemePath: String = getAllThemePath(dataModel.title)
val edit = sp.edit()
+ // 存放键值对
edit.run {
putString(AppVal.KEY_ALL_PATH, allThemePath)
apply()
}
} else {
- getZipData(dataModel.title, dataModel.zipUrl, this,this::onResult)
+ getZipData(
+ dataModel.title, dataModel.zipUrl, this@DetailsActivity, this@DetailsActivity
+ )
}
}
- private fun onResult(isSuccess: Boolean, path: String) {
- binding.themeProgressbar.visibility = View.GONE
- if (isSuccess) {
- val lastIndexOf: Int = path.lastIndexOf(AppVal.res_path)
- val substring = path.subSequence(0, lastIndexOf + AppVal.res_path.length).toString()
-
- val edit = sp.edit()
-
- edit.run {
- putString(AppVal.KEY_ALL_PATH, substring)
- apply()
- }
-
- edit.run {
- putString(dataModel.title, substring)
- apply()
- }
-
- Toast.makeText(this, getString(R.string.succ_apply), Toast.LENGTH_LONG).show()
- finish()
- } else {
- Toast.makeText(this, getString(R.string.fail_apply), Toast.LENGTH_LONG).show()
- }
- }
-
- interface ApplyListener {
- fun applyListener(isSuccess: Boolean, str: String)
- }
-
+ /**
+ * 从指定的URL下载zip文件,并在下载完成后处理该文件。
+ *
+ * @param title 下载文件的标题
+ * @param url 下载文件的URL
+ * @param con 上下文Context
+ * @param listener 处理文件完成后的回调接口
+ */
private fun getZipData(title: String, url: String, con: Context, listener: ApplyListener) {
Glide.with(con).asFile().load(url).addListener(object : RequestListener {
+ //失败回调
override fun onLoadFailed(
e: GlideException?, model: Any?, target: Target, isFirstResource: Boolean
): Boolean {
+ // 回调失败
listener.applyListener(false, "")
return false
}
+ //成功回调
override fun onResourceReady(
resource: File,
model: Any,
@@ -186,7 +179,6 @@ class DetailsActivity : AppCompatActivity() {
dataSource: DataSource,
isFirstResource: Boolean
): Boolean {
-
val fileInputStream = FileInputStream(resource)
dealFile(title, url, fileInputStream, listener)
return false
@@ -201,9 +193,12 @@ class DetailsActivity : AppCompatActivity() {
val zipPath = "${cacheDir}/${title}_ZIP"
val unPath = "${cacheDir}/${title}"
+ // 将下载的zip文件保存到zipPath路径
val zipBoolean = writeNewFile(input, zipPath)
+ // 随机读写
val randomAccessFileInStream =
RandomAccessFileInStream(RandomAccessFile(File(zipPath), "r"))
+
val openInArchive = SevenZip.openInArchive(
ArchiveFormat.SEVEN_ZIP, randomAccessFileInStream
)
@@ -213,6 +208,12 @@ class DetailsActivity : AppCompatActivity() {
if (zipBoolean) {
try {
var filePath: String = ""
+
+ /**
+ * 存档文件中的每个文件项。对于每个文件项,判断是否为文件(非文件夹),
+ * 如果是文件,则将其解压缩到目标路径unPath下的相应位置;
+ * 如果是文件夹,则创建对应的文件夹。
+ */
openInArchive.simpleInterface.archiveItems.forEach { item ->
if (!item.isFolder) {
val file = File(unPath, item.path)
@@ -223,10 +224,10 @@ class DetailsActivity : AppCompatActivity() {
File(unPath, item.path).mkdirs()
}
}
+ //调用接口返回成功
listener.applyListener(true, filePath)
} catch (ex: Exception) {
listener.applyListener(false, "")
-
} finally {
openInArchive.close()
randomAccessFileInStream.close()
@@ -266,9 +267,6 @@ class DetailsActivity : AppCompatActivity() {
}
- private val sp: SharedPreferences = getSharedPreferences(
- AppVal.SHARE_NAME, Context.MODE_PRIVATE
- )
private fun getAllThemePath(zip: String): String {
val result = sp.getString(zip, "")
@@ -281,7 +279,7 @@ class DetailsActivity : AppCompatActivity() {
private fun isChoose(): Boolean {
Settings.Secure.getString(contentResolver, Settings.Secure.DEFAULT_INPUT_METHOD).let { id ->
return id.startsWith(packageName)
- } ?: return false
+ }
}
/**
@@ -296,4 +294,28 @@ class DetailsActivity : AppCompatActivity() {
return false
}
+ /**
+ * 点击设置后的回调接口
+ */
+ override fun applyListener(isSuccess: Boolean, str: String) {
+ binding.themeProgressbar.visibility = View.GONE
+ if (isSuccess) {
+ val lastIndexOf: Int = str.lastIndexOf(AppVal.res_path)
+ val substring = str.subSequence(0, lastIndexOf + AppVal.res_path.length).toString()
+ val edit = sp.edit()
+ edit.run {
+ putString(AppVal.KEY_ALL_PATH, substring)
+ apply()
+ }
+ edit.run {
+ putString(dataModel.title, substring)
+ apply()
+ }
+ Toast.makeText(this, getString(R.string.succ_apply), Toast.LENGTH_LONG).show()
+ finish()
+ } else {
+ Toast.makeText(this, getString(R.string.fail_apply), Toast.LENGTH_LONG).show()
+ }
+ }
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/timber/soft/newkeyboard/listener/ApplyListener.kt b/app/src/main/java/com/timber/soft/newkeyboard/listener/ApplyListener.kt
new file mode 100644
index 0000000..3a218b6
--- /dev/null
+++ b/app/src/main/java/com/timber/soft/newkeyboard/listener/ApplyListener.kt
@@ -0,0 +1,5 @@
+package com.timber.soft.newkeyboard.listener
+
+interface ApplyListener {
+ fun applyListener(isSuccess: Boolean, str: String)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/timber/soft/newkeyboard/tools/ImgTools.kt b/app/src/main/java/com/timber/soft/newkeyboard/tools/ImgTools.kt
deleted file mode 100644
index fe2215b..0000000
--- a/app/src/main/java/com/timber/soft/newkeyboard/tools/ImgTools.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.timber.soft.newkeyboard.tools
-
-object ImgTools {
-
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/timber/soft/newkeyboard/view/MyKeyboardView.kt b/app/src/main/java/com/timber/soft/newkeyboard/view/MyKeyboardView.kt
new file mode 100644
index 0000000..d70439c
--- /dev/null
+++ b/app/src/main/java/com/timber/soft/newkeyboard/view/MyKeyboardView.kt
@@ -0,0 +1,317 @@
+package com.timber.soft.newkeyboard.view
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.content.SharedPreferences
+import android.graphics.BitmapFactory
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Paint
+import android.graphics.Rect
+import android.graphics.drawable.BitmapDrawable
+import android.graphics.drawable.Drawable
+import android.graphics.drawable.StateListDrawable
+import android.inputmethodservice.Keyboard
+import android.inputmethodservice.KeyboardView
+import android.os.Build
+import android.util.AttributeSet
+import android.util.Xml
+import androidx.annotation.RequiresApi
+import androidx.core.content.ContextCompat
+import com.timber.soft.newkeyboard.R
+import com.timber.soft.newkeyboard.tools.AppVal
+import org.xmlpull.v1.XmlPullParser
+import java.io.File
+import java.io.StringReader
+
+@Suppress("DEPRECATION")
+class MyKeyboardView @JvmOverloads constructor(
+ var myContext: Context,
+ attributeSet: AttributeSet? = null,
+ style: Int = 0
+) : KeyboardView(myContext, attributeSet, style) {
+
+ inner class MyConfig {
+ lateinit var functionBackgroundDraw: Drawable
+ lateinit var spBackgroundDraw: Drawable
+ lateinit var normalBackgroundDraw: Drawable
+ var icShittLock: Drawable? =
+ ContextCompat.getDrawable(context, R.drawable.svg_shift_lit)
+ var icDel: Drawable? =
+ ContextCompat.getDrawable(context, R.drawable.svg_dele)
+ var allBg: Drawable? =
+ ContextCompat.getDrawable(context, R.mipmap.main_bg)
+ var icBshift: Drawable? =
+ ContextCompat.getDrawable(context, R.drawable.svg_shift_lit)
+ var icSshift: Drawable? =
+ ContextCompat.getDrawable(context, R.drawable.svg_shift_lit)
+
+ @RequiresApi(Build.VERSION_CODES.M)
+ var keycolor: Int = context.resources.getColor(R.color.white, null)
+
+ private val sp: SharedPreferences = context.getSharedPreferences(
+ AppVal.SHARE_NAME,
+ Context.MODE_PRIVATE
+ )
+
+ private fun getbgic(con: Context, filePath: String): Drawable? {
+ if (!File(filePath).exists()) {
+ return null
+ }
+ return BitmapDrawable(con.resources, BitmapFactory.decodeFile(filePath))
+ }
+
+ private fun getStatus(draw: Drawable, drawPress: Drawable): StateListDrawable {
+ return StateListDrawable().apply {
+ addState(intArrayOf(android.R.attr.state_pressed), drawPress)
+ addState(intArrayOf(), draw)
+ }
+ }
+
+ @RequiresApi(Build.VERSION_CODES.M)
+ private fun gettextcolor(colorXmlPath: String) {
+ val file = File(colorXmlPath)
+ if (!file.exists()) return
+ val xmlP = Xml.newPullParser()
+
+ xmlP.setInput(StringReader(file.readText()))
+ xmlP.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false)
+
+ var eventT = xmlP.eventType
+ while (eventT != XmlPullParser.END_DOCUMENT) {
+ if (eventT == XmlPullParser.START_TAG && (xmlP.name == "color" || xmlP.name == "item")) {
+ val value = xmlP.getAttributeValue(null, "name")
+ if (value != null && value == AppVal.title_color) {
+ keycolor = Color.parseColor(xmlP.nextText())
+ }
+ }
+ eventT = xmlP.next()
+ }
+
+
+ }
+
+
+ init {
+ val default =
+ ContextCompat.getDrawable(context, R.drawable.png_keybg)
+ val press = ContextCompat.getDrawable(
+ context,
+ R.drawable.png_keybg_press
+ )
+ if (press != null) {
+ if (default != null) {
+ val listDrawable = StateListDrawable().apply {
+ addState(intArrayOf(android.R.attr.state_pressed), press)
+ addState(intArrayOf(), default)
+ }
+ functionBackgroundDraw = listDrawable
+ normalBackgroundDraw = listDrawable
+ spBackgroundDraw = listDrawable
+ }
+ }
+ }
+
+ @RequiresApi(Build.VERSION_CODES.M)
+ fun updateConfig(con: Context) {
+ sp.getString(AppVal.KEY_ALL_PATH, "")?.let {
+ getbgic(
+ con,
+ it.plus(AppVal.parent_path).plus(AppVal.title_nor_Bg)
+ )?.let { drawBG ->
+ getbgic(
+ con,
+ it.plus(AppVal.parent_path).plus(AppVal.title_nor_Bg_press)
+ )?.let { drawPressBG ->
+ normalBackgroundDraw = getStatus(drawBG, drawPressBG)
+ }
+
+ }
+ gettextcolor(it.plus(AppVal.color_path))
+ getbgic(con, it.plus(AppVal.parent_path).plus(AppVal.title_sp_Bg))?.let { drawBG ->
+ getbgic(
+ con,
+ it.plus(AppVal.parent_path).plus(AppVal.title_sp_Bg_press)
+ )?.let { drawPressBG ->
+ spBackgroundDraw = getStatus(drawBG, drawPressBG)
+ }
+
+ }
+ getbgic(con, it.plus(AppVal.xx_path).plus(AppVal.title_bg))?.run {
+ allBg = this
+ }
+
+ getbgic(
+ con,
+ it.plus(AppVal.parent_path).plus(AppVal.title_fun_Bg)
+ )?.let { drawBG ->
+ getbgic(
+ con,
+ it.plus(AppVal.parent_path).plus(AppVal.title_func_bg_press)
+ )?.let { drawPressBG ->
+ functionBackgroundDraw = getStatus(drawBG, drawPressBG)
+ }
+
+ }
+
+
+ getbgic(con, it.plus(AppVal.parent_path).plus(AppVal.title_shitf_ic))?.let {
+ icSshift = it
+ icBshift = it
+ }
+ getbgic(
+ con,
+ it.plus(AppVal.parent_path).plus(AppVal.title_del_ic)
+ )?.let { drawBG ->
+ icDel = getStatus(drawBG, drawBG)
+
+
+ }
+ getbgic(con, it.plus(AppVal.parent_path).plus(AppVal.title_shitf_ic_lock))?.let {
+ icShittLock = it
+ }
+
+ }
+ }
+ }
+
+ var config = MyConfig()
+ var shiftStatus = AppVal.Shift_S
+ var xmlMode = AppVal.xml0
+
+ @RequiresApi(Build.VERSION_CODES.M)
+ private var myPaint: Paint = Paint().apply {
+ isAntiAlias = true
+ textAlign = Paint.Align.CENTER
+ textSize = myContext.resources.displayMetrics.scaledDensity * 16f
+ color = config.keycolor
+ }
+
+ @RequiresApi(Build.VERSION_CODES.M)
+ @SuppressLint("SuspiciousIndentation")
+ private fun andDraw(
+ myKey: Keyboard.Key,
+ keyBG: Drawable,
+ icon: Drawable?,
+ canvas: Canvas,
+ ) {
+ myKey.run {
+ keyBG.run {
+ bounds = Rect(
+ x.plus(paddingLeft),
+ y.plus(paddingTop),
+ width.plus(x.plus(paddingLeft)),
+ height.plus(y.plus(paddingTop))
+ )
+ state = currentDrawableState
+ draw(canvas)
+ }
+ }
+ myKey.run {
+ icon?.apply {
+ myKey.icon = this
+
+ var icon_w = myKey.icon.intrinsicWidth.toFloat()
+ var icon_wr = icon_w / myKey.width.toFloat()
+ var icon_h = myKey.icon.intrinsicHeight.toFloat()
+ var icon_hr = icon_h / myKey.height.toFloat()
+
+
+ var tep1 = 0f
+ var tep2 = 0f
+ if (icon_wr > icon_hr) {
+ tep2 = icon_wr
+ tep1 = icon_wr.coerceAtLeast(0.5f)
+
+ } else {
+ tep2 = icon_hr
+ tep1 = icon_hr.coerceAtLeast(0.5f)
+
+ }
+ icon_h = (icon_h / tep2) * tep1
+ icon_w = (icon_w / tep2) * tep1
+ myKey.icon.let {
+ it.bounds = Rect().apply {
+
+ top =
+ (myKey.y + paddingTop + (myKey.height - icon_h) / 2f).toInt()
+ left =
+ (myKey.x + paddingLeft + (myKey.width - icon_w) / 2f).toInt()
+ bottom = (top + icon_h).toInt()
+ right = (left + icon_w).toInt()
+
+ }
+ it.draw(canvas)
+ }
+ }
+
+ myPaint.color = config.keycolor
+ if (!label.isNullOrEmpty()) {
+ val y1 = y.plus(paddingRight).plus((height.div(2f)))
+ .plus((myPaint.textSize.minus(myPaint.descent())).div(2f))
+ val x1 = x.plus(paddingLeft).plus((width.div(2f)))
+ canvas.drawText(label.toString(), x1, y1, myPaint)
+ }
+ }
+ }
+
+ private fun getCurIc(): Drawable? {
+ return when (shiftStatus) {
+ AppVal.Shift_B_lo -> config.icShittLock
+ AppVal.Shift_B -> config.icBshift
+ AppVal.Shift_S -> config.icSshift
+ else -> config.icSshift
+ }
+ }
+
+ @RequiresApi(Build.VERSION_CODES.M)
+ override fun onDraw(canvas: Canvas) {
+ super.onDraw(canvas)
+ keyboard.keys.forEach {
+ when (it.codes[0]) {
+ Keyboard.KEYCODE_SHIFT -> {
+ andDraw(
+ it,
+ config.functionBackgroundDraw,
+ getCurIc(),
+ canvas
+ )
+ }
+
+ AppVal.SHIFT_NUMBER, AppVal.SHIFT_SYMBOL -> {
+ andDraw(it, config.functionBackgroundDraw, null, canvas)
+ }
+
+ Keyboard.KEYCODE_DELETE -> {
+ andDraw(
+ it,
+ config.functionBackgroundDraw,
+ config.icDel,
+ canvas
+ )
+ }
+
+ Keyboard.KEYCODE_MODE_CHANGE, Keyboard.KEYCODE_DONE -> {
+ andDraw(
+ it,
+ config.functionBackgroundDraw,
+ null,
+ canvas
+ )
+ }
+
+ else -> {
+ andDraw(it, config.normalBackgroundDraw, null, canvas)
+ }
+ }
+ }
+ }
+
+ @RequiresApi(Build.VERSION_CODES.M)
+ fun upUi(con: Context) {
+ config.updateConfig(con)
+ background = config.allBg
+ invalidate()
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/png_keybg.9.png b/app/src/main/res/drawable/png_keybg.9.png
new file mode 100644
index 0000000..fcf5166
Binary files /dev/null and b/app/src/main/res/drawable/png_keybg.9.png differ
diff --git a/app/src/main/res/drawable/png_keybg_press.9.png b/app/src/main/res/drawable/png_keybg_press.9.png
new file mode 100644
index 0000000..b3f2727
Binary files /dev/null and b/app/src/main/res/drawable/png_keybg_press.9.png differ
diff --git a/app/src/main/res/drawable/shape_white_keyboard.xml b/app/src/main/res/drawable/shape_white_keyboard.xml
new file mode 100644
index 0000000..1e7a91a
--- /dev/null
+++ b/app/src/main/res/drawable/shape_white_keyboard.xml
@@ -0,0 +1,16 @@
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/svg_dele.xml b/app/src/main/res/drawable/svg_dele.xml
new file mode 100644
index 0000000..1c653c8
--- /dev/null
+++ b/app/src/main/res/drawable/svg_dele.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/svg_shift_lit.xml b/app/src/main/res/drawable/svg_shift_lit.xml
new file mode 100644
index 0000000..858c5ef
--- /dev/null
+++ b/app/src/main/res/drawable/svg_shift_lit.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/layout/view_input.xml b/app/src/main/res/layout/view_input.xml
new file mode 100644
index 0000000..cbc1091
--- /dev/null
+++ b/app/src/main/res/layout/view_input.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-xxxhdpi/main_bg.png b/app/src/main/res/mipmap-xxxhdpi/main_bg.png
new file mode 100644
index 0000000..22eb3bf
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/main_bg.png differ
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 415f48c..510b12c 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -11,4 +11,5 @@
Step 2: Enable
Application successful
Application failed, please try again
+ For normal use, please enter the setting to complete the setting steps.
\ No newline at end of file
diff --git a/app/src/main/res/xml/key_view.xml b/app/src/main/res/xml/key_view.xml
new file mode 100644
index 0000000..16a78b2
--- /dev/null
+++ b/app/src/main/res/xml/key_view.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/xml/keyboard_letter.xml b/app/src/main/res/xml/keyboard_letter.xml
new file mode 100644
index 0000000..c810e6c
--- /dev/null
+++ b/app/src/main/res/xml/keyboard_letter.xml
@@ -0,0 +1,151 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/xml/keyboard_number.xml b/app/src/main/res/xml/keyboard_number.xml
new file mode 100644
index 0000000..23117d4
--- /dev/null
+++ b/app/src/main/res/xml/keyboard_number.xml
@@ -0,0 +1,149 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/xml/keyboard_symbol.xml b/app/src/main/res/xml/keyboard_symbol.xml
new file mode 100644
index 0000000..7470b49
--- /dev/null
+++ b/app/src/main/res/xml/keyboard_symbol.xml
@@ -0,0 +1,157 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file