completely

This commit is contained in:
LUX-Timber 2024-04-07 14:05:46 +08:00
parent 427b1184f6
commit a9d33c1ec3
19 changed files with 1057 additions and 50 deletions

View File

@ -25,6 +25,19 @@
</intent-filter> </intent-filter>
</activity> </activity>
<service
android:name=".AppInputMethodService"
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/key_view" />
</service>
<activity android:name=".activity.DetailsActivity" /> <activity android:name=".activity.DetailsActivity" />
<activity android:name=".activity.ApplyActivity" /> <activity android:name=".activity.ApplyActivity" />
</application> </application>

View File

@ -1,37 +1,100 @@
package com.timber.soft.newkeyboard package com.timber.soft.newkeyboard
import android.inputmethodservice.InputMethodService import android.inputmethodservice.InputMethodService
import android.inputmethodservice.Keyboard
import android.inputmethodservice.KeyboardView.OnKeyboardActionListener import android.inputmethodservice.KeyboardView.OnKeyboardActionListener
import android.os.Build
import android.os.SystemClock
import android.view.KeyboardShortcutGroup
import android.view.View 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 { 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 { override fun onCreateInputView(): View {
return super.onCreateInputView() binding = ViewInputBinding.inflate(layoutInflater, null, false)
TODO("Not yet implemented") 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() { override fun onWindowShown() {
super.onWindowShown() super.onWindowShown()
TODO("Not yet implemented") binding.myCustomInput.upUi(this@AppInputMethodService)
} }
/** /**
* Called when the user presses a key. * Called when the user presses a key.
* *
* 监听特定的按钮 * 监听特定的按钮
*/ */
override fun onPress(primaryCode: Int) { 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?) { 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
}
}
} }

View File

@ -67,7 +67,7 @@ class ApplyActivity : AppCompatActivity() {
private fun isChoose(): Boolean { private fun isChoose(): Boolean {
Settings.Secure.getString(contentResolver, Settings.Secure.DEFAULT_INPUT_METHOD).let { id -> Settings.Secure.getString(contentResolver, Settings.Secure.DEFAULT_INPUT_METHOD).let { id ->
return id.startsWith(packageName) return id.startsWith(packageName)
} ?: return false }
} }
private fun isEnable(): Boolean { private fun isEnable(): Boolean {

View File

@ -22,6 +22,7 @@ import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.target.Target import com.bumptech.glide.request.target.Target
import com.timber.soft.newkeyboard.R import com.timber.soft.newkeyboard.R
import com.timber.soft.newkeyboard.databinding.ActivityDetailsBinding 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.model.DataModel
import com.timber.soft.newkeyboard.tools.AppVal import com.timber.soft.newkeyboard.tools.AppVal
import com.timber.soft.newkeyboard.tools.StatusBarTools import com.timber.soft.newkeyboard.tools.StatusBarTools
@ -36,13 +37,14 @@ import java.io.FileOutputStream
import java.io.InputStream import java.io.InputStream
import java.io.RandomAccessFile import java.io.RandomAccessFile
class DetailsActivity : AppCompatActivity() { class DetailsActivity : AppCompatActivity(), ApplyListener {
private lateinit var binding: ActivityDetailsBinding private lateinit var binding: ActivityDetailsBinding
private lateinit var inputManager: InputMethodManager private lateinit var inputManager: InputMethodManager
private lateinit var previewUrl: String private lateinit var previewUrl: String
private lateinit var zipPath: String private lateinit var zipPath: String
private lateinit var dataModel: DataModel private lateinit var dataModel: DataModel
private lateinit var sp: SharedPreferences
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -117,68 +119,59 @@ class DetailsActivity : AppCompatActivity() {
e.printStackTrace() e.printStackTrace()
} }
// 初始化键值对
sp = getSharedPreferences(
AppVal.SHARE_NAME, Context.MODE_PRIVATE
)
} }
private fun applyTheme() { private fun applyTheme() {
// 检查是否启动键盘并设置 // 检查是否启动键盘并设置
if (!isEnable() || !isChoose()) { if (!isEnable() || !isChoose()) {
Toast.makeText(this, getString(R.string.text_promote), Toast.LENGTH_SHORT).show()
val intent = Intent(this, ApplyActivity::class.java) val intent = Intent(this, ApplyActivity::class.java)
startActivity(intent) startActivity(intent)
return return
} }
binding.themeProgressbar.visibility = View.VISIBLE binding.themeProgressbar.visibility = View.VISIBLE
val file = File(zipPath) val file = File(zipPath)
// 判断缓存中是否存在文件 // 判断缓存中是否存在文件
if (file.exists()) { if (file.exists()) {
val allThemePath: String = getAllThemePath(dataModel.title) val allThemePath: String = getAllThemePath(dataModel.title)
val edit = sp.edit() val edit = sp.edit()
// 存放键值对
edit.run { edit.run {
putString(AppVal.KEY_ALL_PATH, allThemePath) putString(AppVal.KEY_ALL_PATH, allThemePath)
apply() apply()
} }
} else { } 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 * 从指定的URL下载zip文件并在下载完成后处理该文件
if (isSuccess) { *
val lastIndexOf: Int = path.lastIndexOf(AppVal.res_path) * @param title 下载文件的标题
val substring = path.subSequence(0, lastIndexOf + AppVal.res_path.length).toString() * @param url 下载文件的URL
* @param con 上下文Context
val edit = sp.edit() * @param listener 处理文件完成后的回调接口
*/
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)
}
private fun getZipData(title: String, url: String, con: Context, listener: ApplyListener) { private fun getZipData(title: String, url: String, con: Context, listener: ApplyListener) {
Glide.with(con).asFile().load(url).addListener(object : RequestListener<File> { Glide.with(con).asFile().load(url).addListener(object : RequestListener<File> {
//失败回调
override fun onLoadFailed( override fun onLoadFailed(
e: GlideException?, model: Any?, target: Target<File>, isFirstResource: Boolean e: GlideException?, model: Any?, target: Target<File>, isFirstResource: Boolean
): Boolean { ): Boolean {
// 回调失败
listener.applyListener(false, "") listener.applyListener(false, "")
return false return false
} }
//成功回调
override fun onResourceReady( override fun onResourceReady(
resource: File, resource: File,
model: Any, model: Any,
@ -186,7 +179,6 @@ class DetailsActivity : AppCompatActivity() {
dataSource: DataSource, dataSource: DataSource,
isFirstResource: Boolean isFirstResource: Boolean
): Boolean { ): Boolean {
val fileInputStream = FileInputStream(resource) val fileInputStream = FileInputStream(resource)
dealFile(title, url, fileInputStream, listener) dealFile(title, url, fileInputStream, listener)
return false return false
@ -201,9 +193,12 @@ class DetailsActivity : AppCompatActivity() {
val zipPath = "${cacheDir}/${title}_ZIP" val zipPath = "${cacheDir}/${title}_ZIP"
val unPath = "${cacheDir}/${title}" val unPath = "${cacheDir}/${title}"
// 将下载的zip文件保存到zipPath路径
val zipBoolean = writeNewFile(input, zipPath) val zipBoolean = writeNewFile(input, zipPath)
// 随机读写
val randomAccessFileInStream = val randomAccessFileInStream =
RandomAccessFileInStream(RandomAccessFile(File(zipPath), "r")) RandomAccessFileInStream(RandomAccessFile(File(zipPath), "r"))
val openInArchive = SevenZip.openInArchive( val openInArchive = SevenZip.openInArchive(
ArchiveFormat.SEVEN_ZIP, randomAccessFileInStream ArchiveFormat.SEVEN_ZIP, randomAccessFileInStream
) )
@ -213,6 +208,12 @@ class DetailsActivity : AppCompatActivity() {
if (zipBoolean) { if (zipBoolean) {
try { try {
var filePath: String = "" var filePath: String = ""
/**
* 存档文件中的每个文件项对于每个文件项判断是否为文件非文件夹
* 如果是文件则将其解压缩到目标路径unPath下的相应位置
* 如果是文件夹则创建对应的文件夹
*/
openInArchive.simpleInterface.archiveItems.forEach { item -> openInArchive.simpleInterface.archiveItems.forEach { item ->
if (!item.isFolder) { if (!item.isFolder) {
val file = File(unPath, item.path) val file = File(unPath, item.path)
@ -223,10 +224,10 @@ class DetailsActivity : AppCompatActivity() {
File(unPath, item.path).mkdirs() File(unPath, item.path).mkdirs()
} }
} }
//调用接口返回成功
listener.applyListener(true, filePath) listener.applyListener(true, filePath)
} catch (ex: Exception) { } catch (ex: Exception) {
listener.applyListener(false, "") listener.applyListener(false, "")
} finally { } finally {
openInArchive.close() openInArchive.close()
randomAccessFileInStream.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 { private fun getAllThemePath(zip: String): String {
val result = sp.getString(zip, "") val result = sp.getString(zip, "")
@ -281,7 +279,7 @@ class DetailsActivity : AppCompatActivity() {
private fun isChoose(): Boolean { private fun isChoose(): Boolean {
Settings.Secure.getString(contentResolver, Settings.Secure.DEFAULT_INPUT_METHOD).let { id -> Settings.Secure.getString(contentResolver, Settings.Secure.DEFAULT_INPUT_METHOD).let { id ->
return id.startsWith(packageName) return id.startsWith(packageName)
} ?: return false }
} }
/** /**
@ -296,4 +294,28 @@ class DetailsActivity : AppCompatActivity() {
return false 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()
}
}
} }

View File

@ -0,0 +1,5 @@
package com.timber.soft.newkeyboard.listener
interface ApplyListener {
fun applyListener(isSuccess: Boolean, str: String)
}

View File

@ -1,5 +0,0 @@
package com.timber.soft.newkeyboard.tools
object ImgTools {
}

View File

@ -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()
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" >
<shape android:shape="rectangle">
<solid android:color="@color/white"/>
<corners android:radius="5dp"/>
</shape>
</item>
<item android:state_pressed="false">
<shape android:shape="rectangle">
<solid android:color="@color/white"/>
<corners android:radius="5dp"/>
</shape>
</item>
</selector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M830.3,170.3H437.6A178.3,178.3 0,0 0,310.7 223L58.2,475.3a61.5,61.5 0,0 0,0 86.9l252.3,252.3a178.3,178.3 0,0 0,127.1 52.7h392.7A152.9,152.9 0,0 0,983 714.5V323a152.9,152.9 0,0 0,-152.7 -152.7zM760.2,628.8a25.6,25.6 0,0 1,-36.1 36.1L614.1,554.8 504,664.9a25.6,25.6 0,1 1,-36.1 -36.1L578,518.7 467.9,408.5A25.6,25.6 0,1 1,504 372.4l110.1,110.3L724.1,372.4a25.6,25.6 0,0 1,36.1 0,25.6 25.6,0 0,1 0,36.3L650.1,518.7z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M459.7,155.7l-5.5,4.1 -2.4,2 -3.8,3.5 -2.2,2.2 -3.5,3.8 -258.1,305.9 -4.2,5.4c-28.1,40.2 -20.7,93.3 16,123.6l5.9,4.4 3,2 4.9,2.9 5.6,2.8c13,6.1 26.2,8.9 39.5,8.9l58.6,-0 0,142.6 0.2,6.1c4,48.9 44,85.3 91.9,85.3h212.4l6.1,-0.2 2.7,-0.2 4.8,-0.6 4.7,-0.9c43.4,-9.4 73.7,-46.3 73.7,-89.5l-0,-142.6h58.8l6.1,-0.2c35.6,-2.9 65.4,-24.3 78.7,-55.7a90.9,90.9 0,0 0,-14.2 -94.1L582.4,172.4l-4.6,-5 -1.1,-1.1a92.6,92.6 0,0 0,-117.1 -10.6zM525.3,213.9l2.1,1.8 2.7,2.9 255.9,303.5a21,21 0,0 1,3.4 21.9,22.2 22.2,0 0,1 -18.7,13.3l-3.3,0.1 -127.1,-0v212.4l-0.2,2.6a21.9,21.9 0,0 1,-18.3 18.7l-1.5,0.2 -3.7,0.2L405.6,791.3a22,22 0,0 1,-22.2 -19.9l-0.1,-3.2v-210.9h-128.5l-2.8,-0.2a22.8,22.8 0,0 1,-8 -2.5l-1.7,-1 -3.3,-2.4c-7.4,-6.1 -9.1,-18.4 -2.7,-27.5l2.2,-2.9L494.6,217.4l1.4,-1.5 1.5,-1.3 2.9,-2.2c6.8,-4.6 17.3,-4.1 24.9,1.5z"
android:fillColor="#FFFFFF"/>
</vector>

View File

@ -0,0 +1,19 @@
<?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">
<com.timber.soft.newkeyboard.view.MyKeyboardView
android:id="@+id/my_custom_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:focusable="true"
android:focusableInTouchMode="true"
android:keyBackground="@drawable/shape_white_keyboard"
android:keyTextSize="15sp"
android:labelTextSize="15sp"
android:paddingTop="3dp"
android:paddingBottom="3dp" />
</FrameLayout>

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

View File

@ -11,4 +11,5 @@
<string name="apply_step2_eanble">Step 2: Enable</string> <string name="apply_step2_eanble">Step 2: Enable</string>
<string name="succ_apply">Application successful</string> <string name="succ_apply">Application successful</string>
<string name="fail_apply">Application failed, please try again</string> <string name="fail_apply">Application failed, please try again</string>
<string name="text_promote">For normal use, please enter the setting to complete the setting steps.</string>
</resources> </resources>

View 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:icon="@drawable/ic_launcher_background"
android:imeSubtypeLocale="en_US"
android:imeSubtypeMode="keyboard"
android:label="@string/app_name" />
</input-method>

View File

@ -0,0 +1,151 @@
<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
android:keyWidth="10%p"
android:keyHeight="46dp"
android:verticalGap="3dp">
<Row
android:horizontalGap="0.5%"
android:keyWidth="9.45%"
android:keyHeight="46dp"
android:rowEdgeFlags="top">
<Key
android:codes="113"
android:keyEdgeFlags="left"
android:keyLabel="q" />
<Key
android:codes="119"
android:keyLabel="w" />
<Key
android:codes="101"
android:keyLabel="e" />
<Key
android:codes="114"
android:keyLabel="r" />
<Key
android:codes="116"
android:keyLabel="t" />
<Key
android:codes="121"
android:keyLabel="y" />
<Key
android:codes="117"
android:keyLabel="u" />
<Key
android:codes="105"
android:keyLabel="i" />
<Key
android:codes="111"
android:keyLabel="o" />
<Key
android:codes="112"
android:keyEdgeFlags="right"
android:keyLabel="p" />
</Row>
<Row
android:horizontalGap="0.5%"
android:keyWidth="9.444444%"
android:keyHeight="46dp">
<Key
android:codes="97"
android:horizontalGap="5.5%"
android:keyLabel="a" />
<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" />
</Row>
<Row
android:horizontalGap="0.5%"
android:keyWidth="9.5%"
android:keyHeight="46dp">
<!--shift-->
<Key
android:codes="-1"
android:isModifier="true"
android:isSticky="true"
android:keyWidth="14.25%"
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" />
<!--delete-->
<Key
android:codes="-5"
android:isModifier="true"
android:isRepeatable="true"
android:keyWidth="14.25%"
android:keyEdgeFlags="right" />
</Row>
<Row
android:horizontalGap="0.5%"
android:keyWidth="9.5%"
android:keyHeight="46dp"
android:rowEdgeFlags="bottom">
<!--mode change 切到模式2-->
<Key
android:codes="-2"
android:keyWidth="14.25%"
android:keyEdgeFlags="left"
android:keyLabel="\?123" />
<Key
android:codes="44"
android:keyLabel="," />
<Key
android:codes="32"
android:keyWidth="49.5%"
android:keyLabel="English" />
<Key
android:codes="46"
android:keyLabel="." />
<!--Done-->
<Key
android:codes="-4"
android:keyWidth="14.25%"
android:keyEdgeFlags="right"
android:keyLabel="Done" />
</Row>
</Keyboard>

View File

@ -0,0 +1,149 @@
<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
android:verticalGap="3dp">
<Row
android:keyWidth="9.45%"
android:keyHeight="46dp"
android:horizontalGap="0.5%"
android:rowEdgeFlags="top">
<Key
android:codes="49"
android:keyEdgeFlags="left"
android:keyLabel="1" />
<Key android:keyLabel="2"
android:codes="50"/>
<Key android:keyLabel="3"
android:codes="51"/>
<Key android:keyLabel="4"
android:codes="52"/>
<Key android:keyLabel="5"
android:codes="53"/>
<Key android:keyLabel="6"
android:codes="54"/>
<Key android:keyLabel="7"
android:codes="55"/>
<Key android:keyLabel="8"
android:codes="56"/>
<Key android:keyLabel="9"
android:codes="57"/>
<Key
android:keyEdgeFlags="right"
android:codes="48"
android:keyLabel="0" />
</Row>
<Row
android:keyWidth="9.444444%"
android:keyHeight="46dp"
android:horizontalGap="0.5%">
<Key
android:keyEdgeFlags="left"
android:keyLabel="\@"
android:horizontalGap="5.5%"
android:codes="64"/>
<Key android:keyLabel="#"
android:codes="35"/>
<Key android:keyLabel="\$"
android:codes="36"/>
<Key android:keyLabel="%"
android:codes="37"/>
<Key android:keyLabel="&amp;"
android:codes="38"/>
<Key android:keyLabel="-"
android:codes="45"/>
<Key android:keyLabel="+"
android:codes="43"/>
<Key android:keyLabel="("
android:codes="40"/>
<Key
android:keyEdgeFlags="right"
android:codes="41"
android:keyLabel=")" />
</Row>
<Row
android:keyHeight="46dp"
android:keyWidth="9.5%"
android:horizontalGap="0.5%">
<!--more 切换到符号键盘模式-->
<Key
android:codes="-300"
android:isModifier="true"
android:keyWidth="14.25%"
android:keyLabel="more"
android:keyEdgeFlags="left" />
<Key android:keyLabel="*"
android:codes="42" />
<!-- "-->
<Key android:keyLabel="&#034;"
android:codes="34" />
<Key android:keyLabel="'"
android:codes="39" />
<Key android:keyLabel=":"
android:codes="58" />
<Key android:keyLabel=";"
android:codes="59" />
<Key android:keyLabel="!"
android:codes="33" />
<Key android:keyLabel="\?"
android:codes="63" />
<!--delete-->
<Key
android:codes="-5"
android:keyWidth="14.25%"
android:isModifier="true"
android:isRepeatable="true"
android:keyEdgeFlags="right" />
</Row>
<Row
android:horizontalGap="0.5%"
android:keyHeight="46dp"
android:rowEdgeFlags="bottom"
android:keyWidth="9.5%">
<!-- 返回模式1 -->
<Key
android:codes="-2"
android:keyWidth="14.25%"
android:keyEdgeFlags="left"
android:keyLabel="ABC" />
<Key android:keyLabel=","
android:codes="44" />
<Key android:keyLabel="_"
android:codes="95" />
<Key
android:codes="32"
android:keyWidth="29.5%"
android:keyLabel="English" />
<Key android:keyLabel="/"
android:codes="47" />
<Key android:keyLabel="."
android:codes="46" />
<!--Done-->
<Key
android:codes="-4"
android:keyLabel="Done"
android:keyWidth="14.25%"
android:keyEdgeFlags="right" />
</Row>
</Keyboard>

View File

@ -0,0 +1,157 @@
<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
android:verticalGap="3dp">
<Row
android:keyWidth="9.45%"
android:keyHeight="46dp"
android:horizontalGap="0.5%"
android:rowEdgeFlags="top">
<Key
android:codes="126"
android:keyEdgeFlags="left"
android:keyLabel="~" />
<Key android:keyLabel="`"
android:codes="96"/>
<Key android:keyLabel="|"
android:codes="124"/>
<Key android:keyLabel="•"
android:codes="149"/>
<Key android:keyLabel="✔"
android:codes="10004"/>
<Key android:keyLabel="π"
android:codes="960"/>
<Key android:keyLabel="÷"
android:codes="247"/>
<Key android:keyLabel="×"
android:codes="215"/>
<Key android:keyLabel="¶"
android:codes="182"/>
<Key
android:keyEdgeFlags="right"
android:codes="8710"
android:keyLabel="∆" />
</Row>
<Row
android:keyWidth="9.444444%"
android:keyHeight="46dp"
android:horizontalGap="0.5%">
<Key
android:keyEdgeFlags="left"
android:keyLabel="£"
android:horizontalGap="5.5%"
android:codes="163"/>
<Key android:keyLabel="¢"
android:codes="65504"/>
<Key android:keyLabel="€"
android:codes="8364"/>
<Key android:keyLabel="¥"
android:codes="165"/>
<Key android:keyLabel="^"
android:codes="94"/>
<Key android:keyLabel="°"
android:codes="176"/>
<Key android:keyLabel="="
android:codes="61"/>
<Key android:keyLabel="{"
android:codes="123"/>
<Key
android:keyEdgeFlags="right"
android:codes="125"
android:keyLabel="}" />
</Row>
<Row
android:keyHeight="46dp"
android:keyWidth="9.5%"
android:horizontalGap="0.5%">
<!-- shift-->
<Key
android:codes="-301"
android:isModifier="true"
android:keyWidth="14.25%"
android:keyLabel="\?123"
android:keyEdgeFlags="left" />
<Key android:keyLabel="\\"
android:codes="92" />
<Key android:keyLabel="Ⓒ"
android:codes="9400" />
<Key android:keyLabel="®"
android:codes="174" />
<Key android:keyLabel="™"
android:codes="8482" />
<Key android:keyLabel="℅"
android:codes="8453" />
<Key android:keyLabel="["
android:codes="91" />
<Key android:keyLabel="]"
android:codes="93" />
<!--delete-->
<Key
android:codes="-5"
android:keyWidth="14.25%"
android:isModifier="true"
android:isRepeatable="true"
android:keyEdgeFlags="right" />
</Row>
<Row
android:horizontalGap="0.5%"
android:keyHeight="46dp"
android:rowEdgeFlags="bottom"
android:keyWidth="9.5%">
<!--mode change 回到模式1-->
<Key
android:codes="-2"
android:keyWidth="14.25%"
android:keyEdgeFlags="left"
android:keyLabel="ABC" />
<Key android:keyLabel=","
android:codes="46" />
<Key android:keyLabel="&lt;"
android:codes="60" />
<Key
android:codes="32"
android:keyWidth="29.5%"
android:keyLabel="English" />
<Key android:keyLabel="&gt;"
android:codes="62" />
<Key android:keyLabel="."
android:codes="46" />
<!--Done-->
<Key
android:codes="-4"
android:keyLabel="Done"
android:keyWidth="14.25%"
android:keyEdgeFlags="right" />
</Row>
</Keyboard>