completely
This commit is contained in:
parent
427b1184f6
commit
a9d33c1ec3
@ -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>
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
package com.timber.soft.newkeyboard.listener
|
||||
|
||||
interface ApplyListener {
|
||||
fun applyListener(isSuccess: Boolean, str: String)
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
package com.timber.soft.newkeyboard.tools
|
||||
|
||||
object ImgTools {
|
||||
|
||||
}
|
||||
@ -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()
|
||||
}
|
||||
|
||||
}
|
||||
BIN
app/src/main/res/drawable/png_keybg.9.png
Normal file
BIN
app/src/main/res/drawable/png_keybg.9.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.8 KiB |
BIN
app/src/main/res/drawable/png_keybg_press.9.png
Normal file
BIN
app/src/main/res/drawable/png_keybg_press.9.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.5 KiB |
16
app/src/main/res/drawable/shape_white_keyboard.xml
Normal file
16
app/src/main/res/drawable/shape_white_keyboard.xml
Normal 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>
|
||||
9
app/src/main/res/drawable/svg_dele.xml
Normal file
9
app/src/main/res/drawable/svg_dele.xml
Normal 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>
|
||||
9
app/src/main/res/drawable/svg_shift_lit.xml
Normal file
9
app/src/main/res/drawable/svg_shift_lit.xml
Normal 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>
|
||||
19
app/src/main/res/layout/view_input.xml
Normal file
19
app/src/main/res/layout/view_input.xml
Normal 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>
|
||||
BIN
app/src/main/res/mipmap-xxxhdpi/main_bg.png
Normal file
BIN
app/src/main/res/mipmap-xxxhdpi/main_bg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 86 KiB |
@ -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>
|
||||
8
app/src/main/res/xml/key_view.xml
Normal file
8
app/src/main/res/xml/key_view.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:icon="@drawable/ic_launcher_background"
|
||||
android:imeSubtypeLocale="en_US"
|
||||
android:imeSubtypeMode="keyboard"
|
||||
android:label="@string/app_name" />
|
||||
</input-method>
|
||||
151
app/src/main/res/xml/keyboard_letter.xml
Normal file
151
app/src/main/res/xml/keyboard_letter.xml
Normal 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>
|
||||
149
app/src/main/res/xml/keyboard_number.xml
Normal file
149
app/src/main/res/xml/keyboard_number.xml
Normal 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="&"
|
||||
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="""
|
||||
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>
|
||||
157
app/src/main/res/xml/keyboard_symbol.xml
Normal file
157
app/src/main/res/xml/keyboard_symbol.xml
Normal 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="<"
|
||||
android:codes="60" />
|
||||
<Key
|
||||
android:codes="32"
|
||||
android:keyWidth="29.5%"
|
||||
android:keyLabel="English" />
|
||||
|
||||
<Key android:keyLabel=">"
|
||||
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>
|
||||
Loading…
Reference in New Issue
Block a user