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>
</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.ApplyActivity" />
</application>

View File

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

View File

@ -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 {

View File

@ -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<File> {
//失败回调
override fun onLoadFailed(
e: GlideException?, model: Any?, target: Target<File>, 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()
}
}
}

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="succ_apply">Application successful</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>

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>