V1.0.0(1)完成版

This commit is contained in:
lihongwei 2025-05-23 15:01:39 +08:00
parent fcb215592a
commit 397c922af0
59 changed files with 14227 additions and 44 deletions

BIN
app/VividWallpaper.jks Normal file

Binary file not shown.

View File

@ -1,7 +1,10 @@
import java.text.SimpleDateFormat
import java.util.Date
plugins { plugins {
alias(libs.plugins.android.application) alias(libs.plugins.android.application)
} }
val timestamp: String = SimpleDateFormat("MM_dd_HH_mm").format(Date())
android { android {
namespace = "com.wallpaper.vividwallpaper" namespace = "com.wallpaper.vividwallpaper"
compileSdk = 35 compileSdk = 35
@ -11,20 +14,25 @@ android {
minSdk = 23 minSdk = 23
targetSdk = 35 targetSdk = 35
versionCode = 1 versionCode = 1
versionName = "1.0" versionName = "1.0.0"
setProperty("archivesBaseName", "Vivid Wallpaper_V" + versionName + "(${versionCode})_$timestamp")
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
} }
buildTypes { buildTypes {
release { release {
isMinifyEnabled = false isMinifyEnabled = true
proguardFiles( proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"), getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro" "proguard-rules.pro"
) )
} }
} }
buildFeatures {
viewBinding = true
}
compileOptions { compileOptions {
sourceCompatibility = JavaVersion.VERSION_11 sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11
@ -40,4 +48,10 @@ dependencies {
testImplementation(libs.junit) testImplementation(libs.junit)
androidTestImplementation(libs.ext.junit) androidTestImplementation(libs.ext.junit)
androidTestImplementation(libs.espresso.core) 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")
} }

View File

@ -18,4 +18,17 @@
# If you keep the line number information, uncomment this to # If you keep the line number information, uncomment this to
# hide the original source file name. # hide the original source file name.
#-renamesourcefileattribute SourceFile #-renamesourcefileattribute SourceFile
-keepclassmembers class com.wallpaper.vividwallpaper.MyApplication {
public static final java.lang.String DB_NAME;
public static final int DB_VERSION;
}
-keepclassmembers class * {
@androidx.room.Query <methods>;
}
-keep class com.wallpaper.vividwallpaper.room.AppDatabase { *; }
-keep class com.wallpaper.vividwallpaper.room.VividEntity { *; }
-keep class com.wallpaper.vividwallpaper.room.VividEntityDao { *; }

View File

@ -2,7 +2,14 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.SET_WALLPAPER" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
<application <application
android:name=".MyApplication"
android:allowBackup="true" android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules" android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules" android:fullBackupContent="@xml/backup_rules"
@ -13,7 +20,16 @@
android:theme="@style/Theme.VividWallpaper" android:theme="@style/Theme.VividWallpaper"
tools:targetApi="31"> tools:targetApi="31">
<activity <activity
android:name=".MainActivity" android:name=".activity.VividActivity"
android:exported="false" />
<activity
android:name=".activity.MainActivity"
android:exported="false" />
<activity
android:name=".activity.CategoryActivity"
android:exported="false" />
<activity
android:name=".activity.SplashActivity"
android:exported="true"> android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />

12208
app/src/main/assets/vivid.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,24 +0,0 @@
package com.wallpaper.vividwallpaper;
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;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_main);
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;
});
}
}

View File

@ -0,0 +1,47 @@
package com.wallpaper.vividwallpaper;
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import com.wallpaper.vividwallpaper.room.AppDatabase;
import com.wallpaper.vividwallpaper.room.VividEntity;
import com.wallpaper.vividwallpaper.room.VividEntityDao;
import com.wallpaper.vividwallpaper.util.JsonParse;
import com.wallpaper.vividwallpaper.util.VividRepository;
import java.util.List;
public class MyApplication extends Application {
public static MyApplication application;
public static final int DB_VERSION = 1;
public static final String DB_NAME = "wallpaper_database";
private static final String PREF_NAME = "app_preferences";
private static final String KEY_INITIALIZED = "isInit";
@Override
public void onCreate() {
super.onCreate();
application = this;
SharedPreferences preferences = getSharedPreferences(PREF_NAME, MODE_PRIVATE);
boolean isInit = preferences.getBoolean(KEY_INITIALIZED, false);
if (!isInit) {
initDatabase();
preferences.edit().putBoolean(KEY_INITIALIZED, true).apply();
}
}
private void initDatabase() {
VividEntityDao vividEntityDao = AppDatabase.getInstance(getContext()).wallpaperEntityDao();
VividRepository vividRepository = new VividRepository(vividEntityDao);
List<VividEntity> wallpaperEntities = JsonParse.parseJson(getContext(), "vivid.json");
vividRepository.insertAll(wallpaperEntities);
}
public static Context getContext() {
return application.getApplicationContext();
}
}

View File

@ -0,0 +1,79 @@
package com.wallpaper.vividwallpaper.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.ViewModelProvider;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import com.wallpaper.vividwallpaper.R;
import com.wallpaper.vividwallpaper.adapter.VividAdapter;
import com.wallpaper.vividwallpaper.databinding.ActivityCategoryBinding;
import com.wallpaper.vividwallpaper.util.ItemDecoration;
import com.wallpaper.vividwallpaper.util.VividViewModel;
import java.util.ArrayList;
public class CategoryActivity extends AppCompatActivity {
private ActivityCategoryBinding viewBinding;
private VividAdapter dataAdapter;
private VividViewModel viewModel;
private String categoryName;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
viewBinding = ActivityCategoryBinding.inflate(getLayoutInflater());
setContentView(viewBinding.getRoot());
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (view, windowInsets) -> {
Insets bars = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
view.setPadding(bars.left, bars.top, bars.right, bars.bottom);
return windowInsets;
});
setupData();
setupEvents();
}
private void setupData() {
categoryName = getIntent().getStringExtra("name");
if (categoryName == null) {
finish();
return;
}
viewModel = new ViewModelProvider(this).get(VividViewModel.class);
viewBinding.recyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
dataAdapter = new VividAdapter(viewModel, this, new ArrayList<>(), this, 1);
viewBinding.recyclerView.setAdapter(dataAdapter);
ItemDecoration decoration = new ItemDecoration(20, 15, 20);
viewBinding.recyclerView.addItemDecoration(decoration);
}
private void setupEvents() {
viewBinding.back.setOnClickListener(view -> finish());
viewBinding.title.setText(categoryName);
fetchCategoryData();
}
private void fetchCategoryData() {
viewModel
.getCategoryByName(categoryName)
.observe(this, entities -> dataAdapter.refreshData(entities));
}
@Override
protected void onDestroy() {
super.onDestroy();
viewBinding = null;
}
}

View File

@ -0,0 +1,110 @@
package com.wallpaper.vividwallpaper.activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import com.wallpaper.vividwallpaper.R;
import com.wallpaper.vividwallpaper.databinding.ActivityMainBinding;
import com.wallpaper.vividwallpaper.databinding.ItemMainBinding;
import com.wallpaper.vividwallpaper.adapter.MainAdapter;
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding viewBinding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
viewBinding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(viewBinding.getRoot());
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (view, windowInsets) -> {
Insets bars = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
view.setPadding(bars.left, bars.top, bars.right, bars.bottom);
return windowInsets;
});
setupData();
setupEvents();
}
private void setupData() {
MainAdapter viewAdapter = new MainAdapter(this);
viewBinding.mainViewpager2.setAdapter(viewAdapter);
}
private void setupEvents() {
new TabLayoutMediator(viewBinding.mainTabLayout, viewBinding.mainViewpager2, (tab, pos) -> {
ItemMainBinding tabBinding = ItemMainBinding.inflate(LayoutInflater.from(this));
tab.setCustomView(tabBinding.getRoot());
configureTab(tabBinding, pos);
}).attach();
viewBinding.mainTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
modifyTab(tab, true);
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
modifyTab(tab, false);
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
private void modifyTab(TabLayout.Tab tab, boolean selected) {
if (tab.getCustomView() != null) {
ItemMainBinding tabBinding = ItemMainBinding.bind(tab.getCustomView());
int iconId = fetchIcon(tab.getPosition(), selected);
tabBinding.image.setImageResource(iconId);
int color = selected ? R.color.white : R.color.gray;
tabBinding.text.setTextColor(ContextCompat.getColor(MainActivity.this, color));
}
}
});
}
private void configureTab(ItemMainBinding tabBinding, int pos) {
int iconId = fetchIcon(pos, false);
int textColorId = R.color.gray;
switch (pos) {
case 0:
tabBinding.text.setText("Home");
iconId = R.drawable.home;
textColorId = R.color.white;
break;
case 1:
tabBinding.text.setText("Collection");
break;
}
tabBinding.image.setImageResource(iconId);
tabBinding.text.setTextColor(ContextCompat.getColor(this, textColorId));
}
private int fetchIcon(int pos, boolean selected) {
if (pos == 1) {
return selected ? R.drawable.collection : R.drawable.un_collection;
}
return selected ? R.drawable.home : R.drawable.un_home;
}
@Override
protected void onDestroy() {
super.onDestroy();
viewBinding = null;
}
}

View File

@ -0,0 +1,75 @@
package com.wallpaper.vividwallpaper.activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.CountDownTimer;
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.CenterCrop;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.wallpaper.vividwallpaper.R;
import com.wallpaper.vividwallpaper.databinding.ActivitySplashBinding;
public class SplashActivity extends AppCompatActivity {
private ActivitySplashBinding binding;
private static final long TOTAL_TIME = 1000;
private CountDownTimer countDownTimer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
binding = ActivitySplashBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
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 CenterCrop(), new RoundedCorners(32))
.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() {
jumpToMain();
}
};
countDownTimer.start();
}
private void jumpToMain() {
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,237 @@
package com.wallpaper.vividwallpaper.activity;
import static com.wallpaper.vividwallpaper.util.VividUtil.STORAGE_PERMISSION_CODE;
import android.app.WallpaperManager;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Toast;
import androidx.activity.EdgeToEdge;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.lifecycle.ViewModelProvider;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.bumptech.glide.request.target.CustomTarget;
import com.bumptech.glide.request.transition.Transition;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.wallpaper.vividwallpaper.R;
import com.wallpaper.vividwallpaper.room.VividEntity;
import com.wallpaper.vividwallpaper.databinding.ActivityVividBinding;
import com.wallpaper.vividwallpaper.util.VividViewModel;
import com.wallpaper.vividwallpaper.util.VividUtil;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class VividActivity extends AppCompatActivity {
private ActivityVividBinding uiBinding;
private String imgPathRaw, imgPathSrc;
private VividEntity vividData;
private String title;
private Bitmap imgBitmap;
private VividUtil utilHelper;
private VividViewModel viewModelInstance;
private ExecutorService taskExecutor;
private Handler mainHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
uiBinding = ActivityVividBinding.inflate(getLayoutInflater());
setContentView(uiBinding.getRoot());
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (view, insets) -> {
int navHeight = insets.getInsets(WindowInsetsCompat.Type.navigationBars()).bottom;
view.setPadding(0, 0, 0, navHeight);
return insets;
});
setupData();
configureEvents();
}
private void setupData() {
vividData = (VividEntity) getIntent().getSerializableExtra("vivid");
if (vividData == null) {
finish();
return;
}
imgPathRaw = vividData.getOriginal();
imgPathSrc = vividData.getSource();
title = vividData.getName();
mainHandler = new Handler(Looper.getMainLooper());
taskExecutor = Executors.newSingleThreadExecutor();
viewModelInstance = new ViewModelProvider(this).get(VividViewModel.class);
utilHelper = new VividUtil(uiBinding.progressBar, uiBinding.view);
}
private void configureEvents() {
displayProgress();
uiBinding.back.setOnClickListener(view -> finish());
uiBinding.like.setOnClickListener(view -> {
boolean updatedStatus = !vividData.getIsFavorite();
vividData.setIsFavorite(updatedStatus);
viewModelInstance.update(vividData);
});
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
uiBinding.set.setOnClickListener(view -> openBottomSheet());
}
uiBinding.downPicture.setOnClickListener(view -> {
displayProgress();
utilHelper.storeImage(VividActivity.this, imgPathSrc);
});
fetchImage();
updateFavoriteStatus();
}
@Override
public void onRequestPermissionsResult(int reqCode, @NonNull String[] perms, @NonNull int[] results) {
super.onRequestPermissionsResult(reqCode, perms, results);
if (reqCode == STORAGE_PERMISSION_CODE && results.length > 0 && results[0] == PackageManager.PERMISSION_GRANTED) {
utilHelper.storeImage(this, imgPathSrc);
} else {
Toast.makeText(this, "Storage write permission denied", Toast.LENGTH_SHORT).show();
}
}
@RequiresApi(api = Build.VERSION_CODES.N)
private void openBottomSheet() {
BottomSheetDialog dialog = new BottomSheetDialog(this);
View sheetView = LayoutInflater.from(this).inflate(R.layout.set_as_dialog, null);
sheetView.findViewById(R.id.both).setOnClickListener(v -> {
applyWallpaper(imgBitmap, WallpaperManager.FLAG_SYSTEM | WallpaperManager.FLAG_LOCK);
dialog.dismiss();
});
sheetView.findViewById(R.id.lock).setOnClickListener(v -> {
applyWallpaper(imgBitmap, WallpaperManager.FLAG_LOCK);
dialog.dismiss();
});
sheetView.findViewById(R.id.desktop).setOnClickListener(v -> {
applyWallpaper(imgBitmap, WallpaperManager.FLAG_SYSTEM);
dialog.dismiss();
});
dialog.setContentView(sheetView);
dialog.show();
}
private void applyWallpaper(Bitmap bitmap, int flag) {
displayProgress();
taskExecutor.submit(() -> {
try {
configureWallpaper(bitmap, flag);
} catch (Exception e) {
e.printStackTrace();
} finally {
mainHandler.post(() -> {
concealProgress();
uiBinding.set.setEnabled(true);
Toast.makeText(getApplicationContext(), "Wallpaper set successfully", Toast.LENGTH_SHORT).show();
});
}
});
}
private void configureWallpaper(Bitmap bitmap, int flag) {
taskExecutor.submit(() -> {
WallpaperManager manager = WallpaperManager.getInstance(getApplicationContext());
try {
uiBinding.imageView.setDrawingCacheEnabled(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
manager.setBitmap(bitmap, null, true, flag);
} else {
manager.setBitmap(bitmap);
}
} catch (IOException e) {
e.printStackTrace();
}
});
}
private void fetchImage() {
Glide.with(this)
.asBitmap()
.load(imgPathRaw)
.transform(new CenterCrop(), new RoundedCorners(32))
.error(ContextCompat.getDrawable(this, R.mipmap.placeholder))
.override(1080, 1920)
.into(new CustomTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull Bitmap resource, Transition<? super Bitmap> transition) {
uiBinding.imageView.setImageBitmap(resource);
imgBitmap = resource;
concealProgress();
}
@Override
public void onLoadCleared(Drawable placeholder) {
uiBinding.imageView.setImageDrawable(placeholder != null ? placeholder : fetchPlaceholder());
}
@Override
public void onLoadFailed(Drawable errorDrawable) {
uiBinding.imageView.setImageDrawable(errorDrawable != null ? errorDrawable : fetchPlaceholder());
concealProgress();
}
});
}
private Drawable fetchPlaceholder() {
return ContextCompat.getDrawable(this, R.mipmap.placeholder);
}
private void updateFavoriteStatus() {
viewModelInstance.getVividFavorite(imgPathSrc, title).observe(this, wallpaper -> updateLikeButton());
}
private void updateLikeButton() {
uiBinding.like.setImageResource(vividData.getIsFavorite() ? R.drawable.like : R.drawable.un_like);
}
private void concealProgress() {
uiBinding.progressBar.setVisibility(View.GONE);
uiBinding.view.setVisibility(View.GONE);
}
private void displayProgress() {
uiBinding.progressBar.setVisibility(View.VISIBLE);
uiBinding.view.setVisibility(View.VISIBLE);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mainHandler != null) {
mainHandler.removeCallbacksAndMessages(null);
}
if (taskExecutor != null) {
taskExecutor.shutdown();
}
uiBinding = null;
}
}

View File

@ -0,0 +1,33 @@
package com.wallpaper.vividwallpaper.adapter;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import com.wallpaper.vividwallpaper.fragment.HomeFragment;
import com.wallpaper.vividwallpaper.fragment.CollectionFragment;
import java.util.ArrayList;
import java.util.List;
public class MainAdapter extends FragmentStateAdapter {
private final List<Fragment> fragmentList = new ArrayList<>();
public MainAdapter(@NonNull FragmentActivity fragmentActivity) {
super(fragmentActivity);
fragmentList.add(new HomeFragment());
fragmentList.add(new CollectionFragment());
}
@NonNull
@Override
public Fragment createFragment(int position) {
return fragmentList.get(position);
}
@Override
public int getItemCount() {
return fragmentList.size();
}
}

View File

@ -0,0 +1,137 @@
package com.wallpaper.vividwallpaper.adapter;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
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.RecyclerView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.wallpaper.vividwallpaper.R;
import com.wallpaper.vividwallpaper.activity.CategoryActivity;
import com.wallpaper.vividwallpaper.activity.VividActivity;
import com.wallpaper.vividwallpaper.room.VividEntity;
import com.wallpaper.vividwallpaper.util.VividViewModel;
import java.util.List;
public class VividAdapter extends RecyclerView.Adapter<VividAdapter.ItemHolder> {
private final VividViewModel dataViewModel;
private final Context appContext;
private List<VividEntity> vividItems;
private final Activity hostActivity;
private final int displayType;
public VividAdapter(VividViewModel viewModel, Context context, List<VividEntity> items, Activity activity, int type) {
this.dataViewModel = viewModel;
this.appContext = context;
this.vividItems = items;
this.hostActivity = activity;
this.displayType = type;
}
public void refreshData(List<VividEntity> updatedItems) {
this.vividItems = updatedItems;
notifyDataSetChanged();
}
@NonNull
@Override
public ItemHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(appContext).inflate(R.layout.item_vivid, parent, false);
return new ItemHolder(view);
}
@Override
public void onBindViewHolder(ItemHolder holder, int position) {
VividEntity item = vividItems.get(position);
holder.bindData(item);
int height = (position % 2 == 0) ? 800 : 1000;
ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams();
layoutParams.height = height;
holder.itemView.setLayoutParams(layoutParams);
}
@Override
public int getItemCount() {
return vividItems.size();
}
public class ItemHolder extends RecyclerView.ViewHolder {
private final ImageView displayImage;
private final ImageView likeButton;
private final TextView itemTitle;
public ItemHolder(View view) {
super(view);
displayImage = view.findViewById(R.id.item_image_view);
likeButton = view.findViewById(R.id.item_favorite);
itemTitle = view.findViewById(R.id.item_title);
}
public void bindData(VividEntity item) {
String thumbPath = item.getPreviewThumb();
loadThumbnail(thumbPath);
if (displayType == 0) {
itemTitle.setText(item.getName());
Log.d("log", "itemName: " + item.getName());
likeButton.setVisibility(View.GONE);
} else {
itemTitle.setVisibility(View.GONE);
updateLikeButton(item);
}
setupClickEvents(item);
}
private void loadThumbnail(String path) {
Glide.with(appContext)
.load(path)
.transform(new CenterCrop(), new RoundedCorners(32))
.error(R.mipmap.placeholder)
.placeholder(R.mipmap.placeholder)
.into(displayImage);
}
private void updateLikeButton(VividEntity item) {
likeButton.setImageResource(item.getIsFavorite() ? R.drawable.like : R.drawable.un_like);
}
private void setupClickEvents(VividEntity item) {
displayImage.setOnClickListener(v -> {
Intent intent;
if (displayType == 0) {
intent = new Intent(hostActivity, CategoryActivity.class);
intent.putExtra("name", item.getName());
} else {
intent = new Intent(hostActivity, VividActivity.class);
intent.putExtra("vivid", item);
}
hostActivity.startActivity(intent);
});
likeButton.setOnClickListener(v -> handleLikeToggle(item));
}
private void handleLikeToggle(VividEntity item) {
boolean updatedLike = !item.getIsFavorite();
item.setIsFavorite(updatedLike);
saveToDatabase(item);
notifyItemChanged(getAdapterPosition());
}
private void saveToDatabase(VividEntity item) {
dataViewModel.update(item);
}
}
}

View File

@ -0,0 +1,56 @@
package com.wallpaper.vividwallpaper.fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import com.wallpaper.vividwallpaper.databinding.FragmentCollectionBinding;
import com.wallpaper.vividwallpaper.adapter.VividAdapter;
import com.wallpaper.vividwallpaper.util.VividViewModel;
import com.wallpaper.vividwallpaper.util.ItemDecoration;
import java.util.ArrayList;
public class CollectionFragment extends Fragment {
private FragmentCollectionBinding viewBinding;
private VividAdapter dataAdapter;
private VividViewModel viewModel;
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup parent, Bundle savedState) {
viewBinding = FragmentCollectionBinding.inflate(inflater, parent, false);
setupData();
fetchInitialData();
return viewBinding.getRoot();
}
private void setupData() {
viewModel = new ViewModelProvider(this).get(VividViewModel.class);
viewBinding.recyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
dataAdapter = new VividAdapter(viewModel, requireContext(), new ArrayList<>(), requireActivity(), 1);
viewBinding.recyclerView.setAdapter(dataAdapter);
viewBinding.recyclerView.addItemDecoration(new ItemDecoration(20, 15, 20));
}
private void fetchInitialData() {
viewModel.getFavorite().observe(getViewLifecycleOwner(), items -> {
viewBinding.text.setVisibility(items.isEmpty() ? View.VISIBLE : View.GONE);
dataAdapter.refreshData(items);
});
}
@Override
public void onDestroy() {
super.onDestroy();
viewBinding = null;
}
}

View File

@ -0,0 +1,53 @@
package com.wallpaper.vividwallpaper.fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import com.wallpaper.vividwallpaper.databinding.FragmentHomeBinding;
import com.wallpaper.vividwallpaper.adapter.VividAdapter;
import com.wallpaper.vividwallpaper.util.VividViewModel;
import com.wallpaper.vividwallpaper.util.ItemDecoration;
import java.util.ArrayList;
public class HomeFragment extends Fragment {
private FragmentHomeBinding viewBinding;
private VividAdapter dataAdapter;
private VividViewModel viewModel;
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup parent, Bundle savedState) {
viewBinding = FragmentHomeBinding.inflate(inflater, parent, false);
setupData();
fetchInitialData();
return viewBinding.getRoot();
}
private void setupData() {
viewModel = new ViewModelProvider(this).get(VividViewModel.class);
viewBinding.recyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
dataAdapter = new VividAdapter(viewModel, requireContext(), new ArrayList<>(), requireActivity(), 0);
viewBinding.recyclerView.setAdapter(dataAdapter);
viewBinding.recyclerView.addItemDecoration(new ItemDecoration(20, 15, 20));
}
private void fetchInitialData() {
viewModel.getFirstVivid().observe(getViewLifecycleOwner(), items -> dataAdapter.refreshData(items));
}
@Override
public void onDestroy() {
super.onDestroy();
viewBinding = null;
}
}

View File

@ -0,0 +1,29 @@
package com.wallpaper.vividwallpaper.room;
import android.content.Context;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import com.wallpaper.vividwallpaper.MyApplication;
@Database(entities = {VividEntity.class}, version = MyApplication.DB_VERSION, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {
public abstract VividEntityDao wallpaperEntityDao();
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,74 @@
package com.wallpaper.vividwallpaper.room;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
import java.io.Serializable;
@Entity
public class VividEntity implements Serializable {
@PrimaryKey(autoGenerate = true)
private int id;
private String name;
private String original;
private String previewThumb;
private String source;
private Boolean isFavorite;
public VividEntity(String name, String original, String previewThumb, String source, Boolean isFavorite) {
this.name = name;
this.original = original;
this.previewThumb = previewThumb;
this.source = source;
this.isFavorite = isFavorite;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getOriginal() {
return original;
}
public void setOriginal(String original) {
this.original = original;
}
public String getPreviewThumb() {
return previewThumb;
}
public void setPreviewThumb(String previewThumb) {
this.previewThumb = previewThumb;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public Boolean getIsFavorite() {
return isFavorite;
}
public void setIsFavorite(Boolean favorite) {
isFavorite = favorite;
}
}

View File

@ -0,0 +1,30 @@
package com.wallpaper.vividwallpaper.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 VividEntityDao {
@Insert
void insertAll(List<VividEntity> vividEntityList);
@Update
void update(VividEntity vividEntity);
@Query("SELECT * FROM VividEntity WHERE isFavorite = 1 ")
LiveData<List<VividEntity>> getFavorite();
@Query("SELECT * FROM VividEntity WHERE id IN (SELECT MIN(id) FROM VividEntity GROUP BY name)")
LiveData<List<VividEntity>> getFirstVivid();
@Query("SELECT * FROM VividEntity WHERE name = :name")
LiveData<List<VividEntity>> getCategoryByName(String name);
@Query("SELECT isFavorite FROM VividEntity WHERE source = :source AND name = :name")
LiveData<Boolean> getVividFavorite(String source, String name);
}

View File

@ -0,0 +1,69 @@
package com.wallpaper.vividwallpaper.util;
import android.graphics.Rect;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import com.wallpaper.vividwallpaper.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();
}
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,68 @@
package com.wallpaper.vividwallpaper.util;
import android.content.Context;
import com.wallpaper.vividwallpaper.room.VividEntity;
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 JsonParse {
private static String loadJSONFromAsset(Context context, String fileName) {
StringBuilder jsonString = new StringBuilder();
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
context.getAssets().open(fileName)));
String line;
while ((line = reader.readLine()) != null) {
jsonString.append(line);
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
return jsonString.toString();
}
public static List<VividEntity> parseJson(Context context, String fileName) {
List<VividEntity> wallPaperList = new ArrayList<>();
try {
String jsonString = loadJSONFromAsset(context, 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 name = categoryObject.getString("name");
JSONArray listArray = categoryObject.getJSONArray("data");
for (int j = 0; j < listArray.length(); j++) {
JSONObject itemObject = listArray.getJSONObject(j);
String original = itemObject.getString("original");
String previewThumb = itemObject.getString("previewThumb");
String source = itemObject.getString("source");
wallPaperList.add(new VividEntity(name, original, previewThumb, source, false));
}
}
} catch (Exception e) {
e.printStackTrace();
}
return wallPaperList;
}
}

View File

@ -0,0 +1,44 @@
package com.wallpaper.vividwallpaper.util;
import androidx.lifecycle.LiveData;
import com.wallpaper.vividwallpaper.room.VividEntity;
import com.wallpaper.vividwallpaper.room.VividEntityDao;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class VividRepository {
private final VividEntityDao vividEntityDao;
private final ExecutorService executorService;
public VividRepository(VividEntityDao vividEntityDao) {
this.vividEntityDao = vividEntityDao;
this.executorService = Executors.newSingleThreadExecutor();
}
public void insertAll(List<VividEntity> vividEntityList) {
executorService.execute(() -> vividEntityDao.insertAll(vividEntityList));
}
public void update(VividEntity vividEntity) {
executorService.execute(() -> vividEntityDao.update(vividEntity));
}
public LiveData<List<VividEntity>> getFirstVivid() {
return vividEntityDao.getFirstVivid();
}
public LiveData<List<VividEntity>> getFavorite() {
return vividEntityDao.getFavorite();
}
public LiveData<List<VividEntity>> getCategoryByName(String name) {
return vividEntityDao.getCategoryByName(name);
}
public LiveData<Boolean> getVividFavorite(String source, String name) {
return vividEntityDao.getVividFavorite(source, name);
}
}

View File

@ -0,0 +1,139 @@
package com.wallpaper.vividwallpaper.util;
import android.Manifest;
import android.app.Activity;
import android.content.ContentValues;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.provider.MediaStore;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.Toast;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class VividUtil {
public static final int STORAGE_PERMISSION_CODE = 456;
private final ProgressBar loadingBar;
private final ImageView coverView;
public VividUtil(ProgressBar loadingBar, ImageView coverView) {
this.loadingBar = loadingBar;
this.coverView = coverView;
}
public void storeImage(Activity context, String imgUrl) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
new VividSaveTask(context).execute(imgUrl);
} else if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(context,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
STORAGE_PERMISSION_CODE);
} else {
new VividSaveTask(context).execute(imgUrl);
}
}
private class VividSaveTask extends AsyncTask<String, Void, Uri> {
private final Activity context;
private Exception error = null;
public VividSaveTask(Activity context) {
this.context = context;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
setProgressVisible(true);
}
@Override
protected Uri doInBackground(String... urls) {
String imgUrl = urls[0];
String fileName = System.currentTimeMillis() + ".jpg";
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DISPLAY_NAME, fileName);
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
values.put(MediaStore.Images.Media.IS_PENDING, 1);
}
Uri targetUri = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
? MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
: MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
Uri savedUri = context.getContentResolver().insert(targetUri, values);
if (savedUri != null) {
HttpURLConnection conn = null;
try (InputStream input = new URL(imgUrl).openStream();
OutputStream output = context.getContentResolver().openOutputStream(savedUri)) {
conn = (HttpURLConnection) new URL(imgUrl).openConnection();
conn.setDoInput(true);
conn.connect();
if (output != null) {
byte[] buffer = new byte[4096];
int read;
while ((read = input.read(buffer)) != -1) {
output.write(buffer, 0, read);
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
values.clear();
values.put(MediaStore.Images.Media.IS_PENDING, 0);
context.getContentResolver().update(savedUri, values, null, null);
}
return savedUri;
} catch (IOException e) {
error = e;
context.getContentResolver().delete(savedUri, null, null);
} finally {
if (conn != null) {
conn.disconnect();
}
}
}
return null;
}
@Override
protected void onPostExecute(Uri result) {
super.onPostExecute(result);
setProgressVisible(false);
if (result != null) {
Toast.makeText(context, "图片保存成功", Toast.LENGTH_SHORT).show();
} else {
String msg = error != null ? error.getMessage() : "未知错误";
Toast.makeText(context, "保存图片失败: " + msg, Toast.LENGTH_SHORT).show();
}
}
}
private void setProgressVisible(boolean show) {
if (loadingBar != null) {
loadingBar.setVisibility(show ? View.VISIBLE : View.GONE);
}
if (coverView != null) {
coverView.setVisibility(show ? View.VISIBLE : View.GONE);
}
}
}

View File

@ -0,0 +1,43 @@
package com.wallpaper.vividwallpaper.util;
import android.app.Application;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import com.wallpaper.vividwallpaper.room.VividEntityDao;
import com.wallpaper.vividwallpaper.room.AppDatabase;
import com.wallpaper.vividwallpaper.room.VividEntity;
import java.util.List;
public class VividViewModel extends AndroidViewModel {
private final VividRepository vividRepository;
public VividViewModel(@NonNull Application application) {
super(application);
VividEntityDao wallpaperInfoDao = AppDatabase.getInstance(application).wallpaperEntityDao();
vividRepository = new VividRepository(wallpaperInfoDao);
}
public void update(VividEntity vividEntity) {
vividRepository.update(vividEntity);
}
public LiveData<List<VividEntity>> getFirstVivid() {
return vividRepository.getFirstVivid();
}
public LiveData<List<VividEntity>> getFavorite() {
return vividRepository.getFavorite();
}
public LiveData<List<VividEntity>> getCategoryByName(String name) {
return vividRepository.getCategoryByName(name);
}
public LiveData<Boolean> getVividFavorite(String source, String name) {
return vividRepository.getVividFavorite(source, name);
}
}

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M485.6,249.9L198.2,498c-8.3,7.1 -8.3,20.8 0,27.9l287.4,248.2c10.7,9.2 26.4,0.9 26.4,-14L512,263.8c0,-14.8 -15.7,-23.2 -26.4,-13.9zM805.6,249.9L518.2,498c-4.1,3.6 -6.2,8.8 -6.2,14 0,5.2 2.1,10.4 6.2,14l287.4,248.2c10.7,9.2 26.4,0.9 26.4,-14L832,263.8c0,-14.8 -15.7,-23.2 -26.4,-13.9z"
android:fillColor="@color/white"/>
</vector>

View File

@ -0,0 +1,24 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M436.5,815.8l-181.3,-228.3c-6.7,-6.7 -3.4,-16.8 3.4,-23.5 6.7,-6.7 16.8,-3.4 23.5,3.4l147.7,188 144.4,-305.5 151.1,211.5c3.4,6.7 3.4,16.8 -3.4,23.5 -6.7,6.7 -16.8,3.4 -23.5,-3.4l-120.9,-167.9 -141,302.2z"
android:fillColor="@color/white"/>
<path
android:pathData="M268.6,577.5m-50.4,0a50.4,50.4 0,1 0,100.7 0,50.4 50.4,0 1,0 -100.7,0Z"
android:fillColor="@color/white"/>
<path
android:pathData="M436.5,775.6m-50.4,0a50.4,50.4 0,1 0,100.7 0,50.4 50.4,0 1,0 -100.7,0Z"
android:fillColor="@color/white"/>
<path
android:pathData="M577.5,490.2m-50.4,0a50.4,50.4 0,1 0,100.7 0,50.4 50.4,0 1,0 -100.7,0Z"
android:fillColor="@color/white"/>
<path
android:pathData="M711.8,664.8m-50.4,0a50.4,50.4 0,1 0,100.7 0,50.4 50.4,0 1,0 -100.7,0Z"
android:fillColor="@color/white"/>
<path
android:pathData="M785.6,909.8H218.2c-67.1,0 -117.5,-53.7 -117.5,-120.9V449.9c0,-67.1 53.7,-120.9 117.5,-120.9h567.4c67.1,0 117.5,53.7 117.5,120.9v339.1c3.4,67.1 -50.4,120.9 -117.5,120.9zM218.2,382.7c-36.9,0 -70.5,30.2 -70.5,70.5v339.1c0,36.9 30.2,70.5 70.5,70.5h567.4c36.9,0 70.5,-30.2 70.5,-70.5V449.9c0,-36.9 -30.2,-70.5 -70.5,-70.5H218.2zM785.6,275.3H221.6c-13.4,0 -23.5,-10.1 -23.5,-23.5s10.1,-23.5 23.5,-23.5h564c13.4,0 23.5,10.1 23.5,23.5s-10.1,23.5 -23.5,23.5zM684.9,188H319c-13.4,0 -23.5,-10.1 -23.5,-23.5 0,-13.4 10.1,-23.5 23.5,-23.5h366c13.4,0 23.5,10.1 23.5,23.5 3.4,10.1 -10.1,23.5 -23.5,23.5z"
android:fillColor="@color/white"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M512,64a448,448 0,1 0,448 448A448,448 0,0 0,512 64zM757.4,590.1a674.6,674.6 0,0 1,-208 208,73.3 73.3,0 0,1 -75.2,0 674.6,674.6 0,0 1,-208 -208,73.3 73.3,0 1,1 125.4,-75.2 399.4,399.4 0,0 0,34.9 49l17,-211.8a68.8,68.8 0,0 1,137.3 0l16.6,211.5a498.6,498.6 0,0 0,35.2 -48,73.3 73.3,0 1,1 125.4,75.2z"
android:fillColor="#231F20"/>
</vector>

View File

@ -0,0 +1,6 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:startColor="#00FFFFFF"
android:endColor="#80000000"
android:angle="90" />
</shape>

View File

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:fillColor="@color/white"
android:pathData="M1006.8,492.9L544.6,92.2c-18.8,-16.4 -46.4,-16.4 -65.2,0L17.3,492.9c-20.8,18.1 -23.2,49.5 -5.1,70.3 17.7,20.8 49.5,23.2 70.3,5.1L511.9,195.6l429.7,372.7c9.2,8.2 21.2,11.9 32.4,11.9 14,0 27.6,-5.8 37.5,-17.1 18.1,-20.8 16,-52.2 -4.8,-70.3zM1006.8,492.9"/>
<path
android:fillColor="@color/white"
android:pathData="M113.9,567v325.6c0,42 34.5,76.5 76.5,76.5h218.1v-304.5c0,-25.3 20.8,-46.1 46.1,-46.1h114.7c25.3,0 46.1,20.8 46.1,46.1v304.5h218.1c42,0 76.5,-34.5 76.5,-76.5v-325.6L511.9,221.5 113.9,567zM844.3,201h-63.1c-12.6,0 -22.9,10.2 -22.9,22.9v23.9l109.2,94.5L867.5,223.9c-0.3,-12.6 -10.6,-22.9 -23.2,-22.9zM901,88.1s-34.5,56.3 -88.1,99.3c150.9,14 126.3,-131.8 126.3,-131.8 -132.4,-10.2 -131.4,101 -129.7,126.3 20.8,-20.8 49.2,-61.8 91.5,-93.9zM795.2,178.5c-19.5,-16.4 -39.9,-43 -50.5,-53.2 0,0 32.4,20.5 55.6,48.8 2.4,-18.1 6.5,-92.2 -92.2,-84.3 0.3,0 -13.7,103.4 87,88.7zM795.2,178.5"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="38dp"
android:height="32dp"
android:viewportWidth="1216"
android:viewportHeight="1024">
<path
android:fillColor="@color/red"
android:pathData="M853,16c-0.6,-0 -1.4,-0 -2.1,-0 -95.9,0 -182.8,38.6 -246,101.1 -63.1,-62.5 -150,-101.1 -245.9,-101.1 -0.7,0 -1.5,0 -2.2,0 -2.7,-0.1 -6,-0.1 -9.4,-0.1 -179.6,0 -325.8,142.7 -331.6,320.8 0.4,86.1 35.3,163.4 91.6,219.2l495.6,452.2 496.1,-452.7c58,-55.9 94.2,-134 94.9,-220.6 -5.8,-176.4 -152,-319 -331.6,-319 -3.3,0 -6.6,0 -9.9,0.1zM604.9,1008.1z"/>
</vector>

View File

@ -0,0 +1,9 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:angle="45"
android:endColor="#4A90E2"
android:startColor="#A3BFFA"
android:type="linear"
android:useLevel="false" />
<corners android:radius="16sp" />
</shape>

View File

@ -0,0 +1,30 @@
<!-- 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/secondaryProgress">
<clip>
<shape>
<corners android:radius="5dp" />
<solid android:color="#FFD700" /> <!-- 次级进度颜色 -->
</shape>
</clip>
</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,4 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#4A4A4A" />
<corners android:radius="12dp" />
</shape>

View File

@ -0,0 +1,24 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M436.5,815.8l-181.3,-228.3c-6.7,-6.7 -3.4,-16.8 3.4,-23.5 6.7,-6.7 16.8,-3.4 23.5,3.4l147.7,188 144.4,-305.5 151.1,211.5c3.4,6.7 3.4,16.8 -3.4,23.5 -6.7,6.7 -16.8,3.4 -23.5,-3.4l-120.9,-167.9 -141,302.2z"
android:fillColor="@color/gray"/>
<path
android:pathData="M268.6,577.5m-50.4,0a50.4,50.4 0,1 0,100.7 0,50.4 50.4,0 1,0 -100.7,0Z"
android:fillColor="@color/gray"/>
<path
android:pathData="M436.5,775.6m-50.4,0a50.4,50.4 0,1 0,100.7 0,50.4 50.4,0 1,0 -100.7,0Z"
android:fillColor="@color/gray"/>
<path
android:pathData="M577.5,490.2m-50.4,0a50.4,50.4 0,1 0,100.7 0,50.4 50.4,0 1,0 -100.7,0Z"
android:fillColor="@color/gray"/>
<path
android:pathData="M711.8,664.8m-50.4,0a50.4,50.4 0,1 0,100.7 0,50.4 50.4,0 1,0 -100.7,0Z"
android:fillColor="@color/gray"/>
<path
android:pathData="M785.6,909.8H218.2c-67.1,0 -117.5,-53.7 -117.5,-120.9V449.9c0,-67.1 53.7,-120.9 117.5,-120.9h567.4c67.1,0 117.5,53.7 117.5,120.9v339.1c3.4,67.1 -50.4,120.9 -117.5,120.9zM218.2,382.7c-36.9,0 -70.5,30.2 -70.5,70.5v339.1c0,36.9 30.2,70.5 70.5,70.5h567.4c36.9,0 70.5,-30.2 70.5,-70.5V449.9c0,-36.9 -30.2,-70.5 -70.5,-70.5H218.2zM785.6,275.3H221.6c-13.4,0 -23.5,-10.1 -23.5,-23.5s10.1,-23.5 23.5,-23.5h564c13.4,0 23.5,10.1 23.5,23.5s-10.1,23.5 -23.5,23.5zM684.9,188H319c-13.4,0 -23.5,-10.1 -23.5,-23.5 0,-13.4 10.1,-23.5 23.5,-23.5h366c13.4,0 23.5,10.1 23.5,23.5 3.4,10.1 -10.1,23.5 -23.5,23.5z"
android:fillColor="@color/gray"/>
</vector>

View File

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:fillColor="@color/gray"
android:pathData="M1006.8,492.9L544.6,92.2c-18.8,-16.4 -46.4,-16.4 -65.2,0L17.3,492.9c-20.8,18.1 -23.2,49.5 -5.1,70.3 17.7,20.8 49.5,23.2 70.3,5.1L511.9,195.6l429.7,372.7c9.2,8.2 21.2,11.9 32.4,11.9 14,0 27.6,-5.8 37.5,-17.1 18.1,-20.8 16,-52.2 -4.8,-70.3zM1006.8,492.9"/>
<path
android:fillColor="@color/gray"
android:pathData="M113.9,567v325.6c0,42 34.5,76.5 76.5,76.5h218.1v-304.5c0,-25.3 20.8,-46.1 46.1,-46.1h114.7c25.3,0 46.1,20.8 46.1,46.1v304.5h218.1c42,0 76.5,-34.5 76.5,-76.5v-325.6L511.9,221.5 113.9,567zM844.3,201h-63.1c-12.6,0 -22.9,10.2 -22.9,22.9v23.9l109.2,94.5L867.5,223.9c-0.3,-12.6 -10.6,-22.9 -23.2,-22.9zM901,88.1s-34.5,56.3 -88.1,99.3c150.9,14 126.3,-131.8 126.3,-131.8 -132.4,-10.2 -131.4,101 -129.7,126.3 20.8,-20.8 49.2,-61.8 91.5,-93.9zM795.2,178.5c-19.5,-16.4 -39.9,-43 -50.5,-53.2 0,0 32.4,20.5 55.6,48.8 2.4,-18.1 6.5,-92.2 -92.2,-84.3 0.3,0 -13.7,103.4 87,88.7zM795.2,178.5"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="38dp"
android:height="32dp"
android:viewportWidth="1216"
android:viewportHeight="1024">
<path
android:fillColor="@color/gray"
android:pathData="M853,16c-0.6,-0 -1.4,-0 -2.1,-0 -95.9,0 -182.8,38.6 -246,101.1 -63.1,-62.5 -150,-101.1 -245.9,-101.1 -0.7,0 -1.5,0 -2.2,0 -2.7,-0.1 -6,-0.1 -9.4,-0.1 -179.6,0 -325.8,142.7 -331.6,320.8 0.4,86.1 35.3,163.4 91.6,219.2l495.6,452.2 496.1,-452.7c58,-55.9 94.2,-134 94.9,-220.6 -5.8,-176.4 -152,-319 -331.6,-319 -3.3,0 -6.6,0 -9.9,0.1zM604.9,1008.1z"/>
</vector>

View File

@ -0,0 +1,42 @@
<?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"
android:background="@color/blue_black"
tools:context=".activity.CategoryActivity">
<ImageView
android:id="@+id/back"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginStart="25dp"
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="25dp"
android:gravity="center"
android:text="@string/app_name"
android:textColor="@color/white"
android:textSize="24sp"
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="25dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/title" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -5,15 +5,25 @@
android:id="@+id/main" android:id="@+id/main"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".MainActivity"> android:background="@color/blue_black"
tools:context=".activity.MainActivity">
<TextView <androidx.viewpager2.widget.ViewPager2
android:layout_width="wrap_content" android:id="@+id/main_viewpager2"
android:layout_height="wrap_content" android:layout_width="match_parent"
android:text="Hello World!" android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent" android:layout_marginBottom="8dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintBottom_toTopOf="@+id/main_tab_layout"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/main_tab_layout"
android:layout_width="match_parent"
android:layout_height="75dp"
android:layout_marginBottom="16dp"
android:background="@android:color/transparent"
app:layout_constraintBottom_toBottomOf="parent"
app:tabIndicatorHeight="0dp"
app:tabRippleColor="@android:color/transparent" />
</androidx.constraintlayout.widget.ConstraintLayout> </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"
android:background="@color/blue_black"
tools:context=".activity.SplashActivity">
<ImageView
android:id="@+id/splash_image"
android:layout_width="150dp"
android:layout_height="150dp"
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="25sp"
android:textStyle="bold"
android:textColor="@color/white"
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/seek_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,127 @@
<?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"
android:background="@color/blue_black"
tools:context=".activity.VividActivity">
<ImageView
android:id="@+id/image_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/back"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginTop="8dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/back"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/like"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginTop="8dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/un_like"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/bottom_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
app:layout_constraintBottom_toBottomOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/down_picture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/download"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<ProgressBar
android:id="@+id/down_progress"
android:layout_width="24dp"
android:layout_height="24dp"
android:indeterminateTint="@color/white"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/set"
android:layout_width="0dp"
android:layout_height="50dp"
android:background="@drawable/rounded_rectangle_purple"
android:foreground="?attr/selectableItemBackground"
android:paddingHorizontal="20dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/down_picture"
app:layout_constraintWidth_percent="0.5">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/set_wallpaper"
android:textColor="@color/white"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<ImageView
android:id="@+id/view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/gray"
android:focusable="true"
android:clickable="true"
android:visibility="gone" />
<ProgressBar
android:id="@+id/progress_bar"
android:layout_width="48dp"
android:layout_height="48dp"
android:indeterminateTint="@color/white"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</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.CollectionFragment">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="25dp"
android:gravity="center"
android:text="Collection"
android:textColor="@color/white"
android:textSize="24sp"
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"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/title"
android:layout_marginTop="25dp" />
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/you_haven_t_added_any_favorites_yet"
android:textColor="@color/gray"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,30 @@
<?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.HomeFragment">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="25dp"
android:gravity="center"
android:text="Home"
android:textColor="@color/white"
android:textSize="24sp"
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"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/title"
android:layout_marginTop="25dp" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,32 @@
<?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:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="5dp"
android:paddingTop="5dp"
android:background="@drawable/rounded_rectangle_purple">
<ImageView
android:id="@+id/image"
android:layout_width="16dp"
android:layout_height="16dp"
app:layout_constraintBottom_toTopOf="@+id/text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold"
android:gravity="center"
android:layout_marginTop="5dp"
android:text="@string/app_name"
android:textSize="14sp"
app:layout_constraintTop_toBottomOf="@+id/image" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,32 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/item_image_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop" />
<ImageView
android:id="@+id/item_favorite"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginTop="6dp"
android:layout_marginEnd="6dp"
android:src="@drawable/un_like"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/item_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:textColor="@color/white"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,104 @@
<?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="280dp"
android:layout_height="wrap_content"
android:background="@drawable/rounded_rectangle_purple"
android:elevation="8dp"
android:padding="16dp">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Set Wallpaper"
android:textColor="@color/white"
android:textSize="22sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/both"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="24dp"
android:background="@drawable/set_background"
android:padding="14dp"
android:foreground="?attr/selectableItemBackground"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/title">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="DESKTOP AND LOCK"
android:textColor="@color/white"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/lock"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="12dp"
android:background="@drawable/set_background"
android:padding="14dp"
android:foreground="?attr/selectableItemBackground"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/both">
<TextView
android:id="@+id/lock_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="LOCK"
android:textColor="@color/white"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/desktop"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="12dp"
android:layout_marginBottom="16dp"
android:background="@drawable/set_background"
android:padding="14dp"
android:foreground="?attr/selectableItemBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/lock">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="DESKTOP"
android:textColor="@color/white"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,6 +0,0 @@
<?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" />
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -2,4 +2,8 @@
<resources> <resources>
<color name="black">#FF000000</color> <color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color> <color name="white">#FFFFFFFF</color>
<color name="blue_black">#0D1B2A</color>
<color name="blue">#8EE5EE</color>
<color name="gray">#9C979D</color>
<color name="red">#FF005B</color>
</resources> </resources>

View File

@ -1,3 +1,5 @@
<resources> <resources>
<string name="app_name">Vivid Wallpaper</string> <string name="app_name">Vivid Wallpaper</string>
<string name="you_haven_t_added_any_favorites_yet">You haven\'t added any favorites yet💖</string>
<string name="set_wallpaper">Apply Wallpaper</string>
</resources> </resources>

6
keystore.properties Normal file
View File

@ -0,0 +1,6 @@
app_name=Vivid Wallpaper
package_name=com.wallpaper.vividwallpaper
keystoreFile=app/VividWallpaper.jks
key_alias=VividWallpaperkey0
key_store_password=VividWallpaper
key_password=VividWallpaper