V1.0.2(3)修改实现方法,优化项目结构
This commit is contained in:
parent
76b13a60db
commit
ae17cebfa5
@ -6,7 +6,7 @@ plugins {
|
|||||||
id("com.google.gms.google-services")
|
id("com.google.gms.google-services")
|
||||||
id("com.google.firebase.crashlytics")
|
id("com.google.firebase.crashlytics")
|
||||||
}
|
}
|
||||||
val timestamp = SimpleDateFormat("MM_dd_HH_mm").format(Date())
|
val timestamp: String = SimpleDateFormat("MM_dd_HH_mm").format(Date())
|
||||||
android {
|
android {
|
||||||
namespace = "com.key.vibekeyboard"
|
namespace = "com.key.vibekeyboard"
|
||||||
compileSdk = 34
|
compileSdk = 34
|
||||||
@ -19,8 +19,8 @@ android {
|
|||||||
applicationId = "com.key.vibekeyboard"
|
applicationId = "com.key.vibekeyboard"
|
||||||
minSdk = 23
|
minSdk = 23
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = 2
|
versionCode = 3
|
||||||
versionName = "1.0.1"
|
versionName = "1.0.2"
|
||||||
setProperty(
|
setProperty(
|
||||||
"archivesBaseName",
|
"archivesBaseName",
|
||||||
"Mobile Keyboard" + versionName + "(${versionCode})_$timestamp"
|
"Mobile Keyboard" + versionName + "(${versionCode})_$timestamp"
|
||||||
@ -63,7 +63,7 @@ dependencies {
|
|||||||
|
|
||||||
|
|
||||||
// Import the BoM for the Firebase platform
|
// Import the BoM for the Firebase platform
|
||||||
implementation(platform("com.google.firebase:firebase-bom:33.6.0"))
|
implementation(platform("com.google.firebase:firebase-bom:33.7.0"))
|
||||||
|
|
||||||
// Add the dependencies for the Crashlytics and Analytics libraries
|
// Add the dependencies for the Crashlytics and Analytics libraries
|
||||||
// When using the BoM, you don't specify versions in Firebase library dependencies
|
// When using the BoM, you don't specify versions in Firebase library dependencies
|
||||||
|
|||||||
14
app/proguard-rules.pro
vendored
14
app/proguard-rules.pro
vendored
@ -20,18 +20,18 @@
|
|||||||
# hide the original source file name.
|
# hide the original source file name.
|
||||||
#-renamesourcefileattribute SourceFile
|
#-renamesourcefileattribute SourceFile
|
||||||
|
|
||||||
-keepclassmembers class com.key.vibekeyboard.AppApplication {
|
-keepclassmembers class com.key.vibekeyboard.MyApplication {
|
||||||
public static final java.lang.String DB_Name;
|
public static final java.lang.String DB_NAME;
|
||||||
public static final int DB_Version;
|
public static final int DB_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
-keepclassmembers class * {
|
-keepclassmembers class * {
|
||||||
@androidx.room.Query <methods>;
|
@androidx.room.Query <methods>;
|
||||||
}
|
}
|
||||||
-keep class com.key.vibekeyboard.Room.MyDatabase { *; }
|
-keep class com.key.vibekeyboard.data.database.AppDatabase { *; }
|
||||||
-keep class com.key.vibekeyboard.Room.WallpaperInfo { *; }
|
-keep class com.key.vibekeyboard.data.database.entity.WallpaperInfo { *; }
|
||||||
-keep class com.key.vibekeyboard.Room.WallpaperInfoDao { *; }
|
-keep class com.key.vibekeyboard.data.database.dao.WallpaperInfoDao { *; }
|
||||||
-keep class com.key.vibekeyboard.Room.Category { *; }
|
-keep class com.key.vibekeyboard.data.bean.Category { *; }
|
||||||
-keep class com.omicronapplications.** { *; }
|
-keep class com.omicronapplications.** { *; }
|
||||||
-keep class net.sf.sevenzipjbinding.** { *; }
|
-keep class net.sf.sevenzipjbinding.** { *; }
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".AppApplication"
|
android:name=".MyApplication"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
android:fullBackupContent="@xml/backup_rules"
|
android:fullBackupContent="@xml/backup_rules"
|
||||||
@ -17,25 +17,22 @@
|
|||||||
android:theme="@style/Theme.KeyboardDemo"
|
android:theme="@style/Theme.KeyboardDemo"
|
||||||
tools:targetApi="31">
|
tools:targetApi="31">
|
||||||
<activity
|
<activity
|
||||||
android:name=".Activity.WriteActivity"
|
android:name=".ui.activity.WriteActivity"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".Activity.MainActivity"
|
android:name=".ui.activity.MainActivity"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".Activity.PermissionActivity"
|
android:name=".ui.activity.DownloadActivity"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".Activity.DownloadActivity"
|
android:name=".ui.activity.SearchActivity"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".Activity.SearchActivity"
|
android:name=".ui.activity.CategoryActivity"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".Activity.CategoryActivity"
|
android:name=".ui.activity.SplashActivity"
|
||||||
android:exported="false" />
|
|
||||||
<activity
|
|
||||||
android:name=".Activity.SplashActivity"
|
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
@ -45,9 +42,10 @@
|
|||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".Keyboard.KeyboardService"
|
android:name=".inputmethod.service.MyInputMethodService"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
android:label="@string/app_name"
|
||||||
android:permission="android.permission.BIND_INPUT_METHOD">
|
android:permission="android.permission.BIND_INPUT_METHOD">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.view.InputMethod" />
|
<action android:name="android.view.InputMethod" />
|
||||||
|
|||||||
@ -1,138 +0,0 @@
|
|||||||
package com.key.vibekeyboard.Activity;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
|
|
||||||
import com.google.android.material.tabs.TabLayout;
|
|
||||||
import com.google.android.material.tabs.TabLayoutMediator;
|
|
||||||
import com.key.vibekeyboard.Adapter.MainViewpager2Adapter;
|
|
||||||
import com.key.vibekeyboard.AppApplication;
|
|
||||||
import com.key.vibekeyboard.Dialog.PermissionRequestDialog;
|
|
||||||
import com.key.vibekeyboard.Dialog.RecommendedDialog;
|
|
||||||
import com.key.vibekeyboard.R;
|
|
||||||
import com.key.vibekeyboard.Room.Category;
|
|
||||||
import com.key.vibekeyboard.Room.WallpaperInfo;
|
|
||||||
import com.key.vibekeyboard.Utils.Mytool;
|
|
||||||
import com.key.vibekeyboard.databinding.ActivityMainBinding;
|
|
||||||
import com.key.vibekeyboard.databinding.MainTabCustomBinding;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity {
|
|
||||||
|
|
||||||
private ActivityMainBinding binding;
|
|
||||||
private List<WallpaperInfo> list = new ArrayList<>();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
|
|
||||||
// 使用 ViewBinding 绑定布局
|
|
||||||
binding = ActivityMainBinding.inflate(getLayoutInflater());
|
|
||||||
setContentView(binding.getRoot());
|
|
||||||
|
|
||||||
// 创建并设置 ViewPager 适配器
|
|
||||||
MainViewpager2Adapter adapter = new MainViewpager2Adapter(this);
|
|
||||||
binding.mainViewpager.setAdapter(adapter);
|
|
||||||
|
|
||||||
// 解析 Json 文件并随机选取一个分类
|
|
||||||
List<Category> categories = AppApplication.getCategories();
|
|
||||||
Random random = new Random();
|
|
||||||
int randomIndex = random.nextInt(categories.size()); // 随机选取分类索引
|
|
||||||
list = categories.get(randomIndex).getList(); // 获取随机选中的分类中的壁纸列表
|
|
||||||
|
|
||||||
// 判断是否完成步骤1和步骤2,显示相应的对话框
|
|
||||||
if (Mytool.isStep1() && Mytool.isStep2()) {
|
|
||||||
showRecommendedDialog(); // 如果两个步骤都完成,显示推荐对话框
|
|
||||||
} else {
|
|
||||||
showPermissionDialog(); // 否则显示权限请求对话框
|
|
||||||
}
|
|
||||||
|
|
||||||
// binding.mainViewpager.setUserInputEnabled(false);//禁止页面左右滑动
|
|
||||||
|
|
||||||
// 初始化 TabLayout(标签栏)
|
|
||||||
tabLayout();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 显示权限请求对话框
|
|
||||||
public void showPermissionDialog() {
|
|
||||||
PermissionRequestDialog dialog = new PermissionRequestDialog();
|
|
||||||
dialog.show(getSupportFragmentManager(), "PermissionRequestDialog");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 显示推荐壁纸对话框
|
|
||||||
public void showRecommendedDialog() {
|
|
||||||
RecommendedDialog dialog = new RecommendedDialog();
|
|
||||||
if (list != null) {
|
|
||||||
dialog.setList(list); // 设置壁纸列表
|
|
||||||
}
|
|
||||||
dialog.show(getSupportFragmentManager(), "RecommendedDialog");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化 TabLayout,设置标签和关联的 ViewPager
|
|
||||||
public void tabLayout() {
|
|
||||||
// 使用 TabLayoutMediator 连接 TabLayout 和 ViewPager2
|
|
||||||
new TabLayoutMediator(binding.mainTablayout, binding.mainViewpager, (tab, position) -> {
|
|
||||||
// 创建自定义 Tab 视图
|
|
||||||
MainTabCustomBinding tabBinding = MainTabCustomBinding.inflate(LayoutInflater.from(this));
|
|
||||||
tab.setCustomView(tabBinding.getRoot());
|
|
||||||
|
|
||||||
// 设置默认的图标,未选中状态的图标
|
|
||||||
if (position == 0) {
|
|
||||||
tabBinding.iconCustom.setImageResource(R.drawable.home_select); // 第一个 Tab 图标
|
|
||||||
} else if (position == 1) {
|
|
||||||
tabBinding.iconCustom.setImageResource(R.drawable.collection); // 第二个 Tab 图标
|
|
||||||
} else {
|
|
||||||
tabBinding.iconCustom.setImageResource(R.drawable.setting); // 第三个 Tab 图标
|
|
||||||
}
|
|
||||||
}).attach(); // 绑定 TabLayout 和 ViewPager
|
|
||||||
|
|
||||||
// 设置 Tab 选中时和未选中时的图标变化
|
|
||||||
binding.mainTablayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
|
|
||||||
@Override
|
|
||||||
public void onTabSelected(TabLayout.Tab tab) {
|
|
||||||
// 选中时更改图标
|
|
||||||
MainTabCustomBinding tabBinding = MainTabCustomBinding.bind(Objects.requireNonNull(tab.getCustomView()));
|
|
||||||
int position = tab.getPosition();
|
|
||||||
if (position == 0) {
|
|
||||||
tabBinding.iconCustom.setImageResource(R.drawable.home_select); // 选中状态的图标
|
|
||||||
} else if (position == 1) {
|
|
||||||
tabBinding.iconCustom.setImageResource(R.drawable.collection_select); // 第二个 Tab 选中图标
|
|
||||||
} else {
|
|
||||||
tabBinding.iconCustom.setImageResource(R.drawable.setting_select); // 第三个 Tab 选中图标
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTabUnselected(TabLayout.Tab tab) {
|
|
||||||
// 未选中时恢复默认图标
|
|
||||||
MainTabCustomBinding tabBinding = MainTabCustomBinding.bind(Objects.requireNonNull(tab.getCustomView()));
|
|
||||||
int position = tab.getPosition();
|
|
||||||
if (position == 0) {
|
|
||||||
tabBinding.iconCustom.setImageResource(R.drawable.home); // 未选中状态的图标
|
|
||||||
} else if (position == 1) {
|
|
||||||
tabBinding.iconCustom.setImageResource(R.drawable.collection); // 第二个 Tab 未选中图标
|
|
||||||
} else {
|
|
||||||
tabBinding.iconCustom.setImageResource(R.drawable.setting); // 第三个 Tab 未选中图标
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTabReselected(TabLayout.Tab tab) {
|
|
||||||
// 可以留空,或者添加重复选择时的逻辑
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDestroy() {
|
|
||||||
super.onDestroy();
|
|
||||||
binding = null; // 释放 ViewBinding 的引用
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
package com.key.vibekeyboard.Activity;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
|
|
||||||
import com.key.vibekeyboard.databinding.ActivityWriteBinding;
|
|
||||||
|
|
||||||
public class WriteActivity extends AppCompatActivity {
|
|
||||||
|
|
||||||
private ActivityWriteBinding binding;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
binding = ActivityWriteBinding.inflate(getLayoutInflater());
|
|
||||||
setContentView(binding.getRoot());
|
|
||||||
|
|
||||||
binding.back.setOnClickListener(v -> finish());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,88 +0,0 @@
|
|||||||
package com.key.vibekeyboard.Adapter;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
|
||||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
|
||||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
|
||||||
import com.bumptech.glide.request.RequestOptions;
|
|
||||||
import com.key.vibekeyboard.Activity.DownloadActivity;
|
|
||||||
import com.key.vibekeyboard.R;
|
|
||||||
import com.key.vibekeyboard.Room.WallpaperInfo;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class DownlaodRecyclerViewAdapter extends RecyclerView.Adapter<DownlaodRecyclerViewAdapter.DownlaodRecyclerViewHolder> {
|
|
||||||
|
|
||||||
private DownloadActivity downloadActivity;
|
|
||||||
private WallpaperInfo wallpaperInfo;
|
|
||||||
private List<WallpaperInfo> list;
|
|
||||||
|
|
||||||
public DownlaodRecyclerViewAdapter(DownloadActivity downloadActivity, WallpaperInfo wallpaperInfo, List<WallpaperInfo> list) {
|
|
||||||
this.downloadActivity = downloadActivity;
|
|
||||||
this.wallpaperInfo = wallpaperInfo;
|
|
||||||
this.list = list;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public DownlaodRecyclerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
|
||||||
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.home_recycler_item, parent, false);
|
|
||||||
return new DownlaodRecyclerViewHolder(view);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBindViewHolder(@NonNull DownlaodRecyclerViewHolder holder, int position) {
|
|
||||||
|
|
||||||
WallpaperInfo wallpaperInfo1 = list.get(position);
|
|
||||||
|
|
||||||
List<WallpaperInfo> limitedList = list.subList(0, Math.min(20, list.size()));
|
|
||||||
|
|
||||||
holder.imageView.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
Intent intent = new Intent(downloadActivity, DownloadActivity.class);
|
|
||||||
intent.putExtra("wallpaperInfo", wallpaperInfo1); // wallpaperInfo 已经实现了 Parcelable
|
|
||||||
intent.putParcelableArrayListExtra("list", new ArrayList<>(limitedList)); // list 中的 WallpaperInfo 对象实现了 Parcelable
|
|
||||||
downloadActivity.startActivity(intent);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 应用圆角变换
|
|
||||||
RequestOptions options = new RequestOptions()
|
|
||||||
.placeholder(R.mipmap.splash)
|
|
||||||
.error(R.mipmap.splash)
|
|
||||||
.transform(new CenterCrop())
|
|
||||||
.transform(new RoundedCorners(16)); // 设置圆角度数
|
|
||||||
|
|
||||||
Glide.with(downloadActivity)
|
|
||||||
.load(list.get(position).getPreview())
|
|
||||||
.apply(options)
|
|
||||||
.into(holder.imageView);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getItemCount() {
|
|
||||||
return list.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class DownlaodRecyclerViewHolder extends RecyclerView.ViewHolder {
|
|
||||||
|
|
||||||
private ImageView imageView;
|
|
||||||
|
|
||||||
public DownlaodRecyclerViewHolder(@NonNull View itemView) {
|
|
||||||
super(itemView);
|
|
||||||
imageView = itemView.findViewById(R.id.home_recycler_image);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,127 +0,0 @@
|
|||||||
package com.key.vibekeyboard.Adapter;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.recyclerview.widget.DiffUtil;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
|
||||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
|
||||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
|
||||||
import com.bumptech.glide.request.RequestOptions;
|
|
||||||
import com.key.vibekeyboard.Activity.DownloadActivity;
|
|
||||||
import com.key.vibekeyboard.R;
|
|
||||||
import com.key.vibekeyboard.Room.WallpaperInfo;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class FavoriteRecyclerViewAdapter extends RecyclerView.Adapter<FavoriteRecyclerViewAdapter.ViewHolder> {
|
|
||||||
|
|
||||||
|
|
||||||
private Context context;
|
|
||||||
private List<WallpaperInfo> list;
|
|
||||||
|
|
||||||
public FavoriteRecyclerViewAdapter(Context context, List<WallpaperInfo> list) {
|
|
||||||
|
|
||||||
this.context = context;
|
|
||||||
this.list = new ArrayList<>(list);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
|
||||||
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.home_recycler_item, parent, false);
|
|
||||||
return new ViewHolder(view);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
|
||||||
|
|
||||||
WallpaperInfo wallpaperInfo = list.get(position);
|
|
||||||
|
|
||||||
List<WallpaperInfo> limitedList = list.subList(0, Math.min(20, list.size()));
|
|
||||||
|
|
||||||
if (wallpaperInfo != null) {
|
|
||||||
holder.imageView.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
Intent intent = new Intent(context, DownloadActivity.class);
|
|
||||||
intent.putExtra("wallpaperInfo", wallpaperInfo); // wallpaperInfo 已经实现了 Parcelable
|
|
||||||
intent.putParcelableArrayListExtra("list", new ArrayList<>(limitedList)); // list 中的 WallpaperInfo 对象实现了 Parcelable
|
|
||||||
context.startActivity(intent);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 应用圆角变换
|
|
||||||
RequestOptions options = new RequestOptions()
|
|
||||||
.placeholder(R.mipmap.splash)
|
|
||||||
.error(R.mipmap.splash)
|
|
||||||
.transform(new CenterCrop())
|
|
||||||
.transform(new RoundedCorners(16)); // 设置圆角度数
|
|
||||||
if (wallpaperInfo != null) {
|
|
||||||
Glide.with(context)
|
|
||||||
.load(wallpaperInfo.getPreview())
|
|
||||||
.apply(options)
|
|
||||||
.into(holder.imageView);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getItemCount() {
|
|
||||||
return (list != null) ? list.size() : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
|
||||||
|
|
||||||
private ImageView imageView;
|
|
||||||
|
|
||||||
public ViewHolder(@NonNull View itemView) {
|
|
||||||
super(itemView);
|
|
||||||
|
|
||||||
imageView = itemView.findViewById(R.id.home_recycler_image);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 使用 DiffUtil 更新列表
|
|
||||||
public void updateList(List<WallpaperInfo> newList) {
|
|
||||||
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DiffUtil.Callback() {
|
|
||||||
@Override
|
|
||||||
public int getOldListSize() {
|
|
||||||
return list.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getNewListSize() {
|
|
||||||
return newList.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
|
|
||||||
// 通过唯一标识符比较两个项目是否相同
|
|
||||||
return list.get(oldItemPosition).getId() == newList.get(newItemPosition).getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
|
|
||||||
// 比较内容是否相同
|
|
||||||
return list.get(oldItemPosition).equals(newList.get(newItemPosition));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
list.clear();
|
|
||||||
list.addAll(newList);
|
|
||||||
diffResult.dispatchUpdatesTo(this); // 通知 RecyclerView 进行局部更新
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,91 +0,0 @@
|
|||||||
package com.key.vibekeyboard.Adapter;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
|
||||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
|
||||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
|
||||||
import com.bumptech.glide.request.RequestOptions;
|
|
||||||
import com.key.vibekeyboard.Activity.DownloadActivity;
|
|
||||||
import com.key.vibekeyboard.R;
|
|
||||||
import com.key.vibekeyboard.Room.Category;
|
|
||||||
import com.key.vibekeyboard.Room.WallpaperInfo;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class HomeRecyclerViewAdapter extends RecyclerView.Adapter<HomeRecyclerViewAdapter.HomeRecyclerViewHolder> {
|
|
||||||
|
|
||||||
private List<Category> categories;
|
|
||||||
private Context context;
|
|
||||||
|
|
||||||
public HomeRecyclerViewAdapter(Context context,List<Category> categories) {
|
|
||||||
this.context = context;
|
|
||||||
this.categories = categories;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public HomeRecyclerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
|
||||||
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.home_recycler_item, parent, false);
|
|
||||||
return new HomeRecyclerViewHolder(view);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBindViewHolder(@NonNull HomeRecyclerViewHolder holder, int position) {
|
|
||||||
|
|
||||||
Category category = categories.get(position);
|
|
||||||
List<WallpaperInfo> list = category.getList();
|
|
||||||
WallpaperInfo categoryWallpaperInfo = category.getList().get(position);
|
|
||||||
WallpaperInfo wallpaperInfo = category.getList().get(0);
|
|
||||||
|
|
||||||
List<WallpaperInfo> limitedList = list.subList(0, Math.min(20, list.size()));
|
|
||||||
|
|
||||||
holder.imageView.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
Intent intent = new Intent(context, DownloadActivity.class);
|
|
||||||
intent.putExtra("wallpaperInfo", wallpaperInfo); // wallpaperInfo 已经实现了 Parcelable
|
|
||||||
intent.putParcelableArrayListExtra("list", new ArrayList<>(limitedList)); // list 中的 WallpaperInfo 对象实现了 Parcelable
|
|
||||||
context.startActivity(intent);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// 应用圆角变换
|
|
||||||
RequestOptions options = new RequestOptions()
|
|
||||||
.placeholder(R.mipmap.splash)
|
|
||||||
.error(R.mipmap.splash)
|
|
||||||
.transform(new CenterCrop())
|
|
||||||
.transform(new RoundedCorners(16)); // 设置圆角度数
|
|
||||||
|
|
||||||
Glide.with(context)
|
|
||||||
.load(wallpaperInfo.getPreview())
|
|
||||||
.apply(options)
|
|
||||||
.into(holder.imageView);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getItemCount() {
|
|
||||||
return categories.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class HomeRecyclerViewHolder extends RecyclerView.ViewHolder {
|
|
||||||
private ImageView imageView;
|
|
||||||
|
|
||||||
public HomeRecyclerViewHolder(View view) {
|
|
||||||
super(view);
|
|
||||||
imageView = view.findViewById(R.id.home_recycler_image);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,85 +0,0 @@
|
|||||||
package com.key.vibekeyboard.Adapter;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
|
||||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
|
||||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
|
||||||
import com.bumptech.glide.request.RequestOptions;
|
|
||||||
import com.key.vibekeyboard.Activity.DownloadActivity;
|
|
||||||
import com.key.vibekeyboard.Activity.SearchActivity;
|
|
||||||
import com.key.vibekeyboard.R;
|
|
||||||
import com.key.vibekeyboard.Room.WallpaperInfo;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class SearchRecyclerViewAdapter extends RecyclerView.Adapter<SearchRecyclerViewAdapter.ViewHolder> {
|
|
||||||
|
|
||||||
private List<WallpaperInfo> wallpaperList;
|
|
||||||
private SearchActivity context;
|
|
||||||
|
|
||||||
public SearchRecyclerViewAdapter(List<WallpaperInfo> wallpaperList, SearchActivity context) {
|
|
||||||
this.wallpaperList = wallpaperList;
|
|
||||||
this.context = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
|
||||||
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.home_recycler_item, parent, false);
|
|
||||||
return new ViewHolder(view);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
|
||||||
WallpaperInfo wallpaperInfo = wallpaperList.get(position);
|
|
||||||
|
|
||||||
List<WallpaperInfo> limitedList = wallpaperList.subList(0, Math.min(20, wallpaperList.size()));
|
|
||||||
|
|
||||||
holder.imageView.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
Intent intent = new Intent(context, DownloadActivity.class);
|
|
||||||
intent.putExtra("wallpaperInfo", wallpaperInfo); // wallpaperInfo 已经实现了 Parcelable
|
|
||||||
intent.putParcelableArrayListExtra("list", new ArrayList<>(limitedList)); // list 中的 WallpaperInfo 对象实现了 Parcelable
|
|
||||||
context.startActivity(intent);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// 应用圆角变换
|
|
||||||
RequestOptions options = new RequestOptions()
|
|
||||||
.placeholder(R.mipmap.splash)
|
|
||||||
.error(R.mipmap.splash)
|
|
||||||
.transform(new CenterCrop())
|
|
||||||
.transform(new RoundedCorners(16)); // 设置圆角度数
|
|
||||||
|
|
||||||
Glide.with(context)
|
|
||||||
.load(wallpaperInfo.getPreview())
|
|
||||||
.apply(options)
|
|
||||||
.into(holder.imageView);
|
|
||||||
// 根据需要加载其他字段,如图片等
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getItemCount() {
|
|
||||||
return wallpaperList.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
|
||||||
|
|
||||||
private ImageView imageView;
|
|
||||||
|
|
||||||
public ViewHolder(@NonNull View itemView) {
|
|
||||||
super(itemView);
|
|
||||||
imageView = itemView.findViewById(R.id.home_recycler_image);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,190 +0,0 @@
|
|||||||
package com.key.vibekeyboard.Keyboard;
|
|
||||||
|
|
||||||
import static android.content.Context.MODE_PRIVATE;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.graphics.BitmapFactory;
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.util.Xml;
|
|
||||||
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
|
|
||||||
import com.key.vibekeyboard.AppApplication;
|
|
||||||
import com.key.vibekeyboard.R;
|
|
||||||
import com.key.vibekeyboard.Utils.Mytool;
|
|
||||||
import com.key.vibekeyboard.Utils.StaticValue;
|
|
||||||
|
|
||||||
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 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(AppApplication.instance, android.R.drawable.stat_sys_upload);
|
|
||||||
private Drawable iconDel = ContextCompat.getDrawable(AppApplication.instance, android.R.drawable.ic_input_delete);
|
|
||||||
private Drawable BG = ContextCompat.getDrawable(AppApplication.instance, R.color.black);
|
|
||||||
|
|
||||||
private int keyNoramlcolor = AppApplication.instance.getResources().getColor(R.color.white, null);
|
|
||||||
|
|
||||||
private int keyActioncolor = AppApplication.instance.getResources().getColor(R.color.white, null);
|
|
||||||
|
|
||||||
private Drawable iconShiftLock = ContextCompat.getDrawable(AppApplication.instance, android.R.drawable.stat_sys_upload);
|
|
||||||
|
|
||||||
|
|
||||||
public Drawable getBG() {
|
|
||||||
return BG;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Drawable getBgActionDraw() {
|
|
||||||
return BgActionDraw;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Drawable getBgNormalDraw() {
|
|
||||||
return BgNormalDraw;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Drawable getBgSpaceDraw() {
|
|
||||||
return BgSpaceDraw;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Drawable getIconDel() {
|
|
||||||
return iconDel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Drawable getIconShift() {
|
|
||||||
return iconShift;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Drawable getIconShiftLock() {
|
|
||||||
return iconShiftLock;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getKeyNoramlcolor() {
|
|
||||||
return keyNoramlcolor;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public int getKeyActioncolor() {
|
|
||||||
return keyActioncolor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void init() {
|
|
||||||
// iconShift = ContextCompat.getDrawable(CoolKeyboardSkin.app, R.drawable.ico_shift_lit);
|
|
||||||
// iconDel = ContextCompat.getDrawable(CoolKeyboardSkin.app, R.drawable.icon_del);
|
|
||||||
// BG = ContextCompat.getDrawable(CoolKeyboardSkin.app, R.color.white);
|
|
||||||
// keyNoramlcolor = CoolKeyboardSkin.app.getResources().getColor(R.color.white, null);
|
|
||||||
// iconShiftLock = ContextCompat.getDrawable(CoolKeyboardSkin.app, R.drawable.ico_shift_lit);
|
|
||||||
// Drawable drawable1 = ContextCompat.getDrawable(CoolKeyboardSkin.app, R.drawable.de_keybg_press);
|
|
||||||
// Drawable drawable = ContextCompat.getDrawable(CoolKeyboardSkin.app, R.drawable.de_keybg);
|
|
||||||
// StateListDrawable status = Mytool.getStatus(drawable, drawable1);
|
|
||||||
// BgActionDraw = status;
|
|
||||||
// BgNormalDraw = status;
|
|
||||||
// BgSpaceDraw = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
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));
|
|
||||||
Log.d("custom", "filePath" + filePath);
|
|
||||||
return bitmapDrawable;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Drawable getBackGround(Context context, String resDirPath) {
|
|
||||||
String filePath = resDirPath + path_drawxxh + jpg_BG;
|
|
||||||
if (!new File(filePath).exists()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
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 = Mytool.fileToString(file);
|
|
||||||
xmlPullParser.setInput(new StringReader(s));
|
|
||||||
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.equals(color_normal_key)) {
|
|
||||||
keyNoramlcolor = Color.parseColor(xmlPullParser.nextText());
|
|
||||||
|
|
||||||
}
|
|
||||||
if (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 = getSavedWallpaperPath(AppApplication.getContext());
|
|
||||||
if (!resDirPath.isEmpty()) {
|
|
||||||
updateKeyColor(resDirPath);
|
|
||||||
BG = getBackGround(con, resDirPath);
|
|
||||||
BgNormalDraw = getKeyBackGround(con, resDirPath, Bg_normal);
|
|
||||||
BgActionDraw = getKeyBackGround(con, resDirPath, Bg_action_normal);
|
|
||||||
BgSpaceDraw = getKeyBackGround(con, resDirPath, Bg_space_normal);
|
|
||||||
iconDel = getKeyBackGround(con, resDirPath, icon_del);
|
|
||||||
iconShift = getKeyBackGround(con, resDirPath, icon_shift);
|
|
||||||
iconShiftLock = getKeyBackGround(con, resDirPath, icon_shift_lock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSavedWallpaperPath(Context context) {
|
|
||||||
// 读取 SharedPreferences 中保存的路径
|
|
||||||
SharedPreferences sharedPreferences = context.getSharedPreferences("keyboard_prefs", MODE_PRIVATE);
|
|
||||||
return sharedPreferences.getString("wallpaper_path", ""); // 如果没有保存,返回空字符串
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,160 +0,0 @@
|
|||||||
package com.key.vibekeyboard.Keyboard;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.inputmethodservice.InputMethodService;
|
|
||||||
import android.inputmethodservice.KeyboardView;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.inputmethod.EditorInfo;
|
|
||||||
import android.view.inputmethod.InputMethodManager;
|
|
||||||
|
|
||||||
import com.key.vibekeyboard.R;
|
|
||||||
|
|
||||||
|
|
||||||
public class KeyboardService extends InputMethodService implements KeyboardView.OnKeyboardActionListener {
|
|
||||||
private int[] ViewXmls = new int[4]; // 保存不同键盘视图的XML资源ID
|
|
||||||
private MyKeyboard myKeyboard; // 自定义键盘视图的实例
|
|
||||||
|
|
||||||
private int curImeAction; // 当前输入法的动作类型
|
|
||||||
|
|
||||||
public KeyboardService() {
|
|
||||||
// 默认构造函数
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建输入视图的方法,返回键盘视图
|
|
||||||
@Override
|
|
||||||
public View onCreateInputView() {
|
|
||||||
// 初始化不同键盘视图的XML布局文件
|
|
||||||
ViewXmls[0] = R.xml.view_1;
|
|
||||||
ViewXmls[1] = R.xml.view_2;
|
|
||||||
ViewXmls[2] = R.xml.view_3;
|
|
||||||
ViewXmls[3] = R.xml.view_4;
|
|
||||||
|
|
||||||
// 加载主键盘视图布局文件
|
|
||||||
View inputView = LayoutInflater.from(this).inflate(R.layout.keyboard_view, null, false);
|
|
||||||
myKeyboard = inputView.findViewById(R.id.keyboardView); // 绑定键盘视图
|
|
||||||
|
|
||||||
setBackground();
|
|
||||||
|
|
||||||
myKeyboard.setKeyboard(new MyKeyboard.KeyBoard(this, ViewXmls[0])); // 设置默认键盘布局
|
|
||||||
myKeyboard.setOnKeyboardActionListener(this); // 设置键盘操作监听器
|
|
||||||
// myKeyboard.setPreviewEnabled(false); // 可选项,禁用按键预览
|
|
||||||
return inputView;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 当输入法窗口显示时调用
|
|
||||||
@Override
|
|
||||||
public void onWindowShown() {
|
|
||||||
super.onWindowShown();
|
|
||||||
setBackground();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setBackground(){
|
|
||||||
curImeAction = getImeAction(getCurrentInputEditorInfo().imeOptions); // 获取当前的输入法动作类型
|
|
||||||
myKeyboard.updateConfigView(this, curImeAction); // 更新键盘配置视图
|
|
||||||
myKeyboard.invalidate(); // 刷新键盘视图
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取当前输入法的动作类型
|
|
||||||
public int getImeAction(int imeOptions) {
|
|
||||||
int i = imeOptions & EditorInfo.IME_MASK_ACTION;
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 键盘按键被按下时调用
|
|
||||||
@Override
|
|
||||||
public void onKey(int primaryCode, int[] keyCodes) {
|
|
||||||
switch (primaryCode) {
|
|
||||||
case MyKeyboard.KeyBoard.KEYCODE_SHIFT:
|
|
||||||
// 切换到大写字母布局或恢复到小写字母布局
|
|
||||||
if (myKeyboard.getShiftType() == 0) {
|
|
||||||
changeView(3);
|
|
||||||
myKeyboard.setShiftType(1);
|
|
||||||
} else {
|
|
||||||
changeView(0);
|
|
||||||
myKeyboard.setShiftType(0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MyKeyboard.KeyBoard.KEYCODE_MODE_CHANGE:
|
|
||||||
// 切换到符号键盘或字母键盘
|
|
||||||
if (myKeyboard.getViewType() == 0) {
|
|
||||||
changeView(1);
|
|
||||||
} else {
|
|
||||||
changeView(0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MyKeyboard.KeyBoard.KEYCODE_SHIFT_123:
|
|
||||||
// 切换到符号键盘
|
|
||||||
changeView(1);
|
|
||||||
break;
|
|
||||||
case MyKeyboard.KeyBoard.KEYCODE_SHIFT_MORE:
|
|
||||||
// 切换到更多符号键盘
|
|
||||||
changeView(2);
|
|
||||||
break;
|
|
||||||
case MyKeyboard.KeyBoard.KEYCODE_DELETE:
|
|
||||||
// 删除前一个字符
|
|
||||||
getCurrentInputConnection().deleteSurroundingText(1, 0);
|
|
||||||
break;
|
|
||||||
case MyKeyboard.KeyBoard.KEYCODE_DONE:
|
|
||||||
// 完成输入并隐藏键盘
|
|
||||||
getCurrentInputConnection().performEditorAction(curImeAction);
|
|
||||||
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
|
||||||
imm.hideSoftInputFromWindow(myKeyboard.getWindowToken(), 0);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// 处理普通字符输入
|
|
||||||
char value;
|
|
||||||
if (myKeyboard.getShiftType() == 1) {
|
|
||||||
value = Character.toUpperCase((char) primaryCode); // 大写字母
|
|
||||||
} else {
|
|
||||||
value = (char) primaryCode; // 小写字母
|
|
||||||
}
|
|
||||||
getCurrentInputConnection().commitText(String.valueOf(value), 1); // 提交字符到输入连接
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更换键盘视图的方法
|
|
||||||
private void changeView(int i) {
|
|
||||||
myKeyboard.setViewType(i); // 设置键盘视图类型
|
|
||||||
myKeyboard.setShiftType(i); // 设置键盘大小写类型
|
|
||||||
myKeyboard.setKeyboard(new MyKeyboard.KeyBoard(this, ViewXmls[i])); // 设置新的键盘布局
|
|
||||||
}
|
|
||||||
|
|
||||||
// 键被按下时调用
|
|
||||||
@Override
|
|
||||||
public void onPress(int primaryCode) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 键被释放时调用
|
|
||||||
@Override
|
|
||||||
public void onRelease(int primaryCode) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onText(CharSequence text) {
|
|
||||||
// 文本输入时调用(未实现)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void swipeLeft() {
|
|
||||||
// 左滑时调用(未实现)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void swipeRight() {
|
|
||||||
// 右滑时调用(未实现)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void swipeDown() {
|
|
||||||
// 下滑时调用(未实现)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void swipeUp() {
|
|
||||||
// 上滑时调用(未实现)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,219 +0,0 @@
|
|||||||
package com.key.vibekeyboard.Keyboard;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.graphics.Canvas;
|
|
||||||
import android.graphics.Paint;
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.inputmethodservice.Keyboard;
|
|
||||||
import android.inputmethodservice.KeyboardView;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
import android.view.inputmethod.EditorInfo;
|
|
||||||
|
|
||||||
|
|
||||||
import com.key.vibekeyboard.Utils.Mytool;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class MyKeyboard extends KeyboardView {
|
|
||||||
// 自定义键盘视图类,继承自 KeyboardView,用于自定义键盘布局及其行为。
|
|
||||||
|
|
||||||
private Paint mPaint;
|
|
||||||
// 用于绘制键盘的 Paint 对象。
|
|
||||||
|
|
||||||
private int viewType = 0;
|
|
||||||
// 键盘视图的类型,用于区分不同的键盘视图模式。
|
|
||||||
|
|
||||||
private int shiftType = 0;
|
|
||||||
// 当前 Shift 键的状态,0 表示未按下,其他值可能表示按下或锁定状态。
|
|
||||||
|
|
||||||
private CustomViewConfig config;
|
|
||||||
// 键盘的自定义配置对象,包含键盘背景、键的颜色和图标等。
|
|
||||||
|
|
||||||
private int curImeAction;
|
|
||||||
// 当前输入法的动作类型(如搜索、完成等)。
|
|
||||||
|
|
||||||
public MyKeyboard(Context context, AttributeSet attrs) {
|
|
||||||
super(context, attrs);
|
|
||||||
initView();
|
|
||||||
// 初始化视图,配置画笔和其他参数。
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class KeyBoard extends Keyboard {
|
|
||||||
// 自定义键盘类,继承自 Keyboard,用于定义键盘的布局和键值。
|
|
||||||
|
|
||||||
public static final int KEYCODE_SHIFT_MORE = -360;
|
|
||||||
public static final int KEYCODE_SHIFT_123 = -361;
|
|
||||||
// 自定义的键值常量,分别用于切换到更多符号和切换到 123 键盘。
|
|
||||||
|
|
||||||
public KeyBoard(Context context, int layoutTemplateResId) {
|
|
||||||
super(context, layoutTemplateResId);
|
|
||||||
// 使用布局模板资源 ID 初始化键盘对象。
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getShiftType() {
|
|
||||||
return shiftType;
|
|
||||||
// 返回当前 Shift 键的状态。
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setShiftType(int shiftType) {
|
|
||||||
this.shiftType = shiftType;
|
|
||||||
// 设置 Shift 键的状态。
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setViewType(int viewType) {
|
|
||||||
this.viewType = viewType;
|
|
||||||
// 设置键盘视图的类型。
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getViewType() {
|
|
||||||
return viewType;
|
|
||||||
// 返回当前键盘视图的类型。
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDraw(Canvas canvas) {
|
|
||||||
// 重写 onDraw 方法,自定义绘制键盘的方式。
|
|
||||||
|
|
||||||
KeyBoard 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) {
|
|
||||||
// 如果键是 Shift 键,绘制其背景和图标。
|
|
||||||
|
|
||||||
onDrawKeyBackground(key, config.getBgActionDraw(), canvas);
|
|
||||||
Mytool.onDrawKeyIcon(key, getShiftDraw(), canvas, this);
|
|
||||||
|
|
||||||
} else if (code == KeyBoard.KEYCODE_SHIFT_123) {
|
|
||||||
// 如果键是切换到 123 键盘的键,绘制其背景和标签(无文字)。
|
|
||||||
|
|
||||||
onDrawKeyBackground(key, config.getBgActionDraw(), canvas);
|
|
||||||
onDrawLabel(key, canvas, "");
|
|
||||||
|
|
||||||
} else if (code == KeyBoard.KEYCODE_SHIFT_MORE) {
|
|
||||||
// 如果键是切换到更多符号的键,绘制其背景和标签(无文字)。
|
|
||||||
|
|
||||||
onDrawKeyBackground(key, config.getBgActionDraw(), canvas);
|
|
||||||
onDrawLabel(key, canvas, "");
|
|
||||||
|
|
||||||
} else if (code == KeyBoard.KEYCODE_DONE) {
|
|
||||||
// 如果键是完成键,根据当前输入法的动作类型绘制其背景和标签。
|
|
||||||
|
|
||||||
onDrawKeyBackground(key, config.getBgActionDraw(), canvas);
|
|
||||||
if (curImeAction == EditorInfo.IME_ACTION_SEARCH) {
|
|
||||||
onDrawLabel(key, canvas, "Search");
|
|
||||||
} else {
|
|
||||||
onDrawLabel(key, canvas, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (code == KeyBoard.KEYCODE_DELETE) {
|
|
||||||
// 如果键是删除键,绘制其背景、图标和标签(无文字)。
|
|
||||||
|
|
||||||
onDrawKeyBackground(key, config.getBgActionDraw(), canvas);
|
|
||||||
Mytool.onDrawKeyIcon(key, config.getIconDel(), canvas, this);
|
|
||||||
onDrawLabel(key, canvas, "");
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// 其他普通键,设置画笔颜色为普通键颜色,绘制其背景和标签。
|
|
||||||
|
|
||||||
mPaint.setColor(config.getKeyNoramlcolor());
|
|
||||||
onDrawKeyBackground(key, config.getBgNormalDraw(), canvas);
|
|
||||||
onDrawLabel(key, canvas, "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Drawable getShiftDraw() {
|
|
||||||
// 根据 Shift 键的状态返回相应的图标。
|
|
||||||
|
|
||||||
if (shiftType == 0) {
|
|
||||||
return config.getIconShift();
|
|
||||||
} else {
|
|
||||||
return config.getIconShiftLock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initView() {
|
|
||||||
// 初始化视图,配置画笔和自定义视图配置对象。
|
|
||||||
|
|
||||||
config = new CustomViewConfig();
|
|
||||||
mPaint = new Paint();
|
|
||||||
config.init();
|
|
||||||
float texsize = Mytool.spToPpx(20f, this.getContext());
|
|
||||||
mPaint.setTextSize(texsize);
|
|
||||||
setPreviewEnabled(false);
|
|
||||||
// 禁用键预览。
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateConfigView(Context con, int ime) {
|
|
||||||
// 更新键盘配置视图,根据上下文和输入法动作类型更新配置。
|
|
||||||
|
|
||||||
curImeAction = ime;
|
|
||||||
config.updateConfig(con);
|
|
||||||
setBackground(config.getBG());
|
|
||||||
invalidateAllKeys();
|
|
||||||
// 更新键盘背景并刷新所有按键。
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onDrawKeyBackground(Keyboard.Key myKey, Drawable keyBG, Canvas canvas) {
|
|
||||||
// 绘制按键的背景。
|
|
||||||
|
|
||||||
if (keyBG != null) {
|
|
||||||
int left = myKey.x + getPaddingLeft();
|
|
||||||
int top = myKey.y + getPaddingTop();
|
|
||||||
int right = left + myKey.width;
|
|
||||||
int bottom = top + myKey.height;
|
|
||||||
|
|
||||||
keyBG.setBounds(left, top, right, bottom);
|
|
||||||
keyBG.setState(myKey.getCurrentDrawableState());
|
|
||||||
keyBG.draw(canvas);
|
|
||||||
// 设置背景的边界并绘制背景。
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onDrawLabel(Keyboard.Key myKey, Canvas canvas, String custLabel) {
|
|
||||||
// 绘制按键的标签文字。
|
|
||||||
|
|
||||||
boolean b = myKey.label == null || myKey.label == "";
|
|
||||||
if (!b) {
|
|
||||||
float y1 = myKey.y + myKey.height / 2f - (mPaint.descent() + mPaint.ascent()) / 2f;
|
|
||||||
float x1 = myKey.x + getPaddingLeft() + (myKey.width / 2f);
|
|
||||||
x1 -= mPaint.measureText(myKey.label.toString()) / 2f;
|
|
||||||
// 计算标签的绘制位置,居中显示。
|
|
||||||
|
|
||||||
if (!custLabel.isEmpty()) {
|
|
||||||
// 如果提供了自定义标签,使用自定义标签绘制文字。
|
|
||||||
|
|
||||||
float texsize = Mytool.spToPpx(14f, this.getContext());
|
|
||||||
mPaint.setTextSize(texsize);
|
|
||||||
canvas.drawText(custLabel, x1, y1, mPaint);
|
|
||||||
} else {
|
|
||||||
// 否则使用按键的默认标签绘制文字。
|
|
||||||
|
|
||||||
float texsize = Mytool.spToPpx(18f, this.getContext());
|
|
||||||
mPaint.setTextSize(texsize);
|
|
||||||
canvas.drawText(myKey.label.toString(), x1, y1, mPaint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -6,24 +6,25 @@ import android.util.Log;
|
|||||||
|
|
||||||
import com.anythink.core.api.ATSDK;
|
import com.anythink.core.api.ATSDK;
|
||||||
import com.anythink.core.api.NetTrafficeCallback;
|
import com.anythink.core.api.NetTrafficeCallback;
|
||||||
import com.key.vibekeyboard.Room.Category;
|
import com.key.vibekeyboard.data.bean.Category;
|
||||||
import com.key.vibekeyboard.Room.MyDatabase;
|
import com.key.vibekeyboard.data.database.AppDatabase;
|
||||||
import com.key.vibekeyboard.Room.WallpaperInfo;
|
import com.key.vibekeyboard.data.database.entity.WallpaperInfo;
|
||||||
import com.key.vibekeyboard.Utils.Mytool;
|
import com.key.vibekeyboard.utils.JsonUtils;
|
||||||
import com.key.vibekeyboard.topon.AdManager;
|
import com.key.vibekeyboard.topon.AdManager;
|
||||||
|
import com.key.vibekeyboard.utils.TaskExecutorUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class AppApplication extends Application {
|
public class MyApplication extends Application {
|
||||||
|
|
||||||
public static AppApplication instance;
|
public static MyApplication instance;
|
||||||
public static List<Category> categories;
|
public static List<Category> categories;
|
||||||
|
|
||||||
public static final int DB_Version = 1;
|
public static final int DB_VERSION = 1;
|
||||||
public static final String DB_Name = "image_database";
|
public static final String DB_NAME = "keyboard_database";
|
||||||
|
|
||||||
public static final String TAG = "--------------";
|
public static final String TAG = "--------------";
|
||||||
|
|
||||||
@ -35,7 +36,7 @@ public class AppApplication extends Application {
|
|||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
instance = this;
|
instance = this;
|
||||||
categories = Mytool.parseJsonToList("keyboard.json");
|
categories = JsonUtils.parseJson("keyboard.json");
|
||||||
|
|
||||||
// 确保Firebase初始化
|
// 确保Firebase初始化
|
||||||
// FirebaseApp.initializeApp(this);
|
// FirebaseApp.initializeApp(this);
|
||||||
@ -49,12 +50,10 @@ public class AppApplication extends Application {
|
|||||||
|
|
||||||
initSdk();
|
initSdk();
|
||||||
|
|
||||||
Mytool.runIO(new Runnable() {
|
TaskExecutorUtils.executeIO(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
AppDatabase.getInstance().wallpaperInfoDao().insertAll(getAlldataList());
|
||||||
MyDatabase.getInstance().wallpaperInfoDao().insertAll(getAlldataList());
|
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -67,10 +66,9 @@ public class AppApplication extends Application {
|
|||||||
@Override
|
@Override
|
||||||
public void onResultCallback(boolean isEU) {
|
public void onResultCallback(boolean isEU) {
|
||||||
Log.e(TAG, "onResultCallback:" + isEU);
|
Log.e(TAG, "onResultCallback:" + isEU);
|
||||||
if (isEU && ATSDK.getGDPRDataLevel(AppApplication.this) == ATSDK.UNKNOWN) {
|
if (isEU && ATSDK.getGDPRDataLevel(MyApplication.this) == ATSDK.UNKNOWN) {
|
||||||
ATSDK.showGdprAuth(AppApplication.this);
|
ATSDK.showGdprAuth(MyApplication.this);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -87,10 +85,6 @@ public class AppApplication extends Application {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AppApplication getInstance() {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Context getContext() {
|
public static Context getContext() {
|
||||||
return instance.getApplicationContext();
|
return instance.getApplicationContext();
|
||||||
}
|
}
|
||||||
@ -100,21 +94,21 @@ public class AppApplication extends Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static List<WallpaperInfo> getAlldataList() {
|
public static List<WallpaperInfo> getAlldataList() {
|
||||||
List<WallpaperInfo> otherdata = new ArrayList<>();
|
List<WallpaperInfo> wallpaperInfos = new ArrayList<>();
|
||||||
List<Category> mydataList = getCategories();
|
List<Category> categoryList = getCategories();
|
||||||
Set<String> set = new HashSet<>();
|
Set<String> set = new HashSet<>();
|
||||||
for (Category mydata : mydataList) {
|
for (Category category : categoryList) {
|
||||||
List<WallpaperInfo> otherdataList = mydata.getList();
|
List<WallpaperInfo> wallpaperInfoList = category.getList();
|
||||||
for (WallpaperInfo otherdata1 : otherdataList) {
|
for (WallpaperInfo wallpaperInfo : wallpaperInfoList) {
|
||||||
String title = otherdata1.getTitle();
|
String title = wallpaperInfo.getTitle();
|
||||||
if (!set.contains(title)) {
|
if (!set.contains(title)) {
|
||||||
otherdata.add(otherdata1);
|
wallpaperInfos.add(wallpaperInfo);
|
||||||
set.add(title);
|
set.add(title);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return otherdata;
|
return wallpaperInfos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
package com.key.vibekeyboard.Room;
|
|
||||||
|
|
||||||
|
|
||||||
import androidx.room.Database;
|
|
||||||
import androidx.room.Room;
|
|
||||||
import androidx.room.RoomDatabase;
|
|
||||||
|
|
||||||
import com.key.vibekeyboard.AppApplication;
|
|
||||||
|
|
||||||
@Database(entities = {WallpaperInfo.class}, version = AppApplication.DB_Version, exportSchema = false)
|
|
||||||
public abstract class MyDatabase extends RoomDatabase {
|
|
||||||
|
|
||||||
public abstract WallpaperInfoDao wallpaperInfoDao();
|
|
||||||
|
|
||||||
private static MyDatabase INSTANCE;
|
|
||||||
|
|
||||||
public static MyDatabase getInstance() {
|
|
||||||
if (INSTANCE == null) {
|
|
||||||
synchronized (MyDatabase.class) {
|
|
||||||
INSTANCE = Room.databaseBuilder(AppApplication.getContext(), MyDatabase.class, AppApplication.DB_Name).build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return INSTANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
package com.key.vibekeyboard.Room;
|
|
||||||
|
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData;
|
|
||||||
import androidx.room.Dao;
|
|
||||||
import androidx.room.Insert;
|
|
||||||
import androidx.room.Query;
|
|
||||||
import androidx.room.Update;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Dao
|
|
||||||
public interface WallpaperInfoDao {
|
|
||||||
|
|
||||||
@Query("select * from wallpaper_info order by RANDOM() LIMIT 1")
|
|
||||||
WallpaperInfo queryRandomItem();
|
|
||||||
|
|
||||||
@Insert
|
|
||||||
void insertAll(List<WallpaperInfo> likeDataList);
|
|
||||||
|
|
||||||
@Query("select * from wallpaper_info where preview =:pre ")
|
|
||||||
List<WallpaperInfo> checklikelist(String pre);
|
|
||||||
|
|
||||||
@Update
|
|
||||||
void update(WallpaperInfo wallpaperInfo);
|
|
||||||
|
|
||||||
@Query("SELECT * FROM wallpaper_info WHERE islike = :islike")
|
|
||||||
List<WallpaperInfo> getlikelist(boolean islike);
|
|
||||||
@Query("SELECT * FROM wallpaper_info WHERE islike = :islike")
|
|
||||||
LiveData<List<WallpaperInfo>> getLiveLikeList(boolean islike);
|
|
||||||
|
|
||||||
@Query("SELECT * FROM wallpaper_info WHERE isDownloaded = :isdownload")
|
|
||||||
List<WallpaperInfo> getdownloadlist(boolean isdownload);
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,98 +0,0 @@
|
|||||||
package com.key.vibekeyboard.Utils;
|
|
||||||
|
|
||||||
import android.graphics.Rect;
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.recyclerview.widget.GridLayoutManager;
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
|
|
||||||
|
|
||||||
import com.key.vibekeyboard.AppApplication;
|
|
||||||
|
|
||||||
|
|
||||||
// ItemDecoration 是一个自定义的 RecyclerView.ItemDecoration 类,用于在 RecyclerView 中为每个子项设置间距。
|
|
||||||
public class ItemDecoration extends RecyclerView.ItemDecoration {
|
|
||||||
|
|
||||||
// 垂直间距 (vertical spacing)、水平间距 (horizontal spacing) 和额外间距 (extra spacing):这里设置的是第一个的左边距,其它item根据剩余的距离均匀显示。
|
|
||||||
private int v, h, ex;
|
|
||||||
|
|
||||||
// 构造函数,传入 dp 值的垂直、水平和额外间距,并将它们转换为像素值。
|
|
||||||
public ItemDecoration(int v, int h, int ex) {
|
|
||||||
// 将 dp 值转换为像素值并四舍五入
|
|
||||||
this.v = Math.round(dpToPx(v));
|
|
||||||
this.h = Math.round(dpToPx(h));
|
|
||||||
this.ex = Math.round(dpToPx(ex));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重写 getItemOffsets 方法,用于为每个子项设置偏移量(间距)。
|
|
||||||
@Override
|
|
||||||
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
|
|
||||||
super.getItemOffsets(outRect, view, parent, state);
|
|
||||||
|
|
||||||
// 定义网格的列数(spanCount)、子项所占的列数(spanSize)以及子项在网格中的索引(spanIndex)
|
|
||||||
int spanCount = 1; // 列数默认为 1
|
|
||||||
int spanSize = 1; // 子项所占列数默认为 1
|
|
||||||
int spanIndex = 0; // 子项在网格中的索引默认为 0
|
|
||||||
|
|
||||||
// 获取子项在 Adapter 中的位置
|
|
||||||
int childAdapterPosition = parent.getChildAdapterPosition(view);
|
|
||||||
// 获取 RecyclerView 的布局管理器
|
|
||||||
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
|
|
||||||
|
|
||||||
// 如果布局管理器是 StaggeredGridLayoutManager(交错网格布局管理器)
|
|
||||||
if (layoutManager instanceof StaggeredGridLayoutManager) {
|
|
||||||
StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) layoutManager;
|
|
||||||
StaggeredGridLayoutManager.LayoutParams layoutParams = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams();
|
|
||||||
spanCount = staggeredGridLayoutManager.getSpanCount(); // 获取列数
|
|
||||||
// 如果子项占据整行(isFullSpan),将 spanSize 设置为列数
|
|
||||||
if (layoutParams.isFullSpan()) {
|
|
||||||
spanSize = spanCount;
|
|
||||||
}
|
|
||||||
spanIndex = layoutParams.getSpanIndex(); // 获取子项的索引
|
|
||||||
|
|
||||||
// 如果布局管理器是 GridLayoutManager(网格布局管理器)
|
|
||||||
} else if (layoutManager instanceof GridLayoutManager) {
|
|
||||||
GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
|
|
||||||
GridLayoutManager.LayoutParams layoutParams = (GridLayoutManager.LayoutParams) view.getLayoutParams();
|
|
||||||
spanCount = gridLayoutManager.getSpanCount(); // 获取列数
|
|
||||||
spanSize = gridLayoutManager.getSpanSizeLookup().getSpanSize(childAdapterPosition); // 获取子项占据的列数
|
|
||||||
spanIndex = layoutParams.getSpanIndex(); // 获取子项的索引
|
|
||||||
|
|
||||||
// 如果布局管理器是 LinearLayoutManager(线性布局管理器)
|
|
||||||
} else if (layoutManager instanceof LinearLayoutManager) {
|
|
||||||
// 设置子项的左、右和底部的间距
|
|
||||||
outRect.left = v;
|
|
||||||
outRect.right = v;
|
|
||||||
outRect.bottom = h;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果子项占据整行(spanSize == spanCount),设置左、右和底部的间距
|
|
||||||
if (spanSize == spanCount) {
|
|
||||||
outRect.left = v + ex;
|
|
||||||
outRect.right = v + ex;
|
|
||||||
outRect.bottom = h;
|
|
||||||
|
|
||||||
// 如果子项不占据整行,根据网格布局计算左右间距
|
|
||||||
} else {
|
|
||||||
// 计算每个子项的总间距(包括额外间距)
|
|
||||||
int itemAllSpacing = (v * (spanCount + 1) + ex * 2) / spanCount;
|
|
||||||
// 计算子项的左边距
|
|
||||||
int left = v * (spanIndex + 1) - itemAllSpacing * spanIndex + ex;
|
|
||||||
// 计算子项的右边距
|
|
||||||
int right = itemAllSpacing - left;
|
|
||||||
outRect.left = left;
|
|
||||||
outRect.right = right;
|
|
||||||
outRect.bottom = h;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将 dp 值转换为像素值的方法
|
|
||||||
public static float dpToPx(float dpValue) {
|
|
||||||
// 获取当前设备的屏幕密度(dpi)
|
|
||||||
float density = AppApplication.getContext().getResources().getDisplayMetrics().density;
|
|
||||||
// 通过公式 density * dp + 0.5f 将 dp 转换为像素,并返回结果
|
|
||||||
return density * dpValue + 0.5f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,319 +0,0 @@
|
|||||||
package com.key.vibekeyboard.Utils;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.res.AssetManager;
|
|
||||||
import android.graphics.Canvas;
|
|
||||||
import android.graphics.Rect;
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.inputmethodservice.Keyboard;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.provider.Settings;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.util.TypedValue;
|
|
||||||
import android.view.inputmethod.InputMethodInfo;
|
|
||||||
import android.view.inputmethod.InputMethodManager;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
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 com.key.vibekeyboard.AppApplication;
|
|
||||||
import com.key.vibekeyboard.Keyboard.MyKeyboard;
|
|
||||||
import com.key.vibekeyboard.R;
|
|
||||||
import com.key.vibekeyboard.Room.Category;
|
|
||||||
import com.key.vibekeyboard.Room.WallpaperInfo;
|
|
||||||
import com.key.vibekeyboard.callback.DownloadCallback;
|
|
||||||
import com.key.vibekeyboard.callback.UnzipCallback;
|
|
||||||
|
|
||||||
import net.sf.sevenzipjbinding.ArchiveFormat;
|
|
||||||
import net.sf.sevenzipjbinding.IInArchive;
|
|
||||||
import net.sf.sevenzipjbinding.SevenZip;
|
|
||||||
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.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.io.RandomAccessFile;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
public class Mytool {
|
|
||||||
|
|
||||||
// 获取输入法管理服务的实例
|
|
||||||
private static final InputMethodManager methodManager = (InputMethodManager) AppApplication.instance.getSystemService(Context.INPUT_METHOD_SERVICE);
|
|
||||||
// 用于执行异步任务的线程池
|
|
||||||
private static ExecutorService executorService;
|
|
||||||
|
|
||||||
public static void onDrawKeyIcon(Keyboard.Key currentKey,
|
|
||||||
Drawable drawKeyIcon,
|
|
||||||
Canvas myCanvas,
|
|
||||||
MyKeyboard myKeyboardView) {
|
|
||||||
currentKey.icon = drawKeyIcon;
|
|
||||||
currentKey.icon.setBounds(calculateIconBounds(currentKey, drawKeyIcon, myKeyboardView));
|
|
||||||
currentKey.icon.draw(myCanvas);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Rect calculateIconBounds(Keyboard.Key currentKey,
|
|
||||||
Drawable drawKeyIcon,
|
|
||||||
MyKeyboard myKeyboardView) {
|
|
||||||
float icon_w = drawKeyIcon.getIntrinsicWidth();
|
|
||||||
float icon_h = drawKeyIcon.getIntrinsicHeight();
|
|
||||||
float icon_wr = icon_w / currentKey.width;
|
|
||||||
float icon_hr = icon_h / currentKey.height;
|
|
||||||
|
|
||||||
float tep1, tep2;
|
|
||||||
if (icon_wr > icon_hr) {
|
|
||||||
tep2 = icon_wr;
|
|
||||||
tep1 = Math.max(icon_wr, 0.5f);
|
|
||||||
} else {
|
|
||||||
tep2 = icon_hr;
|
|
||||||
tep1 = Math.max(icon_hr, 0.5f);
|
|
||||||
}
|
|
||||||
|
|
||||||
icon_h = (icon_h / tep2) * tep1;
|
|
||||||
icon_w = (icon_w / tep2) * tep1;
|
|
||||||
|
|
||||||
int top = (int) (currentKey.y + myKeyboardView.getPaddingTop() + (currentKey.height - icon_h) / 2);
|
|
||||||
int left = (int) (currentKey.x + myKeyboardView.getPaddingLeft() + (currentKey.width - icon_w) / 2);
|
|
||||||
int bottom = top + (int) icon_h;
|
|
||||||
int right = left + (int) icon_w;
|
|
||||||
|
|
||||||
return new Rect(left, top, right, bottom);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 从资源文件加载JSON数据
|
|
||||||
public static JSONArray loadJSONFromAsset(String filename) {
|
|
||||||
String json;
|
|
||||||
try {
|
|
||||||
AssetManager assetManager = AppApplication.getContext().getAssets();
|
|
||||||
InputStream inputStream = assetManager.open(filename);
|
|
||||||
int size = inputStream.available();
|
|
||||||
byte[] buffer = new byte[size];
|
|
||||||
inputStream.read(buffer);
|
|
||||||
inputStream.close();
|
|
||||||
json = new String(buffer, StandardCharsets.UTF_8);
|
|
||||||
return new JSONArray(json); // 转换为JSONArray
|
|
||||||
} catch (IOException | JSONException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解析JSON数据为列表
|
|
||||||
public static List<Category> parseJsonToList(String filename) {
|
|
||||||
List<Category> dataList = new ArrayList<>();
|
|
||||||
try {
|
|
||||||
JSONArray jsonObject = loadJSONFromAsset(filename);
|
|
||||||
for (int a = 0; a < Objects.requireNonNull(jsonObject).length(); a++) {
|
|
||||||
JSONObject list = jsonObject.getJSONObject(a);
|
|
||||||
Category myData = new Category();
|
|
||||||
List<WallpaperInfo> otherdataList = new ArrayList<>();
|
|
||||||
myData.setClassName(list.getString("className"));
|
|
||||||
JSONArray classArray = list.getJSONArray("list");
|
|
||||||
for (int i = 0; i < classArray.length(); i++) {
|
|
||||||
JSONObject item = classArray.getJSONObject(i);
|
|
||||||
WallpaperInfo otherdata = new WallpaperInfo();
|
|
||||||
otherdata.setDownloaded(false);
|
|
||||||
otherdata.setIslike(false);
|
|
||||||
otherdata.setClassName(myData.getClassName());
|
|
||||||
otherdata.setPreview(item.getString("preview"));
|
|
||||||
otherdata.setThumb(item.getString("thumb"));
|
|
||||||
otherdata.setTitle(item.getString("title"));
|
|
||||||
otherdata.setZipUrl(item.getString("zipUrl"));
|
|
||||||
otherdataList.add(otherdata);
|
|
||||||
}
|
|
||||||
myData.setList(otherdataList);
|
|
||||||
dataList.add(myData);
|
|
||||||
}
|
|
||||||
} catch (JSONException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return dataList;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查输入法步骤2(确认输入法是否为当前应用)
|
|
||||||
public static boolean isStep2() {
|
|
||||||
String string = Settings.Secure.getString(AppApplication.instance.getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
|
|
||||||
return string.startsWith(AppApplication.instance.getPackageName());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查输入法步骤1(确认当前输入法是否被启用)
|
|
||||||
public static boolean isStep1() {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
|
||||||
return methodManager.getEnabledInputMethodList().stream()
|
|
||||||
.anyMatch(inputMethodInfo -> inputMethodInfo.getId().startsWith(AppApplication.instance.getPackageName()));
|
|
||||||
} else {
|
|
||||||
InputMethodManager inputMethodManager = (InputMethodManager) AppApplication.instance.getSystemService(Context.INPUT_METHOD_SERVICE);
|
|
||||||
List<InputMethodInfo> inputMethodList = inputMethodManager.getEnabledInputMethodList();
|
|
||||||
for (InputMethodInfo inputMethodInfo : inputMethodList) {
|
|
||||||
if (inputMethodInfo.getId().startsWith(AppApplication.instance.getPackageName())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解压文件的操作
|
|
||||||
public static void unZip(Context context, String urlpath, File resource, UnzipCallback callback) throws IOException {
|
|
||||||
if (!resource.exists()) { // 如果资源文件不存在,显示下载失败的提示
|
|
||||||
Toast.makeText(context, context.getString(R.string.app_name), Toast.LENGTH_SHORT).show();
|
|
||||||
} else {
|
|
||||||
String itemFilePath = "";
|
|
||||||
|
|
||||||
// 使用应用的外部文件目录来存储解压后的文件
|
|
||||||
File externalDir = context.getExternalFilesDir(null);
|
|
||||||
if (externalDir == null) {
|
|
||||||
externalDir = context.getFilesDir(); // 如果外部存储不可用,则回退到内部存储
|
|
||||||
}
|
|
||||||
|
|
||||||
String extractPath = new File(externalDir, "ExtractedFiles").getAbsolutePath(); // 定义一个专门的文件夹存储解压文件
|
|
||||||
|
|
||||||
RandomAccessFile accessFile = new RandomAccessFile(resource, "r");
|
|
||||||
RandomAccessFileInStream inStream = new RandomAccessFileInStream(accessFile);
|
|
||||||
IInArchive iInArchive = SevenZip.openInArchive(ArchiveFormat.SEVEN_ZIP, inStream);
|
|
||||||
ISimpleInArchiveItem[] archiveItems = iInArchive.getSimpleInterface().getArchiveItems();
|
|
||||||
|
|
||||||
// 解压每一个文件
|
|
||||||
for (int d = 0; d < archiveItems.length; d++) {
|
|
||||||
ISimpleInArchiveItem simple = archiveItems[d];
|
|
||||||
File file = new File(extractPath, simple.getPath()); // 将解压路径设置为外部存储目录
|
|
||||||
if (!simple.isFolder()) { // 如果不是文件夹,解压文件
|
|
||||||
RandomAccessFileOutStream outStream = new RandomAccessFileOutStream(new RandomAccessFile(file, "rw"));
|
|
||||||
simple.extractSlow(outStream);
|
|
||||||
itemFilePath = file.getPath(); // 记录解压后的文件路径
|
|
||||||
Log.d("--------", "path: " + itemFilePath);
|
|
||||||
} else {
|
|
||||||
boolean mkdirs = file.mkdirs(); // 创建文件夹
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inStream.close();
|
|
||||||
iInArchive.close();
|
|
||||||
|
|
||||||
// 截取资源路径
|
|
||||||
int res = itemFilePath.indexOf("res");
|
|
||||||
String substring = itemFilePath.substring(0, res + 3); // 截取资源路径
|
|
||||||
Log.d("--------", "substring: " + substring);
|
|
||||||
|
|
||||||
callback.onUnzipCall(true, substring); // 调用回调函数
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 下载压缩文件操作
|
|
||||||
public static void donwnZip(Context context, String url, DownloadCallback callback) {
|
|
||||||
// 使用Glide库来下载文件
|
|
||||||
Glide.with(context)
|
|
||||||
.asFile() // 指定下载的资源类型为File
|
|
||||||
.load(url) // 设置下载的URL
|
|
||||||
.listener(new RequestListener<File>() {
|
|
||||||
// 添加监听器来处理下载结果
|
|
||||||
@Override
|
|
||||||
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<File> target, boolean isFirstResource) {
|
|
||||||
// 下载失败时的回调
|
|
||||||
try {
|
|
||||||
callback.onDownloadCall(false, null); // 调用回调方法,传递失败状态
|
|
||||||
} catch (FileNotFoundException ex) {
|
|
||||||
throw new RuntimeException(ex); // 如果捕获到FileNotFoundException异常,抛出运行时异常
|
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new RuntimeException(ex); // 如果捕获到IOException异常,抛出运行时异常
|
|
||||||
}
|
|
||||||
return false; // 表示处理了这个事件
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onResourceReady(@NonNull File resource, @NonNull Object model, Target<File> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
|
||||||
// 下载成功时的回调
|
|
||||||
try {
|
|
||||||
// 使用外部存储目录或内部存储目录
|
|
||||||
File externalDir = context.getExternalFilesDir(null);
|
|
||||||
if (externalDir == null) {
|
|
||||||
externalDir = context.getFilesDir(); // 如果外部存储不可用,则回退到内部存储
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将下载文件保存到外部存储的特定文件夹
|
|
||||||
File downloadDir = new File(externalDir, "DownloadedFiles");
|
|
||||||
if (!downloadDir.exists()) {
|
|
||||||
downloadDir.mkdirs(); // 创建目录
|
|
||||||
}
|
|
||||||
|
|
||||||
File destinationFile = new File(downloadDir, resource.getName());
|
|
||||||
copyFile(resource, destinationFile); // 使用FileUtils来复制文件
|
|
||||||
|
|
||||||
callback.onDownloadCall(true, destinationFile); // 调用回调方法,传递成功状态和保存后的文件路径
|
|
||||||
Log.d("--------", "resource: " + destinationFile);
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
throw new RuntimeException(e); // 如果捕获到FileNotFoundException异常,抛出运行时异常
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e); // 如果捕获到IOException异常,抛出运行时异常
|
|
||||||
}
|
|
||||||
return false; // 表示处理了这个事件
|
|
||||||
}
|
|
||||||
}).preload(); // 预加载文件
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void copyFile(File sourceFile, File destinationFile) throws IOException {
|
|
||||||
try (InputStream in = new FileInputStream(sourceFile);
|
|
||||||
OutputStream out = new FileOutputStream(destinationFile)) {
|
|
||||||
byte[] buffer = new byte[1024];
|
|
||||||
int bytesRead;
|
|
||||||
while ((bytesRead = in.read(buffer)) != -1) {
|
|
||||||
out.write(buffer, 0, bytesRead);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将文件内容转换为字符串
|
|
||||||
public static String fileToString(File file) throws IOException {
|
|
||||||
FileInputStream fileInputStream = new FileInputStream(file);
|
|
||||||
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream));
|
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
|
||||||
String lin = "";
|
|
||||||
// 逐行读取文件内容
|
|
||||||
while ((lin = bufferedReader.readLine()) != null) {
|
|
||||||
stringBuilder.append(lin);
|
|
||||||
}
|
|
||||||
bufferedReader.close();
|
|
||||||
String con = stringBuilder.toString(); // 转换为字符串
|
|
||||||
return con;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将SP单位转换为像素单位
|
|
||||||
public static float spToPpx(Float values, Context context) {
|
|
||||||
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, values, context.getResources().getDisplayMetrics());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 运行IO操作的任务
|
|
||||||
public static void runIO(Runnable task) {
|
|
||||||
getExecutorService().execute(task);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取线程池的实例,如果不存在则创建一个单线程池
|
|
||||||
private static ExecutorService getExecutorService() {
|
|
||||||
if (executorService == null) {
|
|
||||||
executorService = Executors.newSingleThreadExecutor();
|
|
||||||
}
|
|
||||||
return executorService;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,75 +0,0 @@
|
|||||||
package com.key.vibekeyboard.Utils;
|
|
||||||
|
|
||||||
import android.content.ActivityNotFoundException;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.pm.PackageInfo;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
public class SettingUtil {
|
|
||||||
public static final String PRIVACY_POLICY_URL = "https://himelody.mystrikingly.com/privacy";
|
|
||||||
public static final String TERMS_OF_SERVICE_URL = "https://himelody.mystrikingly.com/terms";
|
|
||||||
|
|
||||||
// 获取当前应用的版本号
|
|
||||||
public static String getCurrentVersion(Context context) {
|
|
||||||
try {
|
|
||||||
PackageManager packageManager = context.getPackageManager();
|
|
||||||
PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
|
|
||||||
return packageInfo.versionName; // 返回版本名称
|
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return null; // 返回null表示获取版本号失败
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 发送反馈
|
|
||||||
public static void sendFeedback(Context context, String email, String subject) {
|
|
||||||
Intent emailIntent = new Intent(Intent.ACTION_SEND);
|
|
||||||
emailIntent.setType("message/rfc822");
|
|
||||||
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{email});
|
|
||||||
emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
|
|
||||||
try {
|
|
||||||
context.startActivity(Intent.createChooser(emailIntent, "Send Feedback"));
|
|
||||||
} catch (ActivityNotFoundException ex) {
|
|
||||||
Toast.makeText(context, "There is no app that supports sending emails", Toast.LENGTH_LONG).show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分享应用
|
|
||||||
public static void shareApp(Context context) {
|
|
||||||
String appPackageName = context.getPackageName();
|
|
||||||
String appName = context.getApplicationInfo().loadLabel(context.getPackageManager()).toString();
|
|
||||||
String appPlayStoreLink = "https://play.google.com/store/apps/details?id=" + appPackageName;
|
|
||||||
|
|
||||||
Intent shareIntent = new Intent(Intent.ACTION_SEND);
|
|
||||||
shareIntent.setType("text/plain");
|
|
||||||
shareIntent.putExtra(Intent.EXTRA_SUBJECT, "Check out this app: " + appName);
|
|
||||||
shareIntent.putExtra(Intent.EXTRA_TEXT, "Download " + appName + " from Google Play: " + appPlayStoreLink);
|
|
||||||
context.startActivity(Intent.createChooser(shareIntent, "Share " + appName + " via"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 打开隐私政策
|
|
||||||
public static void openPrivacyPolicy(Context context) {
|
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(PRIVACY_POLICY_URL));
|
|
||||||
context.startActivity(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 打开服务条款
|
|
||||||
public static void openTermsOfService(Context context) {
|
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(TERMS_OF_SERVICE_URL));
|
|
||||||
context.startActivity(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 打开Google Play
|
|
||||||
public static void openGooglePlay(Context context, String packageName) {
|
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + packageName));
|
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
try {
|
|
||||||
context.startActivity(intent);
|
|
||||||
} catch (ActivityNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
package com.key.vibekeyboard.Utils;
|
|
||||||
|
|
||||||
public class StaticValue {
|
|
||||||
public static String KEY_NAME = "key_name";
|
|
||||||
public static String KEY_URL = "key_url";
|
|
||||||
public static String KEY_PRE = "key_pre";
|
|
||||||
public static String PATH = "";
|
|
||||||
public static String KEY_TEXT = "";
|
|
||||||
public static String KEY_ISMAINSH = "";
|
|
||||||
public static String KEY_ISshow = "";
|
|
||||||
}
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
package com.key.vibekeyboard.ViewModel;
|
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData;
|
|
||||||
import androidx.lifecycle.ViewModel;
|
|
||||||
|
|
||||||
import com.key.vibekeyboard.Room.MyDatabase;
|
|
||||||
import com.key.vibekeyboard.Room.WallpaperInfo;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class FavoriteViewModel extends ViewModel {
|
|
||||||
private final LiveData<List<WallpaperInfo>> favoriteList;
|
|
||||||
private final MyDatabase database;
|
|
||||||
|
|
||||||
public FavoriteViewModel() {
|
|
||||||
// 获取数据库实例
|
|
||||||
database = MyDatabase.getInstance();
|
|
||||||
// 通过 LiveData 监听数据库中的喜欢列表变化
|
|
||||||
favoriteList = database.wallpaperInfoDao().getLiveLikeList(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 提供一个获取喜欢列表 LiveData 的方法
|
|
||||||
public LiveData<List<WallpaperInfo>> getFavoriteList() {
|
|
||||||
return favoriteList;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
package com.key.vibekeyboard.callback;
|
|
||||||
|
|
||||||
public interface RecommendDialogCallback {
|
|
||||||
|
|
||||||
void onTryNow();
|
|
||||||
}
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
package com.key.vibekeyboard.callback;
|
|
||||||
|
|
||||||
public interface StepDialogCallback {
|
|
||||||
|
|
||||||
void onDisMiss();
|
|
||||||
}
|
|
||||||
@ -1,4 +1,6 @@
|
|||||||
package com.key.vibekeyboard.Room;
|
package com.key.vibekeyboard.data.bean;
|
||||||
|
|
||||||
|
import com.key.vibekeyboard.data.database.entity.WallpaperInfo;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
package com.key.vibekeyboard.data.database;
|
||||||
|
|
||||||
|
|
||||||
|
import androidx.room.Database;
|
||||||
|
import androidx.room.Room;
|
||||||
|
import androidx.room.RoomDatabase;
|
||||||
|
|
||||||
|
import com.key.vibekeyboard.MyApplication;
|
||||||
|
import com.key.vibekeyboard.data.database.entity.WallpaperInfo;
|
||||||
|
import com.key.vibekeyboard.data.database.dao.WallpaperInfoDao;
|
||||||
|
|
||||||
|
@Database(entities = {WallpaperInfo.class}, version = MyApplication.DB_VERSION, exportSchema = false)
|
||||||
|
public abstract class AppDatabase extends RoomDatabase {
|
||||||
|
|
||||||
|
public abstract WallpaperInfoDao wallpaperInfoDao();
|
||||||
|
|
||||||
|
private static AppDatabase INSTANCE;
|
||||||
|
|
||||||
|
public static AppDatabase getInstance() {
|
||||||
|
if (INSTANCE == null) {
|
||||||
|
synchronized (AppDatabase.class) {
|
||||||
|
INSTANCE = Room.databaseBuilder(MyApplication.getContext(), AppDatabase.class, MyApplication.DB_NAME).build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
package com.key.vibekeyboard.data.database.dao;
|
||||||
|
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.room.Dao;
|
||||||
|
import androidx.room.Insert;
|
||||||
|
import androidx.room.Query;
|
||||||
|
import androidx.room.Update;
|
||||||
|
|
||||||
|
import com.key.vibekeyboard.data.database.entity.WallpaperInfo;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
public interface WallpaperInfoDao {
|
||||||
|
|
||||||
|
@Insert
|
||||||
|
void insertAll(List<WallpaperInfo> likeDataList);
|
||||||
|
|
||||||
|
@Query("select * from wallpaper_info where preview =:pre ")
|
||||||
|
List<WallpaperInfo> checklikelist(String pre);
|
||||||
|
|
||||||
|
@Update
|
||||||
|
void update(WallpaperInfo wallpaperInfo);
|
||||||
|
|
||||||
|
@Query("SELECT * FROM wallpaper_info WHERE islike = :dislike")
|
||||||
|
LiveData<List<WallpaperInfo>> getLiveLikeList(boolean dislike);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.key.vibekeyboard.Room;
|
package com.key.vibekeyboard.data.database.entity;
|
||||||
|
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
@ -0,0 +1,170 @@
|
|||||||
|
package com.key.vibekeyboard.inputmethod.service;
|
||||||
|
|
||||||
|
import android.inputmethodservice.InputMethodService;
|
||||||
|
import android.inputmethodservice.Keyboard;
|
||||||
|
import android.inputmethodservice.KeyboardView;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.inputmethod.EditorInfo;
|
||||||
|
import android.view.inputmethod.InputConnection;
|
||||||
|
|
||||||
|
import com.key.vibekeyboard.R;
|
||||||
|
import com.key.vibekeyboard.inputmethod.view.CustomKeyboardView;
|
||||||
|
|
||||||
|
public class MyInputMethodService extends InputMethodService implements KeyboardView.OnKeyboardActionListener {
|
||||||
|
|
||||||
|
private Keyboard keyboardLowercase;
|
||||||
|
private Keyboard keyboardUppercase;
|
||||||
|
private Keyboard keyboardSymbols;
|
||||||
|
private Keyboard keyboardMoreSymbols;
|
||||||
|
private Keyboard currentKeyboard;
|
||||||
|
|
||||||
|
private CustomKeyboardView customKeyboardView;
|
||||||
|
|
||||||
|
private static final int KEYCODE_MORE_SYMBOLS = -1000;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateInputView() {
|
||||||
|
customKeyboardView = (CustomKeyboardView) getLayoutInflater().inflate(R.layout.custom_keyboard_view, null, false);
|
||||||
|
|
||||||
|
initializeKeyboards();
|
||||||
|
setUpCustomKeyboardView();
|
||||||
|
|
||||||
|
return customKeyboardView;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeKeyboards() {
|
||||||
|
keyboardLowercase = new Keyboard(this, R.xml.keyboard_lowercase);
|
||||||
|
keyboardUppercase = new Keyboard(this, R.xml.keyboard_uppercase);
|
||||||
|
keyboardSymbols = new Keyboard(this, R.xml.keyboard_symbols);
|
||||||
|
keyboardMoreSymbols = new Keyboard(this, R.xml.keyboard_more_symbols);
|
||||||
|
|
||||||
|
currentKeyboard = keyboardLowercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setUpCustomKeyboardView() {
|
||||||
|
customKeyboardView.setKeyboard(currentKeyboard);
|
||||||
|
customKeyboardView.setOnKeyboardActionListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onWindowShown() {
|
||||||
|
super.onWindowShown();
|
||||||
|
updateKeyboardBackground(); // 更新背景
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onKey(int primaryCode, int[] keyCodes) {
|
||||||
|
InputConnection inputConnection = getCurrentInputConnection();
|
||||||
|
if (inputConnection == null) return;
|
||||||
|
|
||||||
|
switch (primaryCode) {
|
||||||
|
case Keyboard.KEYCODE_DELETE:
|
||||||
|
handleDelete(inputConnection);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Keyboard.KEYCODE_SHIFT:
|
||||||
|
toggleCaseMode();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Keyboard.KEYCODE_MODE_CHANGE:
|
||||||
|
toggleKeyboardLayout();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Keyboard.KEYCODE_DONE:
|
||||||
|
performActionBasedOnEditorInfo(inputConnection);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEYCODE_MORE_SYMBOLS:
|
||||||
|
toggleMoreSymbolsKeyboard();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
handleCharacterInput(primaryCode, inputConnection);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleDelete(InputConnection inputConnection) {
|
||||||
|
inputConnection.deleteSurroundingText(1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void toggleCaseMode() {
|
||||||
|
if (currentKeyboard == keyboardLowercase) {
|
||||||
|
switchToNewKeyboard(keyboardUppercase);
|
||||||
|
customKeyboardView.setShiftState(CustomKeyboardView.ShiftState.CAPS);
|
||||||
|
} else {
|
||||||
|
switchToNewKeyboard(keyboardLowercase);
|
||||||
|
customKeyboardView.setShiftState(CustomKeyboardView.ShiftState.NORMAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void toggleKeyboardLayout() {
|
||||||
|
if (currentKeyboard == keyboardLowercase || currentKeyboard == keyboardUppercase) {
|
||||||
|
switchToNewKeyboard(keyboardSymbols);
|
||||||
|
} else if (currentKeyboard == keyboardSymbols || currentKeyboard == keyboardMoreSymbols) {
|
||||||
|
switchToNewKeyboard(keyboardLowercase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void switchToNewKeyboard(Keyboard newKeyboard) {
|
||||||
|
if (currentKeyboard != newKeyboard) {
|
||||||
|
currentKeyboard = newKeyboard;
|
||||||
|
customKeyboardView.setKeyboard(currentKeyboard);
|
||||||
|
updateKeyboardBackground();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void performActionBasedOnEditorInfo(InputConnection inputConnection) {
|
||||||
|
EditorInfo editorInfo = getCurrentInputEditorInfo();
|
||||||
|
if ((editorInfo.imeOptions & EditorInfo.IME_ACTION_SEARCH) != 0) {
|
||||||
|
inputConnection.performEditorAction(EditorInfo.IME_ACTION_SEARCH);
|
||||||
|
} else if ((editorInfo.imeOptions & EditorInfo.IME_ACTION_DONE) != 0) {
|
||||||
|
inputConnection.performEditorAction(EditorInfo.IME_ACTION_DONE);
|
||||||
|
} else {
|
||||||
|
inputConnection.performEditorAction(EditorInfo.IME_ACTION_UNSPECIFIED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void toggleMoreSymbolsKeyboard() {
|
||||||
|
switchToNewKeyboard(currentKeyboard == keyboardSymbols ? keyboardMoreSymbols : keyboardSymbols);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleCharacterInput(int primaryCode, InputConnection inputConnection) {
|
||||||
|
char code = (char) primaryCode;
|
||||||
|
inputConnection.commitText(String.valueOf(code), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateKeyboardBackground() {
|
||||||
|
customKeyboardView.updateKeyboardView(this);
|
||||||
|
customKeyboardView.invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPress(int primaryCode) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRelease(int primaryCode) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onText(CharSequence text) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void swipeLeft() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void swipeRight() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void swipeDown() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void swipeUp() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,172 @@
|
|||||||
|
package com.key.vibekeyboard.inputmethod.theme;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.util.Xml;
|
||||||
|
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
|
import com.key.vibekeyboard.R;
|
||||||
|
import com.key.vibekeyboard.utils.FileUtils;
|
||||||
|
import com.key.vibekeyboard.utils.PathRepository;
|
||||||
|
|
||||||
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.StringReader;
|
||||||
|
|
||||||
|
public class KeyboardThemeManager {
|
||||||
|
|
||||||
|
private Drawable actionBackgroundDrawable;
|
||||||
|
private Drawable normalBackgroundDrawable;
|
||||||
|
private Drawable shiftIconDrawable;
|
||||||
|
private Drawable shiftLockIconDrawable;
|
||||||
|
private Drawable deleteIconDrawable;
|
||||||
|
private Drawable returnIconDrawable;
|
||||||
|
private Drawable backgroundDrawable;
|
||||||
|
|
||||||
|
private int normalKeyColor;
|
||||||
|
private int actionKeyColor;
|
||||||
|
|
||||||
|
private static final String COLOR_NORMAL_KEY_TEXT = "key_text_color_normal";
|
||||||
|
private static final String COLOR_ACTION_KEY_TEXT = "key_text_color_functional";
|
||||||
|
|
||||||
|
private static final int DEFAULT_SHIFT_ICON = android.R.drawable.stat_sys_upload;
|
||||||
|
private static final int DEFAULT_SHIFT_LOCK_ICON = android.R.drawable.stat_sys_upload;
|
||||||
|
private static final int DEFAULT_DELETE_ICON = android.R.drawable.ic_input_delete;
|
||||||
|
private static final int DEFAULT_RETURN_ICON = android.R.drawable.screen_background_light_transparent;
|
||||||
|
private static final int DEFAULT_BACKGROUND_COLOR = R.color.black;
|
||||||
|
|
||||||
|
public KeyboardThemeManager(Context context) {
|
||||||
|
shiftIconDrawable = ContextCompat.getDrawable(context, DEFAULT_SHIFT_ICON);
|
||||||
|
shiftLockIconDrawable = ContextCompat.getDrawable(context, DEFAULT_SHIFT_LOCK_ICON);
|
||||||
|
deleteIconDrawable = ContextCompat.getDrawable(context, DEFAULT_DELETE_ICON);
|
||||||
|
returnIconDrawable = ContextCompat.getDrawable(context, DEFAULT_RETURN_ICON);
|
||||||
|
backgroundDrawable = ContextCompat.getDrawable(context, DEFAULT_BACKGROUND_COLOR);
|
||||||
|
normalKeyColor = ContextCompat.getColor(context, R.color.white);
|
||||||
|
actionKeyColor = normalKeyColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Drawable getBackgroundDrawable() {
|
||||||
|
return backgroundDrawable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Drawable getActionBackgroundDrawable() {
|
||||||
|
return actionBackgroundDrawable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Drawable getNormalBackgroundDrawable() {
|
||||||
|
return normalBackgroundDrawable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Drawable getDeleteIconDrawable() {
|
||||||
|
return deleteIconDrawable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Drawable getShiftIconDrawable() {
|
||||||
|
return shiftIconDrawable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Drawable getReturnIconDrawable() {
|
||||||
|
return returnIconDrawable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Drawable getShiftLockIconDrawable() {
|
||||||
|
return shiftLockIconDrawable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNormalKeyColor() {
|
||||||
|
return normalKeyColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getActionKeyColor() {
|
||||||
|
return actionKeyColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateBackground(Context con) {
|
||||||
|
String resDirPath = getWallpaperPath(con);
|
||||||
|
if (!resDirPath.isEmpty()) {
|
||||||
|
updateKeyColors(resDirPath);
|
||||||
|
backgroundDrawable = getKeyboardBackground(con, resDirPath);
|
||||||
|
returnIconDrawable = getDrawableForKeyBackground(con, resDirPath, PathRepository.RETURN_ICON);
|
||||||
|
normalBackgroundDrawable = getDrawableForKeyBackground(con, resDirPath, PathRepository.NORMAL_KEY_BACKGROUND);
|
||||||
|
actionBackgroundDrawable = getDrawableForKeyBackground(con, resDirPath, PathRepository.ACTION_KEY_BACKGROUND);
|
||||||
|
deleteIconDrawable = getDrawableForKeyBackground(con, resDirPath, PathRepository.DELETE_ICON);
|
||||||
|
shiftIconDrawable = getDrawableForKeyBackground(con, resDirPath, PathRepository.SHIFT_ICON);
|
||||||
|
shiftLockIconDrawable = getDrawableForKeyBackground(con, resDirPath, PathRepository.SHIFT_LOCK_ICON);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Drawable getKeyboardBackground(Context context, String resourceDirectoryPath) {
|
||||||
|
String filePath = resourceDirectoryPath + "/drawable-xxhdpi-v4/keyboard_background.jpg";
|
||||||
|
return loadDrawableFromFile(context, filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Drawable getDrawableForKeyBackground(Context context, String resourceDirectoryPath, String drawableName) {
|
||||||
|
String drawablePath = "/drawable-xhdpi-v4/" + drawableName;
|
||||||
|
return loadDrawableFromFile(context, resourceDirectoryPath + drawablePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateKeyColors(String resDirPath) {
|
||||||
|
String colorXmlPath = resDirPath + "/colors.xml";
|
||||||
|
File colorXmlFile = new File(colorXmlPath);
|
||||||
|
|
||||||
|
if (!colorXmlFile.exists()) {
|
||||||
|
Log.w("updateKeyColors", "File not found: " + colorXmlPath);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
XmlPullParser parser = Xml.newPullParser();
|
||||||
|
String fileContent = FileUtils.readFileAsString(colorXmlFile);
|
||||||
|
parser.setInput(new StringReader(fileContent));
|
||||||
|
|
||||||
|
int eventType = parser.getEventType();
|
||||||
|
while (eventType != XmlPullParser.END_DOCUMENT) {
|
||||||
|
if (eventType == XmlPullParser.START_TAG) {
|
||||||
|
String tagName = parser.getName();
|
||||||
|
if ("color".equals(tagName) || "item".equals(tagName)) {
|
||||||
|
String attributeName = parser.getAttributeValue(null, "name");
|
||||||
|
String colorValue = parser.nextText();
|
||||||
|
if (colorValue != null && !colorValue.trim().isEmpty()) {
|
||||||
|
if (COLOR_NORMAL_KEY_TEXT.equals(attributeName)) {
|
||||||
|
normalKeyColor = Color.parseColor(colorValue);
|
||||||
|
} else if (COLOR_ACTION_KEY_TEXT.equals(attributeName)) {
|
||||||
|
actionKeyColor = Color.parseColor(colorValue);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.w("updateKeyColors", "Invalid color value for: " + attributeName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
eventType = parser.next();
|
||||||
|
}
|
||||||
|
} catch (XmlPullParserException | IOException e) {
|
||||||
|
Log.e("updateKeyColors", "Error parsing colors XML", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Drawable loadDrawableFromFile(Context context, String filePath) {
|
||||||
|
File file = new File(filePath);
|
||||||
|
if (file.exists()) {
|
||||||
|
return new BitmapDrawable(context.getResources(), BitmapFactory.decodeFile(filePath));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getWallpaperPath(Context context) {
|
||||||
|
SharedPreferences prefs = context.getSharedPreferences("keyboard_info", Context.MODE_PRIVATE);
|
||||||
|
String path = prefs.getString("wallpaper_path", "");
|
||||||
|
if (path.isEmpty()) {
|
||||||
|
Log.w("KeyboardThemeManager", "Wallpaper path is empty.");
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,137 @@
|
|||||||
|
package com.key.vibekeyboard.inputmethod.view;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.inputmethodservice.Keyboard;
|
||||||
|
import android.inputmethodservice.KeyboardView;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
|
||||||
|
import com.key.vibekeyboard.inputmethod.theme.KeyboardThemeManager;
|
||||||
|
import com.key.vibekeyboard.utils.DrawableUtils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class CustomKeyboardView extends KeyboardView {
|
||||||
|
|
||||||
|
private final Paint mPaint;
|
||||||
|
private final KeyboardThemeManager keyboardThemeManager;
|
||||||
|
private ShiftState shiftState = ShiftState.NORMAL;
|
||||||
|
|
||||||
|
private static final float TEXT_SIZE_NORMAL = 18f;
|
||||||
|
private static final float TEXT_SIZE_LARGE = 20f;
|
||||||
|
|
||||||
|
public CustomKeyboardView(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
keyboardThemeManager = new KeyboardThemeManager(context);
|
||||||
|
mPaint = new Paint();
|
||||||
|
mPaint.setTextSize(DrawableUtils.spToPx(TEXT_SIZE_LARGE, context));
|
||||||
|
setPreviewEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDraw(Canvas canvas) {
|
||||||
|
List<Keyboard.Key> keys = getKeyboard().getKeys();
|
||||||
|
|
||||||
|
for (Keyboard.Key key : keys) {
|
||||||
|
int keyCode = key.codes[0];
|
||||||
|
setPaintColor(keyCode);
|
||||||
|
|
||||||
|
Drawable keyBackground = getKeyBackgroundDrawable(keyCode);
|
||||||
|
if (keyBackground != null) {
|
||||||
|
drawKeyBackground(key, keyBackground, canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (keyCode) {
|
||||||
|
case Keyboard.KEYCODE_SHIFT:
|
||||||
|
DrawableUtils.drawKeyIcon(key, getShiftDrawable(), canvas, this);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Keyboard.KEYCODE_DELETE:
|
||||||
|
DrawableUtils.drawKeyIcon(key, keyboardThemeManager.getDeleteIconDrawable(), canvas, this);
|
||||||
|
drawKeyLabel(key, canvas);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Keyboard.KEYCODE_DONE:
|
||||||
|
DrawableUtils.drawKeyIcon(key, keyboardThemeManager.getReturnIconDrawable(), canvas, this);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
drawKeyLabel(key, canvas);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setPaintColor(int keyCode) {
|
||||||
|
if (isActionKey(keyCode)) {
|
||||||
|
mPaint.setColor(keyboardThemeManager.getActionKeyColor());
|
||||||
|
} else {
|
||||||
|
mPaint.setColor(keyboardThemeManager.getNormalKeyColor());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isActionKey(int keyCode) {
|
||||||
|
return keyCode == Keyboard.KEYCODE_SHIFT || keyCode == Keyboard.KEYCODE_DELETE ||
|
||||||
|
keyCode == Keyboard.KEYCODE_MODE_CHANGE || keyCode == Keyboard.KEYCODE_DONE
|
||||||
|
|| keyCode == -1000 || keyCode == 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Drawable getKeyBackgroundDrawable(int keyCode) {
|
||||||
|
if (isActionKey(keyCode)) {
|
||||||
|
return keyboardThemeManager.getActionBackgroundDrawable();
|
||||||
|
} else {
|
||||||
|
return keyboardThemeManager.getNormalBackgroundDrawable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Drawable getShiftDrawable() {
|
||||||
|
if (shiftState == ShiftState.NORMAL) {
|
||||||
|
return keyboardThemeManager.getShiftIconDrawable();
|
||||||
|
} else if (shiftState == ShiftState.CAPS) {
|
||||||
|
return keyboardThemeManager.getShiftLockIconDrawable();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawKeyBackground(Keyboard.Key key, Drawable keyBackground, Canvas canvas) {
|
||||||
|
if (keyBackground != null) {
|
||||||
|
int left = key.x + getPaddingLeft();
|
||||||
|
int top = key.y + getPaddingTop();
|
||||||
|
int right = left + key.width;
|
||||||
|
int bottom = top + key.height;
|
||||||
|
|
||||||
|
keyBackground.setBounds(left, top, right, bottom);
|
||||||
|
keyBackground.setState(key.getCurrentDrawableState());
|
||||||
|
keyBackground.draw(canvas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawKeyLabel(Keyboard.Key key, Canvas canvas) {
|
||||||
|
if (key.label != null && !key.label.toString().isEmpty()) {
|
||||||
|
float xPos = key.x + getPaddingLeft() + (key.width / 2f);
|
||||||
|
float yPos = key.y + key.height / 2f - (mPaint.descent() + mPaint.ascent()) / 2f;
|
||||||
|
xPos -= mPaint.measureText(key.label.toString()) / 2f;
|
||||||
|
|
||||||
|
mPaint.setTextSize(DrawableUtils.spToPx(TEXT_SIZE_NORMAL, this.getContext()));
|
||||||
|
canvas.drawText(key.label.toString(), xPos, yPos, mPaint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateKeyboardView(Context context) {
|
||||||
|
keyboardThemeManager.updateBackground(context);
|
||||||
|
setBackground(keyboardThemeManager.getBackgroundDrawable());
|
||||||
|
invalidateAllKeys();
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ShiftState {
|
||||||
|
NORMAL, CAPS
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setShiftState(ShiftState state) {
|
||||||
|
this.shiftState = state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -10,7 +10,7 @@ import com.anythink.core.api.ATAdInfo;
|
|||||||
import com.anythink.core.api.AdError;
|
import com.anythink.core.api.AdError;
|
||||||
import com.anythink.interstitial.api.ATInterstitial;
|
import com.anythink.interstitial.api.ATInterstitial;
|
||||||
import com.anythink.interstitial.api.ATInterstitialListener;
|
import com.anythink.interstitial.api.ATInterstitialListener;
|
||||||
import com.key.vibekeyboard.AppApplication;
|
import com.key.vibekeyboard.MyApplication;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -44,14 +44,14 @@ public class AdManager {
|
|||||||
|
|
||||||
private static boolean alreadyShow = false;
|
private static boolean alreadyShow = false;
|
||||||
|
|
||||||
private static List<ATInterstitial> list = new ArrayList<>();
|
private static final List<ATInterstitial> list = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
public static void loadAllAd() {
|
public static void loadAllAd() {
|
||||||
if (list.isEmpty()) {
|
if (list.isEmpty()) {
|
||||||
ATInterstitial mInterstitialAd1 = new ATInterstitial(AppApplication.getContext(), place1Id);
|
ATInterstitial mInterstitialAd1 = new ATInterstitial(MyApplication.getContext(), place1Id);
|
||||||
ATInterstitial mInterstitialAd2 = new ATInterstitial(AppApplication.getContext(), place2Id);
|
ATInterstitial mInterstitialAd2 = new ATInterstitial(MyApplication.getContext(), place2Id);
|
||||||
ATInterstitial mInterstitialAd3 = new ATInterstitial(AppApplication.getContext(), place3Id);
|
ATInterstitial mInterstitialAd3 = new ATInterstitial(MyApplication.getContext(), place3Id);
|
||||||
list.add(mInterstitialAd1);
|
list.add(mInterstitialAd1);
|
||||||
list.add(mInterstitialAd2);
|
list.add(mInterstitialAd2);
|
||||||
list.add(mInterstitialAd3);
|
list.add(mInterstitialAd3);
|
||||||
@ -97,11 +97,11 @@ public class AdManager {
|
|||||||
Collections.shuffle(list);
|
Collections.shuffle(list);
|
||||||
for (ATInterstitial ad : list) {
|
for (ATInterstitial ad : list) {
|
||||||
if (ad.isAdReady()) {
|
if (ad.isAdReady()) {
|
||||||
Log.d(AppApplication.TAG, "-has Cache------------");
|
Log.d(MyApplication.TAG, "-has Cache------------");
|
||||||
return ad;
|
return ad;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Log.d(AppApplication.TAG, "-No Cache------------");
|
Log.d(MyApplication.TAG, "-No Cache------------");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,13 +111,13 @@ public class AdManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInterstitialAdLoaded() {
|
public void onInterstitialAdLoaded() {
|
||||||
Log.d(AppApplication.TAG, "LoadLoaded " + ad.mPlacementId);
|
Log.d(MyApplication.TAG, "LoadLoaded " + ad.mPlacementId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInterstitialAdLoadFail(AdError adError) {
|
public void onInterstitialAdLoadFail(AdError adError) {
|
||||||
listener.loadFail(ad.mPlacementId);
|
listener.loadFail(ad.mPlacementId);
|
||||||
Log.d(AppApplication.TAG, "LoadFail:--" + ad.mPlacementId + "--" + adError.getCode() + "---" + adError.getDesc());
|
Log.d(MyApplication.TAG, "LoadFail:--" + ad.mPlacementId + "--" + adError.getCode() + "---" + adError.getDesc());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -127,7 +127,7 @@ public class AdManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInterstitialAdShow(ATAdInfo atAdInfo) {
|
public void onInterstitialAdShow(ATAdInfo atAdInfo) {
|
||||||
Log.d(AppApplication.TAG, "AdShow " + atAdInfo.getShowId());
|
Log.d(MyApplication.TAG, "AdShow " + atAdInfo.getShowId());
|
||||||
listener.showSuccess();
|
listener.showSuccess();
|
||||||
ad.load();
|
ad.load();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
package com.key.vibekeyboard.Activity;
|
package com.key.vibekeyboard.ui.activity;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@ -6,32 +6,42 @@ import android.view.LayoutInflater;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.activity.EdgeToEdge;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
|
import androidx.core.graphics.Insets;
|
||||||
|
import androidx.core.view.ViewCompat;
|
||||||
|
import androidx.core.view.WindowInsetsCompat;
|
||||||
|
|
||||||
import com.google.android.material.tabs.TabLayout;
|
import com.google.android.material.tabs.TabLayout;
|
||||||
import com.google.android.material.tabs.TabLayoutMediator;
|
import com.google.android.material.tabs.TabLayoutMediator;
|
||||||
import com.key.vibekeyboard.Adapter.CategoryViewPager2Adapter;
|
import com.key.vibekeyboard.ui.adapter.CategoryViewPager2Adapter;
|
||||||
import com.key.vibekeyboard.R;
|
import com.key.vibekeyboard.R;
|
||||||
import com.key.vibekeyboard.Room.Category;
|
import com.key.vibekeyboard.data.bean.Category;
|
||||||
import com.key.vibekeyboard.Utils.Mytool;
|
import com.key.vibekeyboard.utils.JsonUtils;
|
||||||
import com.key.vibekeyboard.databinding.ActivityCategoryBinding;
|
import com.key.vibekeyboard.databinding.ActivityCategoryBinding;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class CategoryActivity extends AppCompatActivity {
|
public class CategoryActivity extends AppCompatActivity {
|
||||||
|
|
||||||
private final List<Category> categories = Mytool.parseJsonToList("keyboard.json");
|
private final List<Category> categories = JsonUtils.parseJson("keyboard.json");
|
||||||
private ActivityCategoryBinding binding;
|
private ActivityCategoryBinding binding;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
|
||||||
binding = ActivityCategoryBinding.inflate(getLayoutInflater());
|
binding = ActivityCategoryBinding.inflate(getLayoutInflater());
|
||||||
setContentView(binding.getRoot());
|
setContentView(binding.getRoot());
|
||||||
|
|
||||||
|
EdgeToEdge.enable(this);
|
||||||
|
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
||||||
|
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||||
|
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||||
|
return insets;
|
||||||
|
});
|
||||||
|
|
||||||
initData();
|
initData();
|
||||||
initEvent();
|
initEvent();
|
||||||
|
|
||||||
@ -43,29 +53,24 @@ public class CategoryActivity extends AppCompatActivity {
|
|||||||
CategoryViewPager2Adapter adapter = new CategoryViewPager2Adapter(this, categories);
|
CategoryViewPager2Adapter adapter = new CategoryViewPager2Adapter(this, categories);
|
||||||
binding.categoryViewPager.setAdapter(adapter);
|
binding.categoryViewPager.setAdapter(adapter);
|
||||||
|
|
||||||
|
|
||||||
new TabLayoutMediator(binding.categoryTab, binding.categoryViewPager, (tab, position) -> {
|
new TabLayoutMediator(binding.categoryTab, binding.categoryViewPager, (tab, position) -> {
|
||||||
|
|
||||||
// 设置自定义视图
|
|
||||||
View customView = LayoutInflater.from(this).inflate(R.layout.category_tab_custom, null);
|
View customView = LayoutInflater.from(this).inflate(R.layout.category_tab_custom, null);
|
||||||
tab.setCustomView(customView);
|
tab.setCustomView(customView);
|
||||||
|
|
||||||
// 设置标题文字
|
|
||||||
TextView textView = customView.findViewById(R.id.category_tab_custom_title);
|
TextView textView = customView.findViewById(R.id.category_tab_custom_title);
|
||||||
Category category = categories.get(position);
|
Category category = categories.get(position);
|
||||||
String dir = category.getClassName();
|
String dir = category.getClassName();
|
||||||
String text = dir.substring(dir.lastIndexOf("_") + 1);
|
String text = dir.substring(dir.lastIndexOf("_") + 1);
|
||||||
text = text.substring(0, 1).toUpperCase() + text.substring(1); // 首字母大写
|
text = text.substring(0, 1).toUpperCase() + text.substring(1);
|
||||||
textView.setText(text);
|
textView.setText(text);
|
||||||
|
|
||||||
|
|
||||||
}).attach();
|
}).attach();
|
||||||
|
|
||||||
// 添加 TabLayout 选中状态监听器
|
|
||||||
binding.categoryTab.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
|
binding.categoryTab.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onTabSelected(TabLayout.Tab tab) {
|
public void onTabSelected(TabLayout.Tab tab) {
|
||||||
// 当 Tab 选中时,将文字设置为红色
|
|
||||||
View customView = tab.getCustomView();
|
View customView = tab.getCustomView();
|
||||||
if (customView != null) {
|
if (customView != null) {
|
||||||
TextView textView = customView.findViewById(R.id.category_tab_custom_title);
|
TextView textView = customView.findViewById(R.id.category_tab_custom_title);
|
||||||
@ -75,7 +80,6 @@ public class CategoryActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTabUnselected(TabLayout.Tab tab) {
|
public void onTabUnselected(TabLayout.Tab tab) {
|
||||||
// 当 Tab 取消选中时,恢复默认颜色
|
|
||||||
View customView = tab.getCustomView();
|
View customView = tab.getCustomView();
|
||||||
if (customView != null) {
|
if (customView != null) {
|
||||||
TextView textView = customView.findViewById(R.id.category_tab_custom_title);
|
TextView textView = customView.findViewById(R.id.category_tab_custom_title);
|
||||||
@ -85,14 +89,12 @@ public class CategoryActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTabReselected(TabLayout.Tab tab) {
|
public void onTabReselected(TabLayout.Tab tab) {
|
||||||
// 可选择性处理重复选中的情况
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 设置第一个 Tab 默认选中并改变颜色
|
|
||||||
TabLayout.Tab firstTab = binding.categoryTab.getTabAt(0);
|
TabLayout.Tab firstTab = binding.categoryTab.getTabAt(0);
|
||||||
if (firstTab != null) {
|
if (firstTab != null) {
|
||||||
firstTab.select(); // 手动选中第一个 Tab
|
firstTab.select();
|
||||||
View customView = firstTab.getCustomView();
|
View customView = firstTab.getCustomView();
|
||||||
if (customView != null) {
|
if (customView != null) {
|
||||||
TextView textView = customView.findViewById(R.id.category_tab_custom_title);
|
TextView textView = customView.findViewById(R.id.category_tab_custom_title);
|
||||||
@ -118,7 +120,6 @@ public class CategoryActivity extends AppCompatActivity {
|
|||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.key.vibekeyboard.Activity;
|
package com.key.vibekeyboard.ui.activity;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
@ -8,25 +8,30 @@ import android.view.View;
|
|||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.activity.EdgeToEdge;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.core.graphics.Insets;
|
||||||
|
import androidx.core.view.ViewCompat;
|
||||||
|
import androidx.core.view.WindowInsetsCompat;
|
||||||
import androidx.recyclerview.widget.GridLayoutManager;
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
import com.bumptech.glide.Glide;
|
||||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
||||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||||
import com.bumptech.glide.request.RequestOptions;
|
import com.bumptech.glide.request.RequestOptions;
|
||||||
import com.key.vibekeyboard.Adapter.DownlaodRecyclerViewAdapter;
|
import com.key.vibekeyboard.data.database.AppDatabase;
|
||||||
import com.key.vibekeyboard.Dialog.PermissionRequestDialog;
|
import com.key.vibekeyboard.ui.adapter.WallpaperAdapter;
|
||||||
|
import com.key.vibekeyboard.ui.dialog.PermissionRequestDialog;
|
||||||
import com.key.vibekeyboard.R;
|
import com.key.vibekeyboard.R;
|
||||||
import com.key.vibekeyboard.Room.MyDatabase;
|
import com.key.vibekeyboard.data.database.entity.WallpaperInfo;
|
||||||
import com.key.vibekeyboard.Room.WallpaperInfo;
|
import com.key.vibekeyboard.utils.DownloadUtils;
|
||||||
import com.key.vibekeyboard.Utils.ItemDecoration;
|
import com.key.vibekeyboard.utils.InputMethodUtils;
|
||||||
import com.key.vibekeyboard.Utils.Mytool;
|
import com.key.vibekeyboard.utils.ItemDecoration;
|
||||||
import com.key.vibekeyboard.Utils.StaticValue;
|
|
||||||
import com.key.vibekeyboard.databinding.ActivityDownloadBinding;
|
import com.key.vibekeyboard.databinding.ActivityDownloadBinding;
|
||||||
import com.key.vibekeyboard.topon.AdManager;
|
import com.key.vibekeyboard.topon.AdManager;
|
||||||
import com.key.vibekeyboard.topon.onActionListener;
|
import com.key.vibekeyboard.topon.onActionListener;
|
||||||
import com.vungle.ads.Ad;
|
import com.key.vibekeyboard.utils.TaskExecutorUtils;
|
||||||
|
import com.key.vibekeyboard.utils.unzipUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -36,10 +41,9 @@ public class DownloadActivity extends AppCompatActivity {
|
|||||||
private ActivityDownloadBinding binding;
|
private ActivityDownloadBinding binding;
|
||||||
private String preview;
|
private String preview;
|
||||||
private String url;
|
private String url;
|
||||||
private String unzipPath;
|
private WallpaperInfo userdata;
|
||||||
private WallpaperInfo otherdata;
|
private Boolean dislike = false;
|
||||||
private Boolean islike = false;
|
private Boolean tempIsLike = false;
|
||||||
private Boolean tempIsLike = false; // 用来暂存状态
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -49,6 +53,13 @@ public class DownloadActivity extends AppCompatActivity {
|
|||||||
binding = ActivityDownloadBinding.inflate(getLayoutInflater());
|
binding = ActivityDownloadBinding.inflate(getLayoutInflater());
|
||||||
setContentView(binding.getRoot());
|
setContentView(binding.getRoot());
|
||||||
|
|
||||||
|
EdgeToEdge.enable(this);
|
||||||
|
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
||||||
|
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||||
|
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||||
|
return insets;
|
||||||
|
});
|
||||||
|
|
||||||
AdManager.loadAllAd();
|
AdManager.loadAllAd();
|
||||||
|
|
||||||
AdManager.showTopOn(this, new onActionListener() {
|
AdManager.showTopOn(this, new onActionListener() {
|
||||||
@ -65,10 +76,10 @@ public class DownloadActivity extends AppCompatActivity {
|
|||||||
@Override
|
@Override
|
||||||
protected void onDestroy() {
|
protected void onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
if (otherdata != null && tempIsLike != null && tempIsLike != islike) {
|
if (userdata != null && tempIsLike != null && tempIsLike != dislike) {
|
||||||
otherdata.setIslike(tempIsLike);
|
userdata.setIslike(tempIsLike);
|
||||||
Mytool.runIO(() -> {
|
TaskExecutorUtils.executeIO(() -> {
|
||||||
MyDatabase.getInstance().wallpaperInfoDao().update(otherdata);
|
AppDatabase.getInstance().wallpaperInfoDao().update(userdata);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
binding = null;
|
binding = null;
|
||||||
@ -86,37 +97,27 @@ public class DownloadActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
preview = wallpaperInfo.getPreview();
|
preview = wallpaperInfo.getPreview();
|
||||||
String name = wallpaperInfo.getTitle();
|
|
||||||
url = wallpaperInfo.getZipUrl();
|
url = wallpaperInfo.getZipUrl();
|
||||||
|
|
||||||
Log.d("DownloadActivity", "wallpaperInfo: " + wallpaperInfo);
|
Log.d("DownloadActivity", "wallpaperInfo: " + wallpaperInfo);
|
||||||
|
|
||||||
binding.downloadTitle.setText(wallpaperInfo.title);
|
binding.downloadTitle.setText(wallpaperInfo.title);
|
||||||
|
|
||||||
DownlaodRecyclerViewAdapter adapter = new DownlaodRecyclerViewAdapter(this, wallpaperInfo, list);
|
WallpaperAdapter adapter = new WallpaperAdapter(this, list);
|
||||||
binding.downloadRecycler.setAdapter(adapter);
|
binding.downloadRecycler.setAdapter(adapter);
|
||||||
binding.downloadRecycler.setLayoutManager(new GridLayoutManager(this, 2));
|
binding.downloadRecycler.setLayoutManager(new GridLayoutManager(this, 2));
|
||||||
binding.downloadRecycler.addItemDecoration(new ItemDecoration(16, 19, 10));
|
binding.downloadRecycler.addItemDecoration(new ItemDecoration(16, 19, 10));
|
||||||
|
|
||||||
Mytool.runIO(() -> {
|
TaskExecutorUtils.executeIO(() -> {
|
||||||
List<WallpaperInfo> existingData = MyDatabase.getInstance().wallpaperInfoDao().checklikelist(preview);
|
List<WallpaperInfo> existingData = AppDatabase.getInstance().wallpaperInfoDao().checklikelist(preview);
|
||||||
|
|
||||||
if (!existingData.isEmpty()) {
|
if (!existingData.isEmpty()) {
|
||||||
otherdata = existingData.get(0);
|
userdata = existingData.get(0);
|
||||||
islike = otherdata.getIslike();
|
dislike = userdata.getIslike();
|
||||||
tempIsLike = islike; // Store the initial islike value
|
tempIsLike = dislike;
|
||||||
|
|
||||||
String path = StaticValue.PATH;
|
|
||||||
|
|
||||||
if (path.equals(otherdata.getPath())) {
|
|
||||||
runOnUiThread(() -> {
|
|
||||||
// Update UI if needed
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
runOnUiThread(() -> {
|
runOnUiThread(() -> {
|
||||||
// Update the favorite icon based on the islike value
|
if (dislike) {
|
||||||
if (islike) {
|
|
||||||
binding.downloadFavorite.setImageResource(android.R.drawable.btn_star_big_on);
|
binding.downloadFavorite.setImageResource(android.R.drawable.btn_star_big_on);
|
||||||
} else {
|
} else {
|
||||||
binding.downloadFavorite.setImageResource(android.R.drawable.btn_star_big_off);
|
binding.downloadFavorite.setImageResource(android.R.drawable.btn_star_big_off);
|
||||||
@ -126,12 +127,11 @@ public class DownloadActivity extends AppCompatActivity {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (wallpaperInfo.getPreview() != null) {
|
if (wallpaperInfo.getPreview() != null) {
|
||||||
// 应用圆角变换
|
|
||||||
RequestOptions options = new RequestOptions()
|
RequestOptions options = new RequestOptions()
|
||||||
.placeholder(R.mipmap.splash)
|
.placeholder(R.mipmap.splash)
|
||||||
.error(R.mipmap.splash)
|
.error(R.mipmap.splash)
|
||||||
.transform(new CenterCrop())
|
.transform(new CenterCrop())
|
||||||
.transform(new RoundedCorners(16)); // 设置圆角度数
|
.transform(new RoundedCorners(16));
|
||||||
|
|
||||||
Glide.with(this)
|
Glide.with(this)
|
||||||
.load(wallpaperInfo.getPreview())
|
.load(wallpaperInfo.getPreview())
|
||||||
@ -141,7 +141,6 @@ public class DownloadActivity extends AppCompatActivity {
|
|||||||
binding.downloadImage.setImageResource(R.mipmap.splash);
|
binding.downloadImage.setImageResource(R.mipmap.splash);
|
||||||
}
|
}
|
||||||
|
|
||||||
unzipPath = getCacheDir() + "/" + name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -176,10 +175,8 @@ public class DownloadActivity extends AppCompatActivity {
|
|||||||
binding.downloadAll.setOnClickListener(new View.OnClickListener() {
|
binding.downloadAll.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
|
|
||||||
Intent intent = new Intent(DownloadActivity.this, CategoryActivity.class);
|
Intent intent = new Intent(DownloadActivity.this, CategoryActivity.class);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -189,34 +186,29 @@ public class DownloadActivity extends AppCompatActivity {
|
|||||||
ProgressBar progressBar = findViewById(R.id.progressBar);
|
ProgressBar progressBar = findViewById(R.id.progressBar);
|
||||||
View view = findViewById(R.id.view);
|
View view = findViewById(R.id.view);
|
||||||
|
|
||||||
// 显示进度条
|
|
||||||
progressBar.setVisibility(View.VISIBLE);
|
progressBar.setVisibility(View.VISIBLE);
|
||||||
view.setVisibility(View.VISIBLE);
|
view.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
if (!Mytool.isStep1() || !Mytool.isStep2()) {
|
if (!InputMethodUtils.isInputMethodEnabled() || !InputMethodUtils.isCurrentInputMethodActive()) {
|
||||||
PermissionRequestDialog dialog = new PermissionRequestDialog();
|
PermissionRequestDialog dialog = new PermissionRequestDialog();
|
||||||
dialog.show(getSupportFragmentManager(), "PermissionRequestDialog");
|
dialog.show(getSupportFragmentManager(), "PermissionRequestDialog");
|
||||||
// 操作结束后隐藏进度条
|
|
||||||
progressBar.setVisibility(View.GONE);
|
progressBar.setVisibility(View.GONE);
|
||||||
view.setVisibility(View.GONE);
|
view.setVisibility(View.GONE);
|
||||||
} else {
|
} else {
|
||||||
Mytool.donwnZip(this, url, (successful, resource) -> {
|
DownloadUtils.downloadFile(this, url, (successful, resource) -> {
|
||||||
if (successful) {
|
if (successful) {
|
||||||
Mytool.unZip(this, unzipPath, resource, (successful1, resDirPath) -> {
|
unzipUtils.unzipFile(this, resource, (successful1, resDirPath) -> {
|
||||||
if (successful1) {
|
if (successful1) {
|
||||||
// 将路径存储到 SharedPreferences
|
SharedPreferences sharedPreferences = getSharedPreferences("keyboard_info", MODE_PRIVATE);
|
||||||
SharedPreferences sharedPreferences = getSharedPreferences("keyboard_prefs", MODE_PRIVATE);
|
|
||||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||||
editor.putString("wallpaper_path", resDirPath);
|
editor.putString("wallpaper_path", resDirPath);
|
||||||
editor.apply(); // 使用 apply() 异步保存
|
editor.apply();
|
||||||
|
|
||||||
StaticValue.PATH = resDirPath;
|
if (userdata != null) {
|
||||||
|
userdata.setPath(resDirPath);
|
||||||
|
userdata.setDownloaded(true);
|
||||||
|
|
||||||
if (otherdata != null) {
|
TaskExecutorUtils.executeIO(() -> AppDatabase.getInstance().wallpaperInfoDao().update(userdata));
|
||||||
otherdata.setPath(resDirPath);
|
|
||||||
otherdata.setDownloaded(true);
|
|
||||||
|
|
||||||
Mytool.runIO(() -> MyDatabase.getInstance().wallpaperInfoDao().update(otherdata));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
runOnUiThread(() -> {
|
runOnUiThread(() -> {
|
||||||
@ -224,7 +216,6 @@ public class DownloadActivity extends AppCompatActivity {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解压完成,隐藏进度条
|
|
||||||
runOnUiThread(() -> {
|
runOnUiThread(() -> {
|
||||||
progressBar.setVisibility(View.GONE);
|
progressBar.setVisibility(View.GONE);
|
||||||
view.setVisibility(View.GONE);
|
view.setVisibility(View.GONE);
|
||||||
@ -233,7 +224,6 @@ public class DownloadActivity extends AppCompatActivity {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// 下载失败,隐藏进度条
|
|
||||||
runOnUiThread(() -> {
|
runOnUiThread(() -> {
|
||||||
progressBar.setVisibility(View.GONE);
|
progressBar.setVisibility(View.GONE);
|
||||||
view.setVisibility(View.GONE);
|
view.setVisibility(View.GONE);
|
||||||
@ -246,7 +236,7 @@ public class DownloadActivity extends AppCompatActivity {
|
|||||||
@Override
|
@Override
|
||||||
public void onBackPressed() {
|
public void onBackPressed() {
|
||||||
super.onBackPressed();
|
super.onBackPressed();
|
||||||
AdManager.showTopOn(this,new onActionListener() {
|
AdManager.showTopOn(this, new onActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onAction() {
|
public void onAction() {
|
||||||
finish();
|
finish();
|
||||||
@ -0,0 +1,142 @@
|
|||||||
|
package com.key.vibekeyboard.ui.activity;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
|
||||||
|
import androidx.activity.EdgeToEdge;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.core.graphics.Insets;
|
||||||
|
import androidx.core.view.ViewCompat;
|
||||||
|
import androidx.core.view.WindowInsetsCompat;
|
||||||
|
|
||||||
|
import com.google.android.material.tabs.TabLayout;
|
||||||
|
import com.google.android.material.tabs.TabLayoutMediator;
|
||||||
|
import com.key.vibekeyboard.ui.adapter.MainViewpager2Adapter;
|
||||||
|
import com.key.vibekeyboard.MyApplication;
|
||||||
|
import com.key.vibekeyboard.ui.dialog.PermissionRequestDialog;
|
||||||
|
import com.key.vibekeyboard.ui.dialog.RecommendedDialog;
|
||||||
|
import com.key.vibekeyboard.R;
|
||||||
|
import com.key.vibekeyboard.data.bean.Category;
|
||||||
|
import com.key.vibekeyboard.data.database.entity.WallpaperInfo;
|
||||||
|
import com.key.vibekeyboard.databinding.ActivityMainBinding;
|
||||||
|
import com.key.vibekeyboard.databinding.MainTabCustomBinding;
|
||||||
|
import com.key.vibekeyboard.utils.InputMethodUtils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class MainActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
private ActivityMainBinding binding;
|
||||||
|
private List<WallpaperInfo> list = new ArrayList<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
binding = ActivityMainBinding.inflate(getLayoutInflater());
|
||||||
|
setContentView(binding.getRoot());
|
||||||
|
|
||||||
|
EdgeToEdge.enable(this);
|
||||||
|
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
||||||
|
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||||
|
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||||
|
return insets;
|
||||||
|
});
|
||||||
|
|
||||||
|
initViewPager();
|
||||||
|
|
||||||
|
loadRandomCategory();
|
||||||
|
|
||||||
|
checkPermissionsAndShowDialog();
|
||||||
|
|
||||||
|
binding.mainViewpager.setUserInputEnabled(false);
|
||||||
|
|
||||||
|
initTabLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initViewPager() {
|
||||||
|
MainViewpager2Adapter adapter = new MainViewpager2Adapter(this);
|
||||||
|
binding.mainViewpager.setAdapter(adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadRandomCategory() {
|
||||||
|
List<Category> categories = MyApplication.getCategories();
|
||||||
|
Random random = new Random();
|
||||||
|
int randomIndex = random.nextInt(categories.size());
|
||||||
|
list = categories.get(randomIndex).getList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkPermissionsAndShowDialog() {
|
||||||
|
if (InputMethodUtils.isInputMethodEnabled() && InputMethodUtils.isCurrentInputMethodActive()) {
|
||||||
|
showRecommendedDialog();
|
||||||
|
} else {
|
||||||
|
showPermissionDialog();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showPermissionDialog() {
|
||||||
|
PermissionRequestDialog dialog = new PermissionRequestDialog();
|
||||||
|
dialog.show(getSupportFragmentManager(), "PermissionRequestDialog");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showRecommendedDialog() {
|
||||||
|
RecommendedDialog dialog = new RecommendedDialog();
|
||||||
|
if (list != null) {
|
||||||
|
dialog.setList(list);
|
||||||
|
}
|
||||||
|
dialog.show(getSupportFragmentManager(), "RecommendedDialog");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initTabLayout() {
|
||||||
|
new TabLayoutMediator(binding.mainTablayout, binding.mainViewpager, (tab, position) -> {
|
||||||
|
MainTabCustomBinding tabBinding = MainTabCustomBinding.inflate(LayoutInflater.from(this));
|
||||||
|
tab.setCustomView(tabBinding.getRoot());
|
||||||
|
|
||||||
|
setTabIcon(tabBinding, position);
|
||||||
|
}).attach();
|
||||||
|
|
||||||
|
binding.mainTablayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
|
||||||
|
@Override
|
||||||
|
public void onTabSelected(TabLayout.Tab tab) {
|
||||||
|
MainTabCustomBinding tabBinding = MainTabCustomBinding.bind(Objects.requireNonNull(tab.getCustomView()));
|
||||||
|
int position = tab.getPosition();
|
||||||
|
setTabIcon(tabBinding, position, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTabUnselected(TabLayout.Tab tab) {
|
||||||
|
MainTabCustomBinding tabBinding = MainTabCustomBinding.bind(Objects.requireNonNull(tab.getCustomView()));
|
||||||
|
int position = tab.getPosition();
|
||||||
|
setTabIcon(tabBinding, position, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTabReselected(TabLayout.Tab tab) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setTabIcon(MainTabCustomBinding tabBinding, int position) {
|
||||||
|
setTabIcon(tabBinding, position, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setTabIcon(MainTabCustomBinding tabBinding, int position, boolean isSelected) {
|
||||||
|
if (position == 0) {
|
||||||
|
tabBinding.iconCustom.setImageResource(isSelected ? R.drawable.home_select : R.drawable.home);
|
||||||
|
} else if (position == 1) {
|
||||||
|
tabBinding.iconCustom.setImageResource(isSelected ? R.drawable.collection_select : R.drawable.collection);
|
||||||
|
} else {
|
||||||
|
tabBinding.iconCustom.setImageResource(isSelected ? R.drawable.setting_select : R.drawable.setting);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
binding = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -1,17 +1,22 @@
|
|||||||
package com.key.vibekeyboard.Activity;
|
package com.key.vibekeyboard.ui.activity;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
|
|
||||||
|
import androidx.activity.EdgeToEdge;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.core.graphics.Insets;
|
||||||
|
import androidx.core.view.ViewCompat;
|
||||||
|
import androidx.core.view.WindowInsetsCompat;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
|
||||||
import com.key.vibekeyboard.Adapter.SearchRecyclerViewAdapter;
|
import com.key.vibekeyboard.R;
|
||||||
import com.key.vibekeyboard.Room.Category;
|
import com.key.vibekeyboard.data.bean.Category;
|
||||||
import com.key.vibekeyboard.Room.WallpaperInfo;
|
import com.key.vibekeyboard.data.database.entity.WallpaperInfo;
|
||||||
import com.key.vibekeyboard.Utils.ItemDecoration;
|
import com.key.vibekeyboard.ui.adapter.WallpaperAdapter;
|
||||||
import com.key.vibekeyboard.Utils.Mytool;
|
import com.key.vibekeyboard.utils.ItemDecoration;
|
||||||
|
import com.key.vibekeyboard.utils.JsonUtils;
|
||||||
import com.key.vibekeyboard.databinding.ActivitySearchBinding;
|
import com.key.vibekeyboard.databinding.ActivitySearchBinding;
|
||||||
import com.key.vibekeyboard.topon.AdManager;
|
import com.key.vibekeyboard.topon.AdManager;
|
||||||
import com.key.vibekeyboard.topon.onActionListener;
|
import com.key.vibekeyboard.topon.onActionListener;
|
||||||
@ -22,9 +27,9 @@ import java.util.List;
|
|||||||
public class SearchActivity extends AppCompatActivity {
|
public class SearchActivity extends AppCompatActivity {
|
||||||
|
|
||||||
private ActivitySearchBinding binding;
|
private ActivitySearchBinding binding;
|
||||||
private List<Category> categories = Mytool.parseJsonToList("keyboard.json");
|
private final List<Category> categories = JsonUtils.parseJson("keyboard.json");
|
||||||
private List<WallpaperInfo> filteredList = new ArrayList<>();
|
private final List<WallpaperInfo> filteredList = new ArrayList<>();
|
||||||
private SearchRecyclerViewAdapter adapter; // 适配器类
|
private WallpaperAdapter adapter;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
@ -33,8 +38,20 @@ public class SearchActivity extends AppCompatActivity {
|
|||||||
binding = ActivitySearchBinding.inflate(getLayoutInflater());
|
binding = ActivitySearchBinding.inflate(getLayoutInflater());
|
||||||
setContentView(binding.getRoot());
|
setContentView(binding.getRoot());
|
||||||
|
|
||||||
|
EdgeToEdge.enable(this);
|
||||||
|
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
||||||
|
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||||
|
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||||
|
return insets;
|
||||||
|
});
|
||||||
|
|
||||||
AdManager.loadAllAd();
|
AdManager.loadAllAd();
|
||||||
|
|
||||||
|
initData();
|
||||||
|
initEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initData(){
|
||||||
AdManager.showTopOn(this, new onActionListener() {
|
AdManager.showTopOn(this, new onActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onAction() {
|
public void onAction() {
|
||||||
@ -42,18 +59,17 @@ public class SearchActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 设置 RecyclerView
|
|
||||||
binding.recyclerView.setLayoutManager(new LinearLayoutManager(this));
|
binding.recyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||||
adapter = new SearchRecyclerViewAdapter(filteredList, this);
|
adapter = new WallpaperAdapter(this, filteredList);
|
||||||
// 为 RecyclerView 添加自定义的间距装饰。
|
|
||||||
ItemDecoration itemDecoration = new ItemDecoration(12, 10, 9);
|
ItemDecoration itemDecoration = new ItemDecoration(12, 10, 9);
|
||||||
binding.recyclerView.addItemDecoration(itemDecoration);
|
binding.recyclerView.addItemDecoration(itemDecoration);
|
||||||
|
|
||||||
binding.recyclerView.setAdapter(adapter);
|
binding.recyclerView.setAdapter(adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initEvent(){
|
||||||
binding.back.setOnClickListener(v -> finish());
|
binding.back.setOnClickListener(v -> finish());
|
||||||
|
|
||||||
// 监听输入框内容变化
|
|
||||||
binding.searchEditText.addTextChangedListener(new TextWatcher() {
|
binding.searchEditText.addTextChangedListener(new TextWatcher() {
|
||||||
@Override
|
@Override
|
||||||
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||||
@ -70,7 +86,6 @@ public class SearchActivity extends AppCompatActivity {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 过滤逻辑,根据输入内容过滤数据
|
|
||||||
private void filter(String text) {
|
private void filter(String text) {
|
||||||
filteredList.clear(); // 清空之前的结果
|
filteredList.clear(); // 清空之前的结果
|
||||||
|
|
||||||
@ -82,13 +97,13 @@ public class SearchActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
adapter.notifyDataSetChanged(); // 通知适配器更新数据
|
adapter.notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDestroy() {
|
protected void onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
binding = null; // 释放 ViewBinding 的引用
|
binding = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1,11 +1,15 @@
|
|||||||
package com.key.vibekeyboard.Activity;
|
package com.key.vibekeyboard.ui.activity;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.CountDownTimer;
|
import android.os.CountDownTimer;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
|
|
||||||
|
import androidx.activity.EdgeToEdge;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.core.graphics.Insets;
|
||||||
|
import androidx.core.view.ViewCompat;
|
||||||
|
import androidx.core.view.WindowInsetsCompat;
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
import com.bumptech.glide.Glide;
|
||||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||||
@ -27,6 +31,13 @@ public class SplashActivity extends AppCompatActivity {
|
|||||||
binding = ActivitySplashBinding.inflate(getLayoutInflater());
|
binding = ActivitySplashBinding.inflate(getLayoutInflater());
|
||||||
setContentView(binding.getRoot());
|
setContentView(binding.getRoot());
|
||||||
|
|
||||||
|
EdgeToEdge.enable(this);
|
||||||
|
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
||||||
|
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||||
|
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||||
|
return insets;
|
||||||
|
});
|
||||||
|
|
||||||
AdManager.loadAllAd();
|
AdManager.loadAllAd();
|
||||||
|
|
||||||
ProgressBar progressBar = binding.progressBar;
|
ProgressBar progressBar = binding.progressBar;
|
||||||
@ -40,7 +51,7 @@ public class SplashActivity extends AppCompatActivity {
|
|||||||
int percentage = (int) (100 - (float) millisUntilFinished / TOTAL_TIME * 100);
|
int percentage = (int) (100 - (float) millisUntilFinished / TOTAL_TIME * 100);
|
||||||
progressBar.setProgress(percentage);
|
progressBar.setProgress(percentage);
|
||||||
},
|
},
|
||||||
this::startMain // 倒计时结束或广告展示结束时,跳转主界面
|
this::startMain
|
||||||
);
|
);
|
||||||
|
|
||||||
countDownTimer.start();
|
countDownTimer.start();
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.key.vibekeyboard.Activity;
|
package com.key.vibekeyboard.ui.activity;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
@ -9,18 +9,31 @@ import androidx.core.view.ViewCompat;
|
|||||||
import androidx.core.view.WindowInsetsCompat;
|
import androidx.core.view.WindowInsetsCompat;
|
||||||
|
|
||||||
import com.key.vibekeyboard.R;
|
import com.key.vibekeyboard.R;
|
||||||
|
import com.key.vibekeyboard.databinding.ActivityWriteBinding;
|
||||||
|
|
||||||
public class PermissionActivity extends AppCompatActivity {
|
public class WriteActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
private ActivityWriteBinding binding;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
binding = ActivityWriteBinding.inflate(getLayoutInflater());
|
||||||
|
setContentView(binding.getRoot());
|
||||||
|
|
||||||
EdgeToEdge.enable(this);
|
EdgeToEdge.enable(this);
|
||||||
setContentView(R.layout.activity_permission);
|
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
||||||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||||
return insets;
|
return insets;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
binding.back.setOnClickListener(v -> finish());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
binding = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,12 +1,12 @@
|
|||||||
package com.key.vibekeyboard.Adapter;
|
package com.key.vibekeyboard.ui.adapter;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentActivity;
|
import androidx.fragment.app.FragmentActivity;
|
||||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||||
|
|
||||||
import com.key.vibekeyboard.Fragment.CategoryFragment;
|
import com.key.vibekeyboard.ui.fragment.CategoryFragment;
|
||||||
import com.key.vibekeyboard.Room.Category;
|
import com.key.vibekeyboard.data.bean.Category;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.key.vibekeyboard.Adapter;
|
package com.key.vibekeyboard.ui.adapter;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@ -14,21 +14,21 @@ import com.bumptech.glide.Glide;
|
|||||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
||||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||||
import com.bumptech.glide.request.RequestOptions;
|
import com.bumptech.glide.request.RequestOptions;
|
||||||
import com.key.vibekeyboard.Activity.DownloadActivity;
|
import com.key.vibekeyboard.ui.activity.DownloadActivity;
|
||||||
import com.key.vibekeyboard.R;
|
import com.key.vibekeyboard.R;
|
||||||
import com.key.vibekeyboard.Room.Category;
|
import com.key.vibekeyboard.data.bean.Category;
|
||||||
import com.key.vibekeyboard.Room.WallpaperInfo;
|
import com.key.vibekeyboard.data.database.entity.WallpaperInfo;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
public class HomeViewPager2Adapter extends RecyclerView.Adapter<HomeViewPager2Adapter.HomeViewPager2ViewHolder> {
|
public class HomeSliderAdapter extends RecyclerView.Adapter<HomeSliderAdapter.HomeViewPager2ViewHolder> {
|
||||||
|
|
||||||
private List<Category> categories;
|
private final List<Category> categories;
|
||||||
private Context context;
|
private final Context context;
|
||||||
|
|
||||||
public HomeViewPager2Adapter(Context context, List<Category> categories) {
|
public HomeSliderAdapter(Context context, List<Category> categories) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.categories = categories;
|
this.categories = categories;
|
||||||
}
|
}
|
||||||
@ -43,10 +43,9 @@ public class HomeViewPager2Adapter extends RecyclerView.Adapter<HomeViewPager2Ad
|
|||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull HomeViewPager2ViewHolder holder, int position) {
|
public void onBindViewHolder(@NonNull HomeViewPager2ViewHolder holder, int position) {
|
||||||
|
|
||||||
int actualPosition = position % categories.size(); // 确保最后一张的视图是第一张
|
int actualPosition = position % categories.size();
|
||||||
Category category = categories.get(actualPosition);
|
Category category = categories.get(actualPosition);
|
||||||
List<WallpaperInfo> list = category.getList();
|
List<WallpaperInfo> list = category.getList();
|
||||||
WallpaperInfo categoryWallpaperInfo = category.getList().get(position);
|
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
int randomIndex = random.nextInt(20);
|
int randomIndex = random.nextInt(20);
|
||||||
WallpaperInfo wallpaperInfo = category.getList().get(randomIndex);
|
WallpaperInfo wallpaperInfo = category.getList().get(randomIndex);
|
||||||
@ -63,12 +62,11 @@ public class HomeViewPager2Adapter extends RecyclerView.Adapter<HomeViewPager2Ad
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 应用圆角变换
|
|
||||||
RequestOptions options = new RequestOptions()
|
RequestOptions options = new RequestOptions()
|
||||||
.placeholder(R.mipmap.splash)
|
.placeholder(R.mipmap.splash)
|
||||||
.error(R.mipmap.splash)
|
.error(R.mipmap.splash)
|
||||||
.transform(new CenterCrop())
|
.transform(new CenterCrop())
|
||||||
.transform(new RoundedCorners(16)); // 设置圆角度数
|
.transform(new RoundedCorners(16));
|
||||||
|
|
||||||
Glide.with(context)
|
Glide.with(context)
|
||||||
.load(wallpaperInfo.getPreview())
|
.load(wallpaperInfo.getPreview())
|
||||||
@ -1,13 +1,13 @@
|
|||||||
package com.key.vibekeyboard.Adapter;
|
package com.key.vibekeyboard.ui.adapter;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentActivity;
|
import androidx.fragment.app.FragmentActivity;
|
||||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||||
|
|
||||||
import com.key.vibekeyboard.Fragment.FavoriteFragment;
|
import com.key.vibekeyboard.ui.fragment.FavoriteFragment;
|
||||||
import com.key.vibekeyboard.Fragment.HomeFragment;
|
import com.key.vibekeyboard.ui.fragment.HomeFragment;
|
||||||
import com.key.vibekeyboard.Fragment.SettingFragment;
|
import com.key.vibekeyboard.ui.fragment.SettingFragment;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -23,7 +23,6 @@ public class MainViewpager2Adapter extends FragmentStateAdapter {
|
|||||||
fragmentList.add(new HomeFragment());
|
fragmentList.add(new HomeFragment());
|
||||||
fragmentList.add(new FavoriteFragment());
|
fragmentList.add(new FavoriteFragment());
|
||||||
fragmentList.add(new SettingFragment());
|
fragmentList.add(new SettingFragment());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.key.vibekeyboard.Adapter;
|
package com.key.vibekeyboard.ui.adapter;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@ -9,25 +9,26 @@ import android.view.ViewGroup;
|
|||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.DiffUtil;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
import com.bumptech.glide.Glide;
|
||||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
||||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||||
import com.bumptech.glide.request.RequestOptions;
|
import com.bumptech.glide.request.RequestOptions;
|
||||||
import com.key.vibekeyboard.Activity.DownloadActivity;
|
import com.key.vibekeyboard.ui.activity.DownloadActivity;
|
||||||
import com.key.vibekeyboard.R;
|
import com.key.vibekeyboard.R;
|
||||||
import com.key.vibekeyboard.Room.WallpaperInfo;
|
import com.key.vibekeyboard.data.database.entity.WallpaperInfo;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class CategoryRecyclerViewAdapter extends RecyclerView.Adapter<CategoryRecyclerViewAdapter.CategoryRecyclerViewHolder> {
|
public class WallpaperAdapter extends RecyclerView.Adapter<WallpaperAdapter.CategoryRecyclerViewHolder> {
|
||||||
|
|
||||||
private Context context;
|
private final Context context;
|
||||||
private List<WallpaperInfo> list;
|
private final List<WallpaperInfo> list;
|
||||||
|
|
||||||
public CategoryRecyclerViewAdapter(Context context, List<WallpaperInfo> list) {
|
public WallpaperAdapter(Context context, List<WallpaperInfo> list) {
|
||||||
|
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.list = list;
|
this.list = list;
|
||||||
@ -53,8 +54,8 @@ public class CategoryRecyclerViewAdapter extends RecyclerView.Adapter<CategoryRe
|
|||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
Intent intent = new Intent(context, DownloadActivity.class);
|
Intent intent = new Intent(context, DownloadActivity.class);
|
||||||
intent.putExtra("wallpaperInfo", wallpaperInfo); // wallpaperInfo 已经实现了 Parcelable
|
intent.putExtra("wallpaperInfo", wallpaperInfo);
|
||||||
intent.putParcelableArrayListExtra("list", new ArrayList<>(limitedList)); // list 中的 WallpaperInfo 对象实现了 Parcelable
|
intent.putParcelableArrayListExtra("list", new ArrayList<>(limitedList));
|
||||||
context.startActivity(intent);
|
context.startActivity(intent);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -63,12 +64,11 @@ public class CategoryRecyclerViewAdapter extends RecyclerView.Adapter<CategoryRe
|
|||||||
Log.e("WallpaperInfo", "WallpaperInfo is null at position: " + position);
|
Log.e("WallpaperInfo", "WallpaperInfo is null at position: " + position);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 应用圆角变换
|
|
||||||
RequestOptions options = new RequestOptions()
|
RequestOptions options = new RequestOptions()
|
||||||
.placeholder(R.mipmap.splash)
|
.placeholder(R.mipmap.splash)
|
||||||
.error(R.mipmap.splash)
|
.error(R.mipmap.splash)
|
||||||
.transform(new CenterCrop())
|
.transform(new CenterCrop())
|
||||||
.transform(new RoundedCorners(16)); // 设置圆角度数
|
.transform(new RoundedCorners(16));
|
||||||
|
|
||||||
Glide.with(context)
|
Glide.with(context)
|
||||||
.load(wallpaperInfo.getPreview())
|
.load(wallpaperInfo.getPreview())
|
||||||
@ -83,11 +83,39 @@ public class CategoryRecyclerViewAdapter extends RecyclerView.Adapter<CategoryRe
|
|||||||
|
|
||||||
public static class CategoryRecyclerViewHolder extends RecyclerView.ViewHolder {
|
public static class CategoryRecyclerViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
private ImageView imageView;
|
private final ImageView imageView;
|
||||||
public CategoryRecyclerViewHolder(View view) {
|
public CategoryRecyclerViewHolder(View view) {
|
||||||
super(view);
|
super(view);
|
||||||
imageView = view.findViewById(R.id.home_recycler_image);
|
imageView = view.findViewById(R.id.home_recycler_image);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateList(List<WallpaperInfo> newList) {
|
||||||
|
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DiffUtil.Callback() {
|
||||||
|
@Override
|
||||||
|
public int getOldListSize() {
|
||||||
|
return list.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getNewListSize() {
|
||||||
|
return newList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
|
||||||
|
return list.get(oldItemPosition).getId() == newList.get(newItemPosition).getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
|
||||||
|
return list.get(oldItemPosition).equals(newList.get(newItemPosition));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
list.clear();
|
||||||
|
list.addAll(newList);
|
||||||
|
diffResult.dispatchUpdatesTo(this);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.key.vibekeyboard.Dialog;
|
package com.key.vibekeyboard.ui.dialog;
|
||||||
|
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@ -21,20 +21,21 @@ import androidx.fragment.app.DialogFragment;
|
|||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
import com.bumptech.glide.Glide;
|
||||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||||
import com.key.vibekeyboard.AppApplication;
|
import com.key.vibekeyboard.MyApplication;
|
||||||
import com.key.vibekeyboard.R;
|
import com.key.vibekeyboard.R;
|
||||||
import com.key.vibekeyboard.Utils.Mytool;
|
|
||||||
import com.key.vibekeyboard.databinding.DialogPermissionBinding;
|
import com.key.vibekeyboard.databinding.DialogPermissionBinding;
|
||||||
|
import com.key.vibekeyboard.utils.InputMethodUtils;
|
||||||
|
|
||||||
public class PermissionRequestDialog extends DialogFragment {
|
public class PermissionRequestDialog extends DialogFragment {
|
||||||
|
|
||||||
private DialogPermissionBinding binding;
|
private DialogPermissionBinding binding;
|
||||||
private InputMethodManager methodManager;
|
private InputMethodManager methodManager;
|
||||||
private ContentObserver inputMethodObserver; // 用于监听输入法变化
|
private ContentObserver inputMethodObserver;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
setCancelable(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -44,21 +45,8 @@ public class PermissionRequestDialog extends DialogFragment {
|
|||||||
return binding.getRoot();
|
return binding.getRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
Dialog dialog = getDialog();
|
|
||||||
setCancelable(true);
|
|
||||||
if (dialog != null && dialog.getWindow() != null) {
|
|
||||||
Window window = dialog.getWindow();
|
|
||||||
window.setLayout((int) (getResources().getDisplayMetrics().widthPixels * 0.9), WindowManager.LayoutParams.WRAP_CONTENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void init() {
|
public void init() {
|
||||||
methodManager = (InputMethodManager) AppApplication.instance.getSystemService(Context.INPUT_METHOD_SERVICE);
|
methodManager = (InputMethodManager) MyApplication.instance.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||||
|
|
||||||
Glide.with(requireContext())
|
Glide.with(requireContext())
|
||||||
.load(R.mipmap.ic_launcher_foreground)
|
.load(R.mipmap.ic_launcher_foreground)
|
||||||
@ -76,18 +64,20 @@ public class PermissionRequestDialog extends DialogFragment {
|
|||||||
|
|
||||||
binding.imageView.setOnClickListener(v -> dismiss());
|
binding.imageView.setOnClickListener(v -> dismiss());
|
||||||
|
|
||||||
// 注册ContentObserver监听输入法变化
|
|
||||||
inputMethodObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
|
inputMethodObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
|
||||||
@Override
|
@Override
|
||||||
public void onChange(boolean selfChange) {
|
public void onChange(boolean selfChange) {
|
||||||
super.onChange(selfChange);
|
super.onChange(selfChange);
|
||||||
if (Mytool.isStep1() && Mytool.isStep2()) {
|
if (InputMethodUtils.isInputMethodEnabled() && InputMethodUtils.isCurrentInputMethodActive()) {
|
||||||
dismiss(); // 条件满足,关闭对话框
|
dismiss();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// 注册观察输入法变化
|
@Override
|
||||||
|
public void onStart() {
|
||||||
|
super.onStart();
|
||||||
requireContext().getContentResolver().registerContentObserver(
|
requireContext().getContentResolver().registerContentObserver(
|
||||||
Settings.Secure.getUriFor(Settings.Secure.DEFAULT_INPUT_METHOD),
|
Settings.Secure.getUriFor(Settings.Secure.DEFAULT_INPUT_METHOD),
|
||||||
false,
|
false,
|
||||||
@ -95,17 +85,41 @@ public class PermissionRequestDialog extends DialogFragment {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update() {
|
@Override
|
||||||
if (Mytool.isStep1()) {
|
public void onStop() {
|
||||||
binding.firstIconTextLayout.setSelected(Mytool.isStep1());
|
super.onStop();
|
||||||
binding.firstIconTextLayout.setClickable(false);
|
if (inputMethodObserver != null) {
|
||||||
|
requireContext().getContentResolver().unregisterContentObserver(inputMethodObserver);
|
||||||
}
|
}
|
||||||
if (Mytool.isStep2()) {
|
}
|
||||||
binding.secondIconTextLayout.setSelected(Mytool.isStep2());
|
|
||||||
binding.secondIconTextLayout.setClickable(false);
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
Dialog dialog = getDialog();
|
||||||
|
if (dialog != null && dialog.getWindow() != null) {
|
||||||
|
Window window = dialog.getWindow();
|
||||||
|
window.setLayout((int) (getResources().getDisplayMetrics().widthPixels * 0.9), WindowManager.LayoutParams.WRAP_CONTENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Mytool.isStep1() && Mytool.isStep2()) {
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update() {
|
||||||
|
boolean isEnabled = InputMethodUtils.isInputMethodEnabled();
|
||||||
|
boolean isActive = InputMethodUtils.isCurrentInputMethodActive();
|
||||||
|
|
||||||
|
if (isEnabled) {
|
||||||
|
binding.firstIconTextLayout.setClickable(false);
|
||||||
|
binding.firstIconTextLayout.setSelected(true);
|
||||||
|
} else {
|
||||||
|
binding.firstIconTextLayout.setClickable(true);
|
||||||
|
binding.firstIconTextLayout.setSelected(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.secondIconTextLayout.setSelected(isActive);
|
||||||
|
|
||||||
|
if (isEnabled && isActive) {
|
||||||
dismiss();
|
dismiss();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,9 +127,7 @@ public class PermissionRequestDialog extends DialogFragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
if (inputMethodObserver != null) {
|
|
||||||
requireContext().getContentResolver().unregisterContentObserver(inputMethodObserver);
|
|
||||||
}
|
|
||||||
binding = null;
|
binding = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.key.vibekeyboard.Dialog;
|
package com.key.vibekeyboard.ui.dialog;
|
||||||
|
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@ -17,9 +17,9 @@ import com.bumptech.glide.Glide;
|
|||||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
||||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||||
import com.bumptech.glide.request.RequestOptions;
|
import com.bumptech.glide.request.RequestOptions;
|
||||||
import com.key.vibekeyboard.Activity.DownloadActivity;
|
import com.key.vibekeyboard.ui.activity.DownloadActivity;
|
||||||
import com.key.vibekeyboard.R;
|
import com.key.vibekeyboard.R;
|
||||||
import com.key.vibekeyboard.Room.WallpaperInfo;
|
import com.key.vibekeyboard.data.database.entity.WallpaperInfo;
|
||||||
import com.key.vibekeyboard.databinding.DialogRecommendedBinding;
|
import com.key.vibekeyboard.databinding.DialogRecommendedBinding;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -28,11 +28,10 @@ import java.util.Random;
|
|||||||
|
|
||||||
public class RecommendedDialog extends DialogFragment {
|
public class RecommendedDialog extends DialogFragment {
|
||||||
|
|
||||||
private DialogRecommendedBinding binding; // 绑定布局文件
|
private DialogRecommendedBinding binding;
|
||||||
private List<WallpaperInfo> list = new ArrayList<>(); // 存储壁纸信息的列表
|
private List<WallpaperInfo> list = new ArrayList<>();
|
||||||
private WallpaperInfo wallpaperInfo; // 当前选择的壁纸信息
|
private WallpaperInfo wallpaperInfo;
|
||||||
|
|
||||||
// 设置壁纸列表
|
|
||||||
public void setList(List<WallpaperInfo> list) {
|
public void setList(List<WallpaperInfo> list) {
|
||||||
this.list = list;
|
this.list = list;
|
||||||
}
|
}
|
||||||
@ -40,7 +39,6 @@ public class RecommendedDialog extends DialogFragment {
|
|||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
// 将布局文件与视图绑定
|
|
||||||
binding = DialogRecommendedBinding.inflate(inflater, container, false);
|
binding = DialogRecommendedBinding.inflate(inflater, container, false);
|
||||||
return binding.getRoot();
|
return binding.getRoot();
|
||||||
}
|
}
|
||||||
@ -49,59 +47,48 @@ public class RecommendedDialog extends DialogFragment {
|
|||||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
|
||||||
// 初始化对话框设置
|
|
||||||
Dialog dialog = getDialog();
|
Dialog dialog = getDialog();
|
||||||
setCancelable(true); // 设置为 true 对话框可点击外面取消
|
setCancelable(true);
|
||||||
if (dialog != null && dialog.getWindow() != null) {
|
if (dialog != null && dialog.getWindow() != null) {
|
||||||
Window window = dialog.getWindow();
|
Window window = dialog.getWindow();
|
||||||
window.setLayout((int) (getResources().getDisplayMetrics().widthPixels * 0.9), WindowManager.LayoutParams.WRAP_CONTENT);
|
window.setLayout((int) (getResources().getDisplayMetrics().widthPixels * 0.9), WindowManager.LayoutParams.WRAP_CONTENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 随机选择一个壁纸
|
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
int randomIndex = random.nextInt(list.size());
|
int randomIndex = random.nextInt(list.size());
|
||||||
wallpaperInfo = list.get(randomIndex); // 获取随机的壁纸信息
|
wallpaperInfo = list.get(randomIndex);
|
||||||
|
|
||||||
List<WallpaperInfo> limitedList = list.subList(0, Math.min(20, list.size()));
|
List<WallpaperInfo> limitedList = list.subList(0, Math.min(20, list.size()));
|
||||||
|
|
||||||
// 加载图像
|
|
||||||
loadImage();
|
loadImage();
|
||||||
|
|
||||||
// 点击图片后进入下载界面
|
|
||||||
binding.imageView.setOnClickListener(new View.OnClickListener() {
|
binding.imageView.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
Intent intent = new Intent(requireContext(), DownloadActivity.class);
|
Intent intent = new Intent(requireContext(), DownloadActivity.class);
|
||||||
// 将选中的壁纸信息传递给下一个 Activity
|
intent.putExtra("wallpaperInfo", wallpaperInfo);
|
||||||
intent.putExtra("wallpaperInfo", wallpaperInfo); // wallpaperInfo 已经实现了 Parcelable
|
intent.putParcelableArrayListExtra("list", new ArrayList<>(limitedList));
|
||||||
// 将壁纸列表传递给下一个 Activity
|
dismiss();
|
||||||
intent.putParcelableArrayListExtra("list", new ArrayList<>(limitedList)); // list 中的 WallpaperInfo 对象实现了 Parcelable
|
requireContext().startActivity(intent);
|
||||||
dismiss(); // 关闭当前对话框
|
|
||||||
requireContext().startActivity(intent); // 启动下载界面
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载图像的方法
|
|
||||||
private void loadImage() {
|
private void loadImage() {
|
||||||
// 判断壁纸的预览图 URL 是否有效
|
|
||||||
if (wallpaperInfo.getPreview() != null && !wallpaperInfo.getPreview().isEmpty()) {
|
if (wallpaperInfo.getPreview() != null && !wallpaperInfo.getPreview().isEmpty()) {
|
||||||
// 设置图像的加载选项
|
|
||||||
RequestOptions options = new RequestOptions()
|
RequestOptions options = new RequestOptions()
|
||||||
.placeholder(R.mipmap.splash)
|
.placeholder(R.mipmap.splash)
|
||||||
.error(R.mipmap.splash)
|
.error(R.mipmap.splash)
|
||||||
.transform(new CenterCrop()) // 中心裁剪,保证图片填满控件
|
.transform(new CenterCrop())
|
||||||
.transform(new RoundedCorners(16)); // 设置圆角,16px
|
.transform(new RoundedCorners(16));
|
||||||
|
|
||||||
// 使用 Glide 加载图像
|
|
||||||
Glide.with(requireContext())
|
Glide.with(requireContext())
|
||||||
.asDrawable() // 指定加载为 Drawable
|
.asDrawable()
|
||||||
.load(wallpaperInfo.getPreview()) // 设置要加载的图片 URL
|
.load(wallpaperInfo.getPreview())
|
||||||
.apply(options) // 应用上面定义的加载选项
|
.apply(options)
|
||||||
.into(binding.imageView); // 设置到 ImageView 上显示
|
.into(binding.imageView);
|
||||||
} else {
|
} else {
|
||||||
// 如果预览图 URL 为空,显示默认图像
|
binding.imageView.setImageResource(R.mipmap.splash);
|
||||||
binding.imageView.setImageResource(R.mipmap.splash); // 默认图像
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.key.vibekeyboard.Fragment;
|
package com.key.vibekeyboard.ui.fragment;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
@ -10,11 +10,11 @@ import androidx.annotation.Nullable;
|
|||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.recyclerview.widget.GridLayoutManager;
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
|
|
||||||
import com.key.vibekeyboard.Adapter.CategoryRecyclerViewAdapter;
|
import com.key.vibekeyboard.ui.adapter.WallpaperAdapter;
|
||||||
import com.key.vibekeyboard.Room.Category;
|
import com.key.vibekeyboard.data.bean.Category;
|
||||||
import com.key.vibekeyboard.Room.WallpaperInfo;
|
import com.key.vibekeyboard.data.database.entity.WallpaperInfo;
|
||||||
import com.key.vibekeyboard.Utils.ItemDecoration;
|
import com.key.vibekeyboard.utils.ItemDecoration;
|
||||||
import com.key.vibekeyboard.Utils.Mytool;
|
import com.key.vibekeyboard.utils.JsonUtils;
|
||||||
import com.key.vibekeyboard.databinding.FragmentCategoryBinding;
|
import com.key.vibekeyboard.databinding.FragmentCategoryBinding;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -25,26 +25,24 @@ public class CategoryFragment extends Fragment {
|
|||||||
|
|
||||||
private static final String ARG_CATEGORY = "category";
|
private static final String ARG_CATEGORY = "category";
|
||||||
private FragmentCategoryBinding binding;
|
private FragmentCategoryBinding binding;
|
||||||
private String category; // 用于存储从外部传入的类别名称。
|
private String category;
|
||||||
private final List<Category> categories = Mytool.parseJsonToList("keyboard.json");
|
private final List<Category> categories = JsonUtils.parseJson("keyboard.json");
|
||||||
|
|
||||||
public CategoryFragment() {
|
public CategoryFragment() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 工厂方法,用于创建 Fragment 的实例,并通过 Bundle 传递类别参数。
|
|
||||||
public static CategoryFragment newInstance(String category) {
|
public static CategoryFragment newInstance(String category) {
|
||||||
CategoryFragment fragment = new CategoryFragment();
|
CategoryFragment fragment = new CategoryFragment();
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putString(ARG_CATEGORY, category); // 将类别参数存储到 Bundle 中。
|
args.putString(ARG_CATEGORY, category);
|
||||||
fragment.setArguments(args); // 将 Bundle 设置为 Fragment 的参数。
|
fragment.setArguments(args);
|
||||||
return fragment;
|
return fragment;
|
||||||
}
|
}
|
||||||
// 当 Fragment 创建时调用,用于初始化一些变量。
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
// 如果 Fragment 有传入的参数,则获取并存储类别名称。
|
|
||||||
if (getArguments() != null) {
|
if (getArguments() != null) {
|
||||||
category = getArguments().getString(ARG_CATEGORY);
|
category = getArguments().getString(ARG_CATEGORY);
|
||||||
}
|
}
|
||||||
@ -58,15 +56,13 @@ public class CategoryFragment extends Fragment {
|
|||||||
|
|
||||||
List<WallpaperInfo> list = getListByClassName(category);
|
List<WallpaperInfo> list = getListByClassName(category);
|
||||||
|
|
||||||
CategoryRecyclerViewAdapter adapter = new CategoryRecyclerViewAdapter(requireContext(),list);
|
WallpaperAdapter adapter = new WallpaperAdapter(requireContext(),list);
|
||||||
binding.categoryRecycler.setAdapter(adapter);
|
binding.categoryRecycler.setAdapter(adapter);
|
||||||
binding.categoryRecycler.setLayoutManager(new GridLayoutManager(getContext(), 2));
|
binding.categoryRecycler.setLayoutManager(new GridLayoutManager(getContext(), 2));
|
||||||
|
|
||||||
// 为 RecyclerView 添加自定义的间距装饰。
|
|
||||||
ItemDecoration itemDecoration = new ItemDecoration(12, 10, 9);
|
ItemDecoration itemDecoration = new ItemDecoration(12, 10, 9);
|
||||||
binding.categoryRecycler.addItemDecoration(itemDecoration);
|
binding.categoryRecycler.addItemDecoration(itemDecoration);
|
||||||
return binding.getRoot();
|
return binding.getRoot();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<WallpaperInfo> getListByClassName(String className) {
|
public List<WallpaperInfo> getListByClassName(String className) {
|
||||||
@ -75,14 +71,13 @@ public class CategoryFragment extends Fragment {
|
|||||||
return category.getList();
|
return category.getList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 如果没有找到,返回一个空列表
|
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
binding = null; // 释放 ViewBinding 的引用
|
binding = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.key.vibekeyboard.Fragment;
|
package com.key.vibekeyboard.ui.fragment;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
@ -11,10 +11,10 @@ import androidx.lifecycle.Observer;
|
|||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.recyclerview.widget.GridLayoutManager;
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
|
|
||||||
import com.key.vibekeyboard.Adapter.FavoriteRecyclerViewAdapter;
|
import com.key.vibekeyboard.data.database.entity.WallpaperInfo;
|
||||||
import com.key.vibekeyboard.Room.WallpaperInfo;
|
import com.key.vibekeyboard.ui.adapter.WallpaperAdapter;
|
||||||
import com.key.vibekeyboard.Utils.ItemDecoration;
|
import com.key.vibekeyboard.utils.ItemDecoration;
|
||||||
import com.key.vibekeyboard.ViewModel.FavoriteViewModel;
|
import com.key.vibekeyboard.viewmodel.WallpaperViewModel;
|
||||||
import com.key.vibekeyboard.databinding.FragmentFavoriteBinding;
|
import com.key.vibekeyboard.databinding.FragmentFavoriteBinding;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -24,7 +24,7 @@ import java.util.List;
|
|||||||
public class FavoriteFragment extends Fragment {
|
public class FavoriteFragment extends Fragment {
|
||||||
|
|
||||||
private FragmentFavoriteBinding binding;
|
private FragmentFavoriteBinding binding;
|
||||||
private FavoriteRecyclerViewAdapter adapter;
|
private WallpaperAdapter adapter;
|
||||||
private final List<WallpaperInfo> wallpaperInfoList = new ArrayList<>();
|
private final List<WallpaperInfo> wallpaperInfoList = new ArrayList<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -32,18 +32,15 @@ public class FavoriteFragment extends Fragment {
|
|||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
binding = FragmentFavoriteBinding.inflate(inflater, container, false);
|
binding = FragmentFavoriteBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
adapter = new FavoriteRecyclerViewAdapter(requireContext(), wallpaperInfoList);
|
adapter = new WallpaperAdapter(requireContext(), wallpaperInfoList);
|
||||||
binding.favoriteRecyclerview.setAdapter(adapter);
|
binding.favoriteRecyclerview.setAdapter(adapter);
|
||||||
|
|
||||||
// 初始化 RecyclerView 和 LayoutManager
|
|
||||||
binding.favoriteRecyclerview.setLayoutManager(new GridLayoutManager(getContext(), 2));
|
binding.favoriteRecyclerview.setLayoutManager(new GridLayoutManager(getContext(), 2));
|
||||||
binding.favoriteRecyclerview.addItemDecoration(new ItemDecoration(16, 19, 10));
|
binding.favoriteRecyclerview.addItemDecoration(new ItemDecoration(16, 19, 10));
|
||||||
|
|
||||||
// 获取 ViewModel 实例
|
WallpaperViewModel wallpaperViewModel = new ViewModelProvider(this).get(WallpaperViewModel.class);
|
||||||
FavoriteViewModel favoriteViewModel = new ViewModelProvider(this).get(FavoriteViewModel.class);
|
|
||||||
|
|
||||||
// 监听 LiveData 的变化并更新 RecyclerView
|
wallpaperViewModel.getFavoriteList().observe(getViewLifecycleOwner(), new Observer<List<WallpaperInfo>>() {
|
||||||
favoriteViewModel.getFavoriteList().observe(getViewLifecycleOwner(), new Observer<List<WallpaperInfo>>() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onChanged(List<WallpaperInfo> wallpaperInfoList) {
|
public void onChanged(List<WallpaperInfo> wallpaperInfoList) {
|
||||||
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.key.vibekeyboard.Fragment;
|
package com.key.vibekeyboard.ui.fragment;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@ -16,25 +16,27 @@ import android.view.ViewTreeObserver;
|
|||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
import com.key.vibekeyboard.Activity.CategoryActivity;
|
import com.key.vibekeyboard.data.database.entity.WallpaperInfo;
|
||||||
import com.key.vibekeyboard.Activity.SearchActivity;
|
import com.key.vibekeyboard.ui.activity.CategoryActivity;
|
||||||
import com.key.vibekeyboard.Adapter.HomeRecyclerViewAdapter;
|
import com.key.vibekeyboard.ui.activity.SearchActivity;
|
||||||
import com.key.vibekeyboard.Adapter.HomeViewPager2Adapter;
|
import com.key.vibekeyboard.ui.adapter.HomeSliderAdapter;
|
||||||
import com.key.vibekeyboard.R;
|
import com.key.vibekeyboard.R;
|
||||||
import com.key.vibekeyboard.Room.Category;
|
import com.key.vibekeyboard.data.bean.Category;
|
||||||
import com.key.vibekeyboard.Utils.ItemDecoration;
|
import com.key.vibekeyboard.ui.adapter.WallpaperAdapter;
|
||||||
import com.key.vibekeyboard.Utils.Mytool;
|
import com.key.vibekeyboard.utils.ItemDecoration;
|
||||||
|
import com.key.vibekeyboard.utils.JsonUtils;
|
||||||
import com.key.vibekeyboard.databinding.FragmentHomeBinding;
|
import com.key.vibekeyboard.databinding.FragmentHomeBinding;
|
||||||
import com.key.vibekeyboard.topon.AdManager;
|
import com.key.vibekeyboard.topon.AdManager;
|
||||||
import com.key.vibekeyboard.topon.onActionListener;
|
import com.key.vibekeyboard.topon.onActionListener;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
|
||||||
public class HomeFragment extends Fragment {
|
public class HomeFragment extends Fragment {
|
||||||
|
|
||||||
private FragmentHomeBinding binding;
|
private FragmentHomeBinding binding;
|
||||||
private HomeViewPager2Adapter homeViewPager2Adapter;
|
private HomeSliderAdapter homeSliderAdapter;
|
||||||
private List<Category> categories;
|
private List<Category> categories;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -53,21 +55,21 @@ public class HomeFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void initData() {
|
public void initData() {
|
||||||
// 解析Json
|
categories = JsonUtils.parseJson("keyboard.json");
|
||||||
categories = Mytool.parseJsonToList("keyboard.json");
|
|
||||||
Log.d("dsd", "size" + categories.size());
|
Log.d("dsd", "size" + categories.size());
|
||||||
|
|
||||||
// 设置ViewPager2
|
homeSliderAdapter = new HomeSliderAdapter(requireContext(), categories);
|
||||||
homeViewPager2Adapter = new HomeViewPager2Adapter(requireContext(), categories);
|
binding.homeViewPager.setAdapter(homeSliderAdapter);
|
||||||
binding.homeViewPager.setAdapter(homeViewPager2Adapter);
|
|
||||||
setupIndicators(categories.size());
|
setupIndicators(categories.size());
|
||||||
|
|
||||||
// 设置RecyclerView
|
Random random = new Random();
|
||||||
|
int randomIndex = random.nextInt(categories.size());
|
||||||
|
List<WallpaperInfo> wallpaperInfos = categories.get(randomIndex).getList();
|
||||||
|
|
||||||
binding.homeRecycler.setLayoutManager(new GridLayoutManager(getContext(), 2));
|
binding.homeRecycler.setLayoutManager(new GridLayoutManager(getContext(), 2));
|
||||||
HomeRecyclerViewAdapter homeRecyclerViewAdapter = new HomeRecyclerViewAdapter(requireContext(), categories);
|
WallpaperAdapter homeRecyclerViewAdapter = new WallpaperAdapter(requireContext(), wallpaperInfos);
|
||||||
binding.homeRecycler.setAdapter(homeRecyclerViewAdapter);
|
binding.homeRecycler.setAdapter(homeRecyclerViewAdapter);
|
||||||
|
|
||||||
// 为 RecyclerView 添加自定义的间距装饰。
|
|
||||||
ItemDecoration itemDecoration = new ItemDecoration(16, 19, 10);
|
ItemDecoration itemDecoration = new ItemDecoration(16, 19, 10);
|
||||||
binding.homeRecycler.addItemDecoration(itemDecoration);
|
binding.homeRecycler.addItemDecoration(itemDecoration);
|
||||||
|
|
||||||
@ -91,8 +93,7 @@ public class HomeFragment extends Fragment {
|
|||||||
binding.homeViewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
|
binding.homeViewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onPageSelected(int position) {
|
public void onPageSelected(int position) {
|
||||||
if (position == homeViewPager2Adapter.getItemCount() - 1) {
|
if (position == homeSliderAdapter.getItemCount() - 1) {
|
||||||
// 如果用户手动滑到了最后的虚拟页面,切换回第一张
|
|
||||||
binding.homeViewPager.postDelayed(() -> binding.homeViewPager.setCurrentItem(0, false), 300);
|
binding.homeViewPager.postDelayed(() -> binding.homeViewPager.setCurrentItem(0, false), 300);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -101,51 +102,43 @@ public class HomeFragment extends Fragment {
|
|||||||
binding.homeSearch.setOnClickListener(new View.OnClickListener() {
|
binding.homeSearch.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
Intent intent = new Intent(getContext(), SearchActivity.class);
|
Intent intent = new Intent(getContext(), SearchActivity.class);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
binding.homeViewPager.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
binding.homeViewPager.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onGlobalLayout() {
|
public void onGlobalLayout() {
|
||||||
// 移除布局监听器,避免重复执行
|
|
||||||
binding.homeViewPager.getViewTreeObserver().removeOnGlobalLayoutListener(this);
|
binding.homeViewPager.getViewTreeObserver().removeOnGlobalLayoutListener(this);
|
||||||
// 动态生成圆点指示器
|
|
||||||
setupIndicators(categories.size());
|
setupIndicators(categories.size());
|
||||||
// 初始设置选中的圆点
|
|
||||||
updateIndicators(0);
|
updateIndicators(0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 设置自动轮播功能
|
|
||||||
autoSlideImages();
|
autoSlideImages();
|
||||||
|
|
||||||
setupViewPagerListener();
|
setupViewPagerListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 自动轮播图片
|
|
||||||
private void autoSlideImages() {
|
private void autoSlideImages() {
|
||||||
final int delay = 3000; // 延迟 3 秒
|
final int delay = 3000;
|
||||||
binding.homeViewPager.postDelayed(new Runnable() {
|
binding.homeViewPager.postDelayed(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (binding == null) {
|
if (binding == null) {
|
||||||
return; // 如果已经销毁,终止任务
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int currentItem = binding.homeViewPager.getCurrentItem();
|
int currentItem = binding.homeViewPager.getCurrentItem();
|
||||||
int nextItem = currentItem + 1;
|
int nextItem = currentItem + 1;
|
||||||
|
|
||||||
if (nextItem >= homeViewPager2Adapter.getItemCount()) {
|
if (nextItem >= homeSliderAdapter.getItemCount()) {
|
||||||
// 如果到达了最后的虚拟页面,瞬间跳回第一张,禁用动画
|
|
||||||
binding.homeViewPager.setCurrentItem(0, false);
|
binding.homeViewPager.setCurrentItem(0, false);
|
||||||
} else {
|
} else {
|
||||||
// 正常切换到下一张,有动画效果
|
|
||||||
binding.homeViewPager.setCurrentItem(nextItem, true);
|
binding.homeViewPager.setCurrentItem(nextItem, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 继续下一次轮播
|
|
||||||
binding.homeViewPager.postDelayed(this, delay);
|
binding.homeViewPager.postDelayed(this, delay);
|
||||||
}
|
}
|
||||||
}, delay);
|
}, delay);
|
||||||
@ -156,9 +149,7 @@ public class HomeFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onPageSelected(int position) {
|
public void onPageSelected(int position) {
|
||||||
super.onPageSelected(position);
|
super.onPageSelected(position);
|
||||||
|
updateIndicators(position);
|
||||||
updateIndicators(position); // 更新圆点
|
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -166,20 +157,19 @@ public class HomeFragment extends Fragment {
|
|||||||
|
|
||||||
private void setupIndicators(int count) {
|
private void setupIndicators(int count) {
|
||||||
LinearLayout indicatorLayout = binding.indicatorLayout;
|
LinearLayout indicatorLayout = binding.indicatorLayout;
|
||||||
indicatorLayout.removeAllViews(); // 清空原有的圆点
|
indicatorLayout.removeAllViews();
|
||||||
|
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
ImageView indicator = new ImageView(getContext());
|
ImageView indicator = new ImageView(getContext());
|
||||||
indicator.setImageResource(R.drawable.circle_indicator); // 默认圆点
|
indicator.setImageResource(R.drawable.circle_indicator);
|
||||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
|
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||||
params.setMargins(8, 0, 8, 0); // 设置圆点间距
|
params.setMargins(8, 0, 8, 0);
|
||||||
indicator.setLayoutParams(params);
|
indicator.setLayoutParams(params);
|
||||||
indicatorLayout.addView(indicator);
|
indicatorLayout.addView(indicator);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 延迟设置选中的圆点
|
indicatorLayout.post(() -> updateIndicators(0));
|
||||||
indicatorLayout.post(() -> updateIndicators(0)); // 设置第一个圆点为选中状态
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateIndicators(int position) {
|
private void updateIndicators(int position) {
|
||||||
@ -189,13 +179,12 @@ public class HomeFragment extends Fragment {
|
|||||||
for (int i = 0; i < childCount; i++) {
|
for (int i = 0; i < childCount; i++) {
|
||||||
ImageView indicator = (ImageView) indicatorLayout.getChildAt(i);
|
ImageView indicator = (ImageView) indicatorLayout.getChildAt(i);
|
||||||
if (i == position) {
|
if (i == position) {
|
||||||
indicator.setImageResource(R.drawable.circle_indicator_selected); // 当前页选中的圆点
|
indicator.setImageResource(R.drawable.circle_indicator_selected);
|
||||||
} else {
|
} else {
|
||||||
indicator.setImageResource(R.drawable.circle_indicator); // 默认圆点
|
indicator.setImageResource(R.drawable.circle_indicator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 强制更新布局,确保圆点大小正确
|
|
||||||
indicatorLayout.requestLayout();
|
indicatorLayout.requestLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,7 +192,6 @@ public class HomeFragment extends Fragment {
|
|||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
if (binding != null) {
|
if (binding != null) {
|
||||||
// 移除所有绑定到 ViewPager 的回调任务
|
|
||||||
binding.homeViewPager.removeCallbacks(null);
|
binding.homeViewPager.removeCallbacks(null);
|
||||||
}
|
}
|
||||||
binding = null;
|
binding = null;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.key.vibekeyboard.Fragment;
|
package com.key.vibekeyboard.ui.fragment;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
@ -8,8 +8,7 @@ import android.view.LayoutInflater;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import com.key.vibekeyboard.R;
|
import com.key.vibekeyboard.utils.SettingUtil;
|
||||||
import com.key.vibekeyboard.Utils.SettingUtil;
|
|
||||||
import com.key.vibekeyboard.databinding.FragmentSettingBinding;
|
import com.key.vibekeyboard.databinding.FragmentSettingBinding;
|
||||||
|
|
||||||
public class SettingFragment extends Fragment {
|
public class SettingFragment extends Fragment {
|
||||||
@ -27,7 +26,6 @@ public class SettingFragment extends Fragment {
|
|||||||
SettingUtil.shareApp(requireContext());
|
SettingUtil.shareApp(requireContext());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
return binding.getRoot();
|
return binding.getRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -0,0 +1,63 @@
|
|||||||
|
package com.key.vibekeyboard.utils;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
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 com.key.vibekeyboard.viewmodel.callbacks.DownloadCallback;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class DownloadUtils {
|
||||||
|
|
||||||
|
public static void downloadFile(Context context, String url, DownloadCallback callback) {
|
||||||
|
Glide.with(context)
|
||||||
|
.asFile()
|
||||||
|
.load(url)
|
||||||
|
.listener(new RequestListener<File>() {
|
||||||
|
@Override
|
||||||
|
public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target<File> target, boolean isFirstResource) {
|
||||||
|
try {
|
||||||
|
callback.onDownloadCall(false, null);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onResourceReady(@NonNull File resource, @NonNull Object model, Target<File> target, @NonNull DataSource dataSource, boolean isFirstResource) {
|
||||||
|
try {
|
||||||
|
File externalDir = context.getExternalFilesDir(null);
|
||||||
|
if (externalDir == null) {
|
||||||
|
externalDir = context.getFilesDir();
|
||||||
|
}
|
||||||
|
|
||||||
|
File downloadDir = new File(externalDir, "DownloadedFiles");
|
||||||
|
if (!downloadDir.exists()) {
|
||||||
|
boolean mkdirs = downloadDir.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
File destinationFile = new File(downloadDir, resource.getName());
|
||||||
|
FileUtils.cloneFile(resource, destinationFile);
|
||||||
|
|
||||||
|
callback.onDownloadCall(true, destinationFile);
|
||||||
|
Log.d("--------", "resource: " + destinationFile);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}).preload();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,55 @@
|
|||||||
|
package com.key.vibekeyboard.utils;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.inputmethodservice.Keyboard;
|
||||||
|
import android.util.TypedValue;
|
||||||
|
|
||||||
|
import com.key.vibekeyboard.inputmethod.view.CustomKeyboardView;
|
||||||
|
|
||||||
|
public class DrawableUtils {
|
||||||
|
|
||||||
|
public static void drawKeyIcon(Keyboard.Key currentKey,
|
||||||
|
Drawable drawKeyIcon,
|
||||||
|
Canvas myCanvas,
|
||||||
|
CustomKeyboardView customKeyboardView) {
|
||||||
|
currentKey.icon = drawKeyIcon;
|
||||||
|
currentKey.icon.setBounds(getIconBounds(currentKey, drawKeyIcon, customKeyboardView));
|
||||||
|
currentKey.icon.draw(myCanvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Rect getIconBounds(Keyboard.Key currentKey,
|
||||||
|
Drawable drawKeyIcon,
|
||||||
|
CustomKeyboardView customKeyboardView) {
|
||||||
|
float icon_w = drawKeyIcon.getIntrinsicWidth();
|
||||||
|
float icon_h = drawKeyIcon.getIntrinsicHeight();
|
||||||
|
float icon_wr = icon_w / currentKey.width;
|
||||||
|
float icon_hr = icon_h / currentKey.height;
|
||||||
|
|
||||||
|
float tep1, tep2;
|
||||||
|
if (icon_wr > icon_hr) {
|
||||||
|
tep2 = icon_wr;
|
||||||
|
tep1 = Math.max(icon_wr, 0.5f);
|
||||||
|
} else {
|
||||||
|
tep2 = icon_hr;
|
||||||
|
tep1 = Math.max(icon_hr, 0.5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
icon_h = (icon_h / tep2) * tep1;
|
||||||
|
icon_w = (icon_w / tep2) * tep1;
|
||||||
|
|
||||||
|
int top = (int) (currentKey.y + customKeyboardView.getPaddingTop() + (currentKey.height - icon_h) / 2);
|
||||||
|
int left = (int) (currentKey.x + customKeyboardView.getPaddingLeft() + (currentKey.width - icon_w) / 2);
|
||||||
|
int bottom = top + (int) icon_h;
|
||||||
|
int right = left + (int) icon_w;
|
||||||
|
|
||||||
|
return new Rect(left, top, right, bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float spToPx(Float values, Context context) {
|
||||||
|
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, values, context.getResources().getDisplayMetrics());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
41
app/src/main/java/com/key/vibekeyboard/utils/FileUtils.java
Normal file
41
app/src/main/java/com/key/vibekeyboard/utils/FileUtils.java
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package com.key.vibekeyboard.utils;
|
||||||
|
|
||||||
|
import android.os.Build;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
|
||||||
|
public class FileUtils {
|
||||||
|
|
||||||
|
public static void cloneFile(File sourceFile, File destinationFile) throws IOException {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
try (InputStream in = Files.newInputStream(sourceFile.toPath());
|
||||||
|
OutputStream out = Files.newOutputStream(destinationFile.toPath())) {
|
||||||
|
byte[] buffer = new byte[1024];
|
||||||
|
int bytesRead;
|
||||||
|
while ((bytesRead = in.read(buffer)) != -1) {
|
||||||
|
out.write(buffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String readFileAsString(File file) throws IOException {
|
||||||
|
FileInputStream fileInputStream = new FileInputStream(file);
|
||||||
|
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream));
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
String lin = "";
|
||||||
|
while ((lin = bufferedReader.readLine()) != null) {
|
||||||
|
stringBuilder.append(lin);
|
||||||
|
}
|
||||||
|
bufferedReader.close();
|
||||||
|
return stringBuilder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
package com.key.vibekeyboard.utils;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.provider.Settings;
|
||||||
|
import android.view.inputmethod.InputMethodInfo;
|
||||||
|
import android.view.inputmethod.InputMethodManager;
|
||||||
|
|
||||||
|
import com.key.vibekeyboard.MyApplication;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class InputMethodUtils {
|
||||||
|
private static final InputMethodManager methodManager =
|
||||||
|
(InputMethodManager) MyApplication.instance.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||||
|
|
||||||
|
public static boolean isInputMethodEnabled() {
|
||||||
|
List<InputMethodInfo> enabledInputMethods = methodManager.getEnabledInputMethodList();
|
||||||
|
for (InputMethodInfo inputMethodInfo : enabledInputMethods) {
|
||||||
|
if (inputMethodInfo.getId().startsWith(MyApplication.instance.getPackageName())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isCurrentInputMethodActive() {
|
||||||
|
String currentInputMethod = Settings.Secure.getString(MyApplication.instance.getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
|
||||||
|
return currentInputMethod != null && currentInputMethod.startsWith(MyApplication.instance.getPackageName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,78 @@
|
|||||||
|
package com.key.vibekeyboard.utils;
|
||||||
|
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
|
||||||
|
|
||||||
|
import com.key.vibekeyboard.MyApplication;
|
||||||
|
|
||||||
|
|
||||||
|
public class ItemDecoration extends RecyclerView.ItemDecoration {
|
||||||
|
|
||||||
|
private final int v;
|
||||||
|
private final int h;
|
||||||
|
private final int ex;
|
||||||
|
|
||||||
|
public ItemDecoration(int v, int h, int ex) {
|
||||||
|
this.v = Math.round(dpToPx(v));
|
||||||
|
this.h = Math.round(dpToPx(h));
|
||||||
|
this.ex = Math.round(dpToPx(ex));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
|
||||||
|
super.getItemOffsets(outRect, view, parent, state);
|
||||||
|
|
||||||
|
int spanCount = 1;
|
||||||
|
int spanSize = 1;
|
||||||
|
int spanIndex = 0;
|
||||||
|
|
||||||
|
int childAdapterPosition = parent.getChildAdapterPosition(view);
|
||||||
|
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
|
||||||
|
|
||||||
|
if (layoutManager instanceof StaggeredGridLayoutManager) {
|
||||||
|
StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) layoutManager;
|
||||||
|
StaggeredGridLayoutManager.LayoutParams layoutParams = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams();
|
||||||
|
spanCount = staggeredGridLayoutManager.getSpanCount();
|
||||||
|
if (layoutParams.isFullSpan()) {
|
||||||
|
spanSize = spanCount;
|
||||||
|
}
|
||||||
|
spanIndex = layoutParams.getSpanIndex();
|
||||||
|
|
||||||
|
} else if (layoutManager instanceof GridLayoutManager) {
|
||||||
|
GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
|
||||||
|
GridLayoutManager.LayoutParams layoutParams = (GridLayoutManager.LayoutParams) view.getLayoutParams();
|
||||||
|
spanCount = gridLayoutManager.getSpanCount();
|
||||||
|
spanSize = gridLayoutManager.getSpanSizeLookup().getSpanSize(childAdapterPosition);
|
||||||
|
spanIndex = layoutParams.getSpanIndex();
|
||||||
|
|
||||||
|
} else if (layoutManager instanceof LinearLayoutManager) {
|
||||||
|
outRect.left = v;
|
||||||
|
outRect.right = v;
|
||||||
|
outRect.bottom = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spanSize == spanCount) {
|
||||||
|
outRect.left = v + ex;
|
||||||
|
outRect.right = v + ex;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
int itemAllSpacing = (v * (spanCount + 1) + ex * 2) / spanCount;
|
||||||
|
int left = v * (spanIndex + 1) - itemAllSpacing * spanIndex + ex;
|
||||||
|
int right = itemAllSpacing - left;
|
||||||
|
outRect.left = left;
|
||||||
|
outRect.right = right;
|
||||||
|
}
|
||||||
|
outRect.bottom = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float dpToPx(float dpValue) {
|
||||||
|
float density = MyApplication.getContext().getResources().getDisplayMetrics().density;
|
||||||
|
return density * dpValue + 0.5f;
|
||||||
|
}
|
||||||
|
}
|
||||||
70
app/src/main/java/com/key/vibekeyboard/utils/JsonUtils.java
Normal file
70
app/src/main/java/com/key/vibekeyboard/utils/JsonUtils.java
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
package com.key.vibekeyboard.utils;
|
||||||
|
|
||||||
|
import android.content.res.AssetManager;
|
||||||
|
|
||||||
|
import com.key.vibekeyboard.MyApplication;
|
||||||
|
import com.key.vibekeyboard.data.bean.Category;
|
||||||
|
import com.key.vibekeyboard.data.database.entity.WallpaperInfo;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class JsonUtils {
|
||||||
|
|
||||||
|
private static JSONArray loadJSONFromAsset(String filename) {
|
||||||
|
String json;
|
||||||
|
try {
|
||||||
|
AssetManager assetManager = MyApplication.getContext().getAssets();
|
||||||
|
InputStream inputStream = assetManager.open(filename);
|
||||||
|
int size = inputStream.available();
|
||||||
|
byte[] buffer = new byte[size];
|
||||||
|
int i = inputStream.read(buffer);
|
||||||
|
inputStream.close();
|
||||||
|
json = new String(buffer, StandardCharsets.UTF_8);
|
||||||
|
return new JSONArray(json);
|
||||||
|
} catch (IOException | JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Category> parseJson(String filename) {
|
||||||
|
List<Category> categories = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
JSONArray jsonObject = loadJSONFromAsset(filename);
|
||||||
|
for (int a = 0; a < Objects.requireNonNull(jsonObject).length(); a++) {
|
||||||
|
JSONObject list = jsonObject.getJSONObject(a);
|
||||||
|
Category myData = new Category();
|
||||||
|
List<WallpaperInfo> wallpaperInfos = new ArrayList<>();
|
||||||
|
myData.setClassName(list.getString("className"));
|
||||||
|
JSONArray classArray = list.getJSONArray("list");
|
||||||
|
for (int i = 0; i < classArray.length(); i++) {
|
||||||
|
JSONObject item = classArray.getJSONObject(i);
|
||||||
|
WallpaperInfo wallpaperInfo = new WallpaperInfo();
|
||||||
|
wallpaperInfo.setDownloaded(false);
|
||||||
|
wallpaperInfo.setIslike(false);
|
||||||
|
wallpaperInfo.setClassName(myData.getClassName());
|
||||||
|
wallpaperInfo.setPreview(item.getString("preview"));
|
||||||
|
wallpaperInfo.setThumb(item.getString("thumb"));
|
||||||
|
wallpaperInfo.setTitle(item.getString("title"));
|
||||||
|
wallpaperInfo.setZipUrl(item.getString("zipUrl"));
|
||||||
|
wallpaperInfos.add(wallpaperInfo);
|
||||||
|
}
|
||||||
|
myData.setList(wallpaperInfos);
|
||||||
|
categories.add(myData);
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return categories;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
package com.key.vibekeyboard.utils;
|
||||||
|
|
||||||
|
public class PathRepository {
|
||||||
|
public static String NORMAL_KEY_BACKGROUND = "btn_keyboard_key_normal_normal.9.png";
|
||||||
|
public static String ACTION_KEY_BACKGROUND = "btn_keyboard_key_functional_normal.9.png";
|
||||||
|
|
||||||
|
public static String DELETE_ICON = "sym_keyboard_delete_normal.png";
|
||||||
|
public static String SHIFT_ICON = "sym_keyboard_shift.png";
|
||||||
|
public static String SHIFT_LOCK_ICON = "sym_keyboard_shift_locked.png";
|
||||||
|
public static String RETURN_ICON = "sym_keyboard_return_normal.png";
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
package com.key.vibekeyboard.utils;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.pm.PackageInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
|
||||||
|
public class SettingUtil {
|
||||||
|
|
||||||
|
public static String getCurrentVersion(Context context) {
|
||||||
|
try {
|
||||||
|
PackageManager packageManager = context.getPackageManager();
|
||||||
|
PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
|
||||||
|
return packageInfo.versionName;
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void shareApp(Context context) {
|
||||||
|
String appPackageName = context.getPackageName();
|
||||||
|
String appName = context.getApplicationInfo().loadLabel(context.getPackageManager()).toString();
|
||||||
|
String appPlayStoreLink = "https://play.google.com/store/apps/details?id=" + appPackageName;
|
||||||
|
|
||||||
|
Intent shareIntent = new Intent(Intent.ACTION_SEND);
|
||||||
|
shareIntent.setType("text/plain");
|
||||||
|
shareIntent.putExtra(Intent.EXTRA_SUBJECT, "Check out this app: " + appName);
|
||||||
|
shareIntent.putExtra(Intent.EXTRA_TEXT, "Download " + appName + " from Google Play: " + appPlayStoreLink);
|
||||||
|
context.startActivity(Intent.createChooser(shareIntent, "Share " + appName + " via"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
package com.key.vibekeyboard.utils;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
public class TaskExecutorUtils {
|
||||||
|
|
||||||
|
private static ExecutorService executorService;
|
||||||
|
|
||||||
|
public static void executeIO(Runnable task) {
|
||||||
|
getExecutorService().execute(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ExecutorService getExecutorService() {
|
||||||
|
if (executorService == null) {
|
||||||
|
executorService = Executors.newSingleThreadExecutor();
|
||||||
|
}
|
||||||
|
return executorService;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
64
app/src/main/java/com/key/vibekeyboard/utils/unzipUtils.java
Normal file
64
app/src/main/java/com/key/vibekeyboard/utils/unzipUtils.java
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package com.key.vibekeyboard.utils;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.key.vibekeyboard.R;
|
||||||
|
import com.key.vibekeyboard.viewmodel.callbacks.UnzipCallback;
|
||||||
|
|
||||||
|
import net.sf.sevenzipjbinding.ArchiveFormat;
|
||||||
|
import net.sf.sevenzipjbinding.IInArchive;
|
||||||
|
import net.sf.sevenzipjbinding.SevenZip;
|
||||||
|
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
|
||||||
|
import net.sf.sevenzipjbinding.impl.RandomAccessFileOutStream;
|
||||||
|
import net.sf.sevenzipjbinding.simple.ISimpleInArchiveItem;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.RandomAccessFile;
|
||||||
|
|
||||||
|
public class unzipUtils {
|
||||||
|
|
||||||
|
public static void unzipFile(Context context, File resource, UnzipCallback callback) throws IOException {
|
||||||
|
if (!resource.exists()) {
|
||||||
|
Toast.makeText(context, context.getString(R.string.error_decompression_file_missing), Toast.LENGTH_SHORT).show();
|
||||||
|
} else {
|
||||||
|
String itemFilePath = "";
|
||||||
|
|
||||||
|
File externalDir = context.getExternalFilesDir(null);
|
||||||
|
if (externalDir == null) {
|
||||||
|
externalDir = context.getFilesDir();
|
||||||
|
}
|
||||||
|
|
||||||
|
String extractPath = new File(externalDir, "ExtractedFiles").getAbsolutePath();
|
||||||
|
|
||||||
|
RandomAccessFile accessFile = new RandomAccessFile(resource, "r");
|
||||||
|
RandomAccessFileInStream inStream = new RandomAccessFileInStream(accessFile);
|
||||||
|
IInArchive iInArchive = SevenZip.openInArchive(ArchiveFormat.SEVEN_ZIP, inStream);
|
||||||
|
ISimpleInArchiveItem[] archiveItems = iInArchive.getSimpleInterface().getArchiveItems();
|
||||||
|
|
||||||
|
for (ISimpleInArchiveItem simple : archiveItems) {
|
||||||
|
File file = new File(extractPath, simple.getPath());
|
||||||
|
if (!simple.isFolder()) {
|
||||||
|
RandomAccessFileOutStream outStream = new RandomAccessFileOutStream(new RandomAccessFile(file, "rw"));
|
||||||
|
simple.extractSlow(outStream);
|
||||||
|
itemFilePath = file.getPath();
|
||||||
|
Log.d("--------", "path: " + itemFilePath);
|
||||||
|
} else {
|
||||||
|
boolean mkdirs = file.mkdirs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inStream.close();
|
||||||
|
iInArchive.close();
|
||||||
|
|
||||||
|
int res = itemFilePath.indexOf("res");
|
||||||
|
String substring = itemFilePath.substring(0, res + 3);
|
||||||
|
Log.d("--------", "substring: " + substring);
|
||||||
|
|
||||||
|
callback.onUnzipCall(true, substring);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
package com.key.vibekeyboard.viewmodel;
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.lifecycle.ViewModel;
|
||||||
|
|
||||||
|
import com.key.vibekeyboard.data.database.AppDatabase;
|
||||||
|
import com.key.vibekeyboard.data.database.entity.WallpaperInfo;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class WallpaperViewModel extends ViewModel {
|
||||||
|
private final LiveData<List<WallpaperInfo>> favoriteList;
|
||||||
|
|
||||||
|
public WallpaperViewModel() {
|
||||||
|
AppDatabase database = AppDatabase.getInstance();
|
||||||
|
favoriteList = database.wallpaperInfoDao().getLiveLikeList(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LiveData<List<WallpaperInfo>> getFavoriteList() {
|
||||||
|
return favoriteList;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.key.vibekeyboard.callback;
|
package com.key.vibekeyboard.viewmodel.callbacks;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.key.vibekeyboard.callback;
|
package com.key.vibekeyboard.viewmodel.callbacks;
|
||||||
|
|
||||||
public interface UnzipCallback {
|
public interface UnzipCallback {
|
||||||
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<item android:drawable="@drawable/rounded_rectangle" android:state_selected="true" />
|
||||||
<item android:drawable="@drawable/un_rounded_corners" android:state_selected="false" />
|
<item android:drawable="@drawable/un_rounded_corners" android:state_selected="false" />
|
||||||
<item android:drawable="@drawable/rounded_corners" android:state_selected="true" />
|
|
||||||
|
|
||||||
</selector>
|
</selector>
|
||||||
@ -5,7 +5,7 @@
|
|||||||
android:id="@+id/main"
|
android:id="@+id/main"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context=".Activity.CategoryActivity">
|
tools:context=".ui.activity.CategoryActivity">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/category_back"
|
android:id="@+id/category_back"
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
android:id="@+id/main"
|
android:id="@+id/main"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context=".Activity.DownloadActivity">
|
tools:context=".ui.activity.DownloadActivity">
|
||||||
|
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@mipmap/activity_background"
|
android:background="@mipmap/activity_background"
|
||||||
tools:context=".Activity.MainActivity">
|
tools:context=".ui.activity.MainActivity">
|
||||||
|
|
||||||
<androidx.viewpager2.widget.ViewPager2
|
<androidx.viewpager2.widget.ViewPager2
|
||||||
android:id="@+id/main_viewpager"
|
android:id="@+id/main_viewpager"
|
||||||
|
|||||||
@ -1,10 +0,0 @@
|
|||||||
<?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:id="@+id/main"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
tools:context=".Activity.PermissionActivity">
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
@ -2,6 +2,7 @@
|
|||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/main"
|
||||||
android:background="@mipmap/activity_background"
|
android:background="@mipmap/activity_background"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@mipmap/activity_background"
|
android:background="@mipmap/activity_background"
|
||||||
tools:context=".Activity.WriteActivity">
|
tools:context=".ui.activity.WriteActivity">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/back"
|
android:id="@+id/back"
|
||||||
|
|||||||
6
app/src/main/res/layout/custom_keyboard_view.xml
Normal file
6
app/src/main/res/layout/custom_keyboard_view.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<com.key.vibekeyboard.inputmethod.view.CustomKeyboardView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/keyboard_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
@ -3,7 +3,7 @@
|
|||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="#00BCD4">
|
android:background="@android:color/transparent">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/imageView"
|
android:id="@+id/imageView"
|
||||||
@ -46,7 +46,7 @@
|
|||||||
android:layout_width="24dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:src="@mipmap/splash" />
|
android:src="@mipmap/ic_launcher_foreground" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@ -71,7 +71,7 @@
|
|||||||
android:layout_width="24dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:src="@mipmap/splash" />
|
android:src="@mipmap/ic_launcher_foreground" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|||||||
@ -4,7 +4,8 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:padding="5dp"
|
android:padding="5dp"
|
||||||
android:background="#00BCD4">
|
android:paddingBottom="25dp"
|
||||||
|
android:background="@color/white">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/imageView"
|
android:id="@+id/imageView"
|
||||||
@ -21,13 +22,14 @@
|
|||||||
android:id="@+id/textView"
|
android:id="@+id/textView"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="25dp"
|
||||||
android:background="@android:color/transparent"
|
android:background="@android:color/transparent"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="@string/today_s_recommendation"
|
android:text="@string/today_s_recommendation"
|
||||||
android:textColor="@color/black"
|
android:textColor="@color/black"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
|
android:layout_marginBottom="25dp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/imageView" />
|
app:layout_constraintTop_toBottomOf="@id/imageView" />
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context=".Fragment.CategoryFragment">
|
tools:context=".ui.fragment.CategoryFragment">
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/category_recycler"
|
android:id="@+id/category_recycler"
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context=".Fragment.FavoriteFragment">
|
tools:context=".ui.fragment.FavoriteFragment">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/favorite_title"
|
android:id="@+id/favorite_title"
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
android:id="@+id/home_root"
|
android:id="@+id/home_root"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context=".Fragment.HomeFragment">
|
tools:context=".ui.fragment.HomeFragment">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/home_title"
|
android:id="@+id/home_title"
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="16dp"
|
android:padding="16dp"
|
||||||
tools:context=".Fragment.SettingFragment">
|
tools:context=".ui.fragment.SettingFragment">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
@ -1,12 +0,0 @@
|
|||||||
<?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.key.vibekeyboard.Keyboard.MyKeyboard
|
|
||||||
android:id="@+id/keyboardView"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="210dp" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
@ -1,5 +1,6 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">Mobile Keyboard</string>
|
<string name="app_name">Mobile Keyboard</string>
|
||||||
|
<string name="error_decompression_file_missing">The decompression file does not exist</string>
|
||||||
<string name="hello_blank_fragment">Hello blank fragment</string>
|
<string name="hello_blank_fragment">Hello blank fragment</string>
|
||||||
<string name="you_have_not_yet_included_any_favorite_photos_in_the_folder">"No favorite photos in this folder yet."</string>
|
<string name="you_have_not_yet_included_any_favorite_photos_in_the_folder">"No favorite photos in this folder yet."</string>
|
||||||
<string name="type_a_message">Type a Message</string>
|
<string name="type_a_message">Type a Message</string>
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
<input-method xmlns:android="http://schemas.android.com/apk/res/android">
|
<input-method xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
<subtype
|
<subtype
|
||||||
android:icon="@drawable/ic_launcher_background"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:imeSubtypeLocale="en_US"
|
android:imeSubtypeLocale="en_US"
|
||||||
android:imeSubtypeMode = "keyboard"
|
android:imeSubtypeMode = "keyboard"
|
||||||
android:label="@string/app_name" />
|
android:label="@string/app_name" />
|
||||||
|
|||||||
@ -8,35 +8,45 @@
|
|||||||
android:codes="113"
|
android:codes="113"
|
||||||
android:keyEdgeFlags="left"
|
android:keyEdgeFlags="left"
|
||||||
android:keyLabel="q" />
|
android:keyLabel="q" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="119"
|
android:codes="119"
|
||||||
android:keyLabel="w" />
|
android:keyLabel="w" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="101"
|
android:codes="101"
|
||||||
android:keyLabel="e" />
|
android:keyLabel="e" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="114"
|
android:codes="114"
|
||||||
android:keyLabel="r" />
|
android:keyLabel="r" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="116"
|
android:codes="116"
|
||||||
android:keyLabel="t" />
|
android:keyLabel="t" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="121"
|
android:codes="121"
|
||||||
android:keyLabel="y" />
|
android:keyLabel="y" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="117"
|
android:codes="117"
|
||||||
android:keyLabel="u" />
|
android:keyLabel="u" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="105"
|
android:codes="105"
|
||||||
android:keyLabel="i" />
|
android:keyLabel="i" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="111"
|
android:codes="111"
|
||||||
android:keyLabel="o" />
|
android:keyLabel="o" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="112"
|
android:codes="112"
|
||||||
android:keyEdgeFlags="right"
|
android:keyEdgeFlags="right"
|
||||||
android:keyLabel="p" />
|
android:keyLabel="p" />
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
<Row
|
<Row
|
||||||
android:horizontalGap="0.5%"
|
android:horizontalGap="0.5%"
|
||||||
android:keyWidth="9.444444%"
|
android:keyWidth="9.444444%"
|
||||||
@ -48,57 +58,72 @@
|
|||||||
<Key
|
<Key
|
||||||
android:codes="115"
|
android:codes="115"
|
||||||
android:keyLabel="s" />
|
android:keyLabel="s" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="100"
|
android:codes="100"
|
||||||
android:keyLabel="d" />
|
android:keyLabel="d" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="102"
|
android:codes="102"
|
||||||
android:keyLabel="f" />
|
android:keyLabel="f" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="103"
|
android:codes="103"
|
||||||
android:keyLabel="g" />
|
android:keyLabel="g" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="104"
|
android:codes="104"
|
||||||
android:keyLabel="h" />
|
android:keyLabel="h" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="106"
|
android:codes="106"
|
||||||
android:keyLabel="j" />
|
android:keyLabel="j" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="107"
|
android:codes="107"
|
||||||
android:keyLabel="k" />
|
android:keyLabel="k" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="108"
|
android:codes="108"
|
||||||
android:keyLabel="l" />
|
android:keyLabel="l" />
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
<Row
|
<Row
|
||||||
android:horizontalGap="0.5%"
|
android:horizontalGap="0.5%"
|
||||||
android:keyWidth="9.5%"
|
android:keyWidth="9.5%"
|
||||||
android:keyHeight="50dp">
|
android:keyHeight="50dp">
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="-1"
|
android:codes="-1"
|
||||||
android:isModifier="true"
|
android:isModifier="true"
|
||||||
android:isSticky="true"
|
android:isSticky="true"
|
||||||
android:keyWidth="14.25%"
|
android:keyWidth="14.25%"
|
||||||
android:keyEdgeFlags="left" />
|
android:keyEdgeFlags="left"
|
||||||
|
android:keyLabel="Shift" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="122"
|
android:codes="122"
|
||||||
android:keyLabel="z" />
|
android:keyLabel="z" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="120"
|
android:codes="120"
|
||||||
android:keyLabel="x" />
|
android:keyLabel="x" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="99"
|
android:codes="99"
|
||||||
android:keyLabel="c" />
|
android:keyLabel="c" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="118"
|
android:codes="118"
|
||||||
android:keyLabel="v" />
|
android:keyLabel="v" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="98"
|
android:codes="98"
|
||||||
android:keyLabel="b" />
|
android:keyLabel="b" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="110"
|
android:codes="110"
|
||||||
android:keyLabel="n" />
|
android:keyLabel="n" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="109"
|
android:codes="109"
|
||||||
android:keyLabel="m" />
|
android:keyLabel="m" />
|
||||||
@ -108,7 +133,8 @@
|
|||||||
android:isModifier="true"
|
android:isModifier="true"
|
||||||
android:isRepeatable="true"
|
android:isRepeatable="true"
|
||||||
android:keyWidth="14.25%"
|
android:keyWidth="14.25%"
|
||||||
android:keyEdgeFlags="right" />
|
android:keyEdgeFlags="right"
|
||||||
|
android:keyLabel="" />
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
<Row
|
<Row
|
||||||
@ -126,16 +152,16 @@
|
|||||||
<Key
|
<Key
|
||||||
android:codes="44"
|
android:codes="44"
|
||||||
android:keyLabel="," />
|
android:keyLabel="," />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="32"
|
android:codes="32"
|
||||||
android:keyWidth="49.5%"
|
android:keyWidth="49.5%"
|
||||||
android:keyLabel="English" />
|
android:keyLabel="Space" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="46"
|
android:codes="46"
|
||||||
android:keyLabel="." />
|
android:keyLabel="." />
|
||||||
|
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="-4"
|
android:codes="-4"
|
||||||
android:keyWidth="14.25%"
|
android:keyWidth="14.25%"
|
||||||
@ -42,11 +42,13 @@
|
|||||||
<Key
|
<Key
|
||||||
android:codes="182"
|
android:codes="182"
|
||||||
android:keyLabel="¶" />
|
android:keyLabel="¶" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="8710"
|
android:codes="8710"
|
||||||
android:keyEdgeFlags="right"
|
android:keyEdgeFlags="right"
|
||||||
android:keyLabel="∆" />
|
android:keyLabel="∆" />
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
<Row
|
<Row
|
||||||
android:horizontalGap="0.5%"
|
android:horizontalGap="0.5%"
|
||||||
android:keyWidth="9.444444%"
|
android:keyWidth="9.444444%"
|
||||||
@ -84,18 +86,20 @@
|
|||||||
<Key
|
<Key
|
||||||
android:codes="123"
|
android:codes="123"
|
||||||
android:keyLabel="{" />
|
android:keyLabel="{" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="125"
|
android:codes="125"
|
||||||
android:keyEdgeFlags="right"
|
android:keyEdgeFlags="right"
|
||||||
android:keyLabel="}" />
|
android:keyLabel="}" />
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
<Row
|
<Row
|
||||||
android:horizontalGap="0.5%"
|
android:horizontalGap="0.5%"
|
||||||
android:keyWidth="9.5%"
|
android:keyWidth="9.5%"
|
||||||
android:keyHeight="50dp">
|
android:keyHeight="50dp">
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="-361"
|
android:codes="-1000"
|
||||||
android:isModifier="true"
|
android:isModifier="true"
|
||||||
android:keyWidth="14.25%"
|
android:keyWidth="14.25%"
|
||||||
android:keyEdgeFlags="left"
|
android:keyEdgeFlags="left"
|
||||||
@ -129,12 +133,12 @@
|
|||||||
android:codes="93"
|
android:codes="93"
|
||||||
android:keyLabel="]" />
|
android:keyLabel="]" />
|
||||||
|
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="-5"
|
android:codes="-5"
|
||||||
android:isModifier="true"
|
android:isModifier="true"
|
||||||
android:isRepeatable="true"
|
android:isRepeatable="true"
|
||||||
android:keyWidth="14.25%"
|
android:keyWidth="14.25%"
|
||||||
|
android:keyLabel=""
|
||||||
android:keyEdgeFlags="right" />
|
android:keyEdgeFlags="right" />
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
@ -157,10 +161,11 @@
|
|||||||
<Key
|
<Key
|
||||||
android:codes="60"
|
android:codes="60"
|
||||||
android:keyLabel="<" />
|
android:keyLabel="<" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="32"
|
android:codes="32"
|
||||||
android:keyWidth="29.5%"
|
android:keyWidth="29.5%"
|
||||||
android:keyLabel="English" />
|
android:keyLabel="Space" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="62"
|
android:codes="62"
|
||||||
@ -10,6 +10,7 @@
|
|||||||
android:codes="49"
|
android:codes="49"
|
||||||
android:keyEdgeFlags="left"
|
android:keyEdgeFlags="left"
|
||||||
android:keyLabel="1" />
|
android:keyLabel="1" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="50"
|
android:codes="50"
|
||||||
android:keyLabel="2" />
|
android:keyLabel="2" />
|
||||||
@ -17,9 +18,11 @@
|
|||||||
<Key
|
<Key
|
||||||
android:codes="51"
|
android:codes="51"
|
||||||
android:keyLabel="3" />
|
android:keyLabel="3" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="52"
|
android:codes="52"
|
||||||
android:keyLabel="4" />
|
android:keyLabel="4" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="53"
|
android:codes="53"
|
||||||
android:keyLabel="5" />
|
android:keyLabel="5" />
|
||||||
@ -31,17 +34,21 @@
|
|||||||
<Key
|
<Key
|
||||||
android:codes="55"
|
android:codes="55"
|
||||||
android:keyLabel="7" />
|
android:keyLabel="7" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="56"
|
android:codes="56"
|
||||||
android:keyLabel="8" />
|
android:keyLabel="8" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="57"
|
android:codes="57"
|
||||||
android:keyLabel="9" />
|
android:keyLabel="9" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="48"
|
android:codes="48"
|
||||||
android:keyEdgeFlags="right"
|
android:keyEdgeFlags="right"
|
||||||
android:keyLabel="0" />
|
android:keyLabel="0" />
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
<Row
|
<Row
|
||||||
android:horizontalGap="0.5%"
|
android:horizontalGap="0.5%"
|
||||||
android:keyWidth="9.444444%"
|
android:keyWidth="9.444444%"
|
||||||
@ -51,9 +58,11 @@
|
|||||||
android:horizontalGap="5.5%"
|
android:horizontalGap="5.5%"
|
||||||
android:keyEdgeFlags="left"
|
android:keyEdgeFlags="left"
|
||||||
android:keyLabel="\@" />
|
android:keyLabel="\@" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="35"
|
android:codes="35"
|
||||||
android:keyLabel="#" />
|
android:keyLabel="#" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="36"
|
android:codes="36"
|
||||||
android:keyLabel="\$" />
|
android:keyLabel="\$" />
|
||||||
@ -77,18 +86,20 @@
|
|||||||
<Key
|
<Key
|
||||||
android:codes="40"
|
android:codes="40"
|
||||||
android:keyLabel="(" />
|
android:keyLabel="(" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="41"
|
android:codes="41"
|
||||||
android:keyEdgeFlags="right"
|
android:keyEdgeFlags="right"
|
||||||
android:keyLabel=")" />
|
android:keyLabel=")" />
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
<Row
|
<Row
|
||||||
android:horizontalGap="0.5%"
|
android:horizontalGap="0.5%"
|
||||||
android:keyWidth="9.5%"
|
android:keyWidth="9.5%"
|
||||||
android:keyHeight="50dp">
|
android:keyHeight="50dp">
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="-360"
|
android:codes="-1000"
|
||||||
android:isModifier="true"
|
android:isModifier="true"
|
||||||
android:keyWidth="14.25%"
|
android:keyWidth="14.25%"
|
||||||
android:keyEdgeFlags="left"
|
android:keyEdgeFlags="left"
|
||||||
@ -122,13 +133,14 @@
|
|||||||
<Key
|
<Key
|
||||||
android:codes="63"
|
android:codes="63"
|
||||||
android:keyLabel="\?" />
|
android:keyLabel="\?" />
|
||||||
<!--delete-->
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="-5"
|
android:codes="-5"
|
||||||
android:isModifier="true"
|
android:isModifier="true"
|
||||||
android:isRepeatable="true"
|
android:isRepeatable="true"
|
||||||
android:keyWidth="14.25%"
|
android:keyWidth="14.25%"
|
||||||
android:keyEdgeFlags="right" />
|
android:keyEdgeFlags="right"
|
||||||
|
android:keyLabel="" />
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
<Row
|
<Row
|
||||||
@ -153,7 +165,7 @@
|
|||||||
<Key
|
<Key
|
||||||
android:codes="32"
|
android:codes="32"
|
||||||
android:keyWidth="29.5%"
|
android:keyWidth="29.5%"
|
||||||
android:keyLabel="English" />
|
android:keyLabel="Space" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="47"
|
android:codes="47"
|
||||||
@ -163,7 +175,6 @@
|
|||||||
android:codes="46"
|
android:codes="46"
|
||||||
android:keyLabel="." />
|
android:keyLabel="." />
|
||||||
|
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="-4"
|
android:codes="-4"
|
||||||
android:keyWidth="14.25%"
|
android:keyWidth="14.25%"
|
||||||
@ -8,71 +8,90 @@
|
|||||||
android:keyHeight="50dp"
|
android:keyHeight="50dp"
|
||||||
android:rowEdgeFlags="top">
|
android:rowEdgeFlags="top">
|
||||||
<Key
|
<Key
|
||||||
android:codes="113"
|
android:codes="81"
|
||||||
android:keyEdgeFlags="left"
|
android:keyEdgeFlags="left"
|
||||||
android:keyLabel="Q" />
|
android:keyLabel="Q" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="119"
|
android:codes="87"
|
||||||
android:keyLabel="W" />
|
android:keyLabel="W" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="101"
|
android:codes="69"
|
||||||
android:keyLabel="E" />
|
android:keyLabel="E" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="114"
|
android:codes="82"
|
||||||
android:keyLabel="R" />
|
android:keyLabel="R" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="116"
|
android:codes="84"
|
||||||
android:keyLabel="T" />
|
android:keyLabel="T" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="121"
|
android:codes="89"
|
||||||
android:keyLabel="Y" />
|
android:keyLabel="Y" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="117"
|
android:codes="85"
|
||||||
android:keyLabel="U" />
|
android:keyLabel="U" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="105"
|
android:codes="73"
|
||||||
android:keyLabel="I" />
|
android:keyLabel="I" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="111"
|
android:codes="79"
|
||||||
android:keyLabel="O" />
|
android:keyLabel="O" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="112"
|
android:codes="80"
|
||||||
android:keyEdgeFlags="right"
|
android:keyEdgeFlags="right"
|
||||||
android:keyLabel="P" />
|
android:keyLabel="P" />
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
<Row
|
<Row
|
||||||
android:horizontalGap="0.5%"
|
android:horizontalGap="0.5%"
|
||||||
android:keyWidth="9.444444%"
|
android:keyWidth="9.444444%"
|
||||||
android:keyHeight="50dp">
|
android:keyHeight="50dp">
|
||||||
<Key
|
<Key
|
||||||
android:codes="97"
|
android:codes="65"
|
||||||
android:horizontalGap="5.5%"
|
android:horizontalGap="5.5%"
|
||||||
android:keyLabel="A" />
|
android:keyLabel="A" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="115"
|
android:codes="83"
|
||||||
android:keyLabel="S" />
|
android:keyLabel="S" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="100"
|
android:codes="68"
|
||||||
android:keyLabel="D" />
|
android:keyLabel="D" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="102"
|
android:codes="70"
|
||||||
android:keyLabel="F" />
|
android:keyLabel="F" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="103"
|
android:codes="71"
|
||||||
android:keyLabel="G" />
|
android:keyLabel="G" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="104"
|
android:codes="72"
|
||||||
android:keyLabel="H" />
|
android:keyLabel="H" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="106"
|
android:codes="74"
|
||||||
android:keyLabel="J" />
|
android:keyLabel="J" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="107"
|
android:codes="75"
|
||||||
android:keyLabel="K" />
|
android:keyLabel="K" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="108"
|
android:codes="76"
|
||||||
android:keyLabel="L" />
|
android:keyLabel="L" />
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
<Row
|
<Row
|
||||||
android:horizontalGap="0.5%"
|
android:horizontalGap="0.5%"
|
||||||
android:keyWidth="9.5%"
|
android:keyWidth="9.5%"
|
||||||
@ -83,27 +102,35 @@
|
|||||||
android:isModifier="true"
|
android:isModifier="true"
|
||||||
android:isSticky="true"
|
android:isSticky="true"
|
||||||
android:keyWidth="14.25%"
|
android:keyWidth="14.25%"
|
||||||
android:keyEdgeFlags="left" />
|
android:keyEdgeFlags="left"
|
||||||
|
android:keyLabel="Shift" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="122"
|
android:codes="90"
|
||||||
android:keyLabel="Z" />
|
android:keyLabel="Z" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="120"
|
android:codes="88"
|
||||||
android:keyLabel="X" />
|
android:keyLabel="X" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="99"
|
android:codes="67"
|
||||||
android:keyLabel="C" />
|
android:keyLabel="C" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="118"
|
android:codes="86"
|
||||||
android:keyLabel="V" />
|
android:keyLabel="V" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="98"
|
android:codes="66"
|
||||||
android:keyLabel="B" />
|
android:keyLabel="B" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="110"
|
android:codes="78"
|
||||||
android:keyLabel="N" />
|
android:keyLabel="N" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="109"
|
android:codes="77"
|
||||||
android:keyLabel="M" />
|
android:keyLabel="M" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
@ -111,7 +138,8 @@
|
|||||||
android:isModifier="true"
|
android:isModifier="true"
|
||||||
android:isRepeatable="true"
|
android:isRepeatable="true"
|
||||||
android:keyWidth="14.25%"
|
android:keyWidth="14.25%"
|
||||||
android:keyEdgeFlags="right" />
|
android:keyEdgeFlags="right"
|
||||||
|
android:keyLabel="" />
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
<Row
|
<Row
|
||||||
@ -132,13 +160,12 @@
|
|||||||
<Key
|
<Key
|
||||||
android:codes="32"
|
android:codes="32"
|
||||||
android:keyWidth="49.5%"
|
android:keyWidth="49.5%"
|
||||||
android:keyLabel="English" />
|
android:keyLabel="Space" />
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="46"
|
android:codes="46"
|
||||||
android:keyLabel="." />
|
android:keyLabel="." />
|
||||||
|
|
||||||
|
|
||||||
<Key
|
<Key
|
||||||
android:codes="-4"
|
android:codes="-4"
|
||||||
android:keyWidth="14.25%"
|
android:keyWidth="14.25%"
|
||||||
@ -146,4 +173,5 @@
|
|||||||
android:keyLabel="Done" />
|
android:keyLabel="Done" />
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
|
|
||||||
</Keyboard>
|
</Keyboard>
|
||||||
@ -1,5 +1,5 @@
|
|||||||
[versions]
|
[versions]
|
||||||
agp = "8.5.1"
|
agp = "8.8.0"
|
||||||
junit = "4.13.2"
|
junit = "4.13.2"
|
||||||
junitVersion = "1.2.1"
|
junitVersion = "1.2.1"
|
||||||
espressoCore = "3.6.1"
|
espressoCore = "3.6.1"
|
||||||
|
|||||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
|||||||
#Fri Sep 06 10:10:49 CST 2024
|
#Fri Sep 06 10:10:49 CST 2024
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
distributionUrl=https\://mirrors.huaweicloud.com/repository/toolkit/gradle/gradle-8.10.2-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user