V1.0.0(1)完成版

This commit is contained in:
lihongwei 2024-12-06 16:45:56 +08:00
parent 1845c3b9a3
commit 21e1194c76
82 changed files with 2831 additions and 183 deletions

BIN
app/ARPaint.jks Normal file

Binary file not shown.

BIN
app/PaintAR.jks Normal file

Binary file not shown.

View File

@ -15,7 +15,7 @@ android {
targetSdk = 34
versionCode = 1
versionName = "1.0.0"
setProperty("archivesBaseName", "PaintAR" + versionName + "(${versionCode})_$timestamp")
setProperty("archivesBaseName", "AR Paint" + versionName + "(${versionCode})_$timestamp")
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

6
app/keystore.properties Normal file
View File

@ -0,0 +1,6 @@
app_name=AR Paint
package_name=com.ar.paintar
keystoreFile=app/ARPaint.jks
key_alias=ARPaintkey0
key_store_password=ARPaint
key_password=ARPaint

View File

@ -18,4 +18,16 @@
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
#-renamesourcefileattribute SourceFile
-keepclassmembers class com.ar.paintar.MyApplication {
public static final java.lang.String Db_Name;
public static final int Db_Version;
}
-keepclassmembers class * {
@androidx.room.Query <methods>;
}
-keep class com.ar.paintar.room.AppDatabase { *; }
-keep class com.ar.paintar.room.ImageData { *; }
-keep class com.ar.paintar.room.ImageDataDao { *; }

View File

@ -17,6 +17,7 @@
android:maxSdkVersion="32" />
<application
android:name=".MyApplication"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
@ -26,8 +27,20 @@
android:supportsRtl="true"
android:theme="@style/Theme.PaintAR"
tools:targetApi="31">
<activity
android:name=".activity.SettingActivity"
android:exported="false" />
<activity
android:name=".activity.CategoryActivity"
android:exported="false" />
<activity
android:name=".activity.PhotoActivity"
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" />

Binary file not shown.

After

Width:  |  Height:  |  Size: 437 KiB

View File

@ -2,13 +2,22 @@ package com.ar.paintar;
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import com.ar.paintar.utils.DatabaseUtil;
import java.util.List;
import java.util.concurrent.Executors;
public class MyApplication extends Application {
private static MyApplication instance;
public static final int DB_VERSION = 1;
public static final String DB_NAME = "image_database";
public static final int Db_Version = 1;
public static final String Db_Name = "image_database";
private static final String PREF_NAME = "preferences";
private static final String KEY_INITIALIZED = "init";
@Override
public void onCreate() {
@ -16,6 +25,22 @@ public class MyApplication extends Application {
instance = 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();
}
}
private void initDatabase() {
Executors.newSingleThreadExecutor().execute(() -> {
DatabaseUtil databaseUtil = new DatabaseUtil(getContext());
List<String> imagePaths = databaseUtil.getAllImagePathsFromAssets();
databaseUtil.insertAllImages(imagePaths);
});
}
public static Context getContext() {

View File

@ -0,0 +1,93 @@
package com.ar.paintar.activity;
import android.content.Intent;
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.ar.paintar.R;
import com.ar.paintar.adapter.PhotoAdapter;
import com.ar.paintar.databinding.ActivityCategoryBinding;
import com.ar.paintar.room.ImageData;
import com.ar.paintar.utils.DatabaseUtil;
import com.ar.paintar.utils.ItemDecoration;
import java.util.ArrayList;
import java.util.List;
public class CategoryActivity extends AppCompatActivity {
private ActivityCategoryBinding binding;
private DatabaseUtil databaseUtil;
private PhotoAdapter adapter;
private String name;
private String title;
@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() {
name = getIntent().getStringExtra("Name");
if (name == null) {
finish();
return;
}
title = name.substring(4);
databaseUtil = new DatabaseUtil(this);
binding.recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
adapter = new PhotoAdapter(this, new ArrayList<>(), this);
binding.recyclerView.setAdapter(adapter);
ItemDecoration itemDecoration = new ItemDecoration(8, 9, 5);
binding.recyclerView.addItemDecoration(itemDecoration);
}
private void initEvent() {
binding.back.setOnClickListener(v -> finish());
binding.text.setText(title);
loadImage();
}
private void loadImage() {
databaseUtil
.getLiveAllCategory(name)
.observe(this, new Observer<List<ImageData>>() {
@Override
public void onChanged(List<ImageData> imageEntries) {
adapter.updateData(imageEntries);
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
binding = null;
}
}

View File

@ -1,6 +1,8 @@
package com.ar.paintar.activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
@ -9,18 +11,127 @@ import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import com.ar.paintar.R;
import com.ar.paintar.adapter.MainAdapter;
import com.ar.paintar.databinding.ActivityMainBinding;
import com.ar.paintar.databinding.MainTabCustomBinding;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
EdgeToEdge.enable(this);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
setContentView(R.layout.activity_main);
initData();
initEvent();
}
private void initData() {
MainAdapter adapter = new MainAdapter(this);
binding.viewpager.setAdapter(adapter);
}
private void initEvent() {
binding.setting.setOnClickListener(v -> {
Intent intent = new Intent(this, SettingActivity.class);
this.startActivity(intent);
});
new TabLayoutMediator(binding.tabLayout, binding.viewpager, (tab, position) -> {
MainTabCustomBinding tabBinding = MainTabCustomBinding.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) {
updateTabIconAndTextColor(tab, true);
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
updateTabIconAndTextColor(tab, false);
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
private void updateTabIconAndTextColor(TabLayout.Tab tab, boolean isSelected) {
if (tab.getCustomView() != null) {
MainTabCustomBinding tabBinding = MainTabCustomBinding.bind(tab.getCustomView());
int iconResId = getIconResource(tab.getPosition(), isSelected);
tabBinding.imageView.setImageResource(iconResId);
int textColor = isSelected ? getResources().getColor(R.color.select, null) : getResources().getColor(R.color.un_select, null);
tabBinding.text.setTextColor(textColor);
}
}
private int getIconResource(int position, boolean isSelected) {
switch (position) {
case 1:
if (isSelected) {
return R.drawable.import_image;
}
return R.drawable.un_import_image;
case 2:
if (isSelected) {
return R.drawable.collect;
}
return R.drawable.un_collect;
default:
if (isSelected) {
return R.drawable.category;
}
return R.drawable.un_category;
}
}
});
}
private void setTabIconAndDotVisibility(MainTabCustomBinding tabBinding, int position) {
switch (position) {
case 0:
tabBinding.imageView.setImageResource(R.drawable.category);
tabBinding.text.setText(R.string.category);
tabBinding.text.setTextColor(getResources().getColor(R.color.select, null));
break;
case 1:
tabBinding.imageView.setImageResource(R.drawable.un_import_image);
tabBinding.text.setText(R.string.import_image);
tabBinding.text.setTextColor(getResources().getColor(R.color.un_select, null));
break;
case 2:
tabBinding.imageView.setImageResource(R.drawable.un_collect);
tabBinding.text.setText(R.string.collect);
tabBinding.text.setTextColor(getResources().getColor(R.color.un_select, null));
break;
}
}
@Override
public void onDestroy() {
super.onDestroy();
binding = null;
}
}

View File

@ -0,0 +1,393 @@
package com.ar.paintar.activity;
import android.Manifest;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.PointF;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.Toast;
import androidx.activity.EdgeToEdge;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.camera.core.Camera;
import androidx.camera.core.CameraControl;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.ImageCaptureException;
import androidx.camera.core.Preview;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import com.ar.paintar.R;
import com.ar.paintar.databinding.ActivityPhotoBinding;
import com.ar.paintar.utils.Permission;
import com.ar.paintar.utils.Tracing;
import com.google.common.util.concurrent.ListenableFuture;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.ExecutionException;
public class PhotoActivity extends AppCompatActivity implements View.OnTouchListener, SeekBar.OnSeekBarChangeListener {
private static final int CAMERA_PERMISSION_REQUEST_CODE = 200;
private static final int STORAGE_PERMISSION_REQUEST_CODE = 201;
private static final int PICK_IMAGE_REQUEST_CODE = 202;
private ActivityPhotoBinding binding;
private final Matrix matrix = new Matrix();
private final Matrix savedMatrix = new Matrix();
private final PointF startPointF = new PointF();
private float initialDistance;
private int mode = MODE_NONE;
private static final int MODE_NONE = 0;
private static final int MODE_DRAG = 1;
private static final int MODE_ZOOM = 2;
private Bitmap bitmap;
private boolean isFlashOn = false;
private boolean isReOn = false;
private Camera camera;
private ImageCapture imageCapture;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityPhotoBinding.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() {
String imagePath = getIntent().getStringExtra("imagePath");
Log.d("image path", "image path: " + imagePath);
if (imagePath != null) {
displayImage(imagePath);
}
}
private void initEvent() {
binding.imageFull.setOnTouchListener(this);
setupListeners();
checkPermissionsAndStartCamera();
}
private void setupListeners() {
binding.seekbar.setOnSeekBarChangeListener(this);
binding.importImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
openImagePicker();
}
});
binding.light.setOnClickListener(v -> toggleFlash());
binding.back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
binding.reversal.setOnClickListener(v -> toggleMirrorEffect());
binding.play.setOnClickListener(v -> takePhoto());
binding.imageFull.setOnTouchListener(this);
}
private void checkPermissionsAndStartCamera() {
String[] permissions = getRequiredPermissions();
if (Permission.hasPermissions(this, permissions)) {
startCamera();
} else {
Permission.requestPermissions(this, permissions, CAMERA_PERMISSION_REQUEST_CODE);
}
}
private void startCamera() {
ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this);
cameraProviderFuture.addListener(() -> {
try {
ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
bindPreview(cameraProvider);
Preview preview = new Preview.Builder().build();
preview.setSurfaceProvider(binding.preview.getSurfaceProvider());
imageCapture = new ImageCapture.Builder().build();
CameraSelector cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA;
cameraProvider.unbindAll();
cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture);
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
}, ContextCompat.getMainExecutor(this));
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == CAMERA_PERMISSION_REQUEST_CODE) {
if (Permission.handlePermissionsResult(grantResults)) {
startCamera();
} else {
Toast.makeText(this, "Camera permissions denied, please enable permissions in Settings", Toast.LENGTH_SHORT).show();
}
} else if (requestCode == STORAGE_PERMISSION_REQUEST_CODE) {
if (Permission.handlePermissionsResult(grantResults)) {
openImagePicker();
} else {
Toast.makeText(this, "Storage permission is denied. Please enable the permission in the Settings", Toast.LENGTH_SHORT).show();
}
}
}
private void takePhoto() {
if (imageCapture == null) {
Toast.makeText(this, "The photo function is not initialized", Toast.LENGTH_SHORT).show();
return;
}
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "photo_" + System.currentTimeMillis() + ".jpg");
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES);
ImageCapture.OutputFileOptions outputOptions = new ImageCapture.OutputFileOptions.Builder(
getContentResolver(),
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
contentValues
).build();
imageCapture.takePicture(
outputOptions,
ContextCompat.getMainExecutor(this),
new ImageCapture.OnImageSavedCallback() {
@Override
public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) {
Toast.makeText(PhotoActivity.this, "The photo has been saved to the album", Toast.LENGTH_SHORT).show();
}
@Override
public void onError(@NonNull ImageCaptureException exception) {
Toast.makeText(PhotoActivity.this, "Photo failure: " + exception.getMessage(), Toast.LENGTH_SHORT).show();
}
}
);
}
private void toggleMirrorEffect() {
float scaleX = binding.imageFull.getScaleX();
binding.imageFull.setScaleX(scaleX * -1);
isReOn = !isReOn;
binding.reversal.setImageResource(isReOn ? R.drawable.reversal : R.drawable.un_reversal);
}
private String[] getRequiredPermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
return new String[]{Manifest.permission.CAMERA, Manifest.permission.READ_MEDIA_IMAGES};
} else {
return new String[]{Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};
}
}
private void toggleFlash() {
if (camera != null) {
CameraControl cameraControl = camera.getCameraControl();
isFlashOn = !isFlashOn;
cameraControl.enableTorch(isFlashOn);
binding.light.setImageResource(isFlashOn ? R.drawable.flash : R.drawable.un_flash);
}
}
private void openImagePicker() {
String[] permissions = Permission.getStoragePermissions();
if (ContextCompat.checkSelfPermission(this, permissions[0]) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, permissions, STORAGE_PERMISSION_REQUEST_CODE);
} else {
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, PICK_IMAGE_REQUEST_CODE);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_IMAGE_REQUEST_CODE && resultCode == RESULT_OK && data != null) {
Uri selectedImageUri = data.getData();
if (selectedImageUri != null) {
binding.imageFull.setImageURI(selectedImageUri);
}
}
}
private void bindPreview(@NonNull ProcessCameraProvider cameraProvider) {
Preview preview = new Preview.Builder().build();
CameraSelector cameraSelector = new CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
.build();
preview.setSurfaceProvider(binding.preview.getSurfaceProvider());
cameraProvider.unbindAll();
camera = cameraProvider.bindToLifecycle(this, cameraSelector, preview);
if (bitmap != null) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
onInitIm(width, height);
}
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
binding.imageFull.setAlpha((100 - progress) / 100f);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
private void displayImage(String imagePath) {
if (imagePath.startsWith("/data/user/")) {
displayImageFromStorage(imagePath);
} else {
displayImageFromAssets(imagePath);
}
}
private void displayImageFromStorage(String imagePath) {
Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
if (bitmap != null) {
binding.imageFull.setImageBitmap(bitmap);
} else {
Toast.makeText(this, "Image loading failed", Toast.LENGTH_SHORT).show();
}
}
private void displayImageFromAssets(String imagePath) {
try {
AssetManager assetManager = getAssets();
InputStream inputStream = assetManager.open(imagePath);
bitmap = BitmapFactory.decodeStream(inputStream);
binding.imageFull.setImageBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(this, "Image loading failed: " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
@Override
public boolean onTouch(View v, MotionEvent event) {
ImageView view = (ImageView) v;
Log.d("----", "--------a=" + event);
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
startPointF.set(event.getX(), event.getY());
mode = MODE_DRAG;
break;
case MotionEvent.ACTION_POINTER_DOWN:
initialDistance = Tracing.getDistance(event);
if (initialDistance > 10f) {
savedMatrix.set(matrix);
mode = MODE_ZOOM;
}
break;
case MotionEvent.ACTION_MOVE:
if (mode == MODE_DRAG) {
matrix.set(savedMatrix);
matrix.postTranslate(event.getX() - startPointF.x, event.getY() - startPointF.y);
} else if (mode == MODE_ZOOM) {
float newDistance = Tracing.getDistance(event);
if (newDistance > 10f) {
float scale = newDistance / initialDistance;
matrix.set(savedMatrix);
matrix.postScale(scale, scale, view.getWidth() / 2f, view.getHeight() / 2f);
}
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
mode = MODE_NONE;
break;
}
view.setImageMatrix(matrix);
return true;
}
private void onInitIm(float imW, float imH) {
Point screen = getScreen();
float newX = screen.x / 2f - imW / 2;
float newY = screen.y / 2f - imH / 2;
matrix.postTranslate(newX, newY);
binding.imageFull.setImageMatrix(matrix);
}
public Point getScreen() {
DisplayMetrics displayMetrics = new DisplayMetrics();
WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
windowManager.getDefaultDisplay().getMetrics(displayMetrics);
int width = displayMetrics.widthPixels;
int height = displayMetrics.heightPixels;
Point point = new Point();
point.x = width;
point.y = height;
return point;
}
@Override
protected void onDestroy() {
super.onDestroy();
binding = null;
}
}

View File

@ -0,0 +1,47 @@
package com.ar.paintar.activity;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import com.ar.paintar.databinding.ActivitySettingBinding;
import com.ar.paintar.utils.Setting;
public class SettingActivity extends AppCompatActivity {
private ActivitySettingBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivitySettingBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
initData();
initEvent();
}
private void initData() {
}
private void initEvent() {
binding.back.setOnClickListener(v -> finish());
binding.version.setText(Setting.getCurrentVersion(this));
binding.share.setOnClickListener(v -> {
Setting.shareApp(this);
});
}
@Override
protected void onDestroy() {
super.onDestroy();
binding = null;
}
}

View File

@ -0,0 +1,80 @@
package com.ar.paintar.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.ar.paintar.R;
import com.ar.paintar.databinding.ActivitySplashBinding;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
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);
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;
});
ProgressBar progressBar = binding.progressBar;
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);
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,110 @@
package com.ar.paintar.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.RecyclerView;
import com.ar.paintar.R;
import com.ar.paintar.activity.CategoryActivity;
import com.ar.paintar.room.ImageData;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
public class CategoryAdapter extends RecyclerView.Adapter<CategoryAdapter.ViewHolder> {
private List<ImageData> imageEntries;
private final Context context;
private Activity activity;
private List<String> categories;
public CategoryAdapter(Context context, List<ImageData> imageEntries, Activity activity, List<String> categories) {
this.context = context;
this.imageEntries = imageEntries;
this.activity = activity;
this.categories = categories;
}
public void updateData(List<ImageData> newFavoriteImages) {
this.imageEntries = newFavoriteImages;
notifyDataSetChanged();
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.item_category, parent, false);
return new CategoryAdapter.ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
ImageData imageData = imageEntries.get(position);
String name = categories.get(position);
holder.bind(imageData, name);
}
@Override
public int getItemCount() {
return imageEntries.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
private ImageView imageView;
private TextView textView;
ViewHolder(View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.image);
textView = itemView.findViewById(R.id.text);
}
void bind(ImageData favoriteImage, String name) {
String favoritePath = favoriteImage.getImagePath();
setItemText(name);
loadImage(favoritePath);
setClickListeners(name);
}
private void setItemText(String name) {
String title = name.substring(4);
textView.setText(title);
}
private void loadImage(String favoritePath) {
String imagePathToLoad = "file:///android_asset/" + favoritePath;
Glide.with(context)
.load(imagePathToLoad)
.transform(new RoundedCorners(32))
.error(R.mipmap.placeholder)
.placeholder(R.mipmap.placeholder)
.into(imageView);
}
private void setClickListeners(String name) {
imageView.setOnClickListener(v -> {
Intent intent = new Intent(context, CategoryActivity.class);
intent.putExtra("Name", name);
context.startActivity(intent);
});
}
}
}

View File

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

View File

@ -0,0 +1,124 @@
package com.ar.paintar.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 androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.ar.paintar.R;
import com.ar.paintar.activity.PhotoActivity;
import com.ar.paintar.room.AppDatabase;
import com.ar.paintar.room.ImageData;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
public class PhotoAdapter extends RecyclerView.Adapter<PhotoAdapter.ViewHolder> {
private List<ImageData> imageEntries;
private final Context context;
private Activity activity;
private final Executor executor = Executors.newSingleThreadExecutor();
public PhotoAdapter(Context context, List<ImageData> imageEntries, Activity activity) {
this.context = context;
this.imageEntries = imageEntries;
this.activity = activity;
}
public void updateData(List<ImageData> newFavoriteImages) {
this.imageEntries = newFavoriteImages;
notifyDataSetChanged();
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.item_photo, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
ImageData imageData = imageEntries.get(position);
holder.bind(imageData);
}
@Override
public int getItemCount() {
return imageEntries.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
ImageView favoriteButton;
ViewHolder(View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.image_view);
favoriteButton = itemView.findViewById(R.id.btn_favorite);
}
void bind(ImageData favoriteImage) {
String favoritePath = favoriteImage.getImagePath();
loadImage(favoritePath);
setFavoriteButton(favoriteImage);
setClickListeners(favoriteImage);
}
private void loadImage(String favoritePath) {
String imagePathToLoad = favoritePath.startsWith("/data/user/")
? favoritePath
: "file:///android_asset/" + favoritePath;
Glide.with(context)
.load(imagePathToLoad)
.transform(new RoundedCorners(32))
.error(R.mipmap.placeholder)
.placeholder(R.mipmap.placeholder)
.into(imageView);
}
private void setFavoriteButton(ImageData favoriteImage) {
favoriteButton.setImageResource(favoriteImage.isFavoriteStatus()
? R.drawable.favorite
: R.drawable.un_favorite);
}
private void setClickListeners(final ImageData favoriteImage) {
imageView.setOnClickListener(v -> {
Intent intent = new Intent(context, PhotoActivity.class);
intent.putExtra("imagePath", favoriteImage.getImagePath());
context.startActivity(intent);
});
favoriteButton.setOnClickListener(v -> toggleFavorite(favoriteImage));
}
private void toggleFavorite(ImageData favoriteImage) {
boolean newStatus = !favoriteImage.isFavoriteStatus();
favoriteImage.setFavoriteStatus(newStatus);
updateImageInDatabase(favoriteImage);
notifyItemChanged(getAdapterPosition());
}
private void updateImageInDatabase(ImageData favoriteImage) {
executor.execute(() -> {
AppDatabase.getInstance(context)
.imageDataDao()
.update(favoriteImage);
});
}
}
}

View File

@ -0,0 +1,101 @@
package com.ar.paintar.fragment;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.recyclerview.widget.GridLayoutManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.ar.paintar.adapter.CategoryAdapter;
import com.ar.paintar.adapter.PhotoAdapter;
import com.ar.paintar.databinding.FragmentCategoryBinding;
import com.ar.paintar.room.AppDatabase;
import com.ar.paintar.room.ImageData;
import com.ar.paintar.utils.DatabaseUtil;
import com.ar.paintar.utils.ItemDecoration;
import com.ar.paintar.utils.Names;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
public class CategoryFragment extends Fragment {
private FragmentCategoryBinding binding;
private final List<String> categories = Names.getAllDir();
private CategoryAdapter adapter;
private DatabaseUtil databaseUtil;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
binding = FragmentCategoryBinding.inflate(inflater, container, false);
initData();
initEvent();
return binding.getRoot();
}
private void initData() {
databaseUtil = new DatabaseUtil(requireContext());
binding.recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2));
adapter = new CategoryAdapter(requireContext(), new ArrayList<>(), requireActivity(),categories);
binding.recyclerView.setAdapter(adapter);
ItemDecoration itemDecoration = new ItemDecoration(16, 19, 10);
binding.recyclerView.addItemDecoration(itemDecoration);
}
private void initEvent() {
loadFirstCategoryImage(categories);
}
private void loadFirstCategoryImage(List<String> originalList) {
Map<Integer, List<ImageData>> queryResultsMap = new HashMap<>();
int totalQueries = originalList.size();
for (int i = 0; i < totalQueries; i++) {
String original = originalList.get(i);
int finalI = i;
databaseUtil
.getFirstCategory(original)
.observe(getViewLifecycleOwner(), new Observer<List<ImageData>>() {
@Override
public void onChanged(List<ImageData> imageEntries) {
queryResultsMap.put(finalI, imageEntries);
if (queryResultsMap.size() == totalQueries) {
List<ImageData> allImageEntries = new CopyOnWriteArrayList<>();
for (int j = 0; j < totalQueries; j++) {
List<ImageData> currentEntries = queryResultsMap.get(j);
if (currentEntries != null) {
allImageEntries.addAll(currentEntries);
}
}
adapter.updateData(allImageEntries);
}
}
});
}
}
@Override
public void onDestroy() {
super.onDestroy();
binding = null;
}
}

View File

@ -0,0 +1,79 @@
package com.ar.paintar.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.ar.paintar.adapter.PhotoAdapter;
import com.ar.paintar.databinding.FragmentFavoriteBinding;
import com.ar.paintar.room.AppDatabase;
import com.ar.paintar.room.ImageData;
import com.ar.paintar.utils.DatabaseUtil;
import com.ar.paintar.utils.ItemDecoration;
import java.util.ArrayList;
import java.util.List;
public class FavoriteFragment extends Fragment {
private FragmentFavoriteBinding binding;
private PhotoAdapter adapter;
private DatabaseUtil databaseUtil;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
binding = FragmentFavoriteBinding.inflate(inflater, container, false);
initData();
initEvent();
return binding.getRoot();
}
private void initData() {
databaseUtil = new DatabaseUtil(requireContext());
binding.recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2));
adapter = new PhotoAdapter(requireContext(), new ArrayList<>(), requireActivity());
binding.recyclerView.setAdapter(adapter);
ItemDecoration itemDecoration = new ItemDecoration(16, 19, 10);
binding.recyclerView.addItemDecoration(itemDecoration);
}
private void initEvent() {
loadFavoriteImages();
}
private void loadFavoriteImages() {
databaseUtil
.getAllFavoriteImageData()
.observe(getViewLifecycleOwner(), new Observer<List<ImageData>>() {
@Override
public void onChanged(List<ImageData> imageEntries) {
if (imageEntries.isEmpty()) {
binding.text.setVisibility(View.VISIBLE);
} else {
binding.text.setVisibility(View.GONE);
}
adapter.updateData(imageEntries);
}
});
}
@Override
public void onDestroy() {
super.onDestroy();
binding = null;
}
}

View File

@ -0,0 +1,199 @@
package com.ar.paintar.fragment;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.recyclerview.widget.GridLayoutManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import com.ar.paintar.adapter.PhotoAdapter;
import com.ar.paintar.databinding.FragmentImportBinding;
import com.ar.paintar.room.AppDatabase;
import com.ar.paintar.room.ImageData;
import com.ar.paintar.utils.DatabaseUtil;
import com.ar.paintar.utils.ItemDecoration;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public class ImportFragment extends Fragment {
private static final int PICK_IMAGE_REQUEST_CODE = 202;
private FragmentImportBinding binding;
private PhotoAdapter adapter;
private final List<String> imagePaths = new ArrayList<>();
private DatabaseUtil databaseUtil;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
binding = FragmentImportBinding.inflate(inflater, container, false);
initData();
initEvent();
return binding.getRoot();
}
private void initData() {
databaseUtil = new DatabaseUtil(requireContext());
binding.recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2));
adapter = new PhotoAdapter(requireContext(), new ArrayList<>(), requireActivity());
binding.recyclerView.setAdapter(adapter);
ItemDecoration itemDecoration = new ItemDecoration(16, 19, 10);
binding.recyclerView.addItemDecoration(itemDecoration);
}
private void initEvent() {
binding.add.setOnClickListener(v -> openImagePicker());
loadImportImage();
}
private void loadImportImage() {
AppDatabase.getInstance(requireContext())
.imageDataDao()
.getLiveAllImportImageData()
.observe(getViewLifecycleOwner(), new Observer<List<ImageData>>() {
@Override
public void onChanged(List<ImageData> imageEntries) {
if (imageEntries.isEmpty()) {
binding.text.setVisibility(View.VISIBLE);
} else {
binding.text.setVisibility(View.GONE);
}
adapter.updateData(imageEntries);
}
});
}
private void openImagePicker() {
Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, PICK_IMAGE_REQUEST_CODE);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_IMAGE_REQUEST_CODE) {
requireActivity();
if (resultCode == Activity.RESULT_OK && data != null) {
Uri selectedImageUri = data.getData();
if (selectedImageUri != null) {
try {
if (isImageSizeAcceptable(selectedImageUri)) {
saveImageToInternalStorage(selectedImageUri);
} else {
Toast.makeText(getContext(), "The image size is out of limit", Toast.LENGTH_SHORT).show();
}
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(getContext(), "Could not get image size: " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
}
}
}
private boolean isImageSizeAcceptable(Uri uri) throws IOException {
InputStream inputStream = requireContext().getContentResolver().openInputStream(uri);
if (inputStream == null) {
return false;
}
long fileSize = inputStream.available();
inputStream.close();
long maxFileSize = 10 * 1024 * 1024;
return fileSize <= maxFileSize;
}
private void saveImageToInternalStorage(Uri uri) {
try {
InputStream inputStream = requireContext().getContentResolver().openInputStream(uri);
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
if (bitmap == null) {
Toast.makeText(getContext(), "Unable to load image", Toast.LENGTH_SHORT).show();
return;
}
File internalStorageDir = requireContext().getFilesDir();
File imageFile = new File(internalStorageDir, System.currentTimeMillis() + ".jpg");
FileOutputStream outputStream = new FileOutputStream(imageFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
outputStream.close();
inputStream.close();
String imagePath = imageFile.getAbsolutePath();
new Thread(() -> {
if (isImageAlreadyExists(imagePath)) {
requireActivity().runOnUiThread(() -> Toast.makeText(getContext(), "The image already exists", Toast.LENGTH_SHORT).show());
imageFile.delete();
return;
}
imagePaths.add(imagePath);
databaseUtil.insertImageData(new ImageData(false, true, imagePath));
}).start();
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(getContext(), "Failed to save picture: " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
private boolean isImageAlreadyExists(String imagePath) {
File newImageFile = new File(imagePath);
for (String path : imagePaths) {
File existingFile = new File(path);
if (filesAreIdentical(existingFile, newImageFile)) {
return true;
}
}
List<ImageData> imageEntries = databaseUtil.getAllImportImageData();
for (ImageData imageData : imageEntries) {
File existingFile = new File(imageData.getImagePath());
if (filesAreIdentical(existingFile, newImageFile)) {
return true;
}
}
return false;
}
private boolean filesAreIdentical(File file1, File file2) {
return file1.length() == file2.length();
}
@Override
public void onDestroy() {
super.onDestroy();
binding = null;
}
}

View File

@ -0,0 +1,29 @@
package com.ar.paintar.room;
import android.content.Context;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import com.ar.paintar.MyApplication;
@Database(entities = {ImageData.class}, version = MyApplication.Db_Version, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {
public abstract ImageDataDao imageDataDao();
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,49 @@
package com.ar.paintar.room;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
import java.io.Serializable;
@Entity
public class ImageData implements Serializable {
@PrimaryKey(autoGenerate = true)
private int id;
private final String imagePath;
private final boolean imageType;
private boolean favoriteStatus = false;
public ImageData(boolean favoriteStatus, Boolean imageType, String imagePath) {
this.favoriteStatus = favoriteStatus;
this.imageType = imageType;
this.imagePath = imagePath;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getImagePath() {
return imagePath;
}
public boolean getImageType() {
return imageType;
}
public boolean isFavoriteStatus() {
return favoriteStatus;
}
public void setFavoriteStatus(boolean favoriteStatus) {
this.favoriteStatus = favoriteStatus;
}
}

View File

@ -0,0 +1,40 @@
package com.ar.paintar.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 ImageDataDao {
@Insert
void insertAll(List<ImageData> imageData);
@Insert
void insert(ImageData imageData);
@Update
void update(ImageData imageData);
@Query("SELECT * FROM ImageData WHERE imagePath LIKE :category || '/%' AND imageType = 0")
LiveData<List<ImageData>> getLiveAllImageDataByCategory(String category);
@Query("SELECT * FROM ImageData WHERE imagePath LIKE :category || '/%' AND imageType = 0 LIMIT 1")
LiveData<List<ImageData>> getLiveFirstImageDataByCategory(String category);
@Query("SELECT * FROM ImageData WHERE imagePath LIKE :category || '/%' AND imageType = 0 LIMIT 1 OFFSET :index")
LiveData<List<ImageData>> getLiveImageDataByIndex(String category, int index);
@Query("SELECT * FROM ImageData WHERE imageType = 1 ")
LiveData<List<ImageData>> getLiveAllImportImageData();
@Query("SELECT * FROM ImageData WHERE imageType = 1 ")
List<ImageData> getAllImportImageData();
@Query("SELECT * FROM ImageData WHERE favoriteStatus = 1 ")
LiveData<List<ImageData>> getLiveAllFavoriteImageData();
}

View File

@ -0,0 +1,75 @@
package com.ar.paintar.utils;
import android.content.Context;
import androidx.lifecycle.LiveData;
import com.ar.paintar.MyApplication;
import com.ar.paintar.room.AppDatabase;
import com.ar.paintar.room.ImageData;
import com.ar.paintar.room.ImageDataDao;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class DatabaseUtil {
private final ImageDataDao imageDataDao;
public DatabaseUtil(Context context) {
AppDatabase db = AppDatabase.getInstance(context);
imageDataDao = db.imageDataDao();
}
public void insertAllImages(List<String> imagePaths) {
List<ImageData> imageEntries = new ArrayList<>();
for (String path : imagePaths) {
imageEntries.add(new ImageData(false, false, path));
}
imageDataDao.insertAll(imageEntries);
}
public List<String> getAllImagePathsFromAssets() {
List<String> imagePaths = new ArrayList<>();
try {
String[] categories = MyApplication.getContext().getAssets().list("");
if (categories != null) {
for (String category : categories) {
if (category.startsWith("png_")) {
String[] files = MyApplication.getContext().getAssets().list(category);
if (files != null) {
for (String file : files) {
imagePaths.add(category + "/" + file);
}
}
}
}
}
} catch (IOException ignored) {
}
return imagePaths;
}
public LiveData<List<ImageData>> getAllFavoriteImageData() {
return imageDataDao.getLiveAllFavoriteImageData();
}
public List<ImageData> getAllImportImageData() {
return imageDataDao.getAllImportImageData();
}
public void insertImageData(ImageData imageData) {
imageDataDao.insert(imageData);
}
public LiveData<List<ImageData>> getFirstCategory(String category) {
return imageDataDao.getLiveFirstImageDataByCategory(category);
}
public LiveData<List<ImageData>> getLiveAllCategory(String category) {
return imageDataDao.getLiveAllImageDataByCategory(category);
}
}

View File

@ -8,7 +8,7 @@ import android.os.Build;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
public class PermissionUtil {
public class Permission {
public static boolean hasPermissions(Activity activity, String[] permissions) {
for (String permission : permissions) {

View File

@ -5,7 +5,7 @@ import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
public class SettingUtil {
public class Setting {
public static String getCurrentVersion(Context context) {
try {

View File

@ -0,0 +1,37 @@
<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,24C44,22.895 43.105,22 42,22C40.895,22 40,22.895 40,24H44ZM24,8C25.105,8 26,7.105 26,6C26,4.895 25.105,4 24,4V8ZM39,40H9V44H39V40ZM8,39V9H4V39H8ZM40,24V39H44V24H40ZM9,8H24V4H9V8ZM9,40C8.448,40 8,39.552 8,39H4C4,41.761 6.239,44 9,44V40ZM39,44C41.761,44 44,41.761 44,39H40C40,39.552 39.552,40 39,40V44ZM8,9C8,8.448 8.448,8 9,8V4C6.239,4 4,6.239 4,9H8Z"
android:fillColor="#FFFFFF"/>
<path
android:pathData="M6,35L16.693,25.198C17.439,24.514 18.578,24.495 19.346,25.154L32,36"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#FFFFFF"
android:strokeLineCap="round"/>
<path
android:pathData="M28,31L32.773,26.226C33.477,25.523 34.591,25.444 35.388,26.041L42,31"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#FFFFFF"
android:strokeLineCap="round"/>
<path
android:pathData="M30,12L42,12"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#FFFFFF"
android:strokeLineCap="round"/>
<path
android:pathData="M36,6V18"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#FFFFFF"
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="M30,36L18,24L30,12V36Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#000000"/>
</vector>

View File

@ -0,0 +1,24 @@
<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="M15,12L18,6H30L33,12H15Z"
android:strokeLineJoin="round"
android:strokeWidth="1"
android:fillColor="#00000000"
android:strokeColor="#000000"/>
<path
android:pathData="M7,12L41,12A3,3 0,0 1,44 15L44,39A3,3 0,0 1,41 42L7,42A3,3 0,0 1,4 39L4,15A3,3 0,0 1,7 12z"
android:strokeLineJoin="round"
android:strokeWidth="1"
android:fillColor="#00000000"
android:strokeColor="#000000"/>
<path
android:pathData="M24,35C28.418,35 32,31.418 32,27C32,22.582 28.418,19 24,19C19.582,19 16,22.582 16,27C16,31.418 19.582,35 24,35Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#000000"/>
</vector>

View File

@ -0,0 +1,34 @@
<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="M17,11l7.071,-7.071l7.071,7.071l-7.071,7.071z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#6200EE"
android:strokeLineCap="round"/>
<path
android:pathData="M30,24l7.071,-7.071l7.071,7.071l-7.071,7.071z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#6200EE"
android:strokeLineCap="round"/>
<path
android:pathData="M4,24l7.071,-7.071l7.071,7.071l-7.071,7.071z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#6200EE"
android:strokeLineCap="round"/>
<path
android:pathData="M17,37l7.071,-7.071l7.071,7.071l-7.071,7.071z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#6200EE"
android:strokeLineCap="round"/>
</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="M5,8C5,6.895 5.895,6 7,6H19L24,12H41C42.105,12 43,12.895 43,14V40C43,41.105 42.105,42 41,42H7C5.895,42 5,41.105 5,40V8Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#6200EE"/>
<path
android:pathData="M24,20L26.243,24.913L31.608,25.528L27.629,29.179L28.702,34.472L24,31.816L19.298,34.472L20.371,29.179L16.392,25.528L21.757,24.913L24,20Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#6200EE"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,13 @@
<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="M15,8C8.925,8 4,12.925 4,19C4,30 17,40 24,42.326C31,40 44,30 44,19C44,12.925 39.075,8 33,8C29.28,8 25.991,9.847 24,12.674C22.009,9.847 18.72,8 15,8Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#d0021b"
android:strokeColor="#d0021b"
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="M24,24m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#2196F3"/>
<path
android:pathData="M23,14L18,24H30L25,34"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#2196F3"
android:strokeLineCap="round"/>
</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="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="M24,28.625V24.625C27.314,24.625 30,21.939 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

@ -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,47 @@
<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,6L34,6A2,2 0,0 1,36 8L36,34A2,2 0,0 1,34 36L8,36A2,2 0,0 1,6 34L6,8A2,2 0,0 1,8 6z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#6200EE"/>
<path
android:pathData="M42,12V39C42,40.657 40.657,42 39,42H12"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#6200EE"
android:strokeLineCap="round"/>
<path
android:pathData="M6,25L13.656,18.194C14.42,17.515 15.574,17.522 16.33,18.209L26,27"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#6200EE"
android:strokeLineCap="round"/>
<path
android:pathData="M22,23L26.785,19.013C27.497,18.419 28.524,18.393 29.265,18.949L36,24"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#6200EE"
android:strokeLineCap="round"/>
<path
android:pathData="M6,19L6,27"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#6200EE"
android:strokeLineCap="round"/>
<path
android:pathData="M36,19V27"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#6200EE"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,47 @@
<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,6L34,6A2,2 0,0 1,36 8L36,34A2,2 0,0 1,34 36L8,36A2,2 0,0 1,6 34L6,8A2,2 0,0 1,8 6z"
android:strokeLineJoin="round"
android:strokeWidth="1"
android:fillColor="#00000000"
android:strokeColor="#000000"/>
<path
android:pathData="M42,12V39C42,40.657 40.657,42 39,42H12"
android:strokeLineJoin="round"
android:strokeWidth="1"
android:fillColor="#00000000"
android:strokeColor="#000000"
android:strokeLineCap="round"/>
<path
android:pathData="M6,25L13.656,18.194C14.42,17.515 15.574,17.522 16.33,18.209L26,27"
android:strokeLineJoin="round"
android:strokeWidth="1"
android:fillColor="#00000000"
android:strokeColor="#000000"
android:strokeLineCap="round"/>
<path
android:pathData="M22,23L26.785,19.013C27.497,18.419 28.524,18.393 29.265,18.949L36,24"
android:strokeLineJoin="round"
android:strokeWidth="1"
android:fillColor="#00000000"
android:strokeColor="#000000"
android:strokeLineCap="round"/>
<path
android:pathData="M6,19L6,27"
android:strokeLineJoin="round"
android:strokeWidth="1"
android:fillColor="#00000000"
android:strokeColor="#000000"
android:strokeLineCap="round"/>
<path
android:pathData="M36,19V27"
android:strokeLineJoin="round"
android:strokeWidth="1"
android:fillColor="#00000000"
android:strokeColor="#000000"
android:strokeLineCap="round"/>
</vector>

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,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#4C9AF7" />
<stroke android:color="@color/white" android:width="4dp"/>
<size
android:width="16dp"
android:height="16dp" />
</shape>

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="M24,6V42"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#2196F3"
android:strokeLineCap="round"/>
<path
android:pathData="M4,34L16,12V34H4Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#2196F3"/>
<path
android:pathData="M44,34H32V12L44,34Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#2196F3"/>
</vector>

View File

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

View File

@ -0,0 +1,10 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:angle="45"
android:endColor="#D1C4E9"
android:startColor="#BBDEFB"
android:type="linear"
android:useLevel="false" />
<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="#0D000000"/>
<corners android:radius="16dp"/>
</shape>

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,38 @@
<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="M35,16C37.761,16 40,13.761 40,11C40,8.239 37.761,6 35,6C32.239,6 30,8.239 30,11C30,13.761 32.239,16 35,16Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"/>
<path
android:pathData="M13,29C15.761,29 18,26.761 18,24C18,21.239 15.761,19 13,19C10.239,19 8,21.239 8,24C8,26.761 10.239,29 13,29Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"/>
<path
android:pathData="M30,13.575L17.339,21.245"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M17.338,26.564L30.679,34.447"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M35,32C37.761,32 40,34.239 40,37C40,39.761 37.761,42 35,42C32.239,42 30,39.761 30,37C30,34.239 32.239,32 35,32Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"/>
</vector>

View File

@ -0,0 +1,27 @@
<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,34 @@
<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="M17,11l7.071,-7.071l7.071,7.071l-7.071,7.071z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#757575"
android:strokeLineCap="round"/>
<path
android:pathData="M30,24l7.071,-7.071l7.071,7.071l-7.071,7.071z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#757575"
android:strokeLineCap="round"/>
<path
android:pathData="M4,24l7.071,-7.071l7.071,7.071l-7.071,7.071z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#757575"
android:strokeLineCap="round"/>
<path
android:pathData="M17,37l7.071,-7.071l7.071,7.071l-7.071,7.071z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#757575"
android:strokeLineCap="round"/>
</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="M5,8C5,6.895 5.895,6 7,6H19L24,12H41C42.105,12 43,12.895 43,14V40C43,41.105 42.105,42 41,42H7C5.895,42 5,41.105 5,40V8Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#757575"/>
<path
android:pathData="M24,20L26.243,24.913L31.608,25.528L27.629,29.179L28.702,34.472L24,31.816L19.298,34.472L20.371,29.179L16.392,25.528L21.757,24.913L24,20Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#757575"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,27 @@
<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="M15,8C8.925,8 4,12.925 4,19C4,30 17,40 24,42.326C31,40 44,30 44,19C44,12.925 39.075,8 33,8C29.28,8 25.991,9.847 24,12.674C22.009,9.847 18.72,8 15,8Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#d0021b"
android:strokeLineCap="round"/>
<path
android:pathData="M28,20L20,28"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#d0021b"
android:strokeLineCap="round"/>
<path
android:pathData="M20,20L28,28"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#d0021b"
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="M24,24m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"/>
<path
android:pathData="M23,14L18,24H30L25,34"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,47 @@
<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,6L34,6A2,2 0,0 1,36 8L36,34A2,2 0,0 1,34 36L8,36A2,2 0,0 1,6 34L6,8A2,2 0,0 1,8 6z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#757575"/>
<path
android:pathData="M42,12V39C42,40.657 40.657,42 39,42H12"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#757575"
android:strokeLineCap="round"/>
<path
android:pathData="M6,25L13.656,18.194C14.42,17.515 15.574,17.522 16.33,18.209L26,27"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#757575"
android:strokeLineCap="round"/>
<path
android:pathData="M22,23L26.785,19.013C27.497,18.419 28.524,18.393 29.265,18.949L36,24"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#757575"
android:strokeLineCap="round"/>
<path
android:pathData="M6,19L6,27"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#757575"
android:strokeLineCap="round"/>
<path
android:pathData="M36,19V27"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#757575"
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="M24,6V42"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"
android:strokeLineCap="round"/>
<path
android:pathData="M4,34L16,12V34H4Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"/>
<path
android:pathData="M44,34H32V12L44,34Z"
android:strokeLineJoin="round"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#333"/>
</vector>

View File

@ -0,0 +1,40 @@
<?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"
xmlns:app="http://schemas.android.com/apk/res-auto"
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="30dp"
android:layout_height="30dp"
android:layout_marginStart="25dp"
android:src="@drawable/back_left"
app:layout_constraintBottom_toBottomOf="@+id/text"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/text" />
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="25dp"
android:gravity="center"
android:textSize="24sp"
android:text="@string/app_name"
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/text" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -5,15 +5,50 @@
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".activity.MainActivity">
<TextView
<ImageView
android:id="@+id/setting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginStart="24dp"
android:src="@drawable/setting"
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="12dp"
android:gravity="center_vertical"
android:text="@string/app_name"
android:textColor="@color/black"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:background="@android:color/transparent"
app:layout_constraintTop_toBottomOf="@id/title"
app:tabIndicatorHeight="0dp"
app:tabRippleColor="@android:color/transparent" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="20dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tab_layout" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,105 @@
<?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.PhotoActivity">
<androidx.camera.view.PreviewView
android:id="@+id/preview"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/image_full"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="matrix"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="25dp"
android:layout_marginTop="25dp"
android:src="@drawable/back_left"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/light"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_marginStart="25dp"
android:layout_marginTop="25dp"
android:layout_marginBottom="25dp"
android:src="@drawable/un_flash"
app:layout_constraintEnd_toStartOf="@+id/reversal"
app:layout_constraintStart_toEndOf="@+id/back"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/reversal"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_marginTop="25dp"
android:layout_marginEnd="25dp"
android:layout_marginBottom="25dp"
android:src="@drawable/un_reversal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/light"
app:layout_constraintTop_toTopOf="parent" />
<SeekBar
android:id="@+id/seekbar"
android:layout_width="0dp"
android:layout_height="33dp"
android:layout_marginStart="50dp"
android:layout_marginEnd="50dp"
android:layout_marginBottom="100dp"
android:max="100"
android:maxHeight="5dp"
android:padding="10dp"
android:progress="0"
android:progressDrawable="@drawable/progress_color"
android:thumb="@drawable/progress_thumb"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<ImageView
android:id="@+id/play"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_marginTop="25dp"
android:background="@drawable/rounded_rectangle"
android:padding="5dp"
android:src="@drawable/camera"
app:layout_constraintEnd_toStartOf="@id/import_image"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/seekbar" />
<ImageView
android:id="@+id/import_image"
android:layout_width="45dp"
android:layout_height="45dp"
android:background="@drawable/rounded_rectangle"
android:padding="5dp"
android:src="@drawable/photo"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/play"
app:layout_constraintTop_toTopOf="@id/play" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,101 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
android:padding="16dp"
tools:context=".activity.SettingActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:id="@+id/back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="9dp"
android:src="@drawable/back_left" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="@string/setting"
android:textSize="24sp"
android:textStyle="bold" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:orientation="vertical">
<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/helpcenter" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:layout_weight="1"
android:text="@string/version"
android:textSize="16sp" />
<TextView
android:id="@+id/version"
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:text="@string/share"
android:textSize="16sp" />
<ImageView
android:id="@+id/share"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/share_right" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

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="25sp"
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,13 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
tools:context=".fragment.CategoryFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>

View File

@ -0,0 +1,27 @@
<?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">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/there_aren_t_any_pictures_here_yet"
android:textColor="@color/dark"
android:textSize="16sp"
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,62 @@
<?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.ImportFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="5dp"
app:layout_constraintBottom_toTopOf="@+id/add"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/there_aren_t_any_pictures_here_yet"
android:textColor="@color/dark"
android:textSize="16sp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:id="@+id/add"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="25dp"
android:background="@drawable/rounded_rectangle_gradient"
android:gravity="center"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintWidth_percent="0.5">
<ImageView
android:layout_width="40dp"
android:layout_height="48dp"
android:layout_gravity="center_horizontal"
android:layout_marginEnd="10dp"
android:padding="5dp"
android:src="@drawable/add" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/import_picture"
android:textColor="@color/white" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,24 @@
<?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"
android:background="@drawable/rounded_rectangle_transparent"
android:gravity="center">
<ImageView
android:id="@+id/image"
android:layout_marginTop="15dp"
android:layout_width="match_parent"
android:layout_height="126dp"
android:layout_marginBottom="10dp"/>
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginBottom="5dp"
android:textColor="@color/select"/>
</LinearLayout>

View File

@ -0,0 +1,20 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="126dp">
<ImageView
android:id="@+id/image_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerInside" />
<ImageView
android:id="@+id/btn_favorite"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_marginBottom="12dp"
android:layout_marginEnd="12dp"
android:src="@drawable/un_favorite" />
</RelativeLayout>

View File

@ -0,0 +1,33 @@
<?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_tab_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="15dp"
android:background="@drawable/rounded_rectangle_gradient">
<ImageView
android:id="@+id/image_view"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginTop="20dp"
android:layout_marginBottom="12dp"
android:src="@drawable/back_left"
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:layout_marginTop="15dp"
android:gravity="center"
android:text="@string/app_name"
android:textSize="15sp"
app:layout_constraintTop_toBottomOf="@+id/image_view" />
</androidx.constraintlayout.widget.ConstraintLayout>

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: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 982 B

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 KiB

View File

@ -2,4 +2,7 @@
<resources>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="dark">#D3D3D3</color>
<color name="select">#6200EE</color>
<color name="un_select">#757575</color>
</resources>

View File

@ -1,3 +1,11 @@
<resources>
<string name="app_name">PaintAR</string>
<string name="app_name">AR Paint</string>
<string name="there_aren_t_any_pictures_here_yet">There aren\'t any pictures here yet</string>
<string name="import_picture">Import picture</string>
<string name="category">Category</string>
<string name="import_image">Import</string>
<string name="collect">Collect</string>
<string name="setting">Setting</string>
<string name="version">Version</string>
<string name="share">Share</string>
</resources>