V1.0.1(2)创建仓库
15
.gitignore
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/caches
|
||||
/.idea/libraries
|
||||
/.idea/modules.xml
|
||||
/.idea/workspace.xml
|
||||
/.idea/navEditor.xml
|
||||
/.idea/assetWizardSettings.xml
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
BIN
FingerKeyboard.test.jks
Normal file
1
app/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
||||
BIN
app/FingerKeyboard.jks
Normal file
BIN
app/FingerKeyboardtest.jks
Normal file
62
app/build.gradle.kts
Normal file
@ -0,0 +1,62 @@
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.android.application)
|
||||
alias(libs.plugins.jetbrains.kotlin.android)
|
||||
}
|
||||
val timestamp: String = SimpleDateFormat("MM_dd_HH_mm").format(Date())
|
||||
android {
|
||||
namespace = "com.example.fingerkeyboard"
|
||||
compileSdk = 34
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "com.finger.keyboard.selection"
|
||||
minSdk =23
|
||||
targetSdk = 34
|
||||
versionCode = 2
|
||||
versionName = "1.0.1"
|
||||
setProperty("archivesBaseName", "Finger Keyboard_" + versionName + "(${versionCode})_$timestamp")
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
isMinifyEnabled = true
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation(libs.appcompat)
|
||||
implementation(libs.material)
|
||||
implementation(libs.activity)
|
||||
implementation(libs.constraintlayout)
|
||||
testImplementation(libs.junit)
|
||||
androidTestImplementation(libs.ext.junit)
|
||||
androidTestImplementation(libs.espresso.core)
|
||||
|
||||
implementation("androidx.activity:activity-compose:1.8.2")
|
||||
implementation("com.google.android.material:material:1.11.0")
|
||||
implementation ("com.github.bumptech.glide:glide:4.16.0")
|
||||
|
||||
implementation("androidx.core:core-ktx:1.12.0")
|
||||
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0")
|
||||
implementation("androidx.appcompat:appcompat:1.6.1")
|
||||
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
||||
|
||||
implementation("com.github.omicronapps:7-Zip-JBinding-4Android:Release-16.02-2.02")
|
||||
implementation ("com.google.code.gson:gson:2.10.1")
|
||||
}
|
||||
28
app/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
-keep class com.omicronapplications.** { *; }
|
||||
-keep class net.sf.sevenzipjbinding.** { *; }
|
||||
-keep class com.google.gson.reflect.TypeToken { *; }
|
||||
-keep class * extends com.google.gson.reflect.TypeToken
|
||||
|
||||
-keep class com.example.fingerkeyboard.data.MyData { *; }
|
||||
-keep class com.example.fingerkeyboard.data.ListName { *; }
|
||||
@ -0,0 +1,26 @@
|
||||
package com.example.fingerkeyboard;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||
assertEquals("com.example.fingerkeyboard", appContext.getPackageName());
|
||||
}
|
||||
}
|
||||
55
app/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:name=".KeyBoard"
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:icon="@mipmap/logo"
|
||||
android:label="@string/app_name"
|
||||
android:largeHeap="true"
|
||||
android:roundIcon="@mipmap/logo"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.Keyboard"
|
||||
tools:targetApi="31">
|
||||
<activity
|
||||
android:name=".HomeActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<service
|
||||
android:name=".tool.MyService"
|
||||
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/im" />
|
||||
</service>
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="false"></activity>
|
||||
<activity
|
||||
android:name=".PreviewActivity"
|
||||
android:exported="false" />
|
||||
|
||||
<activity android:name=".SettingActivity"
|
||||
android:exported="false"/>
|
||||
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
5556
app/src/main/assets/keyboard.json
Normal file
@ -0,0 +1,44 @@
|
||||
package com.example.fingerkeyboard;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.CountDownTimer;
|
||||
|
||||
import com.example.fingerkeyboard.R;
|
||||
import androidx.activity.EdgeToEdge;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
|
||||
public class HomeActivity extends AppCompatActivity {
|
||||
private CountDownTimer countDownTimer;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_home);
|
||||
countDownTimer = new CountDownTimer(1000,500) {
|
||||
@Override
|
||||
public void onTick(long millisUntilFinished) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
Intent intent = new Intent(HomeActivity.this,MainActivity.class);
|
||||
startActivity(intent);
|
||||
finishAffinity();
|
||||
}
|
||||
};
|
||||
goCount();
|
||||
}
|
||||
|
||||
public void goCount(){countDownTimer.start();}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
}
|
||||
}
|
||||
41
app/src/main/java/com/example/fingerkeyboard/KeyBoard.java
Normal file
@ -0,0 +1,41 @@
|
||||
package com.example.fingerkeyboard;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import com.example.fingerkeyboard.data.ListName;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
public class KeyBoard extends Application {
|
||||
public static KeyBoard app;
|
||||
public static List<ListName> listNames;
|
||||
private boolean isinit = false;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
app = this;
|
||||
try {
|
||||
InputStream open = getAssets().open("keyboard.json");
|
||||
String covertStr = Readfile.getCovertStr(open);
|
||||
if (!covertStr.isEmpty()) {
|
||||
Gson gson = new Gson();
|
||||
listNames = gson.fromJson(covertStr, new TypeToken<List<ListName>>() {
|
||||
}.getType());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
public static List<ListName> getuserList() {
|
||||
|
||||
if(listNames != null){
|
||||
return listNames;
|
||||
}
|
||||
return listNames;
|
||||
}
|
||||
}
|
||||
257
app/src/main/java/com/example/fingerkeyboard/MainActivity.java
Normal file
@ -0,0 +1,257 @@
|
||||
package com.example.fingerkeyboard;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.PopupMenu;
|
||||
import android.widget.Toast;
|
||||
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import com.example.fingerkeyboard.R;
|
||||
|
||||
import com.example.fingerkeyboard.fragment.AestheticFragment;
|
||||
import com.example.fingerkeyboard.fragment.CoolFragment;
|
||||
import com.example.fingerkeyboard.fragment.CuteFragment;
|
||||
import com.example.fingerkeyboard.fragment.FestivalFragment;
|
||||
import com.example.fingerkeyboard.fragment.GravityFragment;
|
||||
import com.example.fingerkeyboard.fragment.LoveFragment;
|
||||
import com.example.fingerkeyboard.fragment.NeonFragment;
|
||||
import com.example.fingerkeyboard.fragment.SuperFragment;
|
||||
|
||||
public class MainActivity extends AppCompatActivity implements View.OnClickListener, PopupMenu.OnMenuItemClickListener {
|
||||
|
||||
protected Button btn_love,btn_festival,btn_cute,btn_category;
|
||||
private ImageView image_set;
|
||||
// private Fragment lovefragment,festivalfragment,cutefragment,gravityfragment,neonfragment,coolFragment,aestheticfragment,superfragment;
|
||||
|
||||
private LoveFragment lovefragment;
|
||||
private FestivalFragment festivalfragment;
|
||||
private CuteFragment cutefragment;
|
||||
private GravityFragment gravityfragment;
|
||||
private NeonFragment neonfragment;
|
||||
private CoolFragment coolFragment;
|
||||
private SuperFragment superfragment;
|
||||
|
||||
private AestheticFragment aestheticfragment;
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
initfindview();
|
||||
goLoveFragment();
|
||||
|
||||
}
|
||||
|
||||
private void initfindview(){
|
||||
btn_love = (Button) findViewById(R.id.btn_love);
|
||||
btn_love.setSelected(true);
|
||||
btn_festival = (Button) findViewById(R.id.btn_festival);
|
||||
btn_cute = (Button) findViewById(R.id.btn_cute);
|
||||
btn_category = (Button)findViewById(R.id.btn_category);
|
||||
image_set = (ImageView)findViewById(R.id.image_set);
|
||||
btn_love.setOnClickListener(this);
|
||||
btn_festival.setOnClickListener(this);
|
||||
btn_cute.setOnClickListener(this);
|
||||
btn_category.setOnClickListener(this);
|
||||
image_set.setOnClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
switch (v.getId()){
|
||||
case R.id.btn_love:
|
||||
setBtn();
|
||||
btn_love.setSelected(true);
|
||||
goLoveFragment();
|
||||
break;
|
||||
case R.id.btn_festival:
|
||||
setBtn();
|
||||
btn_festival.setSelected(true);
|
||||
goFestivalFragment();
|
||||
break;
|
||||
case R.id.btn_cute:
|
||||
setBtn();
|
||||
btn_cute.setSelected(true);
|
||||
goCuteFragment();
|
||||
break;
|
||||
case R.id.btn_category:
|
||||
setBtn();
|
||||
btn_category.setSelected(true);
|
||||
PopupMenu popup = new PopupMenu(this, v);
|
||||
MenuInflater inflater = popup.getMenuInflater();
|
||||
inflater.inflate(R.menu.main, popup.getMenu());
|
||||
popup.setOnMenuItemClickListener(this);
|
||||
popup.show();
|
||||
break;
|
||||
case R.id.image_set:
|
||||
Intent intent = new Intent(MainActivity.this, SettingActivity.class);
|
||||
startActivity(intent);
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
private void setBtn(){
|
||||
btn_love.setSelected(false);
|
||||
btn_festival.setSelected(false);
|
||||
btn_cute.setSelected(false);
|
||||
btn_category.setSelected(false);
|
||||
}
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
// TODO Auto-generated method stub
|
||||
switch (item.getItemId()) {
|
||||
case R.id.m_gravity:
|
||||
setmenu();
|
||||
|
||||
goGravityFragment();
|
||||
break;
|
||||
case R.id.m_neon:
|
||||
setmenu();
|
||||
goNeonFragment();
|
||||
case R.id.m_cool:
|
||||
setmenu();
|
||||
goCoolFragment();
|
||||
break;
|
||||
case R.id.m_aesthetic:
|
||||
setmenu();
|
||||
goAestheticFragment();
|
||||
break;
|
||||
case R.id.m_super:
|
||||
setmenu();
|
||||
goSuperFragment();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private void setmenu(){
|
||||
btn_love.setSelected(false);
|
||||
btn_festival.setSelected(false);
|
||||
btn_cute.setSelected(false);
|
||||
btn_category.setSelected(false);
|
||||
}
|
||||
private void goLoveFragment(){
|
||||
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
|
||||
if(lovefragment == null){
|
||||
lovefragment = new LoveFragment();
|
||||
transaction.add(R.id.bottom_layout,lovefragment);
|
||||
}
|
||||
hideFragment(transaction);
|
||||
transaction.show(lovefragment);
|
||||
transaction.commit();
|
||||
}
|
||||
private void goFestivalFragment(){
|
||||
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
|
||||
if(festivalfragment == null){
|
||||
festivalfragment = new FestivalFragment();
|
||||
transaction.add(R.id.bottom_layout,festivalfragment);
|
||||
}
|
||||
hideFragment(transaction);
|
||||
transaction.show(festivalfragment);
|
||||
transaction.commit();
|
||||
}
|
||||
private void goCuteFragment(){
|
||||
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
|
||||
if(cutefragment == null){
|
||||
cutefragment = new CuteFragment();
|
||||
transaction.add(R.id.bottom_layout,cutefragment);
|
||||
}
|
||||
hideFragment(transaction);
|
||||
transaction.show(cutefragment);
|
||||
transaction.commit();
|
||||
}
|
||||
private void goGravityFragment(){
|
||||
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
|
||||
if( gravityfragment== null){
|
||||
gravityfragment = new GravityFragment();
|
||||
transaction.add(R.id.bottom_layout,gravityfragment);
|
||||
}
|
||||
hideFragment(transaction);
|
||||
transaction.show(gravityfragment);
|
||||
transaction.commit();
|
||||
}
|
||||
|
||||
private void goNeonFragment(){
|
||||
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
|
||||
if( neonfragment== null){
|
||||
neonfragment = new NeonFragment();
|
||||
transaction.add(R.id.bottom_layout,neonfragment);
|
||||
}
|
||||
hideFragment(transaction);
|
||||
transaction.show(neonfragment);
|
||||
transaction.commit();
|
||||
}
|
||||
private void goCoolFragment(){
|
||||
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
|
||||
if( coolFragment== null){
|
||||
coolFragment = new CoolFragment();
|
||||
transaction.add(R.id.bottom_layout,coolFragment);
|
||||
}
|
||||
hideFragment(transaction);
|
||||
transaction.show(coolFragment);
|
||||
transaction.commit();
|
||||
}
|
||||
private void goAestheticFragment(){
|
||||
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
|
||||
if( aestheticfragment== null){
|
||||
aestheticfragment = new AestheticFragment();
|
||||
transaction.add(R.id.bottom_layout,aestheticfragment);
|
||||
}
|
||||
hideFragment(transaction);
|
||||
transaction.show(aestheticfragment);
|
||||
transaction.commit();
|
||||
}
|
||||
private void goSuperFragment(){
|
||||
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
|
||||
if( superfragment== null){
|
||||
superfragment = new SuperFragment();
|
||||
transaction.add(R.id.bottom_layout,superfragment);
|
||||
}
|
||||
hideFragment(transaction);
|
||||
transaction.show(superfragment);
|
||||
transaction.commit();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void hideFragment(FragmentTransaction transaction){
|
||||
if(lovefragment != null){
|
||||
transaction.hide(lovefragment);
|
||||
}
|
||||
if(festivalfragment != null){
|
||||
transaction.hide(festivalfragment);
|
||||
}
|
||||
if(cutefragment != null){
|
||||
transaction.hide(cutefragment);
|
||||
}
|
||||
if(gravityfragment != null){
|
||||
transaction.hide(gravityfragment);
|
||||
}
|
||||
if(neonfragment != null){
|
||||
transaction.hide(neonfragment);
|
||||
}
|
||||
if(coolFragment != null){
|
||||
transaction.hide(coolFragment);
|
||||
}
|
||||
if(aestheticfragment != null){
|
||||
transaction.hide(aestheticfragment);
|
||||
}
|
||||
if(superfragment != null){
|
||||
transaction.hide(superfragment);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,188 @@
|
||||
package com.example.fingerkeyboard;
|
||||
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.example.fingerkeyboard.listener.DownloadCallback;
|
||||
import com.example.fingerkeyboard.listener.UnzipCallback;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.DataSource;
|
||||
import com.bumptech.glide.load.engine.GlideException;
|
||||
import com.bumptech.glide.request.RequestListener;
|
||||
import com.bumptech.glide.request.target.Target;
|
||||
import com.example.fingerkeyboard.tool.MyTools;
|
||||
|
||||
import java.io.File;
|
||||
import com.example.fingerkeyboard.R;
|
||||
|
||||
public class PreviewActivity extends AppCompatActivity {
|
||||
private ImageView imageViewBack;
|
||||
private ImageView imageViewPreview;
|
||||
private TextView textViewName;
|
||||
private LinearLayout linearLayoutDown;
|
||||
private ProgressBar progressBarDownload;
|
||||
private ProgressBar progressBarPreview;
|
||||
private String url;
|
||||
private String name;
|
||||
private String preview;
|
||||
public static String KEY_NAME = "key_name";
|
||||
public static String KEY_URL = "key_url";
|
||||
public static String KEY_PRE = "key_pre";
|
||||
private String unzipPath;
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_preview);
|
||||
initView(); //ui属性
|
||||
progressBarPreview.setVisibility(View.VISIBLE);//将进度条设置成可见状态
|
||||
onGetData(); //获取数据
|
||||
|
||||
}
|
||||
public void initView(){
|
||||
imageViewBack = findViewById(R.id.image_view_back_id);
|
||||
imageViewPreview = findViewById(R.id.image_view_preview_id);
|
||||
textViewName = findViewById(R.id.text_view_name_id);
|
||||
linearLayoutDown = findViewById(R.id.linear_layout_download_id);
|
||||
progressBarPreview = findViewById(R.id.progress_bar_preview_id);
|
||||
progressBarDownload = findViewById(R.id.progress_bar_download_id);
|
||||
}
|
||||
|
||||
//获取数据
|
||||
public void onGetData(){
|
||||
Intent intent = getIntent();
|
||||
name = intent.getStringExtra(KEY_NAME);
|
||||
url = intent.getStringExtra(KEY_URL);
|
||||
preview = intent.getStringExtra(KEY_PRE);
|
||||
textViewName.setText(name);
|
||||
Glide.with(this).load(preview).addListener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
||||
progressBarPreview.setVisibility(View.GONE);//将进度条设置成不可见状态
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
||||
progressBarPreview.setVisibility(View.GONE);//将进度条设置成不可见状态
|
||||
return false;
|
||||
}
|
||||
}).into(imageViewPreview);
|
||||
|
||||
File cacheDir = this.getCacheDir();
|
||||
unzipPath = cacheDir + "/" + name;
|
||||
|
||||
Log.d("--------------------","----------name+"+name);
|
||||
setListener();
|
||||
}
|
||||
|
||||
//点击事件
|
||||
private void setListener(){
|
||||
linearLayoutDown.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
setAction();
|
||||
}
|
||||
});
|
||||
imageViewBack.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Log.d("--------------------","----------finish");
|
||||
finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
//按下返回键,实现日志打印
|
||||
super.onBackPressed();
|
||||
Log.d("-------","--------onBackPressed ");
|
||||
}
|
||||
|
||||
private void setAction() {
|
||||
if (!MyTools.isStep1() || !MyTools.isStep2()) {
|
||||
AlertDialog alertDialog2 = new AlertDialog.Builder(this)
|
||||
.setTitle("Worn")
|
||||
.setMessage(getString(R.string.text_hint))
|
||||
.setIcon(R.mipmap.logo)
|
||||
.setPositiveButton("yes", new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
Intent intent = new Intent(PreviewActivity.this,SettingActivity.class);
|
||||
startActivity(intent);
|
||||
}
|
||||
})
|
||||
.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
|
||||
}
|
||||
})
|
||||
.create();
|
||||
alertDialog2.show();
|
||||
return;
|
||||
}
|
||||
|
||||
goApply();
|
||||
}
|
||||
|
||||
private void goApply() {
|
||||
progressBarDownload.setVisibility(View.VISIBLE);
|
||||
String skinPathByName = MyTools.getSkinPathByName(name);
|
||||
Log.d("----skinPathByName","------skinPathByName+"+skinPathByName);
|
||||
if (!skinPathByName.isEmpty()) {
|
||||
setCurrentKeyboardSkin(skinPathByName);
|
||||
progressBarDownload.setVisibility(View.GONE);
|
||||
Toast.makeText(PreviewActivity.this, getString(R.string.set_successful), Toast.LENGTH_SHORT).show();
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
MyTools.downloadZip(url, this, new DownloadCallback() {
|
||||
@Override
|
||||
public void onDownloadCall(boolean successful, File resource) {
|
||||
if (successful) {
|
||||
MyTools.unzipFile(unzipPath, resource, new UnzipCallback() {
|
||||
|
||||
@Override
|
||||
public void onUnzipCall(boolean successful, String resDirPath) {
|
||||
progressBarDownload.setVisibility(View.GONE);
|
||||
if (successful) {
|
||||
MyTools.saveSkinByName(name, resDirPath);
|
||||
setCurrentKeyboardSkin(resDirPath);
|
||||
Toast.makeText(PreviewActivity.this, getString(R.string.set_successful), Toast.LENGTH_SHORT).show();
|
||||
finish();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
} else {
|
||||
progressBarDownload.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setCurrentKeyboardSkin(String resDirPath) {
|
||||
Log.d("---","----path"+resDirPath);
|
||||
MyTools.saveSkin(resDirPath);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
32
app/src/main/java/com/example/fingerkeyboard/Readfile.java
Normal file
@ -0,0 +1,32 @@
|
||||
package com.example.fingerkeyboard;
|
||||
|
||||
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class Readfile {
|
||||
public static String getCovertStr(InputStream stream) {
|
||||
String covertStr = "";
|
||||
try {
|
||||
StringWriter writer = new StringWriter();
|
||||
char[] buffer = new char[stream.available()];
|
||||
Reader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8));
|
||||
int a = 0;
|
||||
while ((a = reader.read(buffer)) != -1) {
|
||||
writer.write(buffer, 0, a);
|
||||
}
|
||||
covertStr = writer.toString();
|
||||
} catch (IOException e) {
|
||||
return covertStr;
|
||||
}
|
||||
return covertStr;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,99 @@
|
||||
package com.example.fingerkeyboard;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import com.example.fingerkeyboard.R;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.example.fingerkeyboard.tool.MyTools;
|
||||
|
||||
|
||||
public class SettingActivity extends AppCompatActivity {
|
||||
|
||||
private BroadcastReceiver broadcastReceiver;
|
||||
|
||||
private ImageView imageViewBack;
|
||||
|
||||
private TextView textViewStep1;
|
||||
private TextView textViewStep2;
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_setting);
|
||||
initView();
|
||||
|
||||
|
||||
//在运行时注册一个广播接收者,以便接收输入法改变的广播消息。
|
||||
broadcastReceiver = new inputReceive();
|
||||
registerReceiver(broadcastReceiver, new IntentFilter(Intent.ACTION_INPUT_METHOD_CHANGED));
|
||||
|
||||
|
||||
refreshStatus();
|
||||
setListener();
|
||||
}
|
||||
|
||||
private void initView(){
|
||||
imageViewBack = findViewById(R.id.image_view_back_id);
|
||||
textViewStep1 = findViewById(R.id.textview_step1);
|
||||
textViewStep2 = findViewById(R.id.textview_step2);
|
||||
}
|
||||
|
||||
private void setListener(){
|
||||
imageViewBack.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
||||
finish();
|
||||
}
|
||||
});
|
||||
textViewStep1.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
MyTools.goSetStep1(SettingActivity.this);
|
||||
|
||||
}
|
||||
});
|
||||
textViewStep2.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
MyTools.goSetStep2();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
unregisterReceiver(broadcastReceiver);
|
||||
}
|
||||
|
||||
private void refreshStatus() {
|
||||
textViewStep2.setSelected(MyTools.isStep2());
|
||||
textViewStep1.setSelected(MyTools.isStep1());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
refreshStatus();
|
||||
}
|
||||
|
||||
class inputReceive extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
refreshStatus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,105 @@
|
||||
package com.example.fingerkeyboard.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.DataSource;
|
||||
import com.bumptech.glide.load.engine.GlideException;
|
||||
import com.bumptech.glide.request.RequestListener;
|
||||
import com.bumptech.glide.request.target.Target;
|
||||
import com.example.fingerkeyboard.PreviewActivity;
|
||||
|
||||
import com.example.fingerkeyboard.R;
|
||||
import com.example.fingerkeyboard.data.MyData;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ThumbAdapter extends RecyclerView.Adapter<ThumbAdapter.ThumbViewHolder> {
|
||||
private Context adapter_context;
|
||||
List< MyData > myDataList = new ArrayList<>();
|
||||
|
||||
//private List<MyData> myDataList;
|
||||
public ThumbAdapter(Context context,List<MyData> list){
|
||||
adapter_context = context;
|
||||
myDataList = list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ThumbViewHolder holder, int position) {
|
||||
|
||||
MyData myData = myDataList.get(position); //获取位置
|
||||
String thumbnail = myData.getThumb(); //获取缩略图
|
||||
Glide.with(adapter_context).load(thumbnail)
|
||||
.error(R.mipmap.ic_launcher)
|
||||
.listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<Drawable> target, boolean isFirstResource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target<Drawable> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.into(holder.getImageViewThumb());
|
||||
holder.getConstraintLayout().setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent(adapter_context, PreviewActivity.class);
|
||||
intent.putExtra(PreviewActivity.KEY_NAME,myData.getResourseName());
|
||||
intent.putExtra(PreviewActivity.KEY_URL,myData.getZipUrl());
|
||||
intent.putExtra(PreviewActivity.KEY_PRE,myData.getPreview());
|
||||
adapter_context.startActivity(intent);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static final class ThumbViewHolder extends RecyclerView.ViewHolder{
|
||||
private ImageView imageViewThumb;
|
||||
private ConstraintLayout constraintLayout;
|
||||
|
||||
public ThumbViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
imageViewThumb = itemView.findViewById(R.id.image_view_key_id);
|
||||
constraintLayout = itemView.findViewById(R.id.constraint_layout_id);
|
||||
}
|
||||
|
||||
public ImageView getImageViewThumb() {
|
||||
return imageViewThumb;
|
||||
}
|
||||
|
||||
public ConstraintLayout getConstraintLayout() {
|
||||
return constraintLayout;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return myDataList.size();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ThumbViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View itemview = LayoutInflater.from(adapter_context).inflate(R.layout.list_thumb,parent,false);
|
||||
ThumbViewHolder thumbViewHolder = new ThumbViewHolder(itemview);
|
||||
return thumbViewHolder;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
package com.example.fingerkeyboard.data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ListName {
|
||||
private String classname;
|
||||
private List<MyData> list;
|
||||
|
||||
public void setClassname(String classname) {
|
||||
this.classname = classname;
|
||||
}
|
||||
|
||||
public void setList(List<MyData> list) {
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
public String getClassname() {
|
||||
return classname;
|
||||
}
|
||||
|
||||
public List<MyData> getList() {
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package com.example.fingerkeyboard.data;
|
||||
|
||||
public class MyData {
|
||||
private String title;
|
||||
private String thumb;
|
||||
private String zipUrl;
|
||||
private String preview;
|
||||
|
||||
public void setResourseName(String resourseName) {
|
||||
this.title = resourseName;
|
||||
}
|
||||
|
||||
public void setThumb(String thumb) {
|
||||
this.thumb = thumb;
|
||||
}
|
||||
|
||||
public void setZipUrl(String zipUrl) {
|
||||
this.zipUrl = zipUrl;
|
||||
}
|
||||
|
||||
public void setPreview(String preview) {
|
||||
this.preview = preview;
|
||||
}
|
||||
|
||||
public String getResourseName() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public String getThumb() {
|
||||
return thumb;
|
||||
}
|
||||
|
||||
public String getZipUrl() {
|
||||
return zipUrl;
|
||||
}
|
||||
|
||||
public String getPreview() {
|
||||
return preview;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
package com.example.fingerkeyboard.fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.example.fingerkeyboard.KeyBoard;
|
||||
|
||||
import com.example.fingerkeyboard.adapter.ThumbAdapter;
|
||||
import com.example.fingerkeyboard.data.MyData;
|
||||
import com.example.fingerkeyboard.tool.MyTools;
|
||||
import com.example.fingerkeyboard.tool.SpaceItem;
|
||||
import com.example.fingerkeyboard.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class AestheticFragment extends Fragment {
|
||||
private RecyclerView recyclerView;
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_festival, container, false);
|
||||
recyclerView = view.findViewById(R.id.recycler_view_id);
|
||||
List<MyData> list = KeyBoard.getuserList().get(6).getList();
|
||||
recyclerView.setAdapter(new ThumbAdapter(getActivity(), list));
|
||||
recyclerView.setLayoutManager(new GridLayoutManager(getActivity(),2));
|
||||
recyclerView.addItemDecoration(new SpaceItem(MyTools.dpToPx(10,getActivity()),MyTools.dpToPx(10,getActivity()),MyTools.dpToPx(10,getActivity())));
|
||||
return view;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
package com.example.fingerkeyboard.fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.example.fingerkeyboard.KeyBoard;
|
||||
|
||||
import com.example.fingerkeyboard.adapter.ThumbAdapter;
|
||||
import com.example.fingerkeyboard.data.MyData;
|
||||
import com.example.fingerkeyboard.tool.MyTools;
|
||||
import com.example.fingerkeyboard.tool.SpaceItem;
|
||||
import com.example.fingerkeyboard.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class CoolFragment extends Fragment {
|
||||
private RecyclerView recyclerView;
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_gravity, container, false);
|
||||
recyclerView = view.findViewById(R.id.recycler_view_id);
|
||||
List<MyData> list = KeyBoard.getuserList().get(5).getList();
|
||||
recyclerView.setAdapter(new ThumbAdapter(getActivity(), list));
|
||||
recyclerView.setLayoutManager(new GridLayoutManager(getActivity(),2));
|
||||
recyclerView.addItemDecoration(new SpaceItem(MyTools.dpToPx(10,getActivity()),MyTools.dpToPx(10,getActivity()),MyTools.dpToPx(10,getActivity())));
|
||||
return view;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
package com.example.fingerkeyboard.fragment;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.example.fingerkeyboard.KeyBoard;
|
||||
import com.example.fingerkeyboard.R;
|
||||
import com.example.fingerkeyboard.adapter.ThumbAdapter;
|
||||
import com.example.fingerkeyboard.data.MyData;
|
||||
import com.example.fingerkeyboard.tool.MyTools;
|
||||
import com.example.fingerkeyboard.tool.SpaceItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class CuteFragment extends Fragment {
|
||||
private RecyclerView recyclerView;
|
||||
|
||||
@SuppressLint("MissingInflatedId")
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
// Inflate the layout for this fragment
|
||||
View view = inflater.inflate(R.layout.fragment_cute, container, false);
|
||||
recyclerView = view.findViewById(R.id.recycler_view_id);
|
||||
List<MyData> list = KeyBoard.getuserList().get(2).getList();
|
||||
recyclerView.setAdapter(new ThumbAdapter(getActivity(), list));
|
||||
recyclerView.setLayoutManager(new GridLayoutManager(getActivity(),2));
|
||||
recyclerView.addItemDecoration(new SpaceItem(MyTools.dpToPx(10,getActivity()),MyTools.dpToPx(10,getActivity()),MyTools.dpToPx(10,getActivity())));
|
||||
return view; }
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
package com.example.fingerkeyboard.fragment;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.example.fingerkeyboard.KeyBoard;
|
||||
import com.example.fingerkeyboard.R;
|
||||
import com.example.fingerkeyboard.adapter.ThumbAdapter;
|
||||
import com.example.fingerkeyboard.data.MyData;
|
||||
import com.example.fingerkeyboard.tool.MyTools;
|
||||
import com.example.fingerkeyboard.tool.SpaceItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class FestivalFragment extends Fragment {
|
||||
private RecyclerView recyclerView;
|
||||
|
||||
@SuppressLint("MissingInflatedId")
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
// Inflate the layout for this fragment
|
||||
View view = inflater.inflate(R.layout.fragment_festival, container, false);
|
||||
recyclerView = view.findViewById(R.id.recycler_view_id);
|
||||
List<MyData> list = KeyBoard.getuserList().get(1).getList();
|
||||
recyclerView.setAdapter(new ThumbAdapter(getActivity(), list));
|
||||
recyclerView.setLayoutManager(new GridLayoutManager(getActivity(),2));
|
||||
recyclerView.addItemDecoration(new SpaceItem(MyTools.dpToPx(10,getActivity()),MyTools.dpToPx(10,getActivity()),MyTools.dpToPx(10,getActivity())));
|
||||
return view;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package com.example.fingerkeyboard.fragment;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.example.fingerkeyboard.KeyBoard;
|
||||
import com.example.fingerkeyboard.R;
|
||||
import com.example.fingerkeyboard.adapter.ThumbAdapter;
|
||||
import com.example.fingerkeyboard.data.MyData;
|
||||
import com.example.fingerkeyboard.tool.MyTools;
|
||||
import com.example.fingerkeyboard.tool.SpaceItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class GravityFragment extends Fragment {
|
||||
private RecyclerView recyclerView;
|
||||
|
||||
@SuppressLint("MissingInflatedId")
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
// Inflate the layout for this fragment
|
||||
View view = inflater.inflate(R.layout.fragment_gravity, container, false);
|
||||
recyclerView = view.findViewById(R.id.recycler_view_id);
|
||||
List<MyData> list = KeyBoard.getuserList().get(3).getList();
|
||||
recyclerView.setAdapter(new ThumbAdapter(getActivity(), list));
|
||||
recyclerView.setLayoutManager(new GridLayoutManager(getActivity(),2));
|
||||
recyclerView.addItemDecoration(new SpaceItem(MyTools.dpToPx(10,getActivity()),MyTools.dpToPx(10,getActivity()),MyTools.dpToPx(10,getActivity())));
|
||||
return view;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
package com.example.fingerkeyboard.fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.example.fingerkeyboard.KeyBoard;
|
||||
import com.example.fingerkeyboard.R;
|
||||
import com.example.fingerkeyboard.adapter.ThumbAdapter;
|
||||
import com.example.fingerkeyboard.data.MyData;
|
||||
import com.example.fingerkeyboard.tool.MyTools;
|
||||
import com.example.fingerkeyboard.tool.SpaceItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class LoveFragment extends Fragment {
|
||||
private RecyclerView recyclerView;
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
// Inflate the layout for this fragment
|
||||
View view = inflater.inflate(R.layout.fragment_love, container, false);
|
||||
recyclerView = view.findViewById(R.id.recycler_view_id);
|
||||
List<MyData> list = KeyBoard.getuserList().get(0).getList();
|
||||
recyclerView.setAdapter(new ThumbAdapter(getActivity(), list));
|
||||
recyclerView.setLayoutManager(new GridLayoutManager(getActivity(),2));
|
||||
recyclerView.addItemDecoration(new SpaceItem(MyTools.dpToPx(10,getActivity()),MyTools.dpToPx(10,getActivity()),MyTools.dpToPx(10,getActivity())));
|
||||
return view;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
package com.example.fingerkeyboard.fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.example.fingerkeyboard.KeyBoard;
|
||||
import com.example.fingerkeyboard.R;
|
||||
import com.example.fingerkeyboard.adapter.ThumbAdapter;
|
||||
import com.example.fingerkeyboard.data.MyData;
|
||||
import com.example.fingerkeyboard.tool.MyTools;
|
||||
import com.example.fingerkeyboard.tool.SpaceItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class NeonFragment extends Fragment {
|
||||
private RecyclerView recyclerView;
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_festival, container, false);
|
||||
recyclerView = view.findViewById(R.id.recycler_view_id);
|
||||
List<MyData> list = KeyBoard.getuserList().get(4).getList();
|
||||
recyclerView.setAdapter(new ThumbAdapter(getActivity(), list));
|
||||
recyclerView.setLayoutManager(new GridLayoutManager(getActivity(),2));
|
||||
recyclerView.addItemDecoration(new SpaceItem(MyTools.dpToPx(10,getActivity()),MyTools.dpToPx(10,getActivity()),MyTools.dpToPx(10,getActivity())));
|
||||
return view;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
package com.example.fingerkeyboard.fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.example.fingerkeyboard.KeyBoard;
|
||||
import com.example.fingerkeyboard.R;
|
||||
import com.example.fingerkeyboard.adapter.ThumbAdapter;
|
||||
import com.example.fingerkeyboard.data.MyData;
|
||||
import com.example.fingerkeyboard.tool.MyTools;
|
||||
import com.example.fingerkeyboard.tool.SpaceItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SuperFragment extends Fragment {
|
||||
private RecyclerView recyclerView;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_festival, container, false);
|
||||
recyclerView = view.findViewById(R.id.recycler_view_id);
|
||||
List<MyData> list = KeyBoard.getuserList().get(7).getList();
|
||||
recyclerView.setAdapter(new ThumbAdapter(getActivity(), list));
|
||||
recyclerView.setLayoutManager(new GridLayoutManager(getActivity(),2));
|
||||
recyclerView.addItemDecoration(new SpaceItem(MyTools.dpToPx(10,getActivity()),MyTools.dpToPx(10,getActivity()),MyTools.dpToPx(10,getActivity())));
|
||||
return view;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
package com.example.fingerkeyboard.listener;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public interface DownloadCallback {
|
||||
|
||||
void onDownloadCall(boolean successful, File resource);
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
package com.example.fingerkeyboard.listener;
|
||||
|
||||
public interface UnzipCallback {
|
||||
|
||||
void onUnzipCall(boolean successful, String resDirPath);
|
||||
}
|
||||
@ -0,0 +1,195 @@
|
||||
package com.example.fingerkeyboard.tool;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.StateListDrawable;
|
||||
import android.util.Log;
|
||||
import android.util.Xml;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.example.fingerkeyboard.KeyBoard;
|
||||
import com.example.fingerkeyboard.R;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.Objects;
|
||||
|
||||
public class CustomViewConfig {
|
||||
private String Bg_action_normal = "btn_keyboard_key_functional_normal.9.png";
|
||||
private String jpg_BG = "keyboard_background.jpg";
|
||||
|
||||
private String jpg_BG_new = "keyboard_background.png";
|
||||
private String color_normal_key = "key_text_color_normal";
|
||||
private String color_action_key = "key_text_color_functional";
|
||||
private String Bg_pressed = "btn_keyboard_key_normal_pressed.9.png";
|
||||
private String Bg_normal = "btn_keyboard_key_normal_normal.9.png";
|
||||
private String path_drawxh = "/drawable-xhdpi-v4/";
|
||||
private String path_drawxxh = "/drawable-xxhdpi-v4/";
|
||||
private String path_color = "/colors.xml";
|
||||
private String icon_del = "sym_keyboard_delete_normal.png";
|
||||
private String icon_shift = "sym_keyboard_shift.png";
|
||||
private String Bg_action_pressed = "btn_keyboard_key_functional_pressed.9.png";
|
||||
private String icon_shift_lock = "sym_keyboard_shift_locked.png";
|
||||
|
||||
private String Bg_space_normal = "btn_keyboard_spacekey_normal_normal.9.png";
|
||||
private String Bg_space_pressed = "btn_keyboard_spacekey_normal_pressed.9.png";
|
||||
|
||||
|
||||
private Drawable BgActionDraw;
|
||||
private Drawable BgSpaceDraw;
|
||||
private Drawable BgNormalDraw;
|
||||
private Drawable iconShift = ContextCompat.getDrawable(com.example.fingerkeyboard.KeyBoard.app, R.drawable.ico_shift_lit);
|
||||
private Drawable iconDel = ContextCompat.getDrawable(com.example.fingerkeyboard.KeyBoard.app, R.drawable.del_icon);
|
||||
private Drawable BG = ContextCompat.getDrawable(com.example.fingerkeyboard.KeyBoard.app, R.drawable.de_keyboard_bg);
|
||||
|
||||
private int keyNoramlcolor = com.example.fingerkeyboard.KeyBoard.app.getResources().getColor(R.color.white, null);
|
||||
|
||||
private int keyActioncolor = com.example.fingerkeyboard.KeyBoard.app.getResources().getColor(R.color.white, null);
|
||||
|
||||
private Drawable iconShiftLock = ContextCompat.getDrawable(com.example.fingerkeyboard.KeyBoard.app, R.drawable.ico_shift_lit);
|
||||
|
||||
public Drawable getBG() {return BG;}
|
||||
|
||||
public Drawable getBgActionDraw() {
|
||||
return BgActionDraw;
|
||||
}
|
||||
|
||||
public Drawable getBgSpaceDraw() {
|
||||
return BgSpaceDraw;
|
||||
}
|
||||
|
||||
public Drawable getBgNormalDraw() {
|
||||
return BgNormalDraw;
|
||||
}
|
||||
|
||||
public Drawable getIconShift() {
|
||||
return iconShift;
|
||||
}
|
||||
|
||||
public Drawable getIconDel() {
|
||||
return iconDel;
|
||||
}
|
||||
|
||||
public Drawable getIconShiftLock() {
|
||||
return iconShiftLock;
|
||||
}
|
||||
|
||||
public int getKeyNoramlcolor() {
|
||||
return keyNoramlcolor;
|
||||
}
|
||||
|
||||
public int getKeyActioncolor() {
|
||||
return keyActioncolor;
|
||||
}
|
||||
|
||||
public void init(){
|
||||
|
||||
iconShift = ContextCompat.getDrawable(com.example.fingerkeyboard.KeyBoard.app, R.drawable.ico_shift_lit);
|
||||
iconDel = ContextCompat.getDrawable(com.example.fingerkeyboard.KeyBoard.app, R.drawable.del_icon);
|
||||
BG = ContextCompat.getDrawable(com.example.fingerkeyboard.KeyBoard.app, R.drawable.de_keyboard_bg);
|
||||
iconShiftLock = ContextCompat.getDrawable(com.example.fingerkeyboard.KeyBoard.app, R.drawable.ico_shift_lit);
|
||||
|
||||
keyNoramlcolor = com.example.fingerkeyboard.KeyBoard.app.getResources().getColor(R.color.white, null);
|
||||
|
||||
Drawable drawable1 = ContextCompat.getDrawable(com.example.fingerkeyboard.KeyBoard.app,R.mipmap.logo);
|
||||
Drawable drawable2 = ContextCompat.getDrawable(KeyBoard.app,R.mipmap.logo);
|
||||
|
||||
|
||||
StateListDrawable state = MyTools.getStatus(drawable2,drawable1);//首先创建了一个StateListDrawable对象status。
|
||||
BgActionDraw = state;
|
||||
BgNormalDraw = state;
|
||||
BgSpaceDraw = state;
|
||||
}
|
||||
|
||||
//获取键盘未按下时背景
|
||||
private Drawable getKeyBackGround(Context context, String resDirPath, String drawName)
|
||||
{
|
||||
String filePath = resDirPath+path_drawxh+drawName; //文件路径
|
||||
File file = new File(filePath);
|
||||
if (!file.exists()) {
|
||||
return null;
|
||||
}
|
||||
BitmapDrawable bitmapDrawable = new BitmapDrawable(context.getResources(), BitmapFactory.decodeFile(filePath));
|
||||
return bitmapDrawable;
|
||||
}
|
||||
private Drawable getBackGround(Context context,String resDirPath)
|
||||
{
|
||||
String filePath = resDirPath+path_drawxxh+jpg_BG;
|
||||
if (!new File(filePath).exists()) {
|
||||
filePath = resDirPath+path_drawxxh+jpg_BG_new;
|
||||
}
|
||||
|
||||
//BitmapDrawable 是对位图(Bitmap)的一种包装。它允许将一个 Bitmap 对象包装成一个可绘制的资源,以便在 Android 应用中使用
|
||||
BitmapDrawable bitmapDrawable = new BitmapDrawable(context.getResources(), BitmapFactory.decodeFile(filePath));
|
||||
return bitmapDrawable;
|
||||
}
|
||||
|
||||
private void updateKeyColor(String resDirPath) {
|
||||
|
||||
String colorXmlPath = resDirPath+path_color;
|
||||
File file = new File(colorXmlPath);
|
||||
if (!file.exists()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
XmlPullParser xmlPullParser = Xml.newPullParser();
|
||||
|
||||
String s = MyTools.parseString(file);
|
||||
xmlPullParser.setInput(new StringReader(s));
|
||||
xmlPullParser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
|
||||
int eventT = xmlPullParser.getEventType();
|
||||
while (eventT != XmlPullParser.END_DOCUMENT) {
|
||||
if (eventT == XmlPullParser.START_TAG && (Objects.equals(xmlPullParser.getName(), "color") || Objects.equals(xmlPullParser.getName(), "item"))) {
|
||||
String value = xmlPullParser.getAttributeValue(null, "name");
|
||||
if (value != null && value.equals(color_normal_key)) {
|
||||
keyNoramlcolor = Color.parseColor(xmlPullParser.nextText());
|
||||
|
||||
}
|
||||
if (value != null && value.equals(color_action_key)) {
|
||||
keyActioncolor = Color.parseColor(xmlPullParser.nextText());
|
||||
|
||||
}
|
||||
}
|
||||
eventT = xmlPullParser.next();
|
||||
}
|
||||
}catch (XmlPullParserException exception){
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void updateConfig( Context con) {
|
||||
String resDirPath = MyTools.getSkin();
|
||||
Log.d("---","----updateConfig"+resDirPath);
|
||||
updateKeyColor(resDirPath);
|
||||
BG = getBackGround(con, resDirPath);
|
||||
|
||||
Drawable keyBackGround = getKeyBackGround(con, resDirPath, Bg_normal);
|
||||
Drawable keyBackGround1 = getKeyBackGround(con, resDirPath, Bg_pressed);
|
||||
BgNormalDraw = MyTools.getStatus(keyBackGround, keyBackGround1);
|
||||
|
||||
Drawable keyBackGround2 = getKeyBackGround(con, resDirPath, Bg_action_normal);
|
||||
Drawable keyBackGround3 = getKeyBackGround(con, resDirPath, Bg_action_pressed);
|
||||
BgActionDraw = MyTools.getStatus(keyBackGround2, keyBackGround3);
|
||||
|
||||
Drawable keyBackGround4 = getKeyBackGround(con, resDirPath, Bg_space_normal);
|
||||
Drawable keyBackGround5 = getKeyBackGround(con, resDirPath, Bg_space_pressed);
|
||||
BgSpaceDraw = MyTools.getStatus(keyBackGround4, keyBackGround5);
|
||||
|
||||
iconDel = getKeyBackGround(con, resDirPath, icon_del);
|
||||
iconShift = getKeyBackGround(con, resDirPath, icon_shift);
|
||||
iconShiftLock = getKeyBackGround(con, resDirPath, icon_shift_lock);
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
package com.example.fingerkeyboard.tool
|
||||
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Rect
|
||||
import android.graphics.drawable.Drawable
|
||||
|
||||
object DrawIcon {
|
||||
public fun onDrawKeyIcon(currentKey: KeyBoard.Key,
|
||||
drawKeyIcon: Drawable,
|
||||
myCanvas: Canvas,
|
||||
myKeyBoardView:MyKeyBoardView
|
||||
){
|
||||
drawKeyIcon.apply {
|
||||
currentKey.icon = this
|
||||
|
||||
var icon_w = currentKey.icon.intrinsicWidth.toFloat()
|
||||
var icon_wr = icon_w / currentKey.width.toFloat()
|
||||
var icon_h = currentKey.icon.intrinsicHeight.toFloat()
|
||||
var icon_hr = icon_h / currentKey.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
|
||||
currentKey.icon.let {
|
||||
it.bounds = Rect().apply {
|
||||
|
||||
top =
|
||||
(currentKey.y + myKeyBoardView.paddingTop + (currentKey.height - icon_h) / 2f).toInt()
|
||||
left =
|
||||
(currentKey.x + myKeyBoardView.paddingLeft + (currentKey.width - icon_w) / 2f).toInt()
|
||||
bottom = (top + icon_h).toInt()
|
||||
right = (left + icon_w).toInt()
|
||||
|
||||
}
|
||||
it.draw(myCanvas)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
850
app/src/main/java/com/example/fingerkeyboard/tool/KeyBoard.java
Normal file
@ -0,0 +1,850 @@
|
||||
package com.example.fingerkeyboard.tool;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.util.Xml;
|
||||
|
||||
import androidx.annotation.XmlRes;
|
||||
|
||||
import com.example.fingerkeyboard.R;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
public class KeyBoard {
|
||||
|
||||
static final String TAG = "Keyboard";
|
||||
|
||||
// Keyboard XML Tags
|
||||
private static final String TAG_KEYBOARD = "Keyboard";
|
||||
private static final String TAG_ROW = "Row";
|
||||
private static final String TAG_KEY = "Key";
|
||||
|
||||
public static final int EDGE_LEFT = 0x01;
|
||||
public static final int EDGE_RIGHT = 0x02;
|
||||
public static final int EDGE_TOP = 0x04;
|
||||
public static final int EDGE_BOTTOM = 0x08;
|
||||
|
||||
public static final int KEYCODE_SHIFT = -1;
|
||||
public static final int KEYCODE_MODE_CHANGE = -2;
|
||||
public static final int KEYCODE_CANCEL = -3;
|
||||
public static final int KEYCODE_DONE = -4;
|
||||
public static final int KEYCODE_DELETE = -5;
|
||||
public static final int KEYCODE_ALT = -6;
|
||||
public static final int KEYCODE_BLANK = 32;
|
||||
public static final int KEYCODE_SHIFT_123 = -360;
|
||||
public static final int KEYCODE_SHIFT_SYMBOL = -361;
|
||||
|
||||
|
||||
/** Keyboard label **/
|
||||
private CharSequence mLabel;
|
||||
|
||||
/** Horizontal gap default for all rows */
|
||||
private int mDefaultHorizontalGap;
|
||||
|
||||
/** Default key width */
|
||||
private int mDefaultWidth;
|
||||
|
||||
/** Default key height */
|
||||
private int mDefaultHeight;
|
||||
|
||||
/** Default gap between rows */
|
||||
private int mDefaultVerticalGap;
|
||||
|
||||
/** Is the keyboard in the shifted state */
|
||||
private boolean mShifted;
|
||||
|
||||
/** Key instance for the shift key, if present */
|
||||
private Key[] mShiftKeys = { null, null };
|
||||
|
||||
/** Key index for the shift key, if present */
|
||||
private int[] mShiftKeyIndices = {-1, -1};
|
||||
|
||||
/** Current key width, while loading the keyboard */
|
||||
private int mKeyWidth;
|
||||
|
||||
/** Current key height, while loading the keyboard */
|
||||
private int mKeyHeight;
|
||||
|
||||
/** Total height of the keyboard, including the padding and keys */
|
||||
private int mTotalHeight;
|
||||
|
||||
/**
|
||||
* Total width of the keyboard, including left side gaps and keys, but not any gaps on the
|
||||
* right side.
|
||||
*/
|
||||
private int mTotalWidth;
|
||||
|
||||
/** List of keys in this keyboard */
|
||||
private List<Key> mKeys;
|
||||
|
||||
/** List of modifier keys such as Shift & Alt, if any */
|
||||
private List<Key> mModifierKeys;
|
||||
|
||||
/** Width of the screen available to fit the keyboard */
|
||||
private int mDisplayWidth;
|
||||
|
||||
/** Height of the screen */
|
||||
private int mDisplayHeight;
|
||||
|
||||
/** Keyboard mode, or zero, if none. */
|
||||
private int mKeyboardMode;
|
||||
|
||||
// Variables for pre-computing nearest keys.
|
||||
|
||||
private static final int GRID_WIDTH = 10;
|
||||
private static final int GRID_HEIGHT = 5;
|
||||
private static final int GRID_SIZE = GRID_WIDTH * GRID_HEIGHT;
|
||||
private int mCellWidth;
|
||||
private int mCellHeight;
|
||||
private int[][] mGridNeighbors;
|
||||
private int mProximityThreshold;
|
||||
/** Number of key widths from current touch point to search for nearest keys. */
|
||||
private static float SEARCH_DISTANCE = 1.8f;
|
||||
|
||||
private ArrayList<Row> rows = new ArrayList<>();
|
||||
|
||||
|
||||
public static class Row {
|
||||
/** Default width of a key in this row. */
|
||||
public int defaultWidth;
|
||||
/** Default height of a key in this row. */
|
||||
public int defaultHeight;
|
||||
/** Default horizontal gap between keys in this row. */
|
||||
public int defaultHorizontalGap;
|
||||
/** Vertical gap following this row. */
|
||||
public int verticalGap;
|
||||
|
||||
ArrayList<Key> mKeys = new ArrayList<>();
|
||||
|
||||
|
||||
public int rowEdgeFlags;
|
||||
|
||||
/** The keyboard mode for this row */
|
||||
public int mode;
|
||||
|
||||
private KeyBoard parent;
|
||||
|
||||
public Row(KeyBoard parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public Row(Resources res, KeyBoard parent, XmlResourceParser parser) {
|
||||
this.parent = parent;
|
||||
TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser),
|
||||
R.styleable.style_view);
|
||||
defaultWidth = getDimensionOrFraction(a,
|
||||
R.styleable.style_view_android_keyWidth,
|
||||
parent.mDisplayWidth, parent.mDefaultWidth);
|
||||
defaultHeight = getDimensionOrFraction(a,
|
||||
R.styleable.style_view_android_keyHeight,
|
||||
parent.mDisplayHeight, parent.mDefaultHeight);
|
||||
defaultHorizontalGap = getDimensionOrFraction(a,
|
||||
R.styleable.style_view_android_horizontalGap,
|
||||
parent.mDisplayWidth, parent.mDefaultHorizontalGap);
|
||||
verticalGap = getDimensionOrFraction(a,
|
||||
R.styleable.style_view_android_verticalGap,
|
||||
parent.mDisplayHeight, parent.mDefaultVerticalGap);
|
||||
a.recycle();
|
||||
a = res.obtainAttributes(Xml.asAttributeSet(parser),
|
||||
R.styleable.style_row);
|
||||
rowEdgeFlags = a.getInt(R.styleable.style_row_android_rowEdgeFlags, 0);
|
||||
mode = a.getResourceId(R.styleable.style_row_android_keyboardMode,
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class for describing the position and characteristics of a single key in the keyboard.
|
||||
*
|
||||
* @attr ref android.R.styleable#King_Keyboard_keyWidth
|
||||
* @attr ref android.R.styleable#King_Keyboard_keyHeight
|
||||
* @attr ref android.R.styleable#King_Keyboard_horizontalGap
|
||||
* @attr ref android.R.styleable#King_Keyboard_Key_codes
|
||||
* @attr ref android.R.styleable#King_Keyboard_Key_keyIcon
|
||||
* @attr ref android.R.styleable#King_Keyboard_Key_keyLabel
|
||||
* @attr ref android.R.styleable#King_Keyboard_Key_iconPreview
|
||||
* @attr ref android.R.styleable#King_Keyboard_Key_isSticky
|
||||
* @attr ref android.R.styleable#King_Keyboard_Key_isRepeatable
|
||||
* @attr ref android.R.styleable#King_Keyboard_Key_isModifier
|
||||
* @attr ref android.R.styleable#King_Keyboard_Key_popupKeyboard
|
||||
* @attr ref android.R.styleable#King_Keyboard_Key_popupCharacters
|
||||
* @attr ref android.R.styleable#King_Keyboard_Key_keyOutputText
|
||||
* @attr ref android.R.styleable#King_Keyboard_Key_keyEdgeFlags
|
||||
*/
|
||||
public static class Key {
|
||||
/**
|
||||
* All the key codes (unicode or custom code) that this key could generate, zero'th
|
||||
* being the most important.
|
||||
*/
|
||||
public int[] codes;
|
||||
|
||||
/** Label to display */
|
||||
public CharSequence label;
|
||||
|
||||
/** Icon to display instead of a label. Icon takes precedence over a label */
|
||||
public Drawable icon;
|
||||
/** Preview version of the icon, for the preview popup */
|
||||
public Drawable iconPreview;
|
||||
/** Width of the key, not including the gap */
|
||||
public int width;
|
||||
/** Height of the key, not including the gap */
|
||||
public int height;
|
||||
/** The horizontal gap before this key */
|
||||
public int gap;
|
||||
/** Whether this key is sticky, i.e., a toggle key */
|
||||
public boolean sticky;
|
||||
/** X coordinate of the key in the keyboard layout */
|
||||
public int x;
|
||||
/** Y coordinate of the key in the keyboard layout */
|
||||
public int y;
|
||||
/** The current pressed state of this key */
|
||||
public boolean pressed;
|
||||
/** If this is a sticky key, is it on? */
|
||||
public boolean on;
|
||||
/** Text to output when pressed. This can be multiple characters, like ".com" */
|
||||
public CharSequence text;
|
||||
/** Popup characters */
|
||||
public CharSequence popupCharacters;
|
||||
|
||||
/**
|
||||
* Flags that specify the anchoring to edges of the keyboard for detecting touch events
|
||||
* that are just out of the boundary of the key. This is a bit mask of
|
||||
* {@link KeyBoard#EDGE_LEFT}, {@link KeyBoard#EDGE_RIGHT}, {@link KeyBoard#EDGE_TOP} and
|
||||
* {@link KeyBoard#EDGE_BOTTOM}.
|
||||
*/
|
||||
public int edgeFlags;
|
||||
/** Whether this is a modifier key, such as Shift or Alt */
|
||||
public boolean modifier;
|
||||
/** The keyboard that this key belongs to */
|
||||
private KeyBoard keyboard;
|
||||
/**
|
||||
* If this key pops up a mini keyboard, this is the resource id for the XML layout for that
|
||||
* keyboard.
|
||||
*/
|
||||
public int popupResId;
|
||||
/** Whether this key repeats itself when held down */
|
||||
public boolean repeatable;
|
||||
|
||||
|
||||
private final static int[] KEY_STATE_NORMAL_ON = {
|
||||
android.R.attr.state_checkable,
|
||||
android.R.attr.state_checked
|
||||
};
|
||||
|
||||
private final static int[] KEY_STATE_PRESSED_ON = {
|
||||
android.R.attr.state_pressed,
|
||||
android.R.attr.state_checkable,
|
||||
android.R.attr.state_checked
|
||||
};
|
||||
|
||||
private final static int[] KEY_STATE_NORMAL_OFF = {
|
||||
android.R.attr.state_checkable
|
||||
};
|
||||
|
||||
private final static int[] KEY_STATE_PRESSED_OFF = {
|
||||
android.R.attr.state_pressed,
|
||||
android.R.attr.state_checkable
|
||||
};
|
||||
|
||||
private final static int[] KEY_STATE_NORMAL = {
|
||||
};
|
||||
|
||||
private final static int[] KEY_STATE_PRESSED = {
|
||||
android.R.attr.state_pressed
|
||||
};
|
||||
|
||||
/** Create an empty key with no attributes. */
|
||||
public Key(Row parent) {
|
||||
keyboard = parent.parent;
|
||||
height = parent.defaultHeight;
|
||||
width = parent.defaultWidth;
|
||||
gap = parent.defaultHorizontalGap;
|
||||
edgeFlags = parent.rowEdgeFlags;
|
||||
}
|
||||
|
||||
/** Create a key with the given top-left coordinate and extract its attributes from
|
||||
* the XML parser.
|
||||
* @param res resources associated with the caller's context
|
||||
* @param parent the row that this key belongs to. The row must already be attached to
|
||||
* a {@link KeyBoard}.
|
||||
* @param x the x coordinate of the top-left
|
||||
* @param y the y coordinate of the top-left
|
||||
* @param parser the XML parser containing the attributes for this key
|
||||
*/
|
||||
public Key(Resources res, Row parent, int x, int y, XmlResourceParser parser) {
|
||||
this(parent);
|
||||
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
|
||||
TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser),
|
||||
R.styleable.style_view);
|
||||
|
||||
width = getDimensionOrFraction(a,
|
||||
R.styleable.style_view_android_keyWidth,
|
||||
keyboard.mDisplayWidth, parent.defaultWidth);
|
||||
height = getDimensionOrFraction(a,
|
||||
R.styleable.style_view_android_keyHeight,
|
||||
keyboard.mDisplayHeight, parent.defaultHeight);
|
||||
gap = getDimensionOrFraction(a,
|
||||
R.styleable.style_view_android_horizontalGap,
|
||||
keyboard.mDisplayWidth, parent.defaultHorizontalGap);
|
||||
a.recycle();
|
||||
a = res.obtainAttributes(Xml.asAttributeSet(parser),
|
||||
R.styleable.style_key);
|
||||
this.x += gap;
|
||||
TypedValue codesValue = new TypedValue();
|
||||
a.getValue(R.styleable.style_key_android_codes,
|
||||
codesValue);
|
||||
if (codesValue.type == TypedValue.TYPE_INT_DEC
|
||||
|| codesValue.type == TypedValue.TYPE_INT_HEX) {
|
||||
codes = new int[] { codesValue.data };
|
||||
} else if (codesValue.type == TypedValue.TYPE_STRING) {
|
||||
codes = parseCSV(codesValue.string.toString());
|
||||
}
|
||||
|
||||
iconPreview = a.getDrawable(R.styleable.style_key_android_iconPreview);
|
||||
if (iconPreview != null) {
|
||||
iconPreview.setBounds(0, 0, iconPreview.getIntrinsicWidth(),
|
||||
iconPreview.getIntrinsicHeight());
|
||||
}
|
||||
popupCharacters = a.getText(
|
||||
R.styleable.style_key_android_popupCharacters);
|
||||
popupResId = a.getResourceId(
|
||||
R.styleable.style_key_android_popupKeyboard, 0);
|
||||
repeatable = a.getBoolean(
|
||||
R.styleable.style_key_android_isRepeatable, false);
|
||||
modifier = a.getBoolean(
|
||||
R.styleable.style_key_android_isModifier, false);
|
||||
sticky = a.getBoolean(
|
||||
R.styleable.style_key_android_isSticky, false);
|
||||
edgeFlags = a.getInt(R.styleable.style_key_android_keyEdgeFlags, 0);
|
||||
edgeFlags |= parent.rowEdgeFlags;
|
||||
|
||||
icon = a.getDrawable(
|
||||
R.styleable.style_key_android_keyIcon);
|
||||
if (icon != null) {
|
||||
icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
|
||||
}
|
||||
label = a.getText(R.styleable.style_key_android_keyLabel);
|
||||
text = a.getText(R.styleable.style_key_android_keyOutputText);
|
||||
|
||||
if (codes == null && !TextUtils.isEmpty(label)) {
|
||||
codes = new int[] { label.charAt(0) };
|
||||
}
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Informs the key that it has been pressed, in case it needs to change its appearance or
|
||||
* state.
|
||||
* @see #onReleased(boolean)
|
||||
*/
|
||||
public void onPressed() {
|
||||
pressed = !pressed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the pressed state of the key.
|
||||
*
|
||||
* <p>Toggled state of the key will be flipped when all the following conditions are
|
||||
* fulfilled:</p>
|
||||
*
|
||||
* <ul>
|
||||
* <li>This is a sticky key, that is, {@link #sticky} is {@code true}.
|
||||
* <li>The parameter {@code inside} is {@code true}.
|
||||
* <li>{@link android.os.Build.VERSION#SDK_INT} is greater than
|
||||
* {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}.
|
||||
* </ul>
|
||||
*
|
||||
* @param inside whether the finger was released inside the key. Works only on Android M and
|
||||
* later. See the method document for details.
|
||||
* @see #onPressed()
|
||||
*/
|
||||
public void onReleased(boolean inside) {
|
||||
pressed = !pressed;
|
||||
if (sticky && inside) {
|
||||
on = !on;
|
||||
}
|
||||
}
|
||||
|
||||
int[] parseCSV(String value) {
|
||||
int count = 0;
|
||||
int lastIndex = 0;
|
||||
if (value.length() > 0) {
|
||||
count++;
|
||||
while ((lastIndex = value.indexOf(",", lastIndex + 1)) > 0) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
int[] values = new int[count];
|
||||
count = 0;
|
||||
StringTokenizer st = new StringTokenizer(value, ",");
|
||||
while (st.hasMoreTokens()) {
|
||||
try {
|
||||
values[count++] = Integer.parseInt(st.nextToken());
|
||||
} catch (NumberFormatException nfe) {
|
||||
Log.e(TAG, "Error parsing keycodes " + value);
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects if a point falls inside this key.
|
||||
* @param x the x-coordinate of the point
|
||||
* @param y the y-coordinate of the point
|
||||
* @return whether or not the point falls inside the key. If the key is attached to an edge,
|
||||
* it will assume that all points between the key and the edge are considered to be inside
|
||||
* the key.
|
||||
*/
|
||||
public boolean isInside(int x, int y) {
|
||||
boolean leftEdge = (edgeFlags & EDGE_LEFT) > 0;
|
||||
boolean rightEdge = (edgeFlags & EDGE_RIGHT) > 0;
|
||||
boolean topEdge = (edgeFlags & EDGE_TOP) > 0;
|
||||
boolean bottomEdge = (edgeFlags & EDGE_BOTTOM) > 0;
|
||||
if ((x >= this.x || (leftEdge && x <= this.x + this.width))
|
||||
&& (x < this.x + this.width || (rightEdge && x >= this.x))
|
||||
&& (y >= this.y || (topEdge && y <= this.y + this.height))
|
||||
&& (y < this.y + this.height || (bottomEdge && y >= this.y))) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the square of the distance between the center of the key and the given point.
|
||||
* @param x the x-coordinate of the point
|
||||
* @param y the y-coordinate of the point
|
||||
* @return the square of the distance of the point from the center of the key
|
||||
*/
|
||||
public int squaredDistanceFrom(int x, int y) {
|
||||
int xDist = this.x + width / 2 - x;
|
||||
int yDist = this.y + height / 2 - y;
|
||||
return xDist * xDist + yDist * yDist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the drawable state for the key, based on the current state and type of the key.
|
||||
* @return the drawable state of the key.
|
||||
* @see android.graphics.drawable.StateListDrawable#setState(int[])
|
||||
*/
|
||||
public int[] getCurrentDrawableState() {
|
||||
int[] states = KEY_STATE_NORMAL;
|
||||
|
||||
if (on) {
|
||||
if (pressed) {
|
||||
states = KEY_STATE_PRESSED_ON;
|
||||
} else {
|
||||
states = KEY_STATE_NORMAL_ON;
|
||||
}
|
||||
} else {
|
||||
if (sticky) {
|
||||
if (pressed) {
|
||||
states = KEY_STATE_PRESSED_OFF;
|
||||
} else {
|
||||
states = KEY_STATE_NORMAL_OFF;
|
||||
}
|
||||
} else {
|
||||
if (pressed) {
|
||||
states = KEY_STATE_PRESSED;
|
||||
}
|
||||
}
|
||||
}
|
||||
return states;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a keyboard from the given xml key layout file.
|
||||
* @param context the application or service context
|
||||
* @param xmlLayoutResId the resource file that contains the keyboard layout and keys.
|
||||
*/
|
||||
public KeyBoard(Context context, int xmlLayoutResId) {
|
||||
this(context, xmlLayoutResId, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a keyboard from the given xml key layout file. Weeds out rows
|
||||
* that have a keyboard mode defined but don't match the specified mode.
|
||||
* @param context the application or service context
|
||||
* @param xmlLayoutResId the resource file that contains the keyboard layout and keys.
|
||||
* @param modeId keyboard mode identifier
|
||||
* @param width sets width of keyboard
|
||||
* @param height sets height of keyboard
|
||||
*/
|
||||
public KeyBoard(Context context, @XmlRes int xmlLayoutResId, int modeId, int width,
|
||||
int height) {
|
||||
mDisplayWidth = width;
|
||||
mDisplayHeight = height;
|
||||
|
||||
mDefaultHorizontalGap = 0;
|
||||
mDefaultWidth = mDisplayWidth / 10;
|
||||
mDefaultVerticalGap = 0;
|
||||
mDefaultHeight = mDefaultWidth;
|
||||
mKeys = new ArrayList<>();
|
||||
mModifierKeys = new ArrayList<>();
|
||||
mKeyboardMode = modeId;
|
||||
loadKeyboard(context, context.getResources().getXml(xmlLayoutResId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a keyboard from the given xml key layout file. Weeds out rows
|
||||
* that have a keyboard mode defined but don't match the specified mode.
|
||||
* @param context the application or service context
|
||||
* @param xmlLayoutResId the resource file that contains the keyboard layout and keys.
|
||||
* @param modeId keyboard mode identifier
|
||||
*/
|
||||
public KeyBoard(Context context, @XmlRes int xmlLayoutResId, int modeId) {
|
||||
DisplayMetrics dm = context.getResources().getDisplayMetrics();
|
||||
mDisplayWidth = dm.widthPixels;
|
||||
mDisplayHeight = dm.heightPixels;
|
||||
//Log.v(TAG, "keyboard's display metrics:" + dm);
|
||||
|
||||
mDefaultHorizontalGap = 0;
|
||||
mDefaultWidth = mDisplayWidth / 10;
|
||||
mDefaultVerticalGap = 0;
|
||||
mDefaultHeight = mDefaultWidth;
|
||||
mKeys = new ArrayList<>();
|
||||
mModifierKeys = new ArrayList<>();
|
||||
mKeyboardMode = modeId;
|
||||
loadKeyboard(context, context.getResources().getXml(xmlLayoutResId));
|
||||
}
|
||||
|
||||
public KeyBoard(Context context, int layoutTemplateResId,
|
||||
CharSequence characters, int columns, int horizontalPadding) {
|
||||
this(context, layoutTemplateResId);
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int column = 0;
|
||||
mTotalWidth = 0;
|
||||
|
||||
Row row = new Row(this);
|
||||
row.defaultHeight = mDefaultHeight;
|
||||
row.defaultWidth = mDefaultWidth;
|
||||
row.defaultHorizontalGap = mDefaultHorizontalGap;
|
||||
row.verticalGap = mDefaultVerticalGap;
|
||||
row.rowEdgeFlags = EDGE_TOP | EDGE_BOTTOM;
|
||||
final int maxColumns = columns == -1 ? Integer.MAX_VALUE : columns;
|
||||
for (int i = 0; i < characters.length(); i++) {
|
||||
char c = characters.charAt(i);
|
||||
if (column >= maxColumns
|
||||
|| x + mDefaultWidth + horizontalPadding > mDisplayWidth) {
|
||||
x = 0;
|
||||
y += mDefaultVerticalGap + mDefaultHeight;
|
||||
column = 0;
|
||||
}
|
||||
final Key key = new Key(row);
|
||||
key.x = x;
|
||||
key.y = y;
|
||||
key.label = String.valueOf(c);
|
||||
key.codes = new int[] { c };
|
||||
column++;
|
||||
x += key.width + key.gap;
|
||||
mKeys.add(key);
|
||||
row.mKeys.add(key);
|
||||
if (x > mTotalWidth) {
|
||||
mTotalWidth = x;
|
||||
}
|
||||
}
|
||||
mTotalHeight = y + mDefaultHeight;
|
||||
rows.add(row);
|
||||
}
|
||||
|
||||
final void resize(int newWidth, int newHeight) {
|
||||
int numRows = rows.size();
|
||||
for (int rowIndex = 0; rowIndex < numRows; ++rowIndex) {
|
||||
Row row = rows.get(rowIndex);
|
||||
int numKeys = row.mKeys.size();
|
||||
int totalGap = 0;
|
||||
int totalWidth = 0;
|
||||
for (int keyIndex = 0; keyIndex < numKeys; ++keyIndex) {
|
||||
Key key = row.mKeys.get(keyIndex);
|
||||
if (keyIndex > 0) {
|
||||
totalGap += key.gap;
|
||||
}
|
||||
totalWidth += key.width;
|
||||
}
|
||||
if (totalGap + totalWidth > newWidth) {
|
||||
int x = 0;
|
||||
float scaleFactor = (float)(newWidth - totalGap) / totalWidth;
|
||||
for (int keyIndex = 0; keyIndex < numKeys; ++keyIndex) {
|
||||
Key key = row.mKeys.get(keyIndex);
|
||||
key.width *= scaleFactor;
|
||||
key.x = x;
|
||||
x += key.width + key.gap;
|
||||
}
|
||||
}
|
||||
}
|
||||
mTotalWidth = newWidth;
|
||||
// TODO: This does not adjust the vertical placement according to the new size.
|
||||
// The main problem in the previous code was horizontal placement/size, but we should
|
||||
// also recalculate the vertical sizes/positions when we get this resize call.
|
||||
}
|
||||
|
||||
public List<Key> getKeys() {
|
||||
return mKeys;
|
||||
}
|
||||
|
||||
public List<Key> getModifierKeys() {
|
||||
return mModifierKeys;
|
||||
}
|
||||
|
||||
protected int getHorizontalGap() {
|
||||
return mDefaultHorizontalGap;
|
||||
}
|
||||
|
||||
protected void setHorizontalGap(int gap) {
|
||||
mDefaultHorizontalGap = gap;
|
||||
}
|
||||
|
||||
protected int getVerticalGap() {
|
||||
return mDefaultVerticalGap;
|
||||
}
|
||||
|
||||
protected void setVerticalGap(int gap) {
|
||||
mDefaultVerticalGap = gap;
|
||||
}
|
||||
|
||||
protected int getKeyHeight() {
|
||||
return mDefaultHeight;
|
||||
}
|
||||
|
||||
protected void setKeyHeight(int height) {
|
||||
mDefaultHeight = height;
|
||||
}
|
||||
|
||||
protected int getKeyWidth() {
|
||||
return mDefaultWidth;
|
||||
}
|
||||
|
||||
protected void setKeyWidth(int width) {
|
||||
mDefaultWidth = width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total height of the keyboard
|
||||
* @return the total height of the keyboard
|
||||
*/
|
||||
public int getHeight() {
|
||||
return mTotalHeight;
|
||||
}
|
||||
|
||||
public int getMinWidth() {
|
||||
return mTotalWidth;
|
||||
}
|
||||
|
||||
public boolean setShifted(boolean shiftState) {
|
||||
for (Key shiftKey : mShiftKeys) {
|
||||
if (shiftKey != null) {
|
||||
shiftKey.on = shiftState;
|
||||
}
|
||||
}
|
||||
if (mShifted != shiftState) {
|
||||
mShifted = shiftState;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isShifted() {
|
||||
return mShifted;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public int[] getShiftKeyIndices() {
|
||||
return mShiftKeyIndices;
|
||||
}
|
||||
|
||||
public int getShiftKeyIndex() {
|
||||
return mShiftKeyIndices[0];
|
||||
}
|
||||
|
||||
private void computeNearestNeighbors() {
|
||||
// Round-up so we don't have any pixels outside the grid
|
||||
mCellWidth = (getMinWidth() + GRID_WIDTH - 1) / GRID_WIDTH;
|
||||
mCellHeight = (getHeight() + GRID_HEIGHT - 1) / GRID_HEIGHT;
|
||||
mGridNeighbors = new int[GRID_SIZE][];
|
||||
int[] indices = new int[mKeys.size()];
|
||||
final int gridWidth = GRID_WIDTH * mCellWidth;
|
||||
final int gridHeight = GRID_HEIGHT * mCellHeight;
|
||||
for (int x = 0; x < gridWidth; x += mCellWidth) {
|
||||
for (int y = 0; y < gridHeight; y += mCellHeight) {
|
||||
int count = 0;
|
||||
for (int i = 0; i < mKeys.size(); i++) {
|
||||
final Key key = mKeys.get(i);
|
||||
if (key.squaredDistanceFrom(x, y) < mProximityThreshold ||
|
||||
key.squaredDistanceFrom(x + mCellWidth - 1, y) < mProximityThreshold ||
|
||||
key.squaredDistanceFrom(x + mCellWidth - 1, y + mCellHeight - 1)
|
||||
< mProximityThreshold ||
|
||||
key.squaredDistanceFrom(x, y + mCellHeight - 1) < mProximityThreshold) {
|
||||
indices[count++] = i;
|
||||
}
|
||||
}
|
||||
int [] cell = new int[count];
|
||||
System.arraycopy(indices, 0, cell, 0, count);
|
||||
mGridNeighbors[(y / mCellHeight) * GRID_WIDTH + (x / mCellWidth)] = cell;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the indices of the keys that are closest to the given point.
|
||||
* @param x the x-coordinate of the point
|
||||
* @param y the y-coordinate of the point
|
||||
* @return the array of integer indices for the nearest keys to the given point. If the given
|
||||
* point is out of range, then an array of size zero is returned.
|
||||
*/
|
||||
public int[] getNearestKeys(int x, int y) {
|
||||
if (mGridNeighbors == null) computeNearestNeighbors();
|
||||
if (x >= 0 && x < getMinWidth() && y >= 0 && y < getHeight()) {
|
||||
int index = (y / mCellHeight) * GRID_WIDTH + (x / mCellWidth);
|
||||
if (index < GRID_SIZE) {
|
||||
return mGridNeighbors[index];
|
||||
}
|
||||
}
|
||||
return new int[0];
|
||||
}
|
||||
|
||||
protected Row createRowFromXml(Resources res, XmlResourceParser parser) {
|
||||
return new Row(res, this, parser);
|
||||
}
|
||||
|
||||
protected Key createKeyFromXml(Resources res, Row parent, int x, int y,
|
||||
XmlResourceParser parser) {
|
||||
return new Key(res, parent, x, y, parser);
|
||||
}
|
||||
|
||||
private void loadKeyboard(Context context, XmlResourceParser parser) {
|
||||
boolean inKey = false;
|
||||
boolean inRow = false;
|
||||
boolean leftMostKey = false;
|
||||
int row = 0;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
Key key = null;
|
||||
Row currentRow = null;
|
||||
Resources res = context.getResources();
|
||||
boolean skipRow = false;
|
||||
|
||||
try {
|
||||
int event;
|
||||
while ((event = parser.next()) != XmlResourceParser.END_DOCUMENT) {
|
||||
if (event == XmlResourceParser.START_TAG) {
|
||||
String tag = parser.getName();
|
||||
if (TAG_ROW.equals(tag)) {
|
||||
inRow = true;
|
||||
x = 0;
|
||||
currentRow = createRowFromXml(res, parser);
|
||||
rows.add(currentRow);
|
||||
skipRow = currentRow.mode != 0 && currentRow.mode != mKeyboardMode;
|
||||
if (skipRow) {
|
||||
skipToEndOfRow(parser);
|
||||
inRow = false;
|
||||
}
|
||||
} else if (TAG_KEY.equals(tag)) {
|
||||
inKey = true;
|
||||
key = createKeyFromXml(res, currentRow, x, y, parser);
|
||||
mKeys.add(key);
|
||||
if (key.codes[0] == KEYCODE_SHIFT) {
|
||||
// Find available shift key slot and put this shift key in it
|
||||
for (int i = 0; i < mShiftKeys.length; i++) {
|
||||
if (mShiftKeys[i] == null) {
|
||||
mShiftKeys[i] = key;
|
||||
mShiftKeyIndices[i] = mKeys.size()-1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mModifierKeys.add(key);
|
||||
} else if (key.codes[0] == KEYCODE_ALT) {
|
||||
mModifierKeys.add(key);
|
||||
}
|
||||
currentRow.mKeys.add(key);
|
||||
} else if (TAG_KEYBOARD.equals(tag)) {
|
||||
parseKeyboardAttributes(res, parser);
|
||||
}
|
||||
} else if (event == XmlResourceParser.END_TAG) {
|
||||
if (inKey) {
|
||||
inKey = false;
|
||||
x += key.gap + key.width;
|
||||
if (x > mTotalWidth) {
|
||||
mTotalWidth = x;
|
||||
}
|
||||
} else if (inRow) {
|
||||
inRow = false;
|
||||
y += currentRow.verticalGap;
|
||||
y += currentRow.defaultHeight;
|
||||
row++;
|
||||
} else {
|
||||
// TODO: error or extend?
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Parse error:" + e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
mTotalHeight = y - mDefaultVerticalGap;
|
||||
}
|
||||
|
||||
private void skipToEndOfRow(XmlResourceParser parser)
|
||||
throws XmlPullParserException, IOException {
|
||||
int event;
|
||||
while ((event = parser.next()) != XmlResourceParser.END_DOCUMENT) {
|
||||
if (event == XmlResourceParser.END_TAG
|
||||
&& parser.getName().equals(TAG_ROW)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void parseKeyboardAttributes(Resources res, XmlResourceParser parser) {
|
||||
TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser),
|
||||
R.styleable.style_view);
|
||||
|
||||
mDefaultWidth = getDimensionOrFraction(a,
|
||||
R.styleable.style_view_android_keyWidth,
|
||||
mDisplayWidth, mDisplayWidth / 10);
|
||||
mDefaultHeight = getDimensionOrFraction(a,
|
||||
R.styleable.style_view_android_keyHeight,
|
||||
mDisplayHeight, 50);
|
||||
mDefaultHorizontalGap = getDimensionOrFraction(a,
|
||||
R.styleable.style_view_android_horizontalGap,
|
||||
mDisplayWidth, 0);
|
||||
mDefaultVerticalGap = getDimensionOrFraction(a,
|
||||
R.styleable.style_view_android_verticalGap,
|
||||
mDisplayHeight, 0);
|
||||
mProximityThreshold = (int) (mDefaultWidth * SEARCH_DISTANCE);
|
||||
mProximityThreshold = mProximityThreshold * mProximityThreshold; // Square it for comparison
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
static int getDimensionOrFraction(TypedArray a, int index, int base, int defValue) {
|
||||
TypedValue value = a.peekValue(index);
|
||||
if (value == null) return defValue;
|
||||
if (value.type == TypedValue.TYPE_DIMENSION) {
|
||||
return a.getDimensionPixelOffset(index, defValue);
|
||||
} else if (value.type == TypedValue.TYPE_FRACTION) {
|
||||
// Round it to avoid values like 47.9999 from getting truncated
|
||||
return Math.round(a.getFraction(index, base, base, defValue));
|
||||
}
|
||||
return defValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1359
app/src/main/java/com/example/fingerkeyboard/tool/KeyBoardView.java
Normal file
@ -0,0 +1,167 @@
|
||||
package com.example.fingerkeyboard.tool;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class MyKeyBoardView extends KeyBoardView{
|
||||
private CustomViewConfig config = new CustomViewConfig();
|
||||
private int shift_status = 0;
|
||||
private int viewType = 0;
|
||||
|
||||
private Context context;
|
||||
|
||||
public void setShift_status(int shift_status) {
|
||||
this.shift_status = shift_status;
|
||||
}
|
||||
|
||||
public int getShift_status() {
|
||||
return shift_status;
|
||||
}
|
||||
|
||||
public void setViewType(int viewType) {
|
||||
this.viewType = viewType;
|
||||
}
|
||||
|
||||
public int getViewType() {
|
||||
return viewType;
|
||||
}
|
||||
|
||||
public MyKeyBoardView(Context context, AttributeSet attrs) {
|
||||
|
||||
super(context, attrs);
|
||||
initView();
|
||||
}
|
||||
|
||||
public MyKeyBoardView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
initView();
|
||||
}
|
||||
|
||||
public MyKeyBoardView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
initView();
|
||||
}
|
||||
|
||||
|
||||
private Paint mPaint;
|
||||
private int leftPressedColor = 0xFFFF0000;
|
||||
private int rightPressedColor = 0xFFAA0000;
|
||||
private int action = -10;
|
||||
private Paint paint = new Paint();
|
||||
private Path pathLeft = new Path();
|
||||
|
||||
|
||||
private void initView() {
|
||||
config.init();
|
||||
context = getContext();
|
||||
mPaint = new Paint();
|
||||
mPaint.setTextAlign(Paint.Align.CENTER);
|
||||
float textSize = MyTools.spToPpx(16f, context);
|
||||
mPaint.setTextSize(textSize);
|
||||
mPaint.setColor(config.getKeyNoramlcolor());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
|
||||
|
||||
KeyBoard keyboard = getKeyboard();
|
||||
List<KeyBoard.Key> keys = keyboard.getKeys();
|
||||
for (int r = 0; r < keys.size(); r++) {
|
||||
KeyBoard.Key key = keys.get(r);
|
||||
int code = key.codes[0];
|
||||
|
||||
mPaint.setColor(config.getKeyActioncolor());
|
||||
if (code == KeyBoard.KEYCODE_MODE_CHANGE) {
|
||||
|
||||
onDrawKeyBackground(key, config.getBgActionDraw(), canvas);
|
||||
onDrawLabel(key, canvas);
|
||||
|
||||
} else if (code == KeyBoard.KEYCODE_SHIFT) {
|
||||
onDrawKeyBackground(key, config.getBgActionDraw(), canvas);
|
||||
DrawIcon.INSTANCE.onDrawKeyIcon(key, getShiftDraw(), canvas, this);
|
||||
|
||||
} else if (code == KeyBoard.KEYCODE_SHIFT_123) {
|
||||
|
||||
onDrawKeyBackground(key, config.getBgActionDraw(), canvas);
|
||||
// DrawIcon.INSTANCE.onDrawKeyIcon(key, getShiftDraw(), canvas, this);
|
||||
onDrawLabel(key, canvas);
|
||||
|
||||
} else if (code == KeyBoard.KEYCODE_SHIFT_SYMBOL) {
|
||||
|
||||
onDrawKeyBackground(key, config.getBgActionDraw(), canvas);
|
||||
// DrawIcon.INSTANCE.onDrawKeyIcon(key, getShiftDraw(), canvas, this);
|
||||
onDrawLabel(key, canvas);
|
||||
|
||||
} else if (code == KeyBoard.KEYCODE_DONE) {
|
||||
onDrawKeyBackground(key, config.getBgActionDraw(), canvas);
|
||||
onDrawLabel(key, canvas);
|
||||
} else if (code == KeyBoard.KEYCODE_DELETE) {
|
||||
onDrawKeyBackground(key, config.getBgActionDraw(), canvas);
|
||||
DrawIcon.INSTANCE.onDrawKeyIcon(key, config.getIconDel(), canvas, this);
|
||||
onDrawLabel(key, canvas);
|
||||
} else {
|
||||
mPaint.setColor(config.getKeyNoramlcolor());
|
||||
onDrawKeyBackground(key, config.getBgNormalDraw(), canvas);
|
||||
onDrawLabel(key, canvas);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void updateConfigView(Context con) {
|
||||
config.updateConfig(con);
|
||||
setBackground(config.getBG());
|
||||
invalidateAllKeys();
|
||||
|
||||
}
|
||||
|
||||
private Drawable getShiftDraw() {
|
||||
if (shift_status == 0) {
|
||||
return config.getIconShift();
|
||||
} else if (shift_status == 1) {
|
||||
return config.getIconShiftLock();
|
||||
} else {
|
||||
return config.getIconShiftLock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void onDrawKeyBackground(KeyBoard.Key myKey,
|
||||
Drawable keyBG,
|
||||
Canvas canvas) {
|
||||
if (keyBG != null) {
|
||||
Rect rect = new Rect(myKey.x + getPaddingLeft(), myKey.y + getPaddingTop(), myKey.width + myKey.x + getPaddingLeft(), myKey.height + myKey.y + getPaddingTop());
|
||||
keyBG.setBounds(rect);
|
||||
keyBG.setState(myKey.getCurrentDrawableState());
|
||||
keyBG.draw(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
private void onDrawLabel(
|
||||
KeyBoard.Key myKey,
|
||||
Canvas canvas) {
|
||||
boolean b = myKey.label == null || myKey.label == "";
|
||||
if (!b) {
|
||||
float y1 = myKey.y + getPaddingRight() + (myKey.height/ 2f) + ((mPaint.getTextSize() - mPaint.descent()) / 2f);
|
||||
float x1 = myKey.x + getPaddingLeft() + ((myKey.width / 2f));
|
||||
canvas.drawText(myKey.label.toString(), x1, y1, mPaint);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
200
app/src/main/java/com/example/fingerkeyboard/tool/MyService.java
Normal file
@ -0,0 +1,200 @@
|
||||
package com.example.fingerkeyboard.tool;
|
||||
|
||||
import android.inputmethodservice.InputMethodService;
|
||||
import android.os.SystemClock;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
|
||||
|
||||
import com.example.fingerkeyboard.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class MyService extends InputMethodService implements KeyBoardView.OnKeyboardActionListener{
|
||||
private long last_click = -1L;
|
||||
|
||||
|
||||
private int[] ViewXmls = new int[3];
|
||||
|
||||
private boolean is_double = false;
|
||||
|
||||
private MyKeyBoardView myKeyBoardView;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public View onCreateInputView() {
|
||||
ViewXmls[0] = R.xml.view_1;
|
||||
ViewXmls[1] = R.xml.view_2;
|
||||
ViewXmls[2] = R.xml.view_3;
|
||||
|
||||
View inputView = LayoutInflater.from(this).inflate(R.layout.customer_input_view, null, false);
|
||||
|
||||
|
||||
myKeyBoardView = (MyKeyBoardView) inputView.findViewById(R.id.my_keyboard_view);
|
||||
myKeyBoardView.setPreviewEnabled(false);
|
||||
|
||||
|
||||
myKeyBoardView.setKeyboard(new KeyBoard(this, ViewXmls[0]));//将自定义的键盘布局到KeyBoard上
|
||||
myKeyBoardView.setOnKeyboardActionListener(this);//设置键盘事件监听器方法
|
||||
return inputView;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onWindowShown() {
|
||||
super.onWindowShown();
|
||||
myKeyBoardView.updateConfigView(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onPress(int primaryCode) {//双击
|
||||
if(primaryCode == KeyBoard.KEYCODE_SHIFT){
|
||||
if(300 > SystemClock.elapsedRealtime() - last_click){
|
||||
is_double = true;
|
||||
|
||||
}
|
||||
last_click = SystemClock.elapsedRealtime();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRelease(int primaryCode) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void switchCapital(Boolean toCapital, KeyBoard keyboard) {
|
||||
|
||||
List<KeyBoard.Key> keys = keyboard.getKeys();
|
||||
for(int n=1;n<keys.size();n++){
|
||||
KeyBoard.Key key = keys.get(n);
|
||||
if(key.label != null && key.label != "" ){
|
||||
if(key.label.length() == 1){
|
||||
String s = key.label.toString();
|
||||
char myChar;
|
||||
if(toCapital){
|
||||
myChar = s.toUpperCase().charAt(0);
|
||||
}else {
|
||||
myChar = s.toLowerCase().charAt(0);
|
||||
}
|
||||
key.label = String.valueOf(myChar);
|
||||
key.codes[0] = (int) myChar;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKey(int primaryCode, int[] keyCodes) {
|
||||
switch (primaryCode){
|
||||
case KeyBoard.KEYCODE_SHIFT:
|
||||
|
||||
int shiftStatus = myKeyBoardView.getShift_status();
|
||||
KeyBoard keyBoard = myKeyBoardView.getKeyboard();
|
||||
|
||||
switch (shiftStatus){
|
||||
case 0://小写
|
||||
if (is_double){
|
||||
myKeyBoardView.setShift_status(2);//固定大写
|
||||
}else {
|
||||
myKeyBoardView.setShift_status(1);//大写
|
||||
}
|
||||
switchCapital(true,keyBoard);//启用大写模式
|
||||
myKeyBoardView.setKeyboard(keyBoard);
|
||||
break;
|
||||
case 1:
|
||||
if(is_double){
|
||||
myKeyBoardView.setShift_status(2);
|
||||
}else {
|
||||
myKeyBoardView.setShift_status(0);
|
||||
switchCapital(false,keyBoard);//不启用大写模式
|
||||
}
|
||||
myKeyBoardView.setKeyboard(keyBoard);
|
||||
break;
|
||||
case 2:
|
||||
myKeyBoardView.setShift_status(0);
|
||||
switchCapital(false,keyBoard);
|
||||
myKeyBoardView.setKeyboard(keyBoard);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case KeyBoard.KEYCODE_SHIFT_123://选择到数字按键
|
||||
changeView(2);
|
||||
break;
|
||||
case KeyBoard.KEYCODE_SHIFT_SYMBOL:
|
||||
changeView(1);
|
||||
break;
|
||||
case KeyBoard.KEYCODE_DELETE:
|
||||
getCurrentInputConnection().deleteSurroundingText(1,0);
|
||||
break;
|
||||
case KeyBoard.KEYCODE_DONE:
|
||||
getCurrentInputConnection().performEditorAction(EditorInfo.IME_ACTION_SEARCH);//执行操作
|
||||
|
||||
break;
|
||||
case KeyBoard.KEYCODE_MODE_CHANGE:
|
||||
if(myKeyBoardView.getViewType() == 0){
|
||||
changeView(1);
|
||||
}else {
|
||||
changeView(0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
char charcode = (char) primaryCode;
|
||||
String s = String.valueOf(charcode);
|
||||
getCurrentInputConnection().commitText(String.valueOf(charcode),1);
|
||||
int shiftStatus_old = myKeyBoardView.getShift_status();
|
||||
KeyBoard keyboard1 = myKeyBoardView.getKeyboard();
|
||||
if(shiftStatus_old == 1){
|
||||
myKeyBoardView.setShift_status(0);
|
||||
switchCapital(false,keyboard1);
|
||||
myKeyBoardView.setKeyboard(keyboard1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void changeView(int type) {
|
||||
myKeyBoardView.setViewType(type);
|
||||
myKeyBoardView.setKeyboard(new KeyBoard(this, ViewXmls[type]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onText(CharSequence text) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swipeLeft() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swipeRight() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swipeDown() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swipeUp() {
|
||||
|
||||
}
|
||||
}
|
||||
258
app/src/main/java/com/example/fingerkeyboard/tool/MyTools.java
Normal file
@ -0,0 +1,258 @@
|
||||
package com.example.fingerkeyboard.tool;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.StateListDrawable;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
import android.view.inputmethod.InputMethodInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.DataSource;
|
||||
import com.bumptech.glide.load.engine.GlideException;
|
||||
import com.bumptech.glide.request.RequestListener;
|
||||
import com.bumptech.glide.request.target.Target;
|
||||
|
||||
|
||||
import net.sf.sevenzipjbinding.ArchiveFormat;
|
||||
import net.sf.sevenzipjbinding.IInArchive;
|
||||
import net.sf.sevenzipjbinding.SevenZip;
|
||||
import net.sf.sevenzipjbinding.SevenZipException;
|
||||
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
|
||||
import net.sf.sevenzipjbinding.impl.RandomAccessFileOutStream;
|
||||
import net.sf.sevenzipjbinding.simple.ISimpleInArchiveItem;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.util.ArrayList;
|
||||
import com.example.fingerkeyboard.KeyBoard;
|
||||
import com.example.fingerkeyboard.data.MyData;
|
||||
import com.example.fingerkeyboard.listener.DownloadCallback;
|
||||
import com.example.fingerkeyboard.listener.UnzipCallback;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class MyTools {
|
||||
private static String sharedpreferenceName = "share_name";
|
||||
private static String sharedpreferenceKey_skin = "key_skin";
|
||||
|
||||
|
||||
private static final SharedPreferences share = KeyBoard.app.getSharedPreferences(
|
||||
sharedpreferenceName, Context.MODE_PRIVATE);
|
||||
|
||||
|
||||
public static StateListDrawable getStatus(Drawable draw, Drawable drawPress) {
|
||||
StateListDrawable stateListDrawable = new StateListDrawable();
|
||||
stateListDrawable.addState(new int[android.R.attr.state_pressed], draw); //按下状态,传入draw
|
||||
stateListDrawable.addState(new int[0], drawPress);
|
||||
return stateListDrawable;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static float spToPpx(Float values, Context context) {
|
||||
float scale = context.getResources().getDisplayMetrics().scaledDensity;//获取屏幕密度比例因子(scale)
|
||||
return values * scale; //返回传入的值×比例因子
|
||||
}
|
||||
|
||||
|
||||
private static final SharedPreferences.Editor editorShare = share.edit();
|
||||
|
||||
|
||||
private static InputMethodManager methodManager = (InputMethodManager) KeyBoard.app.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static String parseString(File file){
|
||||
StringBuilder sBuilder = new StringBuilder();
|
||||
try{
|
||||
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
|
||||
String next = "";
|
||||
while(null != (next = br.readLine())){
|
||||
sBuilder.append(next);
|
||||
}
|
||||
String trim = sBuilder.toString().trim();
|
||||
return trim;
|
||||
} catch (IOException ioException) { //如果文件读取失败,会返回空值
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void saveSkin(String resDirPath) {
|
||||
Log.d("-----","--------saveskin"+resDirPath);
|
||||
editorShare.putString(sharedpreferenceKey_skin, resDirPath);
|
||||
editorShare.apply(); //提交
|
||||
}
|
||||
|
||||
public static String getSkin() {
|
||||
|
||||
return share.getString(sharedpreferenceKey_skin, "");
|
||||
}
|
||||
|
||||
public static String getSkinPathByName(String name){
|
||||
|
||||
Log.d("-----","--------getSkinPathByName"+name);
|
||||
return share.getString(name,"");
|
||||
}
|
||||
|
||||
public static void saveSkinByName(String name, String resDirPath) {
|
||||
editorShare.putString(name, resDirPath);
|
||||
editorShare.apply();
|
||||
}
|
||||
|
||||
//将dp转换为px像素值
|
||||
public static int dpToPx(int dp, Context context) {
|
||||
float density = context.getResources().getDisplayMetrics().density;
|
||||
return (int) (dp * density);
|
||||
}
|
||||
|
||||
private static List<MyData> parseJsonString(String jsonString) {
|
||||
List<MyData> myDataArrayList = new ArrayList<>();
|
||||
try {
|
||||
JSONObject string1 = new JSONObject(jsonString);
|
||||
JSONArray list = string1.getJSONArray("list");
|
||||
for (int g = 0; g < list.length(); g++) {
|
||||
MyData myData = new MyData();
|
||||
JSONObject item = list.getJSONObject(g);
|
||||
String preview = item.getString("preview");
|
||||
String thumb = item.getString("thumb");
|
||||
String title = item.getString("title");
|
||||
String zipUrl = item.getString("zipUrl");
|
||||
myData.setPreview(String.valueOf(preview));
|
||||
myData.setThumb(thumb);
|
||||
myData.setZipUrl(zipUrl);
|
||||
myData.setResourseName(title);
|
||||
myDataArrayList.add(myData);
|
||||
}
|
||||
return myDataArrayList;
|
||||
} catch (JSONException jsonException) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void goSetStep2() {
|
||||
methodManager.showInputMethodPicker();
|
||||
}
|
||||
public static boolean isStep2() {
|
||||
String string = Settings.Secure.getString(KeyBoard.app.getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
|
||||
if (string.startsWith(KeyBoard.app.getPackageName())) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void goSetStep1(Context context) {
|
||||
Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
public static boolean isStep1() {
|
||||
for (InputMethodInfo inputMethodInfo : methodManager.getEnabledInputMethodList()) {
|
||||
if (inputMethodInfo.getId().startsWith(KeyBoard.app.getPackageName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void downloadZip(String url, Context context, DownloadCallback callback) {
|
||||
|
||||
Glide.with(context)
|
||||
.asFile()
|
||||
.load(url)
|
||||
.addListener(new RequestListener<File>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<File> target, boolean isFirstResource) {
|
||||
callback.onDownloadCall(false, null);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onResourceReady(@NonNull File resource, @NonNull Object model, Target<File> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
||||
callback.onDownloadCall(true, resource);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
).preload();
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static void unzipFile(
|
||||
String unzipPath,
|
||||
File resource,
|
||||
UnzipCallback unzipCallback
|
||||
) {
|
||||
if (!resource.exists()) {
|
||||
unzipCallback.onUnzipCall(false, "");
|
||||
return;
|
||||
}
|
||||
String itemFilePath = "";
|
||||
|
||||
RandomAccessFileOutStream outStream = null;
|
||||
IInArchive openInArchive;
|
||||
RandomAccessFileInStream randomAccessFileInStream;
|
||||
try {
|
||||
randomAccessFileInStream = new RandomAccessFileInStream(new RandomAccessFile(resource, "r"));
|
||||
openInArchive = SevenZip.openInArchive(
|
||||
ArchiveFormat.SEVEN_ZIP,
|
||||
randomAccessFileInStream
|
||||
);
|
||||
|
||||
ISimpleInArchiveItem[] archiveItems = openInArchive.getSimpleInterface().getArchiveItems();
|
||||
for (int d = 0; d < archiveItems.length; d++) {
|
||||
ISimpleInArchiveItem simple = archiveItems[d];
|
||||
File file = new File(unzipPath, simple.getPath());
|
||||
if (!simple.isFolder()) {
|
||||
outStream = new RandomAccessFileOutStream(new RandomAccessFile(file, "rw"));
|
||||
simple.extractSlow(outStream);
|
||||
itemFilePath = file.getPath();
|
||||
|
||||
} else {
|
||||
boolean mkdirs = file.mkdirs();
|
||||
}
|
||||
}
|
||||
randomAccessFileInStream.close();
|
||||
openInArchive.close();
|
||||
if (outStream != null) {
|
||||
outStream.close();
|
||||
}
|
||||
int res = itemFilePath.indexOf("res");
|
||||
String substring = itemFilePath.substring(0, res + 3);
|
||||
unzipCallback.onUnzipCall(true, substring);
|
||||
|
||||
} catch (FileNotFoundException | SevenZipException e) {
|
||||
unzipCallback.onUnzipCall(false, "");
|
||||
|
||||
} catch (IOException e) {
|
||||
unzipCallback.onUnzipCall(false, "");
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
package com.example.fingerkeyboard.tool;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class SpaceItem extends RecyclerView.ItemDecoration {
|
||||
private int ex_space = 0;
|
||||
private int v_space = 0;
|
||||
private int h_space = 0;
|
||||
|
||||
@Override
|
||||
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
|
||||
|
||||
int position = parent.getChildAdapterPosition(view);
|
||||
int spanSize = 1;
|
||||
int spanIndex = 0;
|
||||
int spanCount = 1;
|
||||
|
||||
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
|
||||
|
||||
if (layoutManager instanceof GridLayoutManager) {
|
||||
GridLayoutManager layoutManager1 = (GridLayoutManager) layoutManager;
|
||||
GridLayoutManager.LayoutParams layoutParams = (GridLayoutManager.LayoutParams) view.getLayoutParams();
|
||||
spanCount = layoutManager1.getSpanCount();
|
||||
spanSize = layoutManager1.getSpanSizeLookup().getSpanSize(position);
|
||||
spanIndex = layoutParams.getSpanIndex();
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (spanSize == spanCount) {
|
||||
outRect.left = v_space + ex_space;
|
||||
outRect.right = v_space + ex_space;
|
||||
outRect.bottom = h_space;
|
||||
} else {
|
||||
int itemAllSpacing = (v_space * (spanCount + 1) + ex_space * 2) / spanCount;
|
||||
int left = v_space * (spanIndex + 1) - itemAllSpacing * spanIndex + ex_space;
|
||||
int right = itemAllSpacing - left;
|
||||
outRect.left = left;
|
||||
outRect.right = right;
|
||||
outRect.bottom = h_space;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public SpaceItem(int v_space, int h_space, int ex_space) {
|
||||
this.ex_space = ex_space;
|
||||
this.h_space = h_space;
|
||||
this.v_space = v_space;
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
package com.example.fingerkeyboard.tool;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class customerText extends androidx.appcompat.widget.AppCompatTextView {
|
||||
|
||||
|
||||
public customerText(@NonNull Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public customerText(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public customerText(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
|
||||
CharSequence text = getText();
|
||||
|
||||
}
|
||||
}
|
||||
7
app/src/main/res/drawable/btn_download_background.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<corners android:radius="9dp"/>
|
||||
<solid android:color="@color/color_d9c7ff"/>
|
||||
|
||||
</shape>
|
||||
8
app/src/main/res/drawable/btn_main_normal.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<corners android:radius="30dp"/>
|
||||
<solid android:color="@color/color_btn_recent"/>
|
||||
|
||||
|
||||
</shape>
|
||||
8
app/src/main/res/drawable/btn_main_selected.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<corners android:radius="30dp"/>
|
||||
<solid android:color="@color/color_btn"/>
|
||||
|
||||
|
||||
</shape>
|
||||
6
app/src/main/res/drawable/de_keyboard_bg.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/color_d9c7ff"/>
|
||||
|
||||
</shape>
|
||||
9
app/src/main/res/drawable/del_icon.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>
|
||||
6
app/src/main/res/drawable/home_tab_selector.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/btn_main_normal" android:state_selected="false"/>
|
||||
<item android:drawable="@drawable/btn_main_selected"/>
|
||||
|
||||
</selector>
|
||||
170
app/src/main/res/drawable/ic_launcher_background.xml
Normal file
@ -0,0 +1,170 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="#3DDC84"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
</vector>
|
||||
30
app/src/main/res/drawable/ic_launcher_foreground.xml
Normal file
@ -0,0 +1,30 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="85.84757"
|
||||
android:endY="92.4963"
|
||||
android:startX="42.9492"
|
||||
android:startY="49.59793"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
||||
9
app/src/main/res/drawable/ico_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>
|
||||
9
app/src/main/res/drawable/icon_back.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="30dp"
|
||||
android:height="30dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:pathData="M395.2,513.6l323.1,-312.4c19.1,-18.4 19.1,-48.3 0,-66.7 -19.1,-18.4 -49.9,-18.4 -69,0L291.8,480.3c-19.1,18.4 -19.1,48.3 0,66.7l357.6,345.7c9.5,9.2 22,13.8 34.5,13.8 12.5,0 25,-4.6 34.5,-13.8 19.1,-18.4 19.1,-48.2 0,-66.7L395.2,513.6z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
||||
15
app/src/main/res/drawable/icon_download.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="64dp"
|
||||
android:height="64dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:pathData="M512.5,955.4c-5.2,0 -10.3,-2.1 -14.1,-6.3 -7,-7.8 -6.4,-19.8 1.4,-26.8l189.5,-170.6c7.8,-7 19.8,-6.4 26.8,1.4 7,7.8 6.4,19.8 -1.4,26.8L525.2,950.6c-3.6,3.2 -8.1,4.8 -12.7,4.8z"
|
||||
android:fillColor="#ffffff"/>
|
||||
<path
|
||||
android:pathData="M512.5,955.4c-4.6,0 -9.1,-1.7 -12.7,-4.9L310.4,780c-7.8,-7 -8.4,-19 -1.4,-26.8 7,-7.8 19,-8.4 26.8,-1.4l157.9,142.1V462.7c0,-10.5 8.5,-19 19,-19s19,8.5 19,19v473.8c0,7.5 -4.4,14.3 -11.2,17.3 -2.7,1.1 -5.3,1.6 -8,1.6z"
|
||||
android:fillColor="#ffffff"/>
|
||||
<path
|
||||
android:pathData="M758.9,690.1c-10.5,0 -19,-8.5 -19,-19s8.5,-19 19,-19c98.8,0 170.6,-72 170.6,-171.2 0,-95.5 -60.1,-162.2 -153.2,-170 -7.2,-0.6 -13.4,-5.2 -16.1,-12C737,240 666.4,102.7 512.5,102.7S288.1,240 264.9,299.1c-2.6,6.7 -8.9,11.4 -16.1,12 -93.1,7.8 -153.2,74.5 -153.2,170 0,99.2 71.7,171.2 170.6,171.2 10.5,0 19,8.5 19,19s-8.5,19 -19,19c-120.8,0 -208.5,-87.9 -208.5,-209.1 0,-110.8 70.3,-192.4 176.2,-206.5C289.4,142.9 392.8,64.8 512.5,64.8S735.7,143 791.1,274.6c105.9,14 176.2,95.7 176.2,206.5 0.1,121.1 -87.6,209 -208.4,209z"
|
||||
android:fillColor="#ffffff"/>
|
||||
</vector>
|
||||
8
app/src/main/res/drawable/iv_back_background.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<corners android:radius="30dp"/>
|
||||
|
||||
<solid android:color="@color/color_d9c7ff"/>
|
||||
|
||||
</shape>
|
||||
7
app/src/main/res/drawable/step_background.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<corners android:radius="9dp"/>
|
||||
<solid android:color="@color/color_d9c7ff"/>
|
||||
|
||||
</shape>
|
||||
7
app/src/main/res/drawable/step_background_selected.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<corners android:radius="9dp"/>
|
||||
<solid android:color="@color/color_DCDCDC"/>
|
||||
|
||||
</shape>
|
||||
6
app/src/main/res/drawable/step_selector.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_selected="false" android:drawable="@drawable/step_background"/>
|
||||
<item android:state_selected="true" android:drawable="@drawable/step_background_selected"/>
|
||||
|
||||
</selector>
|
||||
40
app/src/main/res/layout/activity_home.xml
Normal file
@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".HomeActivity">
|
||||
<ImageView
|
||||
android:id="@+id/logo"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="80dp"
|
||||
android:src="@mipmap/logo"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="260dp"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Finger Keyboard"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_below="@id/logo"
|
||||
android:layout_marginTop="30dp"
|
||||
android:textSize="30sp"
|
||||
android:textStyle="italic"
|
||||
android:textColor="@color/keyboard_main"
|
||||
/>
|
||||
|
||||
<ProgressBar
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/name"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="30dp"
|
||||
android:indeterminateTint="#C3AFE6" />
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
113
app/src/main/res/layout/activity_main.xml
Normal file
@ -0,0 +1,113 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="70dp"
|
||||
android:background="@color/keyboard_black"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="10dp"
|
||||
app:srcCompat="@mipmap/logo" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textview_wallpaper"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="9dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:text="@string/app_name"
|
||||
android:textColor="#7E49DC"
|
||||
android:textSize="23sp"
|
||||
android:textStyle="bold|italic" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_set"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginLeft="20dp"
|
||||
app:srcCompat="@mipmap/setting" />
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<HorizontalScrollView
|
||||
android:layout_width="wrap_content"
|
||||
android:scrollbars="none"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="35dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<android.widget.Button
|
||||
android:id="@+id/btn_love"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="30dp"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/home_tab_selector"
|
||||
android:gravity="center"
|
||||
android:text="love"
|
||||
android:textColor="#FFFFFFFF"
|
||||
android:textSize="10sp"
|
||||
android:textStyle="italic" />
|
||||
|
||||
<android.widget.Button
|
||||
android:id="@+id/btn_festival"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="30dp"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/home_tab_selector"
|
||||
android:gravity="center"
|
||||
android:text="festival"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="10sp"
|
||||
android:textStyle="italic" />
|
||||
|
||||
<android.widget.Button
|
||||
android:id="@+id/btn_cute"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="30dp"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/home_tab_selector"
|
||||
android:gravity="center"
|
||||
android:text="cute"
|
||||
android:textColor="#FFFFFFFF"
|
||||
android:textSize="10sp"
|
||||
android:textStyle="italic" />
|
||||
|
||||
<android.widget.Button
|
||||
android:id="@+id/btn_category"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:background="@mipmap/down"
|
||||
android:layout_marginLeft="8dp"
|
||||
/>
|
||||
</LinearLayout>
|
||||
</HorizontalScrollView>
|
||||
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/bottom_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="5dp">
|
||||
|
||||
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
94
app/src/main/res/layout/activity_preview.xml
Normal file
@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:context=".PreviewActivity">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_view_back_id"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="45dp"
|
||||
app:srcCompat="@drawable/icon_back"
|
||||
android:padding="15dp"
|
||||
android:src="@drawable/icon_back"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:background="@drawable/iv_back_background"
|
||||
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_view_preview_id"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="15dp"
|
||||
android:layout_marginTop="13dp"
|
||||
android:layout_marginEnd="15dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/image_view_back_id"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_view_name_id"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="#000000"
|
||||
android:text="@string/app_name"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:textSize="16sp"
|
||||
|
||||
|
||||
app:layout_constraintLeft_toLeftOf="@id/image_view_preview_id"
|
||||
app:layout_constraintTop_toBottomOf="@+id/image_view_preview_id"
|
||||
/>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:id="@+id/linear_layout_download_id"
|
||||
android:layout_marginStart="35dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginEnd="35dp"
|
||||
android:paddingTop="14dp"
|
||||
android:paddingBottom="14dp"
|
||||
android:background="@drawable/btn_download_background"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_view_name_id">
|
||||
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView2"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_gravity="center"
|
||||
android:src="@drawable/icon_download"/>
|
||||
</LinearLayout>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_bar_preview_id"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminateTint="@color/color_d9c7ff"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintLeft_toLeftOf="@id/image_view_preview_id"
|
||||
app:layout_constraintRight_toRightOf="@id/image_view_preview_id"
|
||||
app:layout_constraintTop_toTopOf="@id/image_view_preview_id"
|
||||
app:layout_constraintBottom_toBottomOf="@id/image_view_preview_id"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_bar_download_id"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:indeterminateTint="@color/keyboard_black"
|
||||
app:layout_constraintLeft_toLeftOf="@+id/linear_layout_download_id"
|
||||
app:layout_constraintRight_toRightOf="@id/linear_layout_download_id"
|
||||
app:layout_constraintTop_toTopOf="@id/linear_layout_download_id"
|
||||
app:layout_constraintBottom_toBottomOf="@id/linear_layout_download_id"/>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
66
app/src/main/res/layout/activity_setting.xml
Normal file
@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_view_back_id"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="45dp"
|
||||
app:srcCompat="@drawable/icon_back"
|
||||
android:padding="15dp"
|
||||
android:src="@drawable/icon_back"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:background="@drawable/iv_back_background"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="55dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/set"
|
||||
android:textColor="@color/keyboard_main"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="12dp"
|
||||
android:id="@+id/textview_step1"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
android:layout_marginTop="190dp"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="17sp"
|
||||
android:gravity="center"
|
||||
android:text="@string/step1"
|
||||
android:background="@drawable/step_selector"
|
||||
app:layout_constraintTop_toBottomOf="@id/image_view_back_id" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="12dp"
|
||||
android:id="@+id/textview_step2"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
android:layout_marginTop="14dp"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="17sp"
|
||||
android:gravity="center"
|
||||
android:text="@string/step2"
|
||||
android:background="@drawable/step_selector"
|
||||
app:layout_constraintTop_toBottomOf="@id/textview_step1" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
17
app/src/main/res/layout/customer_input_view.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
|
||||
<com.example.fingerkeyboard.tool.MyKeyBoardView
|
||||
android:id="@+id/my_keyboard_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="210dp"
|
||||
android:keyBackground="@drawable/de_keyboard_bg"
|
||||
android:padding="2dp" />
|
||||
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
21
app/src/main/res/layout/fragment_aesthetic.xml
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/white"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_view_id"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
21
app/src/main/res/layout/fragment_cool.xml
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/white"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_view_id"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
21
app/src/main/res/layout/fragment_cute.xml
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/white"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_view_id"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
21
app/src/main/res/layout/fragment_festival.xml
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/white"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_view_id"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
21
app/src/main/res/layout/fragment_gravity.xml
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/white"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_view_id"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
21
app/src/main/res/layout/fragment_love.xml
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/white"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_view_id"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
21
app/src/main/res/layout/fragment_neon.xml
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/white"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_view_id"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
21
app/src/main/res/layout/fragment_super.xml
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/white"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_view_id"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
18
app/src/main/res/layout/list_thumb.xml
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/constraint_layout_id"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_view_key_id"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="110dp"
|
||||
android:scaleType="fitXY"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
14
app/src/main/res/menu/main.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:id="@+id/m_gravity"
|
||||
android:title="gravity" />
|
||||
<item android:id="@+id/m_neon"
|
||||
android:title="neon"/>
|
||||
<item android:id="@+id/m_cool"
|
||||
android:title="cool"/>
|
||||
<item android:id="@+id/m_aesthetic"
|
||||
android:title="aesthetic"/>
|
||||
<item android:id="@+id/m_super"
|
||||
android:title="super"/>
|
||||
</menu>
|
||||
BIN
app/src/main/res/mipmap-hdpi/down.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
app/src/main/res/mipmap-hdpi/logo.png
Normal file
|
After Width: | Height: | Size: 57 KiB |
BIN
app/src/main/res/mipmap-hdpi/setting.png
Normal file
|
After Width: | Height: | Size: 464 B |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 982 B |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
7
app/src/main/res/values-night/themes.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Base.Theme.FingerKeyboard" parent="Theme.Material3.DayNight.NoActionBar">
|
||||
<!-- Customize your dark theme here. -->
|
||||
<!-- <item name="colorPrimary">@color/my_dark_primary</item> -->
|
||||
</style>
|
||||
</resources>
|
||||
9
app/src/main/res/values/array.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string-array name="spinner">
|
||||
<item>neon</item>
|
||||
<item>cool</item>
|
||||
<item>aesthetic</item>
|
||||
<item>btn_super</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
12
app/src/main/res/values/colors.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="black">#FF000000</color>
|
||||
<color name="white">#FFFFFFFF</color>
|
||||
<color name="keyboard_main">#8E63DA</color>
|
||||
<color name="keyboard_black">#C3AFE6</color>
|
||||
<color name="color_trans">#80FFFFFF</color>
|
||||
<color name="color_btn_recent">#80787373</color>
|
||||
<color name="color_btn">#8E63DA</color>
|
||||
<color name="color_d9c7ff">#BC9BF6</color>
|
||||
<color name="color_DCDCDC">#DCDCDC</color>
|
||||
</resources>
|
||||
11
app/src/main/res/values/strings.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<resources>
|
||||
<string name="app_name">Finger Keyboard</string>
|
||||
<string name="step1">Step One</string>
|
||||
<string name="step2">Step Two</string>
|
||||
<string name="text_hint">For normal use, please enter the setting to complete the setting steps.</string>
|
||||
<string name="set_successful">Apply the keyboard skin successfully</string>
|
||||
<string name="set">Settings</string>
|
||||
<!-- TODO: Remove or change this placeholder text -->
|
||||
<string name="hello_blank_fragment">Hello blank fragment</string>
|
||||
|
||||
</resources>
|
||||
81
app/src/main/res/values/style.xml
Normal file
@ -0,0 +1,81 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<declare-styleable name="style_view_keyboard">
|
||||
|
||||
<attr name="android:keyBackground"/>
|
||||
|
||||
<attr name="android:keyTextSize"/>
|
||||
|
||||
<attr name="android:labelTextSize"/>
|
||||
|
||||
<attr name="android:keyTextColor"/>
|
||||
|
||||
<attr name="android:keyPreviewLayout"/>
|
||||
|
||||
<attr name="android:keyPreviewOffset"/>
|
||||
|
||||
<attr name="android:keyPreviewHeight"/>
|
||||
|
||||
<attr name="android:verticalCorrection"/>
|
||||
|
||||
<attr name="android:popupLayout"/>
|
||||
|
||||
<attr name="android:shadowColor"/>
|
||||
|
||||
<attr name="android:shadowRadius"/>
|
||||
</declare-styleable>
|
||||
|
||||
|
||||
<declare-styleable name="style_row">
|
||||
|
||||
<attr name="android:rowEdgeFlags"/>
|
||||
|
||||
<attr name="android:keyboardMode"/>
|
||||
</declare-styleable>
|
||||
|
||||
|
||||
<declare-styleable name="style_key">
|
||||
|
||||
<attr name="android:codes"/>
|
||||
|
||||
<attr name="android:popupKeyboard"/>
|
||||
|
||||
<attr name="android:popupCharacters"/>
|
||||
|
||||
<attr name="android:keyEdgeFlags"/>
|
||||
|
||||
<attr name="android:isModifier"/>
|
||||
|
||||
<attr name="android:isSticky"/>
|
||||
|
||||
<attr name="android:isRepeatable"/>
|
||||
|
||||
<attr name="android:iconPreview"/>
|
||||
|
||||
<attr name="android:keyOutputText"/>
|
||||
|
||||
<attr name="android:keyLabel"/>
|
||||
|
||||
<attr name="android:keyIcon"/>
|
||||
|
||||
<attr name="android:keyboardMode"/>
|
||||
</declare-styleable>
|
||||
|
||||
|
||||
<declare-styleable name="Style_Pre_state">
|
||||
|
||||
<attr name="android:state_long_pressable"/>
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="style_view">
|
||||
|
||||
<attr name="android:keyWidth"/>
|
||||
|
||||
<attr name="android:keyHeight"/>
|
||||
|
||||
<attr name="android:horizontalGap"/>
|
||||
|
||||
<attr name="android:verticalGap"/>
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
8
app/src/main/res/values/themes.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="Theme.Keyboard" parent="Theme.MaterialComponents.DayNight.NoActionBar" >
|
||||
<item name="android:statusBarColor">@color/keyboard_black</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
13
app/src/main/res/xml/backup_rules.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Sample backup rules file; uncomment and customize as necessary.
|
||||
See https://developer.android.com/guide/topics/data/autobackup
|
||||
for details.
|
||||
Note: This file is ignored for devices older that API 31
|
||||
See https://developer.android.com/about/versions/12/backup-restore
|
||||
-->
|
||||
<full-backup-content>
|
||||
<!--
|
||||
<include domain="sharedpref" path="."/>
|
||||
<exclude domain="sharedpref" path="device.xml"/>
|
||||
-->
|
||||
</full-backup-content>
|
||||
19
app/src/main/res/xml/data_extraction_rules.xml
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Sample data extraction rules file; uncomment and customize as necessary.
|
||||
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
|
||||
for details.
|
||||
-->
|
||||
<data-extraction-rules>
|
||||
<cloud-backup>
|
||||
<!-- TODO: Use <include> and <exclude> to control what is backed up.
|
||||
<include .../>
|
||||
<exclude .../>
|
||||
-->
|
||||
</cloud-backup>
|
||||
<!--
|
||||
<device-transfer>
|
||||
<include .../>
|
||||
<exclude .../>
|
||||
</device-transfer>
|
||||
-->
|
||||
</data-extraction-rules>
|
||||
11
app/src/main/res/xml/im.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<input-method xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<subtype
|
||||
android:icon="@drawable/ic_launcher_background"
|
||||
android:imeSubtypeLocale="en_US"
|
||||
android:imeSubtypeMode = "keyboard"
|
||||
android:label="@string/app_name" />
|
||||
|
||||
</input-method>
|
||||
149
app/src/main/res/xml/view_1.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:keyHeight="50dp">
|
||||
|
||||
<Row
|
||||
android:keyWidth="9.45%"
|
||||
android:keyHeight="50dp"
|
||||
android:horizontalGap="0.5%"
|
||||
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:keyWidth="9.444444%"
|
||||
android:keyHeight="50dp"
|
||||
android:horizontalGap="0.5%">
|
||||
<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:keyHeight="50dp"
|
||||
android:keyWidth="9.5%"
|
||||
android:horizontalGap="0.5%">
|
||||
|
||||
<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" />
|
||||
|
||||
<Key
|
||||
android:codes="-5"
|
||||
android:isModifier="true"
|
||||
android:isRepeatable="true"
|
||||
android:keyWidth="14.25%"
|
||||
android:keyEdgeFlags="right" />
|
||||
</Row>
|
||||
|
||||
<Row
|
||||
android:horizontalGap="0.5%"
|
||||
android:keyHeight="50dp"
|
||||
android:rowEdgeFlags="bottom"
|
||||
android:keyWidth="9.5%">
|
||||
|
||||
<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="45.5%"
|
||||
android:keyLabel="English" />
|
||||
|
||||
<Key
|
||||
android:codes="46"
|
||||
android:keyLabel="." />
|
||||
|
||||
|
||||
<Key
|
||||
android:codes="-4"
|
||||
android:keyWidth="18.25%"
|
||||
android:keyLabel="Search"
|
||||
android:keyEdgeFlags="right" />
|
||||
</Row>
|
||||
|
||||
</Keyboard>
|
||||
148
app/src/main/res/xml/view_2.xml
Normal file
@ -0,0 +1,148 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<Row
|
||||
android:keyWidth="9.45%"
|
||||
android:keyHeight="50dp"
|
||||
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="50dp"
|
||||
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="50dp"
|
||||
android:keyWidth="9.5%"
|
||||
android:horizontalGap="0.5%">
|
||||
|
||||
<Key
|
||||
android:codes="-360"
|
||||
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="50dp"
|
||||
android:rowEdgeFlags="bottom"
|
||||
android:keyWidth="9.5%">
|
||||
|
||||
<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="25.5%"
|
||||
android:keyLabel="English" />
|
||||
|
||||
<Key android:keyLabel="/"
|
||||
android:codes="47" />
|
||||
|
||||
<Key android:keyLabel="."
|
||||
android:codes="46" />
|
||||
|
||||
|
||||
<Key
|
||||
android:codes="-4"
|
||||
android:keyLabel="Search"
|
||||
android:keyWidth="18.25%"
|
||||
android:keyEdgeFlags="right" />
|
||||
</Row>
|
||||
|
||||
</Keyboard>
|
||||
154
app/src/main/res/xml/view_3.xml
Normal file
@ -0,0 +1,154 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<Row
|
||||
android:keyWidth="9.45%"
|
||||
android:keyHeight="50dp"
|
||||
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="50dp"
|
||||
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="50dp"
|
||||
android:keyWidth="9.5%"
|
||||
android:horizontalGap="0.5%">
|
||||
|
||||
<Key
|
||||
android:codes="-361"
|
||||
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" />
|
||||
|
||||
|
||||
<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="50dp"
|
||||
android:rowEdgeFlags="bottom"
|
||||
android:keyWidth="9.5%">
|
||||
|
||||
<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="25.5%"
|
||||
android:keyLabel="English" />
|
||||
|
||||
<Key android:keyLabel=">"
|
||||
android:codes="62" />
|
||||
|
||||
<Key android:keyLabel="."
|
||||
android:codes="46" />
|
||||
|
||||
<Key
|
||||
android:codes="-4"
|
||||
android:keyLabel="Search"
|
||||
android:keyWidth="18.25%"
|
||||
android:keyEdgeFlags="right" />
|
||||
</Row>
|
||||
|
||||
</Keyboard>
|
||||
@ -0,0 +1,17 @@
|
||||
package com.example.fingerkeyboard;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
||||
6
build.gradle.kts
Normal file
@ -0,0 +1,6 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
plugins {
|
||||
alias(libs.plugins.android.application) apply false
|
||||
alias(libs.plugins.jetbrains.kotlin.android) apply false
|
||||
|
||||
}
|
||||
23
gradle.properties
Normal file
@ -0,0 +1,23 @@
|
||||
# Project-wide Gradle settings.
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. For more details, visit
|
||||
# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
|
||||
# org.gradle.parallel=true
|
||||
# AndroidX package structure to make it clearer which packages are bundled with the
|
||||
# Android operating system, and which are packaged with your app's APK
|
||||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||
android.useAndroidX=true
|
||||
# Enables namespacing of each library's R class so that its R class includes only the
|
||||
# resources declared in the library itself and none from the library's dependencies,
|
||||
# thereby reducing the size of the R class for that library
|
||||
android.nonTransitiveRClass=true
|
||||
android.nonFinalResIds=false
|
||||
android.enableR8.fullMode=false
|
||||
24
gradle/libs.versions.toml
Normal file
@ -0,0 +1,24 @@
|
||||
[versions]
|
||||
agp = "8.4.0"
|
||||
junit = "4.13.2"
|
||||
junitVersion = "1.1.5"
|
||||
espressoCore = "3.5.1"
|
||||
appcompat = "1.7.0"
|
||||
material = "1.12.0"
|
||||
kotlin = "2.0.0"
|
||||
activity = "1.9.0"
|
||||
constraintlayout = "2.1.4"
|
||||
|
||||
[libraries]
|
||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||
ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
||||
espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
|
||||
appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
|
||||
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
|
||||
activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
|
||||
constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
|
||||
|
||||
[plugins]
|
||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||
jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
||||
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
6
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
#Thu Jun 13 16:03:18 CST 2024
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
185
gradlew
vendored
Normal file
@ -0,0 +1,185 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
case $i in
|
||||
0) set -- ;;
|
||||
1) set -- "$args0" ;;
|
||||
2) set -- "$args0" "$args1" ;;
|
||||
3) set -- "$args0" "$args1" "$args2" ;;
|
||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=`save "$@"`
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||