V1.0.0(1)完成版

This commit is contained in:
lihongwei 2024-12-13 15:50:43 +08:00
parent 657243bed0
commit 5c38587a1b
92 changed files with 9770 additions and 183 deletions

BIN
app/KeyboardStyle.jks Normal file

Binary file not shown.

View File

@ -17,7 +17,7 @@ android {
versionName = "1.0.0"
setProperty(
"archivesBaseName",
"Keyboard Style" + versionName + "(${versionCode})_$timestamp"
"Keyboard Style_" + versionName + "(${versionCode})_$timestamp"
)
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
@ -50,4 +50,14 @@ dependencies {
testImplementation(libs.junit)
androidTestImplementation(libs.ext.junit)
androidTestImplementation(libs.espresso.core)
implementation("com.github.bumptech.glide:glide:4.16.0")
annotationProcessor("com.github.bumptech.glide:compiler:4.16.0")
implementation ("androidx.room:room-runtime:2.6.1")
annotationProcessor ("androidx.room:room-compiler:2.6.1")
implementation("com.github.omicronapps:7-Zip-JBinding-4Android:Release-16.02-2.02")
}

6
app/keystore.properties Normal file
View File

@ -0,0 +1,6 @@
app_name=Keyboard Style
package_name=com.key.keyboardstyle
keystoreFile=app/KeyboardStyle.jks
key_alias=KeyboardStylekey0
key_store_password=KeyboardStyle
key_password=KeyboardStyle

View File

@ -18,4 +18,19 @@
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
#-renamesourcefileattribute SourceFile
-keepclassmembers class com.key.keyboardstyle.MyApplication {
public static final java.lang.String Db_Name;
public static final int Db_Version;
}
-keepclassmembers class * {
@androidx.room.Query <methods>;
}
-keep class com.key.keyboardstyle.room.AppDatabase { *; }
-keep class com.key.keyboardstyle.room.KeyboardWallpaper { *; }
-keep class com.key.keyboardstyle.room.KeyboardWallpaperDao { *; }
-keep class com.key.keyboardstyle.room.Category { *; }
-keep class com.omicronapplications.** { *; }
-keep class net.sf.sevenzipjbinding.** { *; }

View File

@ -2,7 +2,11 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:name=".MyApplication"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
@ -12,8 +16,23 @@
android:supportsRtl="true"
android:theme="@style/Theme.KeyboardStyle"
tools:targetApi="31">
<activity
android:name=".activity.TestActivity"
android:exported="false" />
<activity
android:name=".activity.DownloadActivity"
android:exported="false" />
<activity
android:name=".activity.CategoryActivity"
android:exported="false" />
<activity
android:name=".activity.SearchActivity"
android:exported="false" />
<activity
android:name=".activity.MainActivity"
android:exported="false" />
<activity
android:name=".activity.SplashActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@ -21,6 +40,20 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".keyboard.KeyboardService"
android:enabled="true"
android:exported="true"
android:permission="android.permission.BIND_INPUT_METHOD">
<intent-filter>
<action android:name="android.view.InputMethod" />
</intent-filter>
<meta-data
android:name="android.view.im"
android:resource="@xml/im" />
</service>
</application>
</manifest>

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

View File

@ -2,10 +2,20 @@ package com.key.keyboardstyle;
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import com.key.keyboardstyle.utils.DatabaseUtils;
import java.util.concurrent.Executors;
public class MyApplication extends Application {
private static Application application;
public static String PATH = "";
public static final int Db_Version = 1;
public static final String Db_Name = "Keyboard_Wallpaper";
private static final String PREF_NAME = "preferences";
private static final String KEY_INITIALIZED = "init";
@Override
public void onCreate() {
@ -13,9 +23,29 @@ public class MyApplication extends Application {
application = this;
SharedPreferences preferences = getSharedPreferences(PREF_NAME, MODE_PRIVATE);
boolean init = preferences.getBoolean(KEY_INITIALIZED, false);
if (!init) {
initDatabase();
preferences.edit().putBoolean(KEY_INITIALIZED, true).apply();
}
}
public static Application getApplication() {
return application;
}
public static Context getContext() {
return application.getApplicationContext();
}
private void initDatabase() {
Executors.newSingleThreadExecutor().execute(() -> {
DatabaseUtils databaseUtil = new DatabaseUtils(getContext());
databaseUtil.insertAll();
});
}
}

View File

@ -0,0 +1,101 @@
package com.key.keyboardstyle.activity;
import android.os.Bundle;
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 androidx.lifecycle.Observer;
import androidx.recyclerview.widget.GridLayoutManager;
import com.key.keyboardstyle.R;
import com.key.keyboardstyle.adapter.StyleAdapter;
import com.key.keyboardstyle.databinding.ActivityCategoryBinding;
import com.key.keyboardstyle.room.KeyboardWallpaper;
import com.key.keyboardstyle.utils.DatabaseUtils;
import com.key.keyboardstyle.utils.ItemDecoration;
import java.util.ArrayList;
import java.util.List;
public class CategoryActivity extends AppCompatActivity {
private ActivityCategoryBinding binding;
private StyleAdapter adapter;
private String title;
private KeyboardWallpaper keyboardWallpaper;
private DatabaseUtils databaseUtils;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityCategoryBinding.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;
});
initData();
initEvent();
}
private void initData() {
keyboardWallpaper = (KeyboardWallpaper) getIntent().getSerializableExtra("KeyboardWallpaper");
if (keyboardWallpaper == null) {
finish();
return;
}
databaseUtils = new DatabaseUtils(this);
title = keyboardWallpaper.getClassName();
binding.recyclerView.setLayoutManager(new GridLayoutManager(this, 2));
adapter = new StyleAdapter(this, this, new ArrayList<>(), 2);
binding.recyclerView.setAdapter(adapter);
ItemDecoration itemDecoration = new ItemDecoration(16, 19, 10);
binding.recyclerView.addItemDecoration(itemDecoration);
}
private void initEvent() {
binding.title.setText(capitalizeFirstLetter(title));
binding.back.setOnClickListener(v -> finish());
loadCategory();
}
private void loadCategory() {
databaseUtils
.getCategory(title)
.observe(this, new Observer<List<KeyboardWallpaper>>() {
@Override
public void onChanged(List<KeyboardWallpaper> keyboardWallpapers) {
adapter.updateData(keyboardWallpapers);
}
});
}
private String capitalizeFirstLetter(String text) {
if (text == null || text.isEmpty()) {
return text;
}
return text.substring(0, 1).toUpperCase() + text.substring(1);
}
@Override
protected void onDestroy() {
super.onDestroy();
binding = null;
}
}

View File

@ -0,0 +1,174 @@
package com.key.keyboardstyle.activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.Toast;
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 androidx.lifecycle.Observer;
import androidx.recyclerview.widget.GridLayoutManager;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.key.keyboardstyle.MyApplication;
import com.key.keyboardstyle.R;
import com.key.keyboardstyle.adapter.StyleAdapter;
import com.key.keyboardstyle.databinding.ActivityDownloadBinding;
import com.key.keyboardstyle.dialog.PermissionRequestDialog;
import com.key.keyboardstyle.room.AppDatabase;
import com.key.keyboardstyle.room.KeyboardWallpaper;
import com.key.keyboardstyle.utils.DatabaseUtils;
import com.key.keyboardstyle.utils.ItemDecoration;
import com.key.keyboardstyle.utils.KeyboardUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class DownloadActivity extends AppCompatActivity {
private ActivityDownloadBinding binding;
private KeyboardWallpaper keyboardWallpaper;
private DatabaseUtils databaseUtils;
private StyleAdapter adapter;
private String zipPath;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityDownloadBinding.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;
});
initData();
initEvent();
}
private void initData() {
keyboardWallpaper = (KeyboardWallpaper) getIntent().getSerializableExtra("KeyboardWallpaper");
if (keyboardWallpaper == null) {
finish();
return;
}
databaseUtils = new DatabaseUtils(this);
zipPath = keyboardWallpaper.getZipUrl();
binding.recommended.setLayoutManager(new GridLayoutManager(this, 2));
adapter = new StyleAdapter(this, this, new ArrayList<>(), 2);
binding.recommended.setAdapter(adapter);
ItemDecoration itemDecoration = new ItemDecoration(16, 19, 10);
binding.recommended.addItemDecoration(itemDecoration);
}
private void initEvent() {
binding.back.setOnClickListener(v -> finish());
binding.title.setText(keyboardWallpaper.getTitle());
binding.home.setOnClickListener(v -> {
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
});
binding.download.setOnClickListener(v -> download());
loadDownloadImage();
loadRecommend();
}
private void loadDownloadImage() {
Glide.with(this)
.load(keyboardWallpaper.getThumb())
.transform(new RoundedCorners(32))
.error(R.mipmap.placeholder)
.placeholder(R.mipmap.placeholder)
.into(binding.image);
}
private void loadRecommend() {
int offset = new Random().nextInt(800);
databaseUtils
.getRecommended(20, offset)
.observe(this, new Observer<List<KeyboardWallpaper>>() {
@Override
public void onChanged(List<KeyboardWallpaper> keyboardWallpapers) {
adapter.updateData(keyboardWallpapers);
}
});
}
private void download() {
show();
if (!KeyboardUtils.isStep1() || !KeyboardUtils.isStep2()) {
PermissionRequestDialog dialog = new PermissionRequestDialog();
dialog.show(getSupportFragmentManager(), "PermissionRequestDialog");
hide();
} else {
KeyboardUtils.downloadAndUnzip(this, zipPath, (successful, resource) -> {
if (successful) {
KeyboardUtils.unzip(this, resource, (successful1, resDirPath) -> {
if (successful1) {
SharedPreferences sharedPreferences = getSharedPreferences("keyboard_prefs", MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("wallpaper_path", resDirPath);
editor.apply();
MyApplication.PATH = resDirPath;
if (keyboardWallpaper != null) {
keyboardWallpaper.setPath(resDirPath);
keyboardWallpaper.setDownloaded(true);
KeyboardUtils.runIO(() -> AppDatabase.getInstance(this).keyboardWallpaperDao().update(keyboardWallpaper));
}
} else {
runOnUiThread(() -> {
Toast.makeText(DownloadActivity.this, "Decompression failure", Toast.LENGTH_SHORT).show();
});
}
runOnUiThread(() -> {
hide();
Intent intent = new Intent(DownloadActivity.this, TestActivity.class);
startActivity(intent);
});
});
} else {
runOnUiThread(this::hide);
}
});
}
}
private void show() {
binding.progressBar.setVisibility(View.VISIBLE);
binding.view.setVisibility(View.VISIBLE);
}
private void hide() {
binding.progressBar.setVisibility(View.GONE);
binding.view.setVisibility(View.GONE);
}
@Override
protected void onDestroy() {
super.onDestroy();
binding = null;
}
}

View File

@ -1,6 +1,8 @@
package com.key.keyboardstyle.activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
@ -8,8 +10,12 @@ 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.keyboardstyle.R;
import com.key.keyboardstyle.adapter.MainAdapter;
import com.key.keyboardstyle.databinding.ActivityMainBinding;
import com.key.keyboardstyle.databinding.ItemTabLayoutCustomBinding;
public class MainActivity extends AppCompatActivity {
@ -32,9 +38,87 @@ public class MainActivity extends AppCompatActivity {
}
private void initData() {
MainAdapter adapter = new MainAdapter(this);
binding.viewPager2.setAdapter(adapter);
}
private void initEvent() {
binding.viewPager2.setUserInputEnabled(false);
new TabLayoutMediator(binding.tabLayout, binding.viewPager2, (tab, position) -> {
ItemTabLayoutCustomBinding tabBinding = ItemTabLayoutCustomBinding.inflate(LayoutInflater.from(this));
tab.setCustomView(tabBinding.getRoot());
setTabIconAndDotVisibility(tabBinding, position);
}).attach();
binding.tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
updateTabIcon(tab, true);
showDot(tab);
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
updateTabIcon(tab, false);
hideDot(tab);
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
private void updateTabIcon(TabLayout.Tab tab, boolean isSelected) {
if (tab.getCustomView() != null) {
ItemTabLayoutCustomBinding tabBinding = ItemTabLayoutCustomBinding.bind(tab.getCustomView());
int iconResId = getIconResource(tab.getPosition(), isSelected);
tabBinding.iconCustom.setImageResource(iconResId);
}
}
private int getIconResource(int position, boolean isSelected) {
switch (position) {
case 1:
return R.drawable.collection;
case 2:
return R.drawable.setting;
default:
return R.drawable.category;
}
}
});
}
private void setTabIconAndDotVisibility(ItemTabLayoutCustomBinding tabBinding, int position) {
switch (position) {
case 1:
tabBinding.iconCustom.setImageResource(R.drawable.collection);
break;
case 2:
tabBinding.iconCustom.setImageResource(R.drawable.setting);
break;
default:
tabBinding.iconCustom.setImageResource(R.drawable.category);
tabBinding.dotView.setVisibility(View.VISIBLE);
break;
}
}
private void showDot(TabLayout.Tab tab) {
View dotView = tab.view.findViewById(R.id.dot_view);
if (dotView != null) {
dotView.setVisibility(View.VISIBLE);
}
}
private void hideDot(TabLayout.Tab tab) {
View dotView = tab.view.findViewById(R.id.dot_view);
if (dotView != null) {
dotView.setVisibility(View.GONE);
}
}

View File

@ -0,0 +1,101 @@
package com.key.keyboardstyle.activity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
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 androidx.recyclerview.widget.GridLayoutManager;
import com.key.keyboardstyle.R;
import com.key.keyboardstyle.adapter.StyleAdapter;
import com.key.keyboardstyle.databinding.ActivitySearchBinding;
import com.key.keyboardstyle.room.KeyboardWallpaper;
import com.key.keyboardstyle.utils.DatabaseUtils;
import com.key.keyboardstyle.utils.ItemDecoration;
import java.util.ArrayList;
import java.util.List;
public class SearchActivity extends AppCompatActivity {
private ActivitySearchBinding binding;
private StyleAdapter adapter;
private DatabaseUtils databaseUtils;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivitySearchBinding.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;
});
initData();
initEvent();
}
private void initData() {
databaseUtils = new DatabaseUtils(this);
binding.recyclerView.setLayoutManager(new GridLayoutManager(this, 2));
adapter = new StyleAdapter(this, this, new ArrayList<>(), 2);
binding.recyclerView.setAdapter(adapter);
ItemDecoration itemDecoration = new ItemDecoration(16, 19, 10);
binding.recyclerView.addItemDecoration(itemDecoration);
}
private void initEvent() {
binding.back.setOnClickListener(v -> finish());
binding.editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
getAllSearch(charSequence.toString());
}
@Override
public void afterTextChanged(Editable editable) {
}
});
}
private void getAllSearch(String title) {
new Thread(new Runnable() {
@Override
public void run() {
List<KeyboardWallpaper> keyboardWallpapers = databaseUtils.getAllSearch(title);
runOnUiThread(new Runnable() {
@Override
public void run() {
adapter.updateData(keyboardWallpapers);
}
});
}
}).start();
}
@Override
protected void onDestroy() {
super.onDestroy();
binding = null;
}
}

View File

@ -0,0 +1,77 @@
package com.key.keyboardstyle.activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.widget.ProgressBar;
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.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.key.keyboardstyle.R;
import com.key.keyboardstyle.databinding.ActivitySplashBinding;
public class SplashActivity extends AppCompatActivity {
private ActivitySplashBinding binding;
private static final long TOTAL_TIME = 3000;
private CountDownTimer countDownTimer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivitySplashBinding.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;
});
Glide.with(this)
.load(R.mipmap.ic_launcher)
.transform(new RoundedCorners(16))
.into(binding.splashImage);
countDownTimer = new CountDownTimer(TOTAL_TIME,100) {
@Override
public void onTick(long millisUntilFinished) {
int percentage = (int) (100 - (float) millisUntilFinished / TOTAL_TIME * 100);
binding.progressBar.setProgress(percentage);
}
@Override
public void onFinish() {
startMain();
}
};
countDownTimer.start();
}
private void startMain() {
binding.progressBar.setProgress(100);
Intent intent = new Intent(SplashActivity.this, MainActivity.class);
startActivity(intent);
finish();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (countDownTimer != null) {
countDownTimer.cancel();
}
binding = null;
}
}

View File

@ -0,0 +1,58 @@
package com.key.keyboardstyle.activity;
import android.content.Context;
import android.os.Bundle;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
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.key.keyboardstyle.R;
import com.key.keyboardstyle.databinding.ActivityTestBinding;
public class TestActivity extends AppCompatActivity {
private ActivityTestBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityTestBinding.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;
});
binding.back.setOnClickListener(v -> finish());
}
@Override
protected void onResume() {
super.onResume();
binding.edit.requestFocus();
binding.edit.postDelayed(new Runnable() {
@Override
public void run() {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(binding.edit, InputMethodManager.SHOW_IMPLICIT);
}
}, 200);
}
@Override
protected void onDestroy() {
super.onDestroy();
binding = null;
}
}

View File

@ -0,0 +1,39 @@
package com.key.keyboardstyle.adapter;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import com.key.keyboardstyle.fragment.CategoryFragment;
import com.key.keyboardstyle.fragment.FavoriteFragment;
import com.key.keyboardstyle.fragment.SettingFragment;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class MainAdapter extends FragmentStateAdapter {
private final List<Fragment> fragments;
public MainAdapter(@NonNull FragmentActivity fragmentActivity) {
super(fragmentActivity);
fragments = new ArrayList<>(Arrays.asList(
new CategoryFragment(),
new FavoriteFragment(),
new SettingFragment()
));
}
@NonNull
@Override
public Fragment createFragment(int position) {
return fragments.get(position);
}
@Override
public int getItemCount() {
return fragments.size();
}
}

View File

@ -0,0 +1,160 @@
package com.key.keyboardstyle.adapter;
import android.app.Activity;
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 android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.ListAdapter;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.Key;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.key.keyboardstyle.R;
import com.key.keyboardstyle.activity.CategoryActivity;
import com.key.keyboardstyle.activity.DownloadActivity;
import com.key.keyboardstyle.room.AppDatabase;
import com.key.keyboardstyle.room.KeyboardWallpaper;
import com.key.keyboardstyle.utils.DatabaseUtils;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
public class StyleAdapter extends RecyclerView.Adapter<StyleAdapter.StyleViewHolder> {
private final Context context;
private final Activity activity;
private List<KeyboardWallpaper> keyboardWallpapers;
private final int type;
private final DatabaseUtils databaseUtils;
private final Executor executor = Executors.newSingleThreadExecutor();
public StyleAdapter(Context context, Activity activity, List<KeyboardWallpaper> keyboardWallpapers, int type) {
super();
this.context = context;
this.activity = activity;
this.keyboardWallpapers = keyboardWallpapers;
this.type = type;
this.databaseUtils = new DatabaseUtils(context);
}
public void updateData(List<KeyboardWallpaper> newKeyboardWallpapers) {
this.keyboardWallpapers = newKeyboardWallpapers;
notifyDataSetChanged();
}
@NonNull
@Override
public StyleViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.item_wallpaper, parent, false);
return new StyleViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull StyleViewHolder holder, int position) {
KeyboardWallpaper keyboardWallpaper = keyboardWallpapers.get(position);
holder.bind(keyboardWallpaper);
}
@Override
public int getItemCount() {
return keyboardWallpapers.size();
}
public class StyleViewHolder extends RecyclerView.ViewHolder {
private final ImageView imageView;
private final ImageView favorite;
private final TextView textView;
public StyleViewHolder(View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.image_wallpaper);
favorite = itemView.findViewById(R.id.favorite_wallpaper);
this.textView = itemView.findViewById(R.id.title_wallpaper);
}
void bind(KeyboardWallpaper keyboardWallpaper) {
String imagePath = keyboardWallpaper.getPreview();
loadImage(imagePath);
setText(keyboardWallpaper);
setFavoriteButton(keyboardWallpaper);
setClickListeners(keyboardWallpaper);
}
private void loadImage(String imagePath) {
Glide.with(context)
.load(imagePath)
.transform(new RoundedCorners(32))
.error(R.mipmap.placeholder)
.placeholder(R.mipmap.placeholder)
.into(imageView);
}
private void setText(KeyboardWallpaper keyboardWallpaper) {
String text;
if (type == 1) {
text = keyboardWallpaper.getClassName();
} else {
text = keyboardWallpaper.getTitle();
}
textView.setText(capitalizeFirstLetter(text));
}
private void setFavoriteButton(KeyboardWallpaper keyboardWallpaper) {
favorite.setImageResource(keyboardWallpaper.getFavorite()
? R.drawable.favorite
: R.drawable.un_favorite);
}
private void setClickListeners(KeyboardWallpaper keyboardWallpaper) {
imageView.setOnClickListener(v -> {
Intent intent;
if (type == 1) {
intent = new Intent(context, CategoryActivity.class);
} else {
intent = new Intent(context, DownloadActivity.class);
}
intent.putExtra("KeyboardWallpaper", keyboardWallpaper);
activity.startActivity(intent);
});
favorite.setOnClickListener(v -> toggleFavorite(keyboardWallpaper));
}
private void toggleFavorite(KeyboardWallpaper keyboardWallpaper) {
boolean newStatus = !keyboardWallpaper.getFavorite();
keyboardWallpaper.setFavorite(newStatus);
updateImageInDatabase(keyboardWallpaper);
notifyItemChanged(getAdapterPosition());
}
private void updateImageInDatabase(KeyboardWallpaper keyboardWallpaper) {
executor.execute(() -> {
databaseUtils.update(keyboardWallpaper);
});
}
private String capitalizeFirstLetter(String text) {
if (text == null || text.isEmpty()) {
return text;
}
return text.substring(0, 1).toUpperCase() + text.substring(1);
}
}
}

View File

@ -0,0 +1,9 @@
package com.key.keyboardstyle.callback;
import java.io.File;
import java.io.IOException;
public interface DownloadCallback {
void onDownloadCall(boolean successful, File resource) throws IOException;
}

View File

@ -0,0 +1,6 @@
package com.key.keyboardstyle.callback;
public interface UnzipCallback {
void onUnzipCall(boolean successful, String resDirPath);
}

View File

@ -0,0 +1,120 @@
package com.key.keyboardstyle.dialog;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.database.ContentObserver;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.key.keyboardstyle.MyApplication;
import com.key.keyboardstyle.R;
import com.key.keyboardstyle.databinding.DialogPermissionBinding;
import com.key.keyboardstyle.utils.KeyboardUtils;
public class PermissionRequestDialog extends DialogFragment {
private DialogPermissionBinding binding;
private InputMethodManager methodManager;
private ContentObserver inputMethodObserver;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = DialogPermissionBinding.inflate(inflater, container, false);
init();
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() {
methodManager = (InputMethodManager) MyApplication.getApplication().getSystemService(Context.INPUT_METHOD_SERVICE);
Glide.with(requireContext())
.load(R.mipmap.ic_launcher_foreground)
.transform(new RoundedCorners(16))
.into(binding.imageView);
binding.step1.setOnClickListener(v -> {
Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS);
startActivity(intent);
});
binding.step2.setOnClickListener(v -> {
methodManager.showInputMethodPicker();
});
binding.imageView.setOnClickListener(v -> dismiss());
inputMethodObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
if (KeyboardUtils.isStep1() && KeyboardUtils.isStep2()) {
dismiss();
}
}
};
requireContext().getContentResolver().registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.DEFAULT_INPUT_METHOD),
false,
inputMethodObserver
);
}
public void update() {
if (KeyboardUtils.isStep1()) {
binding.step1.setSelected(KeyboardUtils.isStep1());
binding.step1.setClickable(false);
}
if (KeyboardUtils.isStep2()) {
binding.step2.setSelected(KeyboardUtils.isStep2());
binding.step2.setClickable(false);
}
if (KeyboardUtils.isStep1() && KeyboardUtils.isStep2()) {
dismiss();
}
}
@Override
public void onDestroy() {
super.onDestroy();
if (inputMethodObserver != null) {
requireContext().getContentResolver().unregisterContentObserver(inputMethodObserver);
}
binding = null;
}
}

View File

@ -0,0 +1,103 @@
package com.key.keyboardstyle.fragment;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.key.keyboardstyle.activity.SearchActivity;
import com.key.keyboardstyle.adapter.StyleAdapter;
import com.key.keyboardstyle.databinding.FragmentCategoryBinding;
import com.key.keyboardstyle.room.KeyboardWallpaper;
import com.key.keyboardstyle.utils.DatabaseUtils;
import com.key.keyboardstyle.utils.ItemDecoration;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class CategoryFragment extends Fragment {
private FragmentCategoryBinding binding;
private StyleAdapter categoryAdapter, recommendedAdapter;
private DatabaseUtils databaseUtils;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
binding = FragmentCategoryBinding.inflate(inflater, container, false);
initData();
initEvent();
return binding.getRoot();
}
private void initData() {
databaseUtils = new DatabaseUtils(requireContext());
binding.category.setLayoutManager(new GridLayoutManager(requireContext(), 1, LinearLayoutManager.HORIZONTAL,false));
binding.recommended.setLayoutManager(new GridLayoutManager(requireContext(), 2));
categoryAdapter = new StyleAdapter(requireContext(), requireActivity(), new ArrayList<>(), 1);
recommendedAdapter = new StyleAdapter(requireContext(), requireActivity(), new ArrayList<>(), 2);
binding.category.setAdapter(categoryAdapter);
binding.recommended.setAdapter(recommendedAdapter);
ItemDecoration itemDecorationCategory = new ItemDecoration(0, 0, 5);
ItemDecoration itemDecorationRecommended = new ItemDecoration(16, 19, 10);
binding.category.addItemDecoration(itemDecorationCategory);
binding.recommended.addItemDecoration(itemDecorationRecommended);
}
private void initEvent() {
binding.search.setOnClickListener(v -> {
Intent intent = new Intent(requireContext(), SearchActivity.class);
requireActivity().startActivity(intent);
});
loadAllFirstCategory();
loadRecommend();
}
private void loadAllFirstCategory() {
databaseUtils
.getAllFirstCategory()
.observe(getViewLifecycleOwner(), new Observer<List<KeyboardWallpaper>>() {
@Override
public void onChanged(List<KeyboardWallpaper> keyboardWallpapers) {
categoryAdapter.updateData(keyboardWallpapers);
}
});
}
private void loadRecommend() {
int offset = new Random().nextInt(800);
databaseUtils
.getRecommended(20, offset)
.observe(getViewLifecycleOwner(), new Observer<List<KeyboardWallpaper>>() {
@Override
public void onChanged(List<KeyboardWallpaper> keyboardWallpapers) {
recommendedAdapter.updateData(keyboardWallpapers);
}
});
}
@Override
public void onDestroy() {
super.onDestroy();
binding = null;
}
}

View File

@ -0,0 +1,79 @@
package com.key.keyboardstyle.fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.recyclerview.widget.GridLayoutManager;
import com.key.keyboardstyle.adapter.StyleAdapter;
import com.key.keyboardstyle.databinding.FragmentFavoriteBinding;
import com.key.keyboardstyle.room.KeyboardWallpaper;
import com.key.keyboardstyle.utils.DatabaseUtils;
import com.key.keyboardstyle.utils.ItemDecoration;
import java.util.ArrayList;
import java.util.List;
public class FavoriteFragment extends Fragment {
private FragmentFavoriteBinding binding;
private DatabaseUtils databaseUtils;
private StyleAdapter adapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
binding = FragmentFavoriteBinding.inflate(inflater, container, false);
initData();
initEvent();
return binding.getRoot();
}
private void initData() {
databaseUtils = new DatabaseUtils(requireContext());
binding.recyclerView.setLayoutManager(new GridLayoutManager(requireContext(), 2));
adapter = new StyleAdapter(requireContext(), requireActivity(), new ArrayList<>(), 2);
binding.recyclerView.setAdapter(adapter);
ItemDecoration itemDecoration = new ItemDecoration(16, 19, 10);
binding.recyclerView.addItemDecoration(itemDecoration);
}
private void initEvent() {
lodAllFavorite();
}
private void lodAllFavorite() {
databaseUtils
.getAllFavorite()
.observe(getViewLifecycleOwner(), new Observer<List<KeyboardWallpaper>>() {
@Override
public void onChanged(List<KeyboardWallpaper> keyboardWallpapers) {
if (keyboardWallpapers.isEmpty()) {
binding.backgroundText.setVisibility(View.VISIBLE);
} else {
binding.backgroundText.setVisibility(View.GONE);
}
adapter.updateData(keyboardWallpapers);
}
});
}
@Override
public void onDestroy() {
super.onDestroy();
binding = null;
}
}

View File

@ -0,0 +1,44 @@
package com.key.keyboardstyle.fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.fragment.app.Fragment;
import com.key.keyboardstyle.databinding.FragmentSettingBinding;
import com.key.keyboardstyle.utils.SettingUtils;
public class SettingFragment extends Fragment {
private FragmentSettingBinding binding;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
binding = FragmentSettingBinding.inflate(inflater, container, false);
initData();
initEvent();
return binding.getRoot();
}
private void initData() {
}
private void initEvent() {
binding.version.setText(SettingUtils.getCurrentVersion(requireContext()));
binding.share.setOnClickListener(v -> SettingUtils.shareApp(requireContext()));
}
@Override
public void onDestroy() {
super.onDestroy();
binding = null;
}
}

View File

@ -0,0 +1,174 @@
package com.key.keyboardstyle.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.Xml;
import androidx.core.content.ContextCompat;
import com.key.keyboardstyle.MyApplication;
import com.key.keyboardstyle.R;
import com.key.keyboardstyle.utils.KeyboardUtils;
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(MyApplication.getApplication(), android.R.drawable.stat_sys_upload);
private Drawable iconDel = ContextCompat.getDrawable(MyApplication.getApplication(), android.R.drawable.ic_input_delete);
private Drawable BG = ContextCompat.getDrawable(MyApplication.getApplication(), R.color.black);
private int keyNormalColor = MyApplication.getApplication().getResources().getColor(R.color.white, null);
private int keyActionColor = MyApplication.getApplication().getResources().getColor(R.color.white, null);
private Drawable iconShiftLock = ContextCompat.getDrawable(MyApplication.getApplication(), 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 getKeyNormalColor() {
return keyNormalColor;
}
public int getKeyActionColor() {
return keyActionColor;
}
public void init() {
}
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;
}
return new BitmapDrawable(context.getResources(), BitmapFactory.decodeFile(filePath));
}
private Drawable getBackGround(Context context, String resDirPath) {
String filePath = resDirPath + path_drawxxh + jpg_BG;
if (!new File(filePath).exists()) {
return null;
}
return new BitmapDrawable(context.getResources(), BitmapFactory.decodeFile(filePath));
}
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 = KeyboardUtils.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)) {
keyNormalColor = Color.parseColor(xmlPullParser.nextText());
}
if (value.equals(color_action_key)) {
keyActionColor = Color.parseColor(xmlPullParser.nextText());
}
}
eventT = xmlPullParser.next();
}
} catch (XmlPullParserException ignored) {
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void updateConfig(Context con) {
String resDirPath = getSavedWallpaperPath(MyApplication.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 = context.getSharedPreferences("keyboard_prefs", MODE_PRIVATE);
return sharedPreferences.getString("wallpaper_path", "");
}
}

View File

@ -0,0 +1,136 @@
package com.key.keyboardstyle.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.keyboardstyle.R;
public class KeyboardService extends InputMethodService implements KeyboardView.OnKeyboardActionListener {
private final int[] viewXmlFiles = new int[4];
private MyKeyboard myKeyboard;
private int curImeAction;
public KeyboardService() {
}
@Override
public View onCreateInputView() {
viewXmlFiles[0] = R.xml.view_1;
viewXmlFiles[1] = R.xml.view_2;
viewXmlFiles[2] = R.xml.view_3;
viewXmlFiles[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, viewXmlFiles[0]));
myKeyboard.setOnKeyboardActionListener(this);
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, viewXmlFiles[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() {
}
}

View File

@ -0,0 +1,177 @@
package com.key.keyboardstyle.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.keyboardstyle.utils.KeyboardUtils;
import java.util.List;
public class MyKeyboard extends KeyboardView {
private Paint mPaint;
private int viewType = 0;
private int shiftType = 0;
private CustomViewConfig config;
private int curImeAction;
public MyKeyboard(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public static class KeyBoard extends Keyboard {
public static final int KEYCODE_SHIFT_MORE = -360;
public static final int KEYCODE_SHIFT_123 = -361;
public KeyBoard(Context context, int layoutTemplateResId) {
super(context, layoutTemplateResId);
}
}
public int getShiftType() {
return shiftType;
}
public void setShiftType(int shiftType) {
this.shiftType = shiftType;
}
public void setViewType(int viewType) {
this.viewType = viewType;
}
public int getViewType() {
return viewType;
}
@Override
public void onDraw(Canvas canvas) {
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) {
onDrawKeyBackground(key, config.getBgActionDraw(), canvas);
KeyboardUtils.onDrawKeyIcon(key, getShiftDraw(), canvas, this);
} else if (code == KeyBoard.KEYCODE_SHIFT_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);
KeyboardUtils.onDrawKeyIcon(key, config.getIconDel(), canvas, this);
onDrawLabel(key, canvas, "");
} else {
mPaint.setColor(config.getKeyNormalColor());
onDrawKeyBackground(key, config.getBgNormalDraw(), canvas);
onDrawLabel(key, canvas, "");
}
}
}
private Drawable getShiftDraw() {
if (shiftType == 0) {
return config.getIconShift();
} else {
return config.getIconShiftLock();
}
}
private void initView() {
config = new CustomViewConfig();
mPaint = new Paint();
config.init();
float texSize = KeyboardUtils.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 customLabel) {
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 (!customLabel.isEmpty()) {
float texSize = KeyboardUtils.spToPpx(14f, this.getContext());
mPaint.setTextSize(texSize);
canvas.drawText(customLabel, x1, y1, mPaint);
} else {
float texSize = KeyboardUtils.spToPpx(18f, this.getContext());
mPaint.setTextSize(texSize);
canvas.drawText(myKey.label.toString(), x1, y1, mPaint);
}
}
}
}

View File

@ -0,0 +1,30 @@
package com.key.keyboardstyle.room;
import android.content.Context;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import com.key.keyboardstyle.MyApplication;
@Database(entities = {KeyboardWallpaper.class}, version = MyApplication.Db_Version, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {
public abstract KeyboardWallpaperDao keyboardWallpaperDao();
private static volatile AppDatabase INSTANCE;
public static AppDatabase getInstance(Context context) {
if (INSTANCE == null) {
synchronized (AppDatabase.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
AppDatabase.class, MyApplication.Db_Name)
.build();
}
}
}
return INSTANCE;
}
}

View File

@ -0,0 +1,29 @@
package com.key.keyboardstyle.room;
import java.util.List;
public class Category {
private String className;
private List<KeyboardWallpaper> keyboardWallpapers;
public Category(String className, List<KeyboardWallpaper> keyboardWallpapers) {
this.className = className;
this.keyboardWallpapers = keyboardWallpapers;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public List<KeyboardWallpaper> getKeyboardWallpapers() {
return keyboardWallpapers;
}
public void setKeyboardWallpapers(List<KeyboardWallpaper> keyboardWallpapers) {
this.keyboardWallpapers = keyboardWallpapers;
}
}

View File

@ -0,0 +1,106 @@
package com.key.keyboardstyle.room;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
import java.io.Serializable;
@Entity
public class KeyboardWallpaper implements Serializable {
@PrimaryKey(autoGenerate = true)
public int id;
public String preview;
public String thumb;
public String className;
public String title;
public String zipUrl;
public boolean isFavorite;
public boolean isDownloaded;
public String path;
public KeyboardWallpaper(String preview, String thumb, String className, String title, String zipUrl, boolean isFavorite, boolean isDownloaded, String path) {
this.preview = preview;
this.thumb = thumb;
this.className = className;
this.title = title;
this.zipUrl = zipUrl;
this.isFavorite = isFavorite;
this.isDownloaded = isDownloaded;
this.path = path;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPreview() {
return preview;
}
public void setPreview(String preview) {
this.preview = preview;
}
public String getThumb() {
return thumb;
}
public void setThumb(String thumb) {
this.thumb = thumb;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getZipUrl() {
return zipUrl;
}
public void setZipUrl(String zipUrl) {
this.zipUrl = zipUrl;
}
public boolean getFavorite() {
return isFavorite;
}
public void setFavorite(Boolean favorite) {
isFavorite = favorite;
}
public boolean getDownloaded() {
return isDownloaded;
}
public void setDownloaded(Boolean downloaded) {
isDownloaded = downloaded;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
}

View File

@ -0,0 +1,37 @@
package com.key.keyboardstyle.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 KeyboardWallpaperDao {
@Insert
void insertAll(List<KeyboardWallpaper> keyboardWallpapers);
@Update
void update(KeyboardWallpaper keyboardWallpaper);
@Query("SELECT * FROM KeyboardWallpaper WHERE isFavorite = 1 ")
LiveData<List<KeyboardWallpaper>> getAllFavorite();
@Query("SELECT * FROM KeyboardWallpaper WHERE id IN (SELECT MIN(id) FROM KeyboardWallpaper GROUP BY className)")
LiveData<List<KeyboardWallpaper>> getAllFirstCategory();
@Query("SELECT * FROM KeyboardWallpaper LIMIT :limit OFFSET :offset")
LiveData<List<KeyboardWallpaper>> getRecommended(int limit, int offset);
@Query("SELECT * FROM KeyboardWallpaper WHERE className = :className ")
LiveData<List<KeyboardWallpaper>> getAllCategory(String className);
@Query("SELECT * FROM KeyboardWallpaper WHERE title LIKE '%' || :title || '%'")
List<KeyboardWallpaper> getAllSearch(String title);
}

View File

@ -0,0 +1,63 @@
package com.key.keyboardstyle.utils;
import android.content.Context;
import androidx.lifecycle.LiveData;
import com.key.keyboardstyle.room.AppDatabase;
import com.key.keyboardstyle.room.Category;
import com.key.keyboardstyle.room.KeyboardWallpaper;
import com.key.keyboardstyle.room.KeyboardWallpaperDao;
import java.util.ArrayList;
import java.util.List;
public class DatabaseUtils {
private final KeyboardWallpaperDao keyboardWallpaperDao;
public DatabaseUtils(Context context) {
AppDatabase db = AppDatabase.getInstance(context);
keyboardWallpaperDao = db.keyboardWallpaperDao();
}
public void insertAll() {
keyboardWallpaperDao.insertAll(getAllKeyboardWallpaper());
}
private List<KeyboardWallpaper> getAllKeyboardWallpaper() {
List<Category> categories = JsonParser.parseJson("keyboard.json");
List<KeyboardWallpaper> keyboardWallpapers = new ArrayList<>();
for (Category category : categories) {
keyboardWallpapers.addAll(category.getKeyboardWallpapers());
}
return keyboardWallpapers;
}
public void update(KeyboardWallpaper keyboardWallpaper) {
keyboardWallpaperDao.update(keyboardWallpaper);
}
public LiveData<List<KeyboardWallpaper>> getAllFavorite() {
return keyboardWallpaperDao.getAllFavorite();
}
public LiveData<List<KeyboardWallpaper>> getAllFirstCategory() {
return keyboardWallpaperDao.getAllFirstCategory();
}
public LiveData<List<KeyboardWallpaper>> getRecommended(int limit,int offset) {
return keyboardWallpaperDao.getRecommended(limit, offset);
}
public LiveData<List<KeyboardWallpaper>> getCategory(String className) {
return keyboardWallpaperDao.getAllCategory(className);
}
public List<KeyboardWallpaper> getAllSearch(String title) {
return keyboardWallpaperDao.getAllSearch(title);
}
}

View File

@ -0,0 +1,76 @@
package com.key.keyboardstyle.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.keyboardstyle.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;
}
}

View File

@ -0,0 +1,66 @@
package com.key.keyboardstyle.utils;
import com.key.keyboardstyle.MyApplication;
import com.key.keyboardstyle.room.Category;
import com.key.keyboardstyle.room.KeyboardWallpaper;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class JsonParser {
private static String loadJSONFromAsset(String fileName) {
StringBuilder jsonString = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(MyApplication.getContext().getAssets().open(fileName)))) {
String line;
while ((line = reader.readLine()) != null) {
jsonString.append(line);
}
} catch (IOException e) {
e.printStackTrace();
}
return jsonString.toString();
}
public static List<Category> parseJson(String fileName) {
List<Category> categories = new ArrayList<>();
try {
String jsonString = loadJSONFromAsset(fileName);
if (jsonString.isEmpty()) {
throw new IllegalArgumentException("JSON file is empty or invalid.");
}
JSONArray jsonArray = new JSONArray(jsonString);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject categoryObject = jsonArray.getJSONObject(i);
String className = categoryObject.getString("className");
JSONArray listArray = categoryObject.getJSONArray("list");
List<KeyboardWallpaper> imageList = new ArrayList<>();
for (int j = 0; j < listArray.length(); j++) {
JSONObject imageObject = listArray.getJSONObject(j);
String preview = imageObject.getString("preview");
String thumb = imageObject.getString("thumb");
String title = imageObject.getString("title");
String zipUrl = imageObject.getString("zipUrl");
imageList.add(new KeyboardWallpaper(preview, thumb, className, title, zipUrl, false, false, ""));
}
categories.add(new Category(className, imageList));
}
} catch (Exception e) {
e.printStackTrace();
}
return categories;
}
}

View File

@ -0,0 +1,231 @@
package com.key.keyboardstyle.utils;
import android.content.Context;
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.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.keyboardstyle.MyApplication;
import com.key.keyboardstyle.R;
import com.key.keyboardstyle.callback.DownloadCallback;
import com.key.keyboardstyle.callback.UnzipCallback;
import com.key.keyboardstyle.keyboard.MyKeyboard;
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.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.io.RandomAccessFile;
import java.nio.file.Files;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class KeyboardUtils {
private static final InputMethodManager methodManager = (InputMethodManager) MyApplication.getApplication().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);
}
public static boolean isStep1() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return methodManager.getEnabledInputMethodList().stream()
.anyMatch(inputMethodInfo -> inputMethodInfo.getId().startsWith(MyApplication.getApplication().getPackageName()));
} else {
InputMethodManager inputMethodManager = (InputMethodManager) MyApplication.getApplication().getSystemService(Context.INPUT_METHOD_SERVICE);
List<InputMethodInfo> inputMethodList = inputMethodManager.getEnabledInputMethodList();
for (InputMethodInfo inputMethodInfo : inputMethodList) {
if (inputMethodInfo.getId().startsWith(MyApplication.getApplication().getPackageName())) {
return true;
}
}
return false;
}
}
public static boolean isStep2() {
String string = Settings.Secure.getString(MyApplication.getApplication().getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
return string.startsWith(MyApplication.getApplication().getPackageName());
}
public static void unzip(Context context, 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 (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();
} else {
boolean mkdirs = file.mkdirs();
}
}
inStream.close();
iInArchive.close();
int res = itemFilePath.indexOf("res");
String substring = itemFilePath.substring(0, res + 3);
callback.onUnzipCall(true, substring);
}
}
public static void downloadAndUnzip(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()) {
downloadDir.mkdirs();
}
File destinationFile = new File(downloadDir, resource.getName());
copyFile(resource, destinationFile);
callback.onDownloadCall(true, destinationFile);
} catch (IOException e) {
throw new RuntimeException(e);
}
return false;
}
}).preload();
}
public static void copyFile(File sourceFile, File destinationFile) throws IOException {
if (android.os.Build.VERSION.SDK_INT >= android.os.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 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();
return stringBuilder.toString();
}
public static float spToPpx(Float values, Context context) {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, values, context.getResources().getDisplayMetrics());
}
public static void runIO(Runnable task) {
getExecutorService().execute(task);
}
private static ExecutorService getExecutorService() {
if (executorService == null) {
executorService = Executors.newSingleThreadExecutor();
}
return executorService;
}
}

View File

@ -0,0 +1,33 @@
package com.key.keyboardstyle.utils;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
public class SettingUtils {
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"));
}
}

View File

@ -0,0 +1,20 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M5.799,24H41.799"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M17.799,36L5.799,24L17.799,12"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,25 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M10,28L38,28A4,4 0,0 1,42 32L42,38A4,4 0,0 1,38 42L10,42A4,4 0,0 1,6 38L6,32A4,4 0,0 1,10 28z"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"/>
<path
android:pathData="M20,7H10C7.791,7 6,8.791 6,11V17C6,19.209 7.791,21 10,21H20"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M34,14m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"/>
<path
android:pathData="M34,14m-3,0a3,3 0,1 1,6 0a3,3 0,1 1,-6 0"
android:fillColor="#333"/>
</vector>

View File

@ -0,0 +1,20 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M43,23V14C43,12.895 42.105,12 41,12H24L19,6H7C5.895,6 5,6.895 5,8V40C5,41.105 5.895,42 7,42H22"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M35,27L37.243,31.913L42.609,32.528L38.629,36.179L39.702,41.472L35,38.816L30.298,41.472L31.371,36.179L27.392,32.528L32.757,31.913L35,27Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="4dp"
android:height="4dp"
android:viewportWidth="4"
android:viewportHeight="4">
<group>
<clip-path
android:pathData="M0,0h4v4h-4z"/>
<path
android:pathData="M2,4C3.1046,4 4,3.1046 4,2C4,0.8954 3.1046,0 2,0C0.8954,0 0,0.8954 0,2C0,3.1046 0.8954,4 2,4Z"
android:fillColor="#2196F3"/>
</group>
</vector>

View File

@ -0,0 +1,33 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M39,6H9C7.343,6 6,7.343 6,9V39C6,40.657 7.343,42 9,42H39C40.657,42 42,40.657 42,39V9C42,7.343 40.657,6 39,6Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"/>
<path
android:pathData="M32,28L24,36L16,28"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M24,20V35.5"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M16,14H32"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M23.999,5L17.886,17.478L4,19.491L14.059,29.325L11.654,43L23.999,36.419L36.345,43L33.959,29.325L44,19.491L30.191,17.478L23.999,5Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#d0021b"
android:strokeColor="#d0021b"/>
</vector>

View File

@ -0,0 +1,19 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M44,44V20L24,4L4,20L4,44H16V26H32V44H44Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"/>
<path
android:pathData="M24,44V34"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
</vector>

View File

@ -1,170 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
<vector
android:height="108dp"
android:width="108dp"
android:viewportHeight="108"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z"/>
<path android:fillColor="#00000000" android:pathData="M9,0L9,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,0L19,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M29,0L29,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M39,0L39,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M49,0L49,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M59,0L59,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M69,0L69,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M79,0L79,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M89,0L89,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M99,0L99,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,9L108,9"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,19L108,19"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,29L108,29"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,39L108,39"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,49L108,49"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,59L108,59"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,69L108,69"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,79L108,79"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,89L108,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,99L108,99"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,29L89,29"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,39L89,39"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,49L89,49"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,59L89,59"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,69L89,69"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,79L89,79"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M29,19L29,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M39,19L39,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M49,19L49,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M59,19L59,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M69,19L69,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M79,19L79,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
</vector>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/rounded_rectangle" android:state_selected="true" />
<item android:drawable="@drawable/rounded_rectangle_blue" android:state_selected="false" />
</selector>

View File

@ -0,0 +1,21 @@
<!-- res/drawable/seekbar_progress_drawable.xml -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape>
<corners android:radius="5dp" />
<solid android:color="#D3D3D3" />
</shape>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<corners android:radius="5dp" />
<gradient
android:startColor="#4891FF"
android:endColor="#6CE89E"
android:angle="0" />
</shape>
</clip>
</item>
</layer-list>

View File

@ -0,0 +1,5 @@
<!-- res/drawable/rounded_rectangle.xml -->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/gray"/>
<corners android:radius="16dp"/>
</shape>

View File

@ -0,0 +1,5 @@
<!-- res/drawable/rounded_rectangle.xml -->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/blue"/>
<corners android:radius="16dp"/>
</shape>

View File

@ -0,0 +1,26 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M21,38C30.389,38 38,30.389 38,21C38,11.611 30.389,4 21,4C11.611,4 4,11.611 4,21C4,30.389 11.611,38 21,38Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"/>
<path
android:pathData="M26.657,14.343C25.209,12.895 23.209,12 21,12C18.791,12 16.791,12.895 15.343,14.343"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M33.222,33.222L41.707,41.707"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,18 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M18.284,43.171C14.933,42.174 11.95,40.321 9.588,37.867C10.469,36.823 11,35.473 11,34C11,30.686 8.314,28 5,28C4.8,28 4.601,28.01 4.406,28.029C4.14,26.728 4,25.38 4,24C4,21.91 4.321,19.894 4.916,18C4.944,18 4.972,18 5,18C8.314,18 11,15.314 11,12C11,11.049 10.779,10.149 10.385,9.35C12.698,7.2 15.521,5.59 18.652,4.723C19.644,6.668 21.667,8 24,8C26.333,8 28.356,6.668 29.348,4.723C32.479,5.59 35.303,7.2 37.615,9.35C37.221,10.149 37,11.049 37,12C37,15.314 39.686,18 43,18C43.028,18 43.056,18 43.084,18C43.679,19.894 44,21.91 44,24C44,25.38 43.86,26.728 43.594,28.029C43.399,28.01 43.201,28 43,28C39.686,28 37,30.686 37,34C37,35.473 37.531,36.823 38.412,37.867C36.05,40.321 33.067,42.174 29.716,43.171C28.943,40.752 26.676,39 24,39C21.324,39 19.057,40.752 18.284,43.171Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"/>
<path
android:pathData="M24,31C27.866,31 31,27.866 31,24C31,20.134 27.866,17 24,17C20.134,17 17,20.134 17,24C17,27.866 20.134,31 24,31Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"/>
</vector>

View File

@ -0,0 +1,74 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M8,12C10.209,12 12,10.209 12,8C12,5.791 10.209,4 8,4C5.791,4 4,5.791 4,8C4,10.209 5.791,12 8,12Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:fillType="evenOdd"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M10,42C13.314,42 16,39.314 16,36C16,32.686 13.314,30 10,30C6.686,30 4,32.686 4,36C4,39.314 6.686,42 10,42Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:fillType="evenOdd"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M38,44C41.314,44 44,41.314 44,38C44,34.686 41.314,32 38,32C34.686,32 32,34.686 32,38C32,41.314 34.686,44 38,44Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:fillType="evenOdd"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M22,28C26.418,28 30,24.418 30,20C30,15.582 26.418,12 22,12C17.582,12 14,15.582 14,20C14,24.418 17.582,28 22,28Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:fillType="evenOdd"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M34,12C36.209,12 38,10.209 38,8C38,5.791 36.209,4 34,4C31.791,4 30,5.791 30,8C30,10.209 31.791,12 34,12Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:fillType="evenOdd"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M11,11L15,15"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M30,12L28,14"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M34,33.5L28,26"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M14,31L18,27"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,28 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M28,6H42V20"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M42,29.474V39C42,40.657 40.657,42 39,42H9C7.343,42 6,40.657 6,39V9C6,7.343 7.343,6 9,6L18,6"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M25.8,22.2L41.1,6.9"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M23.999,5L17.886,17.478L4,19.491L14.059,29.325L11.654,43L23.999,36.419L36.345,43L33.959,29.325L44,19.491L30.191,17.478L23.999,5Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#FFFFFF"/>
</vector>

View File

@ -0,0 +1,23 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M24,44C29.523,44 34.523,41.761 38.142,38.142C41.761,34.523 44,29.523 44,24C44,18.477 41.761,13.477 38.142,9.858C34.523,6.239 29.523,4 24,4C18.477,4 13.477,6.239 9.858,9.858C6.239,13.477 4,18.477 4,24C4,29.523 6.239,34.523 9.858,38.142C13.477,41.761 18.477,44 24,44Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"/>
<path
android:pathData="M24,28.625V24.625C27.314,24.625 30,21.938 30,18.625C30,15.311 27.314,12.625 24,12.625C20.686,12.625 18,15.311 18,18.625"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M24,37.625C25.381,37.625 26.5,36.506 26.5,35.125C26.5,33.744 25.381,32.625 24,32.625C22.619,32.625 21.5,33.744 21.5,35.125C21.5,36.506 22.619,37.625 24,37.625Z"
android:fillColor="#333"
android:fillType="evenOdd"/>
</vector>

View File

@ -0,0 +1,41 @@
<?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.CategoryActivity">
<ImageView
android:id="@+id/back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:src="@drawable/back"
app:layout_constraintBottom_toBottomOf="@+id/title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/title" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/app_name"
android:textColor="@color/black"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/title" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,126 @@
<?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.DownloadActivity">
<ImageView
android:id="@+id/back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:src="@drawable/back"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/app_name"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="250dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:scaleType="centerInside"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/title" />
<LinearLayout
android:id="@+id/download"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_marginTop="16dp"
android:background="@drawable/rounded_rectangle"
android:backgroundTint="#4891FF"
android:gravity="center"
android:orientation="horizontal"
android:paddingStart="32dp"
android:paddingEnd="32dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/image">
<ImageView
android:id="@+id/download_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:src="@drawable/download" />
<TextView
android:id="@+id/download_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/set_this_on_your_keyboard"
android:textColor="@color/black"
android:textSize="14sp" />
</LinearLayout>
<TextView
android:id="@+id/recommended_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:text="@string/today_s_recommendation"
android:textColor="@color/black"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/download" />
<ImageView
android:id="@+id/home"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:src="@drawable/home"
app:layout_constraintBottom_toBottomOf="@+id/recommended_text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/recommended_text" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recommended"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/recommended_text" />
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="@+id/view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#80000000"
android:clickable="true"
android:focusable="true"
android:visibility="gone" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -7,13 +7,19 @@
android:layout_height="match_parent"
tools:context=".activity.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/view_pager2"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/tab_layout"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="100dp"
app:layout_constraintBottom_toBottomOf="parent"
app:tabIndicatorHeight="0dp"
app:tabRippleColor="@android:color/transparent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,51 @@
<?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.SearchActivity">
<ImageView
android:id="@+id/back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:src="@drawable/back"
app:layout_constraintBottom_toBottomOf="@+id/title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/title" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/search"
android:textColor="@color/black"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:hint="@string/search..."
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/title" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/edit_text" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,50 @@
<?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:activity=".activity.SplashActivity">
<ImageView
android:id="@+id/splash_image"
android:layout_width="150dp"
android:layout_height="150dp"
android:src="@mipmap/ic_launcher"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.388" />
<TextView
android:id="@+id/splash_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="@string/app_name"
android:textSize="24sp"
android:textStyle="bold"
android:gravity="center"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/splash_image" />
<ProgressBar
android:id="@+id/progress_bar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp"
android:layout_height="5dp"
android:layout_marginStart="53dp"
android:layout_marginEnd="53dp"
android:layout_marginBottom="80dp"
android:max="100"
android:progress="0"
android:progressDrawable="@drawable/progress_color"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,45 @@
<?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.TestActivity">
<ImageView
android:id="@+id/back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:src="@drawable/back"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/download_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/wallpaper_test"
android:textColor="@color/black"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/edit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:hint="@string/enter_text_and_see_your_wallpaper_in_action"
android:padding="16dp"
android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/time_to_change_your_keyboard"
android:textSize="14sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/imageView"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:src="@mipmap/ic_launcher_foreground"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/title" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginBottom="16dp"
android:text=""
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/imageView" />
<TextView
android:id="@+id/step1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="@drawable/permission_select"
android:paddingStart="16dp"
android:paddingTop="5dp"
android:paddingEnd="16dp"
android:paddingBottom="5dp"
android:text="@string/step_1_select"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/imageView" />
<TextView
android:id="@+id/step2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="@drawable/permission_select"
android:paddingStart="16dp"
android:paddingTop="5dp"
android:paddingEnd="16dp"
android:paddingBottom="5dp"
android:text="@string/step_2_enable"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/step1" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragment.CategoryFragment">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/app_name"
android:textColor="#000000"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/search"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:src="@drawable/search"
app:layout_constraintBottom_toBottomOf="@+id/title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/title" />
<TextView
android:id="@+id/category_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:text="@string/category"
android:textColor="@color/black"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/title" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/category"
android:layout_width="match_parent"
android:layout_height="150dp"
android:layout_marginTop="16dp"
app:layout_constraintTop_toBottomOf="@id/category_text" />
<TextView
android:id="@+id/recommended_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="@string/today_s_recommendation"
android:textColor="@color/black"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/category" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recommended"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/recommended_text" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragment.FavoriteFragment">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/favorite"
android:textColor="@color/black"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/background_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/oops_no_favorites_yet_start_collecting_your_favorites_and_make_this_page_shine"
android:textColor="@color/black"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/title" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/title" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".fragment.SettingFragment">
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="center"
android:text="@string/setting"
android:textStyle="bold"
android:textColor="@color/black"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="25dp"
android:orientation="vertical"
app:layout_constraintTop_toBottomOf="@+id/text">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:orientation="horizontal"
android:padding="16dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/version" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:layout_weight="1"
android:textColor="@color/black"
android:text="@string/version"
android:textSize="14sp" />
<TextView
android:id="@+id/version"
android:textColor="@color/black"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:clickable="true"
android:focusable="true"
android:orientation="horizontal"
android:padding="16dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/share" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:layout_weight="1"
android:textColor="@color/black"
android:text="@string/share"
android:textSize="14sp" />
<ImageView
android:id="@+id/share"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/share_right" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<ImageView
android:id="@+id/icon_custom"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<View
android:id="@+id/dot_view"
android:layout_width="5dp"
android:layout_height="5dp"
android:layout_marginTop="6dp"
android:background="@drawable/dot"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/icon_custom"
app:layout_constraintStart_toStartOf="@+id/icon_custom"
app:layout_constraintTop_toBottomOf="@+id/icon_custom" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,43 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/title_wallpaper"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/rounded_rectangle"
android:ellipsize="end"
android:maxLines="1"
android:paddingStart="7dp"
android:paddingTop="3dp"
android:paddingEnd="7dp"
android:paddingBottom="3dp"
android:textColor="@color/white"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/image_wallpaper"
android:layout_width="144dp"
android:layout_height="106dp"
android:layout_marginTop="5dp"
android:scaleType="centerInside"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/title_wallpaper" />
<ImageView
android:id="@+id/favorite_wallpaper"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginEnd="12dp"
android:layout_marginBottom="12dp"
android:src="@drawable/un_favorite"
app:layout_constraintBottom_toBottomOf="@+id/image_wallpaper"
app:layout_constraintEnd_toEndOf="@+id/image_wallpaper" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,12 @@
<?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.keyboardstyle.keyboard.MyKeyboard
android:id="@+id/keyboardView"
android:layout_width="match_parent"
android:layout_height="210dp" />
</LinearLayout>

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
<background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
<background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 982 B

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -2,4 +2,6 @@
<resources>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="gray">#40000000</color>
<color name="blue">#4891FF</color>
</resources>

View File

@ -1,3 +1,20 @@
<resources>
<string name="app_name">Keyboard Style</string>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>
<string name="search...">Search…</string>
<string name="category">Category</string>
<string name="today_s_recommendation">Today\'s recommendation</string>
<string name="search">Search</string>
<string name="setting">Setting</string>
<string name="version">Version</string>
<string name="share">Share</string>
<string name="oops_no_favorites_yet_start_collecting_your_favorites_and_make_this_page_shine">Oops! No favorites yet! 🌟 Start collecting your favorites and make this page shine! ✨💖</string>
<string name="wallpaper_test">Wallpaper Test</string>
<string name="enter_text_and_see_your_wallpaper_in_action">Enter text and see your wallpaper in action!</string>
<string name="set_this_on_your_keyboard">Set this on your keyboard! ✨</string>
<string name="favorite">Favorite</string>
<string name="step_1_select">Step 1 : Select</string>
<string name="step_2_enable">Step 2 : Enable</string>
<string name="time_to_change_your_keyboard">Time to change your keyboard!</string>
</resources>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<input-method xmlns:android="http://schemas.android.com/apk/res/android">
<subtype
android:icon="@drawable/ic_launcher_background"
android:imeSubtypeLocale="en_US"
android:imeSubtypeMode = "keyboard"
android:label="@string/app_name" />
</input-method>

View File

@ -0,0 +1,146 @@
<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android">
<Row
android:horizontalGap="0.5%"
android:keyWidth="9.45%"
android:keyHeight="50dp">
<Key
android:codes="113"
android:keyEdgeFlags="left"
android:keyLabel="q" />
<Key
android:codes="119"
android:keyLabel="w" />
<Key
android:codes="101"
android:keyLabel="e" />
<Key
android:codes="114"
android:keyLabel="r" />
<Key
android:codes="116"
android:keyLabel="t" />
<Key
android:codes="121"
android:keyLabel="y" />
<Key
android:codes="117"
android:keyLabel="u" />
<Key
android:codes="105"
android:keyLabel="i" />
<Key
android:codes="111"
android:keyLabel="o" />
<Key
android:codes="112"
android:keyEdgeFlags="right"
android:keyLabel="p" />
</Row>
<Row
android:horizontalGap="0.5%"
android:keyWidth="9.444444%"
android:keyHeight="50dp">
<Key
android:codes="97"
android:horizontalGap="5.5%"
android:keyLabel="a" />
<Key
android:codes="115"
android:keyLabel="s" />
<Key
android:codes="100"
android:keyLabel="d" />
<Key
android:codes="102"
android:keyLabel="f" />
<Key
android:codes="103"
android:keyLabel="g" />
<Key
android:codes="104"
android:keyLabel="h" />
<Key
android:codes="106"
android:keyLabel="j" />
<Key
android:codes="107"
android:keyLabel="k" />
<Key
android:codes="108"
android:keyLabel="l" />
</Row>
<Row
android:horizontalGap="0.5%"
android:keyWidth="9.5%"
android:keyHeight="50dp">
<Key
android:codes="-1"
android:isModifier="true"
android:isSticky="true"
android:keyWidth="14.25%"
android:keyEdgeFlags="left" />
<Key
android:codes="122"
android:keyLabel="z" />
<Key
android:codes="120"
android:keyLabel="x" />
<Key
android:codes="99"
android:keyLabel="c" />
<Key
android:codes="118"
android:keyLabel="v" />
<Key
android:codes="98"
android:keyLabel="b" />
<Key
android:codes="110"
android:keyLabel="n" />
<Key
android:codes="109"
android:keyLabel="m" />
<Key
android:codes="-5"
android:isModifier="true"
android:isRepeatable="true"
android:keyWidth="14.25%"
android:keyEdgeFlags="right" />
</Row>
<Row
android:horizontalGap="0.5%"
android:keyWidth="9.5%"
android:keyHeight="50dp"
android:rowEdgeFlags="bottom">
<Key
android:codes="-2"
android:keyWidth="14.25%"
android:keyEdgeFlags="left"
android:keyLabel="\?123" />
<Key
android:codes="44"
android:keyLabel="," />
<Key
android:codes="32"
android:keyWidth="49.5%"
android:keyLabel="English" />
<Key
android:codes="46"
android:keyLabel="." />
<Key
android:codes="-4"
android:keyWidth="14.25%"
android:keyEdgeFlags="right"
android:keyLabel="Done" />
</Row>
</Keyboard>

View File

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

View File

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

View File

@ -0,0 +1,149 @@
<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
android:keyHeight="50dp">
<Row
android:horizontalGap="0.5%"
android:keyWidth="9.45%"
android:keyHeight="50dp"
android:rowEdgeFlags="top">
<Key
android:codes="113"
android:keyEdgeFlags="left"
android:keyLabel="Q" />
<Key
android:codes="119"
android:keyLabel="W" />
<Key
android:codes="101"
android:keyLabel="E" />
<Key
android:codes="114"
android:keyLabel="R" />
<Key
android:codes="116"
android:keyLabel="T" />
<Key
android:codes="121"
android:keyLabel="Y" />
<Key
android:codes="117"
android:keyLabel="U" />
<Key
android:codes="105"
android:keyLabel="I" />
<Key
android:codes="111"
android:keyLabel="O" />
<Key
android:codes="112"
android:keyEdgeFlags="right"
android:keyLabel="P" />
</Row>
<Row
android:horizontalGap="0.5%"
android:keyWidth="9.444444%"
android:keyHeight="50dp">
<Key
android:codes="97"
android:horizontalGap="5.5%"
android:keyLabel="A" />
<Key
android:codes="115"
android:keyLabel="S" />
<Key
android:codes="100"
android:keyLabel="D" />
<Key
android:codes="102"
android:keyLabel="F" />
<Key
android:codes="103"
android:keyLabel="G" />
<Key
android:codes="104"
android:keyLabel="H" />
<Key
android:codes="106"
android:keyLabel="J" />
<Key
android:codes="107"
android:keyLabel="K" />
<Key
android:codes="108"
android:keyLabel="L" />
</Row>
<Row
android:horizontalGap="0.5%"
android:keyWidth="9.5%"
android:keyHeight="50dp">
<Key
android:codes="-1"
android:isModifier="true"
android:isSticky="true"
android:keyWidth="14.25%"
android:keyEdgeFlags="left" />
<Key
android:codes="122"
android:keyLabel="Z" />
<Key
android:codes="120"
android:keyLabel="X" />
<Key
android:codes="99"
android:keyLabel="C" />
<Key
android:codes="118"
android:keyLabel="V" />
<Key
android:codes="98"
android:keyLabel="B" />
<Key
android:codes="110"
android:keyLabel="N" />
<Key
android:codes="109"
android:keyLabel="M" />
<Key
android:codes="-5"
android:isModifier="true"
android:isRepeatable="true"
android:keyWidth="14.25%"
android:keyEdgeFlags="right" />
</Row>
<Row
android:horizontalGap="0.5%"
android:keyWidth="9.5%"
android:keyHeight="50dp"
android:rowEdgeFlags="bottom">
<Key
android:codes="-2"
android:keyWidth="14.25%"
android:keyEdgeFlags="left"
android:keyLabel="\?123" />
<Key
android:codes="44"
android:keyLabel="," />
<Key
android:codes="32"
android:keyWidth="49.5%"
android:keyLabel="English" />
<Key
android:codes="46"
android:keyLabel="." />
<Key
android:codes="-4"
android:keyWidth="14.25%"
android:keyEdgeFlags="right"
android:keyLabel="Done" />
</Row>
</Keyboard>

View File

@ -1,6 +1,6 @@
#Mon Dec 09 16:45:47 CST 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
distributionUrl=https://mirrors.huaweicloud.com/repository/toolkit/gradle/gradle-8.7-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@ -16,6 +16,9 @@ dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven("https://jitpack.io")
}
}