V1.0.0(1)完成版
BIN
app/ARDrawingSpace.jks
Normal file
15
app/proguard-rules.pro
vendored
@ -18,4 +18,17 @@
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
#-renamesourcefileattribute SourceFile
|
||||
|
||||
-keepclassmembers class com.ardrawing.ardrawingspace.MyApplication {
|
||||
public static final java.lang.String DATABASE_NAME;
|
||||
public static final int DATABASE_VERSION;
|
||||
}
|
||||
|
||||
-keepclassmembers class * {
|
||||
@androidx.room.Query <methods>;
|
||||
}
|
||||
|
||||
-keep class com.ardrawing.ardrawingspace.room.AppDatabase { *; }
|
||||
-keep class com.ardrawing.ardrawingspace.room.SpaceEntity { *; }
|
||||
-keep class com.ardrawing.ardrawingspace.room.SpaceEntityDao { *; }
|
||||
@ -8,7 +8,6 @@
|
||||
<uses-feature android:name="android.hardware.camera" />
|
||||
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
||||
|
||||
<uses-permission
|
||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="32" />
|
||||
@ -26,6 +25,15 @@
|
||||
tools:targetApi="31">
|
||||
<activity
|
||||
android:name=".activity.MainActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".activity.DrawingActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".activity.CategoryActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".activity.SplashActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
@ -4,6 +4,8 @@ import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import com.ardrawing.ardrawingspace.util.FileParsingAndInitialization;
|
||||
|
||||
public class MyApplication extends Application {
|
||||
public static MyApplication application;
|
||||
public static final String DATABASE_NAME = "database";
|
||||
@ -27,8 +29,8 @@ public class MyApplication extends Application {
|
||||
}
|
||||
|
||||
private void initDatabase() {
|
||||
// InitDatabase initDatabase = new InitDatabase(getContext());
|
||||
// initDatabase.insertImagesToDatabase();
|
||||
FileParsingAndInitialization fileParsingAndInitialization = new FileParsingAndInitialization(application);
|
||||
fileParsingAndInitialization.insertImagesToDatabase();
|
||||
}
|
||||
|
||||
public static Context getContext() {
|
||||
|
||||
@ -0,0 +1,84 @@
|
||||
package com.ardrawing.ardrawingspace.activity;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.activity.EdgeToEdge;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
|
||||
import com.ardrawing.ardrawingspace.R;
|
||||
import com.ardrawing.ardrawingspace.adapter.SpaceRecyclerViewAdapter;
|
||||
import com.ardrawing.ardrawingspace.databinding.ActivityCategoryBinding;
|
||||
import com.ardrawing.ardrawingspace.room.SpaceEntity;
|
||||
import com.ardrawing.ardrawingspace.util.ItemDecoration;
|
||||
import com.ardrawing.ardrawingspace.viewmodel.SpaceViewModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CategoryActivity extends AppCompatActivity {
|
||||
private ActivityCategoryBinding binding;
|
||||
private SpaceRecyclerViewAdapter adapter;
|
||||
private SpaceViewModel viewModel;
|
||||
private String title;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
EdgeToEdge.enable(this);
|
||||
binding = ActivityCategoryBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
||||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||
return insets;
|
||||
});
|
||||
|
||||
initData();
|
||||
initEvent();
|
||||
}
|
||||
|
||||
private void initData() {
|
||||
String path = getIntent().getStringExtra("imagePath");
|
||||
if (path == null) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
String[] parts = path.split("/");
|
||||
title = parts[0].split("_")[1];
|
||||
|
||||
viewModel = new ViewModelProvider(this).get(SpaceViewModel.class);
|
||||
|
||||
binding.recyclerView.setLayoutManager(new GridLayoutManager(this, 2));
|
||||
adapter = new SpaceRecyclerViewAdapter(this, new ArrayList<>(), 2);
|
||||
binding.recyclerView.setAdapter(adapter);
|
||||
|
||||
binding.recyclerView.addItemDecoration(new ItemDecoration(35, 15, 20));
|
||||
}
|
||||
|
||||
private void initEvent() {
|
||||
binding.back.setOnClickListener(v -> finish());
|
||||
binding.text.setText(title);
|
||||
loadImage();
|
||||
}
|
||||
|
||||
private void loadImage() {
|
||||
viewModel
|
||||
.getEntityByImagePath(title)
|
||||
.observe(this, spaceEntityList -> {
|
||||
adapter.updateItems(spaceEntityList);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
binding = null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,284 @@
|
||||
package com.ardrawing.ardrawingspace.activity;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Matrix;
|
||||
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.view.MotionEvent;
|
||||
import android.view.View;
|
||||
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.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.ardrawing.ardrawingspace.R;
|
||||
import com.ardrawing.ardrawingspace.databinding.ActivityDrawingBinding;
|
||||
import com.ardrawing.ardrawingspace.util.DocumentManipulationTool;
|
||||
import com.ardrawing.ardrawingspace.util.PermissionTool;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class DrawingActivity extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener, View.OnTouchListener {
|
||||
private ActivityDrawingBinding binding;
|
||||
|
||||
private static final int CAMERA_PERMISSION_REQUEST = 200;
|
||||
private static final int STORAGE_PERMISSION_REQUEST = 201;
|
||||
private static final int PICK_IMAGE_REQUEST = 202;
|
||||
|
||||
private static final int MODE_NONE = 0;
|
||||
private static final int MODE_DRAG = 1;
|
||||
private static final int MODE_ZOOM = 2;
|
||||
|
||||
private final Matrix matrix = new Matrix();
|
||||
private final Matrix savedMatrix = new Matrix();
|
||||
private final PointF startPoint = new PointF();
|
||||
private float initialDistance;
|
||||
private int mode = MODE_NONE;
|
||||
|
||||
private boolean isFlash = false;
|
||||
private Camera camera;
|
||||
private ImageCapture imageCapture;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
binding = ActivityDrawingBinding.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;
|
||||
});
|
||||
|
||||
setupEventListeners();
|
||||
}
|
||||
|
||||
private void setupEventListeners() {
|
||||
String imagePath = getIntent().getStringExtra("imagePath");
|
||||
if (imagePath == null) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
DocumentManipulationTool.loadImageByPath(imagePath, binding.imageView, this);
|
||||
|
||||
binding.imageView.setOnTouchListener(this);
|
||||
binding.seekbar.setOnSeekBarChangeListener(this);
|
||||
binding.photo.setOnClickListener(v -> handleImagePicker());
|
||||
binding.flash.setOnClickListener(v -> toggleFlash());
|
||||
binding.back.setOnClickListener(v -> finish());
|
||||
binding.camera.setOnClickListener(v -> captureAndSaveImage());
|
||||
|
||||
checkAndRequestPermissions();
|
||||
}
|
||||
|
||||
private void checkAndRequestPermissions() {
|
||||
String[] permissions = getPermissions();
|
||||
if (!PermissionTool.hasPermission(this, permissions)) {
|
||||
PermissionTool.reqPermission(this, permissions, CAMERA_PERMISSION_REQUEST);
|
||||
} else {
|
||||
setupCamera();
|
||||
}
|
||||
}
|
||||
|
||||
private void setupCamera() {
|
||||
ListenableFuture<ProcessCameraProvider> future = ProcessCameraProvider.getInstance(this);
|
||||
future.addListener(() -> {
|
||||
try {
|
||||
ProcessCameraProvider provider = future.get();
|
||||
Preview preview = new Preview.Builder().build();
|
||||
preview.setSurfaceProvider(binding.preview.getSurfaceProvider());
|
||||
|
||||
imageCapture = new ImageCapture.Builder().build();
|
||||
CameraSelector selector = new CameraSelector.Builder()
|
||||
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
|
||||
.build();
|
||||
|
||||
provider.unbindAll();
|
||||
camera = provider.bindToLifecycle(this, selector, preview, imageCapture);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}, ContextCompat.getMainExecutor(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
handlePermissionResult(requestCode, grantResults);
|
||||
}
|
||||
|
||||
private void handlePermissionResult(int requestCode, int[] grantResults) {
|
||||
if (requestCode == CAMERA_PERMISSION_REQUEST && PermissionTool.gotPermission(grantResults)) {
|
||||
setupCamera();
|
||||
} else if (requestCode == STORAGE_PERMISSION_REQUEST && PermissionTool.gotPermission(grantResults)) {
|
||||
handleImagePicker();
|
||||
} else {
|
||||
showToast("Permission denied. Please enable it in Settings.");
|
||||
}
|
||||
}
|
||||
|
||||
private void captureAndSaveImage() {
|
||||
if (imageCapture == null) {
|
||||
showToast("Camera not Init");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hasCameraPermission()) {
|
||||
requestCameraPermission();
|
||||
return;
|
||||
}
|
||||
|
||||
ImageCapture.OutputFileOptions options = new ImageCapture.OutputFileOptions.Builder(
|
||||
getContentResolver(),
|
||||
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
|
||||
prepareContentValues()
|
||||
).build();
|
||||
|
||||
imageCapture.takePicture(options, ContextCompat.getMainExecutor(this), new ImageCapture.OnImageSavedCallback() {
|
||||
@Override
|
||||
public void onImageSaved(@NonNull ImageCapture.OutputFileResults output) {
|
||||
showToast("Successful photo shoot");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(@NonNull ImageCaptureException exception) {
|
||||
showToast("Photo shoot failed");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void handleImagePicker() {
|
||||
String[] permissions = PermissionTool.getPermission();
|
||||
if (ContextCompat.checkSelfPermission(this, permissions[0]) != PackageManager.PERMISSION_GRANTED) {
|
||||
ActivityCompat.requestPermissions(this, permissions, STORAGE_PERMISSION_REQUEST);
|
||||
} else {
|
||||
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
|
||||
startActivityForResult(intent, PICK_IMAGE_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null) {
|
||||
Uri imageUri = data.getData();
|
||||
if (imageUri != null) {
|
||||
binding.imageView.setImageURI(imageUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
binding.imageView.setAlpha((100 - progress) / 100f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
ImageView view = (ImageView) v;
|
||||
switch (event.getActionMasked()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
savedMatrix.set(matrix);
|
||||
startPoint.set(event.getX(), event.getY());
|
||||
mode = MODE_DRAG;
|
||||
break;
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
initialDistance = DocumentManipulationTool.computeTouchDistance(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() - startPoint.x, event.getY() - startPoint.y);
|
||||
} else if (mode == MODE_ZOOM && event.getPointerCount() >= 2) {
|
||||
float newDist = DocumentManipulationTool.computeTouchDistance(event);
|
||||
if (newDist > 10f) {
|
||||
float scale = newDist / 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 toggleFlash() {
|
||||
if (camera != null) {
|
||||
isFlash = !isFlash;
|
||||
camera.getCameraControl().enableTorch(isFlash);
|
||||
binding.flash.setImageResource(isFlash ? R.drawable.flash : R.drawable.un_flash);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasCameraPermission() {
|
||||
return ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
private void requestCameraPermission() {
|
||||
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, CAMERA_PERMISSION_REQUEST);
|
||||
}
|
||||
|
||||
private ContentValues prepareContentValues() {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(MediaStore.MediaColumns.DISPLAY_NAME, "photo_" + System.currentTimeMillis() + ".jpg");
|
||||
values.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
|
||||
values.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES);
|
||||
return values;
|
||||
}
|
||||
|
||||
private String[] getPermissions() {
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU ?
|
||||
new String[]{Manifest.permission.CAMERA, Manifest.permission.READ_MEDIA_IMAGES} :
|
||||
new String[]{Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};
|
||||
}
|
||||
|
||||
private void showToast(String message) {
|
||||
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
binding = null;
|
||||
}
|
||||
}
|
||||
@ -1,26 +1,166 @@
|
||||
package com.ardrawing.ardrawingspace.activity;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.activity.EdgeToEdge;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
|
||||
import com.ardrawing.ardrawingspace.R;
|
||||
import com.ardrawing.ardrawingspace.adapter.ViewPagerAdapter;
|
||||
import com.ardrawing.ardrawingspace.databinding.ActivityMainBinding;
|
||||
import com.ardrawing.ardrawingspace.databinding.TabCustomBinding;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import com.google.android.material.tabs.TabLayoutMediator;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
private ActivityMainBinding viewBinding;
|
||||
|
||||
private static final int[] ACTIVE_ICONS = {
|
||||
R.drawable.home, R.drawable.resource_import, R.drawable.collection
|
||||
};
|
||||
|
||||
private static final int[] INACTIVE_ICONS = {
|
||||
R.drawable.un_home, R.drawable.un_import, R.drawable.un_collection
|
||||
};
|
||||
|
||||
private static final int COLOR_BLACK = R.color.black;
|
||||
private static final int COLOR_GRAY = R.color.gray;
|
||||
|
||||
private static final TabConfig[] TAB_CONFIGS = {
|
||||
new TabConfig(R.drawable.home, "Category", COLOR_BLACK),
|
||||
new TabConfig(R.drawable.un_import, "Import", COLOR_GRAY),
|
||||
new TabConfig(R.drawable.un_collection, "Favorite", COLOR_GRAY)
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
configureEdgeToEdge();
|
||||
initializeBinding();
|
||||
setupWindowInsets();
|
||||
|
||||
initData();
|
||||
initEvent();
|
||||
}
|
||||
|
||||
private void configureEdgeToEdge() {
|
||||
EdgeToEdge.enable(this);
|
||||
setContentView(R.layout.activity_main);
|
||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
||||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||
return insets;
|
||||
}
|
||||
|
||||
private void initializeBinding() {
|
||||
viewBinding = ActivityMainBinding.inflate(LayoutInflater.from(this));
|
||||
setContentView(viewBinding.getRoot());
|
||||
}
|
||||
|
||||
private void setupWindowInsets() {
|
||||
View mainLayout = findViewById(R.id.main);
|
||||
ViewCompat.setOnApplyWindowInsetsListener(mainLayout, (view, windowInsets) -> {
|
||||
Insets bars = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||
view.setPadding(bars.left, bars.top, bars.right, bars.bottom);
|
||||
return windowInsets;
|
||||
});
|
||||
}
|
||||
|
||||
private void initData() {
|
||||
ViewPagerAdapter pagerAdapter = new ViewPagerAdapter(this);
|
||||
viewBinding.viewPager.setAdapter(pagerAdapter);
|
||||
}
|
||||
|
||||
private void initEvent() {
|
||||
TabLayoutMediator mediator = new TabLayoutMediator(
|
||||
viewBinding.tabLayout,
|
||||
viewBinding.viewPager,
|
||||
this::configureTabView
|
||||
);
|
||||
mediator.attach();
|
||||
|
||||
viewBinding.tabLayout.addOnTabSelectedListener(createTabListener());
|
||||
}
|
||||
|
||||
private void configureTabView(TabLayout.Tab tab, int index) {
|
||||
TabCustomBinding tabViewBinding = TabCustomBinding.inflate(LayoutInflater.from(this));
|
||||
tab.setCustomView(tabViewBinding.getRoot());
|
||||
TabConfig config = determineTabConfig(index);
|
||||
tabViewBinding.imageView.setImageResource(config.iconId);
|
||||
tabViewBinding.title.setText(config.label);
|
||||
tabViewBinding.title.setTextColor(fetchColor(config.textColorId));
|
||||
}
|
||||
|
||||
private TabLayout.OnTabSelectedListener createTabListener() {
|
||||
return new TabLayout.OnTabSelectedListener() {
|
||||
@Override
|
||||
public void onTabSelected(TabLayout.Tab tab) {
|
||||
refreshTabAppearance(tab, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabUnselected(TabLayout.Tab tab) {
|
||||
refreshTabAppearance(tab, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabReselected(TabLayout.Tab tab) {
|
||||
}
|
||||
|
||||
private void refreshTabAppearance(TabLayout.Tab tab, boolean active) {
|
||||
View customView = tab.getCustomView();
|
||||
if (customView != null) {
|
||||
TabCustomBinding tabBinding = TabCustomBinding.bind(customView);
|
||||
updateTabIcon(tabBinding, tab.getPosition(), active);
|
||||
updateTabTextColor(tabBinding, active);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTabIcon(TabCustomBinding tabBinding, int pos, boolean active) {
|
||||
int iconId = fetchIconResource(pos, active);
|
||||
tabBinding.imageView.setImageResource(iconId);
|
||||
}
|
||||
|
||||
private void updateTabTextColor(TabCustomBinding tabBinding, boolean active) {
|
||||
int colorId = active ? COLOR_BLACK : COLOR_GRAY;
|
||||
tabBinding.title.setTextColor(fetchColor(colorId));
|
||||
}
|
||||
|
||||
private int fetchIconResource(int pos, boolean active) {
|
||||
return active ? ACTIVE_ICONS[pos] : INACTIVE_ICONS[pos];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private TabConfig determineTabConfig(int index) {
|
||||
if (index >= 0 && index < TAB_CONFIGS.length) {
|
||||
return TAB_CONFIGS[index];
|
||||
}
|
||||
throw new IllegalStateException("Unexpected tab index: " + index);
|
||||
}
|
||||
|
||||
private static class TabConfig {
|
||||
final int iconId;
|
||||
final String label;
|
||||
final int textColorId;
|
||||
|
||||
TabConfig(int iconId, String label, int textColorId) {
|
||||
this.iconId = iconId;
|
||||
this.label = label;
|
||||
this.textColorId = textColorId;
|
||||
}
|
||||
}
|
||||
|
||||
private int fetchColor(int colorRes) {
|
||||
return ContextCompat.getColor(this, colorRes);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (viewBinding != null) {
|
||||
viewBinding = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,78 @@
|
||||
package com.ardrawing.ardrawingspace.activity;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.CountDownTimer;
|
||||
|
||||
import androidx.activity.EdgeToEdge;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
|
||||
import com.ardrawing.ardrawingspace.R;
|
||||
import com.ardrawing.ardrawingspace.databinding.ActivitySplashBinding;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
|
||||
import kotlin.Unit;
|
||||
import kotlin.jvm.functions.Function0;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
|
||||
public class SplashActivity extends AppCompatActivity {
|
||||
private ActivitySplashBinding binding;
|
||||
private static final long TOTAL_TIME = 1000;
|
||||
private CountDownTimer countDownTimer;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
EdgeToEdge.enable(this);
|
||||
|
||||
binding = ActivitySplashBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
|
||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
||||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||
return insets;
|
||||
});
|
||||
|
||||
Glide.with(this)
|
||||
.load(R.mipmap.ic_launcher)
|
||||
.transform(new RoundedCorners(16))
|
||||
.into(binding.splashImage);
|
||||
|
||||
countDownTimer = new CountDownTimer(TOTAL_TIME, 100) {
|
||||
@Override
|
||||
public void onTick(long millisUntilFinished) {
|
||||
int percentage = (int) (100 - (float) millisUntilFinished / TOTAL_TIME * 100);
|
||||
binding.progressBar.setProgress(percentage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
startMain();
|
||||
}
|
||||
};
|
||||
|
||||
countDownTimer.start();
|
||||
}
|
||||
|
||||
private void startMain() {
|
||||
binding.progressBar.setProgress(100);
|
||||
|
||||
Intent intent = new Intent(SplashActivity.this, MainActivity.class);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (countDownTimer != null) {
|
||||
countDownTimer.cancel();
|
||||
}
|
||||
binding = null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,205 @@
|
||||
package com.ardrawing.ardrawingspace.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.DiffUtil;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.ardrawing.ardrawingspace.R;
|
||||
import com.ardrawing.ardrawingspace.activity.CategoryActivity;
|
||||
import com.ardrawing.ardrawingspace.activity.DrawingActivity;
|
||||
import com.ardrawing.ardrawingspace.room.AppDatabase;
|
||||
import com.ardrawing.ardrawingspace.room.SpaceEntity;
|
||||
import com.ardrawing.ardrawingspace.util.AppExecutors;
|
||||
import com.ardrawing.ardrawingspace.util.DeleteCallback;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SpaceRecyclerViewAdapter extends RecyclerView.Adapter<SpaceRecyclerViewAdapter.ItemViewHolder> {
|
||||
private static final int DISPLAY_MODE_CATEGORY = 0;
|
||||
private static final int DISPLAY_MODE_DRAWING = 1;
|
||||
private static final int CORNER_RADIUS = 32;
|
||||
private static final int PLACEHOLDER_RES = R.mipmap.placeholder;
|
||||
private static final int LIKE_ICON = R.drawable.like;
|
||||
private static final int UNLIKE_ICON = R.drawable.un_like;
|
||||
|
||||
private List<SpaceEntity> spaceEntityList;
|
||||
private final Context context;
|
||||
private final int displayMode;
|
||||
private DeleteCallback deleteCallback;
|
||||
|
||||
public SpaceRecyclerViewAdapter(Context context, List<SpaceEntity> spaceEntityList, int displayMode) {
|
||||
this.context = context;
|
||||
this.spaceEntityList = new ArrayList<>(spaceEntityList);
|
||||
this.displayMode = displayMode;
|
||||
}
|
||||
|
||||
public void updateItems(List<SpaceEntity> newItems) {
|
||||
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new SpaceDiffCallback(this.spaceEntityList, newItems));
|
||||
this.spaceEntityList = new ArrayList<>(newItems);
|
||||
diffResult.dispatchUpdatesTo(this);
|
||||
}
|
||||
|
||||
public void setDeleteCallback(DeleteCallback deleteCallback) {
|
||||
this.deleteCallback = deleteCallback;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
LayoutInflater inflater = LayoutInflater.from(context);
|
||||
View itemView = inflater.inflate(R.layout.item_space, parent, false);
|
||||
return new ItemViewHolder(itemView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ItemViewHolder holder, int position) {
|
||||
SpaceEntity currentItem = spaceEntityList.get(position);
|
||||
String displayName = getTitle(currentItem);
|
||||
holder.renderItem(currentItem, displayName, displayMode);
|
||||
}
|
||||
|
||||
private String getTitle(SpaceEntity item) {
|
||||
if (displayMode == DISPLAY_MODE_CATEGORY) {
|
||||
String path = item.getImagePath();
|
||||
String[] segments = path.split("/");
|
||||
return segments.length > 0 ? segments[0].split("_")[1] : "";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return spaceEntityList.size();
|
||||
}
|
||||
|
||||
public class ItemViewHolder extends RecyclerView.ViewHolder {
|
||||
private final ImageView previewImage;
|
||||
private final ImageView likeIcon;
|
||||
private final ImageView deleteIcon;
|
||||
private final TextView titleText;
|
||||
|
||||
public ItemViewHolder(@NonNull View view) {
|
||||
super(view);
|
||||
previewImage = view.findViewById(R.id.item_image);
|
||||
likeIcon = view.findViewById(R.id.like);
|
||||
deleteIcon = view.findViewById(R.id.delete);
|
||||
titleText = view.findViewById(R.id.title);
|
||||
}
|
||||
|
||||
void renderItem(SpaceEntity item, String displayName, int mode) {
|
||||
if (mode == DISPLAY_MODE_CATEGORY) {
|
||||
titleText.setText(displayName);
|
||||
titleText.setVisibility(View.VISIBLE);
|
||||
likeIcon.setVisibility(View.GONE);
|
||||
deleteIcon.setVisibility(View.GONE);
|
||||
} else if (mode == DISPLAY_MODE_DRAWING) {
|
||||
titleText.setVisibility(View.GONE);
|
||||
likeIcon.setVisibility(View.VISIBLE);
|
||||
deleteIcon.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
loadImageContent(item.getImagePath());
|
||||
updateFavoriteIcon(item);
|
||||
attachListeners(item, mode);
|
||||
}
|
||||
|
||||
private void loadImageContent(String path) {
|
||||
String formattedPath = adjustImagePath(path);
|
||||
Glide.with(context)
|
||||
.load(formattedPath)
|
||||
.placeholder(PLACEHOLDER_RES)
|
||||
.apply(new RequestOptions()
|
||||
.transform(new CenterCrop(), new RoundedCorners(CORNER_RADIUS)))
|
||||
.into(previewImage);
|
||||
}
|
||||
|
||||
private String adjustImagePath(String path) {
|
||||
return path.startsWith("/data/user/") ? path : "file:///android_asset/" + path;
|
||||
}
|
||||
|
||||
private void updateFavoriteIcon(SpaceEntity item) {
|
||||
int iconRes = item.isFavorite() ? LIKE_ICON : UNLIKE_ICON;
|
||||
likeIcon.setImageResource(iconRes);
|
||||
}
|
||||
|
||||
private void attachListeners(SpaceEntity item, int mode) {
|
||||
previewImage.setOnClickListener(v -> handleImageTap(item, mode));
|
||||
likeIcon.setOnClickListener(v -> toggleFavorite(item));
|
||||
deleteIcon.setOnClickListener(v -> onDeleteClicked(item));
|
||||
}
|
||||
|
||||
private void onDeleteClicked(SpaceEntity item) {
|
||||
int position = getAdapterPosition();
|
||||
if (position != RecyclerView.NO_POSITION && deleteCallback != null) {
|
||||
deleteCallback.onDelete(item);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleImageTap(SpaceEntity item, int mode) {
|
||||
Intent intent = createIntent(item, mode);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
private Intent createIntent(SpaceEntity item, int mode) {
|
||||
Class<?> targetActivity = mode == DISPLAY_MODE_CATEGORY ? CategoryActivity.class : DrawingActivity.class;
|
||||
return new Intent(context, targetActivity)
|
||||
.putExtra("imagePath", item.getImagePath());
|
||||
}
|
||||
|
||||
private void toggleFavorite(SpaceEntity item) {
|
||||
item.setFavorite(!item.isFavorite());
|
||||
persistItemUpdate(item);
|
||||
notifyItemChanged(getAdapterPosition());
|
||||
}
|
||||
|
||||
private void persistItemUpdate(SpaceEntity item) {
|
||||
AppExecutors.getInstance().diskIO().execute(() -> {
|
||||
AppDatabase db = AppDatabase.getInstance(context);
|
||||
db.dao().update(item);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static class SpaceDiffCallback extends DiffUtil.Callback {
|
||||
private final List<SpaceEntity> oldList;
|
||||
private final List<SpaceEntity> newList;
|
||||
|
||||
public SpaceDiffCallback(List<SpaceEntity> oldList, List<SpaceEntity> newList) {
|
||||
this.oldList = oldList != null ? new ArrayList<>(oldList) : new ArrayList<>();
|
||||
this.newList = newList != null ? new ArrayList<>(newList) : new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOldListSize() {
|
||||
return oldList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNewListSize() {
|
||||
return newList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
|
||||
return oldList.get(oldItemPosition).getId() == newList.get(newItemPosition).getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
|
||||
return oldList.get(oldItemPosition).equals(newList.get(newItemPosition));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
package com.ardrawing.ardrawingspace.adapter;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
|
||||
import com.ardrawing.ardrawingspace.fragment.FavoriteFragment;
|
||||
import com.ardrawing.ardrawingspace.fragment.HomeFragment;
|
||||
import com.ardrawing.ardrawingspace.fragment.ImportFragment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ViewPagerAdapter extends FragmentStateAdapter {
|
||||
private final List<Fragment> fragmentList;
|
||||
|
||||
public ViewPagerAdapter(@NonNull FragmentActivity fragmentActivity) {
|
||||
super(fragmentActivity);
|
||||
fragmentList = new ArrayList<>();
|
||||
fragmentList.add(new HomeFragment());
|
||||
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();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,76 @@
|
||||
package com.ardrawing.ardrawingspace.fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.ardrawing.ardrawingspace.R;
|
||||
import com.ardrawing.ardrawingspace.adapter.SpaceRecyclerViewAdapter;
|
||||
import com.ardrawing.ardrawingspace.databinding.FragmentFavoriteBinding;
|
||||
import com.ardrawing.ardrawingspace.room.SpaceEntity;
|
||||
import com.ardrawing.ardrawingspace.util.ItemDecoration;
|
||||
import com.ardrawing.ardrawingspace.viewmodel.SpaceViewModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class FavoriteFragment extends Fragment {
|
||||
private FragmentFavoriteBinding binding;
|
||||
private SpaceViewModel viewModel;
|
||||
private SpaceRecyclerViewAdapter adapter;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
binding = FragmentFavoriteBinding.inflate(inflater, container, false);
|
||||
|
||||
initData();
|
||||
initEvent();
|
||||
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
private void initData() {
|
||||
viewModel = new ViewModelProvider(this).get(SpaceViewModel.class);
|
||||
|
||||
binding.recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2));
|
||||
|
||||
adapter = new SpaceRecyclerViewAdapter(requireContext(), new ArrayList<>(), 2);
|
||||
binding.recyclerView.setAdapter(adapter);
|
||||
|
||||
binding.recyclerView.addItemDecoration(new ItemDecoration(35, 15, 20));
|
||||
}
|
||||
|
||||
private void initEvent() {
|
||||
loadLike();
|
||||
}
|
||||
|
||||
private void loadLike() {
|
||||
viewModel
|
||||
.getFavorite()
|
||||
.observe(getViewLifecycleOwner(), new Observer<List<SpaceEntity>>() {
|
||||
@Override
|
||||
public void onChanged(List<SpaceEntity> spaceEntityList) {
|
||||
if (spaceEntityList.isEmpty()) {
|
||||
binding.text.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
binding.text.setVisibility(View.GONE);
|
||||
}
|
||||
adapter.updateItems(spaceEntityList);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
binding = null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
package com.ardrawing.ardrawingspace.fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.ardrawing.ardrawingspace.R;
|
||||
import com.ardrawing.ardrawingspace.adapter.SpaceRecyclerViewAdapter;
|
||||
import com.ardrawing.ardrawingspace.databinding.FragmentFavoriteBinding;
|
||||
import com.ardrawing.ardrawingspace.databinding.FragmentHomeBinding;
|
||||
import com.ardrawing.ardrawingspace.room.SpaceEntity;
|
||||
import com.ardrawing.ardrawingspace.util.ItemDecoration;
|
||||
import com.ardrawing.ardrawingspace.viewmodel.SpaceViewModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class HomeFragment extends Fragment {
|
||||
private FragmentHomeBinding binding;
|
||||
private SpaceViewModel viewModel;
|
||||
private SpaceRecyclerViewAdapter adapter;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
binding = FragmentHomeBinding.inflate(inflater, container, false);
|
||||
|
||||
initData();
|
||||
initEvent();
|
||||
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
private void initData() {
|
||||
viewModel = new ViewModelProvider(this).get(SpaceViewModel.class);
|
||||
|
||||
binding.recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2));
|
||||
|
||||
adapter = new SpaceRecyclerViewAdapter(requireContext(), new ArrayList<>(), 0);
|
||||
binding.recyclerView.setAdapter(adapter);
|
||||
|
||||
binding.recyclerView.addItemDecoration(new ItemDecoration(35, 15, 20));
|
||||
}
|
||||
|
||||
private void initEvent() {
|
||||
loadLike();
|
||||
}
|
||||
|
||||
private void loadLike() {
|
||||
viewModel
|
||||
.getMinById()
|
||||
.observe(getViewLifecycleOwner(), new Observer<List<SpaceEntity>>() {
|
||||
@Override
|
||||
public void onChanged(List<SpaceEntity> spaceEntityList) {
|
||||
if (spaceEntityList.isEmpty()) {
|
||||
binding.text.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
binding.text.setVisibility(View.GONE);
|
||||
}
|
||||
adapter.updateItems(spaceEntityList);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
binding = null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,118 @@
|
||||
package com.ardrawing.ardrawingspace.fragment;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.ardrawing.ardrawingspace.adapter.SpaceRecyclerViewAdapter;
|
||||
import com.ardrawing.ardrawingspace.databinding.FragmentImportBinding;
|
||||
import com.ardrawing.ardrawingspace.room.SpaceEntity;
|
||||
import com.ardrawing.ardrawingspace.util.DeleteCallback;
|
||||
import com.ardrawing.ardrawingspace.util.ItemDecoration;
|
||||
import com.ardrawing.ardrawingspace.util.UploadUtil;
|
||||
import com.ardrawing.ardrawingspace.viewmodel.SpaceViewModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ImportFragment extends Fragment implements DeleteCallback {
|
||||
private static final int PICK_IMAGE_REQUEST_CODE = 202;
|
||||
private FragmentImportBinding binding;
|
||||
private SpaceRecyclerViewAdapter adapter;
|
||||
private SpaceViewModel viewModel;
|
||||
private final List<String> imagePaths = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
binding = FragmentImportBinding.inflate(inflater, container, false);
|
||||
|
||||
initData();
|
||||
initEvent();
|
||||
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
private void initData() {
|
||||
viewModel = new ViewModelProvider(this).get(SpaceViewModel.class);
|
||||
|
||||
binding.recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2));
|
||||
|
||||
adapter = new SpaceRecyclerViewAdapter(requireContext(), new ArrayList<>(), 1);
|
||||
binding.recyclerView.setAdapter(adapter);
|
||||
adapter.setDeleteCallback(this);
|
||||
|
||||
binding.recyclerView.addItemDecoration(new ItemDecoration(35, 15, 20));
|
||||
}
|
||||
|
||||
private void initEvent() {
|
||||
binding.upload.setOnClickListener(v -> {
|
||||
openImagePicker();
|
||||
});
|
||||
|
||||
loadAllImportImage();
|
||||
}
|
||||
|
||||
private void loadAllImportImage() {
|
||||
viewModel
|
||||
.getImportLiveData()
|
||||
.observe(getViewLifecycleOwner(), new Observer<List<SpaceEntity>>() {
|
||||
@Override
|
||||
public void onChanged(List<SpaceEntity> spaceEntityList) {
|
||||
if (spaceEntityList.isEmpty()) {
|
||||
binding.text.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
binding.text.setVisibility(View.GONE);
|
||||
}
|
||||
adapter.updateItems(spaceEntityList);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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 && resultCode == Activity.RESULT_OK && data != null) {
|
||||
Uri selectedImageUri = data.getData();
|
||||
if (selectedImageUri != null) {
|
||||
processImage(selectedImageUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processImage(Uri imageUri) {
|
||||
if (UploadUtil.isImageSizeValid(imageUri, requireContext())) {
|
||||
UploadUtil.saveImageByPath(imageUri, imagePaths, viewModel, requireContext());
|
||||
} else {
|
||||
Toast.makeText(getContext(), "The image size is out of limit", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
binding = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDelete(SpaceEntity entity) {
|
||||
UploadUtil.deleteImageByPath(entity, viewModel, requireContext());
|
||||
loadAllImportImage();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
package com.ardrawing.ardrawingspace.util;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class AppExecutors {
|
||||
private static AppExecutors instance;
|
||||
|
||||
// 磁盘 I/O 线程池(单线程,用于数据库操作)
|
||||
private final Executor diskIO;
|
||||
|
||||
// 主线程执行器(用于 UI 更新)
|
||||
private final Executor mainThread;
|
||||
|
||||
// 网络线程池(可根据需要调整线程数)
|
||||
private final Executor networkIO;
|
||||
|
||||
private AppExecutors() {
|
||||
this.diskIO = Executors.newSingleThreadExecutor();
|
||||
this.mainThread = new MainThreadExecutor();
|
||||
this.networkIO = Executors.newFixedThreadPool(3); // 3 个线程处理网络任务
|
||||
}
|
||||
|
||||
public static AppExecutors getInstance() {
|
||||
if (instance == null) {
|
||||
synchronized (AppExecutors.class) {
|
||||
if (instance == null) {
|
||||
instance = new AppExecutors();
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public Executor diskIO() {
|
||||
return diskIO;
|
||||
}
|
||||
|
||||
public Executor mainThread() {
|
||||
return mainThread;
|
||||
}
|
||||
|
||||
public Executor networkIO() {
|
||||
return networkIO;
|
||||
}
|
||||
|
||||
private static class MainThreadExecutor implements Executor {
|
||||
private final Handler mainThreadHandler = new Handler(Looper.getMainLooper());
|
||||
|
||||
@Override
|
||||
public void execute(Runnable command) {
|
||||
mainThreadHandler.post(command);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package com.ardrawing.ardrawingspace.util;
|
||||
|
||||
import com.ardrawing.ardrawingspace.room.SpaceEntity;
|
||||
|
||||
public interface DeleteCallback {
|
||||
void onDelete(SpaceEntity entity);
|
||||
}
|
||||
@ -0,0 +1,78 @@
|
||||
package com.ardrawing.ardrawingspace.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class DocumentManipulationTool {
|
||||
private static final boolean IS_DEBUG = false;
|
||||
|
||||
public static float computeTouchDistance(MotionEvent event) {
|
||||
if (event == null || event.getPointerCount() < 2) return 0f;
|
||||
|
||||
float deltaX = event.getX(1) - event.getX(0);
|
||||
float deltaY = event.getY(1) - event.getY(0);
|
||||
return (float) Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
||||
}
|
||||
|
||||
public static void loadImageByPath(String path, ImageView imageView, Context context) {
|
||||
if (isInvalidInput(path, imageView, context)) return;
|
||||
|
||||
if (path.startsWith("/data/user/")) {
|
||||
loadCheck(path, imageView, context);
|
||||
} else {
|
||||
loadTry(path, imageView, context);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isInvalidInput(String path, ImageView imageView, Context context) {
|
||||
return path == null || imageView == null || context == null;
|
||||
}
|
||||
|
||||
private static void loadCheck(String path, ImageView imageView, Context context) {
|
||||
Bitmap bitmap = decodeBitmapFromFile(path);
|
||||
if (bitmap != null) {
|
||||
imageView.setImageBitmap(bitmap);
|
||||
} else {
|
||||
displayError(context, "Failed to load image from storage");
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadTry(String path, ImageView imageView, Context context) {
|
||||
try (InputStream inputStream = context.getAssets().open(path)) {
|
||||
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
|
||||
if (bitmap != null) {
|
||||
imageView.setImageBitmap(bitmap);
|
||||
} else {
|
||||
displayError(context, "Failed to decode asset image");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
displayError(context, "Failed to load image from assets");
|
||||
}
|
||||
}
|
||||
|
||||
private static Bitmap decodeBitmapFromFile(String path) {
|
||||
if (path.isEmpty()) return null;
|
||||
return BitmapFactory.decodeFile(path);
|
||||
}
|
||||
|
||||
private static void displayError(Context context, String message) {
|
||||
if (context != null) {
|
||||
showToast(context, message);
|
||||
}
|
||||
}
|
||||
|
||||
private static void showToast(Context context, String message) {
|
||||
if (IS_DEBUG) {
|
||||
Log.d("FileUtil", message);
|
||||
}
|
||||
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
package com.ardrawing.ardrawingspace.util;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.res.AssetManager;
|
||||
import android.util.Log;
|
||||
|
||||
import com.ardrawing.ardrawingspace.room.SpaceEntity;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class FileParsingAndInitialization {
|
||||
private final Application application;
|
||||
private static final String IMAGE_PREFIX = "png_";
|
||||
private static final String IMAGE_EXTENSION = ".jpg";
|
||||
|
||||
public FileParsingAndInitialization(Application application) {
|
||||
this.application = application;
|
||||
}
|
||||
|
||||
public void insertImagesToDatabase() {
|
||||
AssetManager assetManager = application.getAssets();
|
||||
try {
|
||||
String[] directories = assetManager.list("");
|
||||
if (directories == null) {
|
||||
Log.w("InitDatabase", "No directories found in assets");
|
||||
return;
|
||||
}
|
||||
|
||||
for (String dir : directories) {
|
||||
if (!dir.startsWith(IMAGE_PREFIX)) continue;
|
||||
importImagesFromDirectory(dir);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e("InitDatabase", "Failed to list asset directories", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void importImagesFromDirectory(String directory) {
|
||||
AssetManager assetManager = application.getAssets();
|
||||
try {
|
||||
String[] files = assetManager.list(directory);
|
||||
if (files == null) {
|
||||
Log.w("InitDatabase", "No files found in directory: " + directory);
|
||||
return;
|
||||
}
|
||||
|
||||
List<SpaceEntity> imageList = new ArrayList<>();
|
||||
for (String file : files) {
|
||||
if (file.endsWith(IMAGE_EXTENSION)) {
|
||||
String imagePath = directory + "/" + file;
|
||||
imageList.add(new SpaceEntity(imagePath, false, false));
|
||||
}
|
||||
}
|
||||
|
||||
if (!imageList.isEmpty()) {
|
||||
insertImagesAsync(imageList);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e("InitDatabase", "Failed to list files in directory: " + directory, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void insertImagesAsync(List<SpaceEntity> imageList) {
|
||||
new Thread(() -> {
|
||||
SpaceRepository repository = new SpaceRepository(application);
|
||||
repository.insertAll(imageList);
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
package com.ardrawing.ardrawingspace.util;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
public final class PermissionTool {
|
||||
private PermissionTool() {
|
||||
// 防止实例化
|
||||
}
|
||||
|
||||
private static final boolean IS_DEBUG = false;
|
||||
|
||||
public static boolean hasPermission(Activity activity, String[] permissions) {
|
||||
if (isInvalidInput(activity, permissions)) return false;
|
||||
|
||||
for (String permission : permissions) {
|
||||
if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void reqPermission(Activity activity, String[] permissions, int requestCode) {
|
||||
if (isValidInput(activity, permissions)) {
|
||||
ActivityCompat.requestPermissions(activity, permissions, requestCode);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean gotPermission(int[] grantResults) {
|
||||
if (grantResults == null || grantResults.length == 0) return false;
|
||||
|
||||
for (int result : grantResults) {
|
||||
if (result != PackageManager.PERMISSION_GRANTED) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static String[] getPermission() {
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
|
||||
? new String[]{Manifest.permission.READ_MEDIA_IMAGES}
|
||||
: new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};
|
||||
}
|
||||
|
||||
private static boolean isInvalidInput(Activity activity, String[] permissions) {
|
||||
return activity == null || permissions == null;
|
||||
}
|
||||
|
||||
private static boolean isValidInput(Activity activity, String[] permissions) {
|
||||
if (IS_DEBUG) {
|
||||
Log.d("PermissionUtil", "Validating input");
|
||||
}
|
||||
return activity != null && permissions != null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package com.ardrawing.ardrawingspace.util;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import com.ardrawing.ardrawingspace.room.SpaceEntity;
|
||||
import com.ardrawing.ardrawingspace.viewmodel.SpaceViewModel;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SpaceRepository {
|
||||
private final Application application;
|
||||
|
||||
public SpaceRepository(Application application) {
|
||||
this.application = application;
|
||||
}
|
||||
|
||||
public void insertAll(List<SpaceEntity> entities) {
|
||||
SpaceViewModel viewModel = new SpaceViewModel(application);
|
||||
viewModel.insertAll(entities);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,156 @@
|
||||
package com.ardrawing.ardrawingspace.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.ardrawing.ardrawingspace.room.SpaceEntity;
|
||||
import com.ardrawing.ardrawingspace.viewmodel.SpaceViewModel;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
public class UploadUtil {
|
||||
private static final Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||
|
||||
private static final boolean IS_DEBUG = false;
|
||||
|
||||
public static void saveImageByPath(Uri imageUri, List<String> imagePaths, SpaceViewModel viewModel, Context context) {
|
||||
if (isInvalidInput(imageUri, imagePaths, viewModel, context)) return;
|
||||
|
||||
try (InputStream inputStream = context.getContentResolver().openInputStream(imageUri)) {
|
||||
Bitmap bitmap = decodeBitmapFromStream(inputStream);
|
||||
if (bitmap == null) {
|
||||
displayToast(context, "Unable to load image");
|
||||
return;
|
||||
}
|
||||
|
||||
File imageFile = createImageFile(context, generateUniqueImageName());
|
||||
saveBitmapToFile(bitmap, imageFile);
|
||||
|
||||
String savedImagePath = imageFile.getAbsolutePath();
|
||||
executeImageSavingAsync(savedImagePath, imagePaths, viewModel, context, imageFile);
|
||||
} catch (IOException e) {
|
||||
displayToast(context, "Failed to save picture");
|
||||
}
|
||||
}
|
||||
|
||||
public static void deleteImageByPath(SpaceEntity spaceEntity, SpaceViewModel viewModel, Context context) {
|
||||
if (isInvalidEntity(spaceEntity, viewModel, context)) return;
|
||||
|
||||
File imageFile = new File(spaceEntity.getImagePath());
|
||||
if (!imageFile.exists()) {
|
||||
displayToast(context, "Image does not exist");
|
||||
return;
|
||||
}
|
||||
|
||||
if (imageFile.delete()) {
|
||||
viewModel.delete(spaceEntity);
|
||||
displayToast(context, "Image deleted successfully");
|
||||
} else {
|
||||
displayToast(context, "Failed to delete image");
|
||||
}
|
||||
}
|
||||
|
||||
private static void executeImageSavingAsync(String savedImagePath, List<String> imagePaths, SpaceViewModel viewModel, Context context, File imageFile) {
|
||||
new Thread(() -> {
|
||||
if (checkImageDuplicate(savedImagePath, imagePaths, viewModel)) {
|
||||
imageFile.delete();
|
||||
displayToast(context, "The image already exists");
|
||||
return;
|
||||
}
|
||||
|
||||
imagePaths.add(savedImagePath);
|
||||
viewModel.insert(new SpaceEntity(savedImagePath, true, false));
|
||||
}).start();
|
||||
}
|
||||
|
||||
private static boolean checkImageDuplicate(String imagePath, List<String> imagePaths, SpaceViewModel viewModel) {
|
||||
File newImageFile = new File(imagePath);
|
||||
if (!newImageFile.exists()) return false;
|
||||
|
||||
for (String path : imagePaths) {
|
||||
File existingFile = new File(path);
|
||||
if (compareFilesBySize(existingFile, newImageFile)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
List<SpaceEntity> spaceEntityList = viewModel.getImport();
|
||||
for (SpaceEntity data : spaceEntityList) {
|
||||
File existingFile = new File(data.getImagePath());
|
||||
if (compareFilesBySize(existingFile, newImageFile)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean compareFilesBySize(File file1, File file2) {
|
||||
return file1.exists() && file2.exists() && file1.length() == file2.length();
|
||||
}
|
||||
|
||||
private static Bitmap decodeBitmapFromStream(InputStream inputStream) {
|
||||
return BitmapFactory.decodeStream(inputStream);
|
||||
}
|
||||
|
||||
private static File createImageFile(Context context, String fileName) {
|
||||
return new File(context.getFilesDir(), fileName + ".jpg");
|
||||
}
|
||||
|
||||
private static void saveBitmapToFile(Bitmap bitmap, File file) throws IOException {
|
||||
try (FileOutputStream outputStream = new FileOutputStream(file)) {
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
|
||||
}
|
||||
}
|
||||
|
||||
private static void displayToast(Context context, String message) {
|
||||
if (isInvalidToastInput(context, message)) return;
|
||||
mainHandler.post(() -> Toast.makeText(context, message, Toast.LENGTH_SHORT).show());
|
||||
}
|
||||
|
||||
private static boolean isInvalidToastInput(Context context, String message) {
|
||||
if (IS_DEBUG) {
|
||||
Log.d("UploadUtil", "Checking toast input");
|
||||
}
|
||||
return context == null || message == null;
|
||||
}
|
||||
|
||||
private static boolean isInvalidInput(Uri imageUri, List<String> imagePaths, SpaceViewModel viewModel, Context context) {
|
||||
return imageUri == null || imagePaths == null || viewModel == null || context == null;
|
||||
}
|
||||
|
||||
private static boolean isInvalidEntity(SpaceEntity spaceEntity, SpaceViewModel viewModel, Context context) {
|
||||
return spaceEntity == null || spaceEntity.getImagePath() == null || viewModel == null || context == null;
|
||||
}
|
||||
|
||||
private static String generateUniqueImageName() {
|
||||
return String.valueOf(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
public static boolean isImageSizeValid(Uri imageUri, Context context) {
|
||||
if (isInvalidSizeCheck(imageUri, context)) return false;
|
||||
|
||||
try (InputStream inputStream = context.getContentResolver().openInputStream(imageUri)) {
|
||||
if (inputStream == null) return false;
|
||||
long imageSize = inputStream.available();
|
||||
long maxSize = 10 * 1024 * 1024; // 10MB
|
||||
return imageSize <= maxSize;
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isInvalidSizeCheck(Uri imageUri, Context context) {
|
||||
return imageUri == null || context == null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,6 +28,10 @@ public class SpaceViewModel extends AndroidViewModel {
|
||||
executorService.execute(() -> dao.insert(spaceEntity));
|
||||
}
|
||||
|
||||
public void insertAll(List<SpaceEntity> spaceEntityList) {
|
||||
executorService.execute(() -> dao.insertAll(spaceEntityList));
|
||||
}
|
||||
|
||||
public void delete(SpaceEntity spaceEntity) {
|
||||
executorService.execute(() -> dao.delete(spaceEntity));
|
||||
}
|
||||
|
||||
12
app/src/main/res/drawable/back.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M515.2,102.4c5.9,0 11.9,0.6 17.9,2 42.2,9.5 68.3,50.3 58.5,91.1L434,502.8l157.7,325.7c9.8,40.8 -16.3,81.6 -58.5,91.1a80.9,80.9 0,0 1,-17.9 2c-35.6,0 -67.8,-23.6 -76.3,-58.6L272.4,503.8h-0.5l0.3,-1 -0.3,-1h0.5l166.6,-340.8C447.4,126 479.6,102.4 515.2,102.4m0,-58.5c-61.2,0 -114.1,39.3 -131.2,96.3L222.1,471.4a59,59 0,0 0,-8.7 29.6,58.5 58.5,0 0,0 8.9,33.8l161.4,348.2C400.7,940.5 453.8,980.1 515.3,980.1c10.3,0 20.7,-1.2 30.8,-3.5 36.3,-8.2 66.8,-29.9 86.2,-61.1a131.4,131.4 0,0 0,16.3 -100.9,59.5 59.5,0 0,0 -4.2,-11.8l-145,-299.4 144.3,-281.3a58.8,58.8 0,0 0,4.8 -13,131.5 131.5,0 0,0 -16.3,-100.9c-19.3,-31.1 -49.9,-52.8 -86.1,-61A138.8,138.8 0,0 0,515.2 43.9z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M357.1,458.8a14.6,14.6 0,0 1,-13.1 -21.2l73.1,-146.3a14.6,14.6 0,0 1,26.2 13.1l-73.1,146.3c-2.6,5.1 -7.7,8.1 -13.1,8.1zM459.5,254a14.6,14.6 0,0 1,-13.1 -21.2l14.6,-29.3a14.6,14.6 0,0 1,26.2 13.1l-14.6,29.3c-2.6,5.1 -7.7,8.1 -13.1,8.1zM693.6,458.2a58.5,58.5 0,1 1,0 117,58.5 58.5,0 0,1 0,-117m0,-58.5c-64.5,0 -117,52.5 -117,117s52.5,117 117,117 117,-52.5 117,-117 -52.5,-117 -117,-117z"/>
|
||||
</vector>
|
||||
9
app/src/main/res/drawable/camera.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:pathData="M512,320c-141.4,0 -256,114.6 -256,256s114.6,256 256,256c141.4,0 256,-114.6 256,-256s-114.6,-256 -256,-256zM657.8,701c-69,80.5 -190.2,89.8 -270.7,20.8 -80.5,-69 -89.8,-190.2 -20.8,-270.7 69,-80.5 190.2,-89.8 270.7,-20.8 80.5,69 89.8,190.2 20.8,270.7zM512,448c8.8,0 16,7.2 16,16s-7.2,16 -16,16c-53,0 -96,43 -96,96l0,0.1c0,8.8 -7.2,16 -16,16s-16,-7.2 -16,-16l0,-0.1c0,-70.7 57.3,-128 128,-128zM943.7,289.3l-138.7,-23.1 -43.9,-109.9c-14.7,-36.6 -49.7,-60.3 -89.1,-60.3l-320,0c-39.4,0 -74.4,23.7 -89.2,60.4l-43.9,109.9 -138.7,23.1c-46.5,7.7 -80.3,47.5 -80.3,94.7l0,480c0,52.9 43.1,96 96,96l832,0c52.9,0 96,-43.1 96,-96l0,-480c0,-47.1 -33.8,-86.9 -80.3,-94.7zM960,864c0,17.7 -14.3,32 -32,32l-832,0c-17.7,0 -32,-14.3 -32,-32l0,-480c0,-15.6 11.3,-29 26.8,-31.6l174.2,-29 57.3,-143.3c4.9,-12.1 16.6,-20.1 29.7,-20.1l320,0c13.1,0 24.8,8 29.7,20.1l57.3,143.3 174.2,29c15.4,2.6 26.8,15.9 26.8,31.6l0,480z"
|
||||
android:fillColor="@color/black"/>
|
||||
</vector>
|
||||
9
app/src/main/res/drawable/collection.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M146.3,768h731.4L877.7,73.1L219.4,73.1a74,74 0,0 0,-73.1 73.1v621.7zM219.4,0h694.9c10.7,0 19.5,3.4 26.3,10.2 6.8,6.9 10.2,15.7 10.2,26.3L950.8,804.6a35.6,35.6 0,0 1,-10.2 26.3,35.6 35.6,0 0,1 -26.3,10.2L109.7,841.1l-36.6,66.3L73.1,146.3C73.9,105.1 88.2,70.7 116,42.9 143.8,15.1 178.3,0.8 219.4,0zM201.1,841.1a56.1,56.1 0,0 0,-38.3 16.5,51.9 51.9,0 0,0 -15.5,38.3c0,15.2 5.1,28 15.5,38.3 10.2,10.2 23,15.8 38.3,16.5L877.7,950.9v-109.7L201.1,841.1zM201.1,768L950.8,768L950.8,950.9a74.1,74.1 0,0 1,-73.1 73.1L201.1,1024c-36.6,-0.7 -66.9,-13.2 -90.8,-37.2C86.3,962.9 73.9,932.6 73.1,896c0.7,-36.6 13.2,-66.9 37.2,-90.8 24,-24 54.3,-36.4 90.8,-37.2zM365.7,73.1v286.9l109.7,-88L585.1,360L585.1,73.1L365.7,73.1zM292.6,0h365.7v435.4a35.7,35.7 0,0 1,-21.1 32.6,34.5 34.5,0 0,1 -38.3,-4L475.4,365.7 352,464a34.5,34.5 0,0 1,-38.3 3.9A35.7,35.7 0,0 1,292.6 435.5L292.6,0z"/>
|
||||
</vector>
|
||||
15
app/src/main/res/drawable/delete.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:fillColor="#FF0000"
|
||||
android:pathData="M896,186.2 L128,186.2c-12.8,0 -23.3,10.4 -23.3,23.3l0,162.9c0,12.8 10.4,23.3 23.3,23.3s23.3,-10.4 23.3,-23.3L151.3,232.7l721.5,0 0,151.3c0,12.8 10.4,23.3 23.3,23.3s23.3,-10.4 23.3,-23.3L919.3,209.5C919.3,196.6 908.8,186.2 896,186.2z"/>
|
||||
<path
|
||||
android:fillColor="#FF0000"
|
||||
android:pathData="M826.2,325.8c-12.8,0 -23.3,10.4 -23.3,23.3l0,570.2L651.6,919.3 651.6,570.2c0,-12.8 -10.4,-23.3 -23.3,-23.3s-23.3,10.4 -23.3,23.3l0,349.1L418.9,919.3 418.9,453.8l209.5,0c12.8,0 23.3,-10.4 23.3,-23.3s-10.4,-23.3 -23.3,-23.3L395.6,407.3c-12.8,0 -23.3,10.4 -23.3,23.3l0,488.7L221.1,919.3 221.1,349.1c0,-12.8 -10.4,-23.3 -23.3,-23.3s-23.3,10.4 -23.3,23.3l0,593.5c0,12.8 10.4,23.3 23.3,23.3l628.4,0c12.8,0 23.3,-10.4 23.3,-23.3L849.5,349.1C849.5,336.2 839,325.8 826.2,325.8z"/>
|
||||
<path
|
||||
android:fillColor="#FF0000"
|
||||
android:pathData="M244.4,139.6l523.6,0c12.8,0 23.3,-10.4 23.3,-23.3s-10.4,-23.3 -23.3,-23.3L244.4,93.1c-12.8,0 -23.3,10.4 -23.3,23.3S231.5,139.6 244.4,139.6z"/>
|
||||
</vector>
|
||||
12
app/src/main/res/drawable/flash.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:fillColor="@color/white"
|
||||
android:pathData="M702.9,92.7l-109.1,384h161.9L395.7,916.2l70.6,-381H268.3L702.9,92.7m0,-54.9c-0.7,0 -1.4,3 -2.2,3 -12.3,0.4 -23.6,6.1 -32.8,13 -2.3,1.7 -4.5,4.3 -6.5,6.4l-434.7,437.7c-16.7,16.8 -21.6,39.9 -12.5,61.7 9.1,21.8 30.4,34.1 54,34.1h127.9l-58,319.3c-4.8,26.2 8.7,53.4 32.8,64.6 7.9,3.7 16.4,6 24.7,6a58.1,58.1 0,0 0,45.1 -20.9l360,-434.2c14.5,-17.5 17.5,-49 7.9,-69.5 -9.6,-20.5 -30.3,-40.9 -53,-40.9h-84.7l87.6,-305.3c1.8,-5.7 2.8,-11 2.8,-17.3 0,-31.9 -25.5,-57.8 -57.3,-57.8l-1.3,-0z"/>
|
||||
<path
|
||||
android:fillColor="@color/white"
|
||||
android:pathData="M395.7,501.5a14.6,14.6 0,0 1,-10.7 -24.6l190.2,-204.8a14.6,14.6 0,1 1,21.4 19.9l-190.2,204.8a14.5,14.5 0,0 1,-10.7 4.7zM587.5,618.5a14.6,14.6 0,0 1,-11.5 -23.6l56.9,-73.1a14.6,14.6 0,1 1,23.1 18l-56.9,73.1a14.6,14.6 0,0 1,-11.6 5.6zM542,677a14.4,14.4 0,0 1,-9 -3.1,14.6 14.6,0 0,1 -2.6,-20.5l11.4,-14.6a14.6,14.6 0,0 1,20.5 -2.6,14.6 14.6,0 0,1 2.6,20.5l-11.4,14.6a14.6,14.6 0,0 1,-11.6 5.7z"/>
|
||||
</vector>
|
||||
9
app/src/main/res/drawable/home.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:pathData="M230.4,992c-64,0 -115.2,-51.2 -115.2,-115.2L115.2,544 76.8,582.4C70.4,588.8 57.6,595.2 44.8,595.2c-12.8,0 -25.6,-6.4 -32,-12.8C6.4,569.6 0,556.8 0,544 0,537.6 6.4,524.8 12.8,512l467.2,-467.2C486.4,38.4 499.2,32 512,32s25.6,6.4 32,12.8L1011.2,512C1017.6,524.8 1024,537.6 1024,544c0,12.8 -6.4,25.6 -12.8,32 -6.4,6.4 -19.2,12.8 -32,12.8s-25.6,-6.4 -32,-12.8L512,147.2 211.2,448l0,422.4c0,12.8 12.8,25.6 25.6,25.6l115.2,0 0,-185.6c0,-25.6 19.2,-44.8 44.8,-44.8l230.4,0c25.6,0 44.8,19.2 44.8,44.8s-19.2,44.8 -44.8,44.8L441.6,755.2l0,185.6c0,25.6 -19.2,44.8 -44.8,44.8L230.4,985.6zM627.2,992c-25.6,0 -44.8,-19.2 -44.8,-44.8 0,-25.6 19.2,-44.8 44.8,-44.8l160,0c12.8,0 25.6,-12.8 25.6,-25.6l0,-256c0,-25.6 19.2,-44.8 44.8,-44.8 25.6,0 44.8,19.2 44.8,44.8l0,256c0,64 -51.2,115.2 -115.2,115.2L627.2,992z"
|
||||
android:fillColor="@color/black"/>
|
||||
</vector>
|
||||
4
app/src/main/res/drawable/layout_background.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<corners android:radius="8dp"/>
|
||||
<gradient android:startColor="#F5F5F5" android:endColor="#FFFFFF" android:angle="270"/>
|
||||
</shape>
|
||||
9
app/src/main/res/drawable/like.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:fillColor="#FF0000"
|
||||
android:pathData="M780.2,97.5a73.1,73.1 0,0 1,73.1 73.1v755.8l-341.3,-152.4L170.7,926.5L170.7,170.7a73.1,73.1 0,0 1,73.1 -73.1h536.4zM780.2,170.7L243.8,170.7v643l268.2,-119.7 268.2,119.7L780.2,170.7z"/>
|
||||
</vector>
|
||||
15
app/src/main/res/drawable/photo.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:pathData="M96,192v640c0,17.7 14.3,32 32,32h448.3c17.4,0 32.2,-13.7 32.7,-31.1 0.5,-18.1 -14,-32.9 -32,-32.9L203.3,800l194.8,-194.8 31.1,31.1 45.3,45.3 36.7,36.7c12.5,12.5 32.8,12.5 45.3,0s12.5,-32.8 0,-45.3l-36.7,-36.7 247.9,-247.9 97,97c2.6,12.5 12.4,22.3 24.9,24.9 2.1,0.4 4.3,0.7 6.5,0.7 17.7,0 31.9,-14.9 31.9,-32.6L928,192c0,-17.7 -14.3,-32 -32,-32L128,160c-17.7,0 -32,14.3 -32,32zM864,394.3l-96.4,-96.4 -293.2,293.2 -76.4,-76.4 -238,238.1L160,224h704v170.3z"
|
||||
android:fillColor="@color/black"/>
|
||||
<path
|
||||
android:pathData="M914.7,799.5c0,-17.7 -14.6,-32.2 -32.2,-32.2l-115,-0.2 149.6,-149.6c12.4,-12.4 12.6,-32.7 0.2,-45.1 -12.5,-12.5 -33.1,-12.4 -45.6,0.1L722.2,721.8l0.4,-114.7c0,-17.7 -14.4,-31.7 -31.7,-32 -18,0.4 -32.2,14.5 -32.2,32.2l-0.1,192.1c0,17.7 14.3,32 32,32h192c17.7,0.1 32.1,-14.2 32.1,-31.9z"
|
||||
android:fillColor="@color/black"/>
|
||||
<path
|
||||
android:pathData="M320.1,383.8m-64,0a64,64 0,1 0,128 0,64 64,0 1,0 -128,0Z"
|
||||
android:fillColor="@color/black"/>
|
||||
</vector>
|
||||
20
app/src/main/res/drawable/progress_gradient.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<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>
|
||||
9
app/src/main/res/drawable/progress_thumb.xml
Normal 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="#6CE89E" />
|
||||
<stroke android:color="@color/white" android:width="4dp"/>
|
||||
<size
|
||||
android:width="16dp"
|
||||
android:height="16dp" />
|
||||
</shape>
|
||||
18
app/src/main/res/drawable/resource_import.xml
Normal file
@ -0,0 +1,18 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M560.9,379.4c-13.1,-16.7 -31.5,-26.4 -50.4,-26.4 -18.2,0 -35.1,8.5 -47.5,24.4L355.3,521.4c-13.9,17.7 -17.5,37.3 -9.6,53.5 7.4,15.3 23.5,23 44.1,23h67.9a14.2,14.2 0,1 0,0 -28.4h-67.9c-9.3,0 -16.1,-1.9 -18.6,-7 -2.9,-6.1 -0.5,-14.2 6.6,-23.3l107.7,-144.3c14.3,-18.2 38.3,-16.9 52.9,1.7l108,141.3c7,8.9 9.4,17.9 6.3,24.3 -3.5,7.2 -13.1,7.2 -18.5,7.2h-48.5c-7.8,0 -9.1,8.5 -9.1,16.4v51.1c0,30.4 -27.2,57 -55.4,57 -23.7,0 -44.5,-11.1 -51.8,-29.7a13.8,13.8 0,0 0,-18.1 -8c-7.3,2.9 -10.3,11.1 -7.4,18.4 11.5,29.5 41.9,47.8 77.2,47.8 44.1,0 84,-39.1 84,-85.4v-39.1h29.1c20.5,0 36.5,-7.8 44.1,-23.3 8,-16.5 4.5,-35.9 -9.4,-53.6l-107.9,-141.6z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M460.9,628.8a13.8,13.8 0,0 0,0 -20.1c-5.3,-5.2 -14.8,-5.2 -20,0a13.8,13.8 0,0 0,-4.1 10.1c0,3.7 1.4,7.4 4.1,10.1 2.7,2.6 6.2,4.1 10.1,4.1 3.7,0 7.2,-1.6 9.9,-4.3z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M512,50C257.3,50 50,257.3 50,512 50,766.7 257.3,974 512,974S974,766.7 974,512C974,257.3 766.7,50 512,50zM512,917.1C288.6,917.1 106.9,735.4 106.9,512S288.6,106.9 512,106.9 917.1,288.6 917.1,512 735.4,917.1 512,917.1z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M606.5,167a14.3,14.3 0,0 0,-17.5 10c-2.1,7.6 2.4,15.4 10,17.5C741.6,233.4 841.2,364 841.2,512a14.2,14.2 0,0 0,28.4 0c0,-160.8 -108.2,-302.7 -263.1,-345zM512,182.8a342.5,342.5 0,0 1,19.2 0.5,14.2 14.2,0 0,0 0.8,-28.4 370.6,370.6 0,0 0,-19.9 -0.6,14.2 14.2,0 0,0 -0,28.4z"/>
|
||||
</vector>
|
||||
9
app/src/main/res/drawable/rounded_rectangle.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<gradient
|
||||
android:angle="45"
|
||||
android:startColor="#87CEEB"
|
||||
android:endColor="#90EE90"
|
||||
android:type="linear"
|
||||
android:useLevel="false" />
|
||||
<corners android:radius="16dp" />
|
||||
</shape>
|
||||
4
app/src/main/res/drawable/text_background.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<corners android:radius="4dp"/>
|
||||
<solid android:color="#E0E0E0"/>
|
||||
</shape>
|
||||
9
app/src/main/res/drawable/un_collection.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:fillColor="@color/gray"
|
||||
android:pathData="M146.3,768h731.4L877.7,73.1L219.4,73.1a74,74 0,0 0,-73.1 73.1v621.7zM219.4,0h694.9c10.7,0 19.5,3.4 26.3,10.2 6.8,6.9 10.2,15.7 10.2,26.3L950.8,804.6a35.6,35.6 0,0 1,-10.2 26.3,35.6 35.6,0 0,1 -26.3,10.2L109.7,841.1l-36.6,66.3L73.1,146.3C73.9,105.1 88.2,70.7 116,42.9 143.8,15.1 178.3,0.8 219.4,0zM201.1,841.1a56.1,56.1 0,0 0,-38.3 16.5,51.9 51.9,0 0,0 -15.5,38.3c0,15.2 5.1,28 15.5,38.3 10.2,10.2 23,15.8 38.3,16.5L877.7,950.9v-109.7L201.1,841.1zM201.1,768L950.8,768L950.8,950.9a74.1,74.1 0,0 1,-73.1 73.1L201.1,1024c-36.6,-0.7 -66.9,-13.2 -90.8,-37.2C86.3,962.9 73.9,932.6 73.1,896c0.7,-36.6 13.2,-66.9 37.2,-90.8 24,-24 54.3,-36.4 90.8,-37.2zM365.7,73.1v286.9l109.7,-88L585.1,360L585.1,73.1L365.7,73.1zM292.6,0h365.7v435.4a35.7,35.7 0,0 1,-21.1 32.6,34.5 34.5,0 0,1 -38.3,-4L475.4,365.7 352,464a34.5,34.5 0,0 1,-38.3 3.9A35.7,35.7 0,0 1,292.6 435.5L292.6,0z"/>
|
||||
</vector>
|
||||
12
app/src/main/res/drawable/un_flash.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:fillColor="@color/black"
|
||||
android:pathData="M702.9,92.7l-109.1,384h161.9L395.7,916.2l70.6,-381H268.3L702.9,92.7m0,-54.9c-0.7,0 -1.4,3 -2.2,3 -12.3,0.4 -23.6,6.1 -32.8,13 -2.3,1.7 -4.5,4.3 -6.5,6.4l-434.7,437.7c-16.7,16.8 -21.6,39.9 -12.5,61.7 9.1,21.8 30.4,34.1 54,34.1h127.9l-58,319.3c-4.8,26.2 8.7,53.4 32.8,64.6 7.9,3.7 16.4,6 24.7,6a58.1,58.1 0,0 0,45.1 -20.9l360,-434.2c14.5,-17.5 17.5,-49 7.9,-69.5 -9.6,-20.5 -30.3,-40.9 -53,-40.9h-84.7l87.6,-305.3c1.8,-5.7 2.8,-11 2.8,-17.3 0,-31.9 -25.5,-57.8 -57.3,-57.8l-1.3,-0z"/>
|
||||
<path
|
||||
android:fillColor="@color/black"
|
||||
android:pathData="M395.7,501.5a14.6,14.6 0,0 1,-10.7 -24.6l190.2,-204.8a14.6,14.6 0,1 1,21.4 19.9l-190.2,204.8a14.5,14.5 0,0 1,-10.7 4.7zM587.5,618.5a14.6,14.6 0,0 1,-11.5 -23.6l56.9,-73.1a14.6,14.6 0,1 1,23.1 18l-56.9,73.1a14.6,14.6 0,0 1,-11.6 5.6zM542,677a14.4,14.4 0,0 1,-9 -3.1,14.6 14.6,0 0,1 -2.6,-20.5l11.4,-14.6a14.6,14.6 0,0 1,20.5 -2.6,14.6 14.6,0 0,1 2.6,20.5l-11.4,14.6a14.6,14.6 0,0 1,-11.6 5.7z"/>
|
||||
</vector>
|
||||
9
app/src/main/res/drawable/un_home.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:pathData="M230.4,992c-64,0 -115.2,-51.2 -115.2,-115.2L115.2,544 76.8,582.4C70.4,588.8 57.6,595.2 44.8,595.2c-12.8,0 -25.6,-6.4 -32,-12.8C6.4,569.6 0,556.8 0,544 0,537.6 6.4,524.8 12.8,512l467.2,-467.2C486.4,38.4 499.2,32 512,32s25.6,6.4 32,12.8L1011.2,512C1017.6,524.8 1024,537.6 1024,544c0,12.8 -6.4,25.6 -12.8,32 -6.4,6.4 -19.2,12.8 -32,12.8s-25.6,-6.4 -32,-12.8L512,147.2 211.2,448l0,422.4c0,12.8 12.8,25.6 25.6,25.6l115.2,0 0,-185.6c0,-25.6 19.2,-44.8 44.8,-44.8l230.4,0c25.6,0 44.8,19.2 44.8,44.8s-19.2,44.8 -44.8,44.8L441.6,755.2l0,185.6c0,25.6 -19.2,44.8 -44.8,44.8L230.4,985.6zM627.2,992c-25.6,0 -44.8,-19.2 -44.8,-44.8 0,-25.6 19.2,-44.8 44.8,-44.8l160,0c12.8,0 25.6,-12.8 25.6,-25.6l0,-256c0,-25.6 19.2,-44.8 44.8,-44.8 25.6,0 44.8,19.2 44.8,44.8l0,256c0,64 -51.2,115.2 -115.2,115.2L627.2,992z"
|
||||
android:fillColor="@color/gray"/>
|
||||
</vector>
|
||||
18
app/src/main/res/drawable/un_import.xml
Normal file
@ -0,0 +1,18 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:fillColor="@color/gray"
|
||||
android:pathData="M560.9,379.4c-13.1,-16.7 -31.5,-26.4 -50.4,-26.4 -18.2,0 -35.1,8.5 -47.5,24.4L355.3,521.4c-13.9,17.7 -17.5,37.3 -9.6,53.5 7.4,15.3 23.5,23 44.1,23h67.9a14.2,14.2 0,1 0,0 -28.4h-67.9c-9.3,0 -16.1,-1.9 -18.6,-7 -2.9,-6.1 -0.5,-14.2 6.6,-23.3l107.7,-144.3c14.3,-18.2 38.3,-16.9 52.9,1.7l108,141.3c7,8.9 9.4,17.9 6.3,24.3 -3.5,7.2 -13.1,7.2 -18.5,7.2h-48.5c-7.8,0 -9.1,8.5 -9.1,16.4v51.1c0,30.4 -27.2,57 -55.4,57 -23.7,0 -44.5,-11.1 -51.8,-29.7a13.8,13.8 0,0 0,-18.1 -8c-7.3,2.9 -10.3,11.1 -7.4,18.4 11.5,29.5 41.9,47.8 77.2,47.8 44.1,0 84,-39.1 84,-85.4v-39.1h29.1c20.5,0 36.5,-7.8 44.1,-23.3 8,-16.5 4.5,-35.9 -9.4,-53.6l-107.9,-141.6z"/>
|
||||
<path
|
||||
android:fillColor="@color/gray"
|
||||
android:pathData="M460.9,628.8a13.8,13.8 0,0 0,0 -20.1c-5.3,-5.2 -14.8,-5.2 -20,0a13.8,13.8 0,0 0,-4.1 10.1c0,3.7 1.4,7.4 4.1,10.1 2.7,2.6 6.2,4.1 10.1,4.1 3.7,0 7.2,-1.6 9.9,-4.3z"/>
|
||||
<path
|
||||
android:fillColor="@color/gray"
|
||||
android:pathData="M512,50C257.3,50 50,257.3 50,512 50,766.7 257.3,974 512,974S974,766.7 974,512C974,257.3 766.7,50 512,50zM512,917.1C288.6,917.1 106.9,735.4 106.9,512S288.6,106.9 512,106.9 917.1,288.6 917.1,512 735.4,917.1 512,917.1z"/>
|
||||
<path
|
||||
android:fillColor="@color/gray"
|
||||
android:pathData="M606.5,167a14.3,14.3 0,0 0,-17.5 10c-2.1,7.6 2.4,15.4 10,17.5C741.6,233.4 841.2,364 841.2,512a14.2,14.2 0,0 0,28.4 0c0,-160.8 -108.2,-302.7 -263.1,-345zM512,182.8a342.5,342.5 0,0 1,19.2 0.5,14.2 14.2,0 0,0 0.8,-28.4 370.6,370.6 0,0 0,-19.9 -0.6,14.2 14.2,0 0,0 -0,28.4z"/>
|
||||
</vector>
|
||||
9
app/src/main/res/drawable/un_like.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:fillColor="@color/gray"
|
||||
android:pathData="M780.2,97.5a73.1,73.1 0,0 1,73.1 73.1v755.8l-341.3,-152.4L170.7,926.5L170.7,170.7a73.1,73.1 0,0 1,73.1 -73.1h536.4zM780.2,170.7L243.8,170.7v643l268.2,-119.7 268.2,119.7L780.2,170.7z"/>
|
||||
</vector>
|
||||
9
app/src/main/res/drawable/upload.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M512,85.3a426.7,426.7 0,1 0,426.7 426.7A426.7,426.7 0,0 0,512 85.3zM676.3,429.7l-30.3,30.3a20.9,20.9 0,0 1,-29.9 0L554.7,398.1v348.6a21.3,21.3 0,0 1,-21.3 21.3h-42.7a21.3,21.3 0,0 1,-21.3 -21.3L469.3,398.1l-61.4,61.9a21.3,21.3 0,0 1,-30.3 0l-29.9,-30.3a21.3,21.3 0,0 1,0 -30.3l133.5,-134a32,32 0,0 1,22.6 -9.4h16.2a32.9,32.9 0,0 1,22.6 9.4l133.5,134a21.3,21.3 0,0 1,0 30.3z"/>
|
||||
</vector>
|
||||
40
app/src/main/res/layout/activity_category.xml
Normal 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: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:application=".activity.CategoryActivity">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/back"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_marginStart="25dp"
|
||||
android:src="@drawable/back"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/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>
|
||||
98
app/src/main/res/layout/activity_drawing.xml
Normal file
@ -0,0 +1,98 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#00000000"
|
||||
tools:application=".activity.DrawingActivity">
|
||||
|
||||
<androidx.camera.view.PreviewView
|
||||
android:id="@+id/preview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/image_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="matrix" />
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/back"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="match_parent"
|
||||
android:clickable="true"
|
||||
android:padding="8dp"
|
||||
android:src="@drawable/back" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/bottom_controls"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#80000000"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent">
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/seekbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:max="100"
|
||||
android:maxHeight="5dp"
|
||||
android:progress="0"
|
||||
android:progressDrawable="@drawable/progress_gradient"
|
||||
android:thumb="@drawable/progress_thumb" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/flash"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:padding="8dp"
|
||||
android:src="@drawable/un_flash" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/camera"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:padding="8dp"
|
||||
android:src="@drawable/camera" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/photo"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:padding="8dp"
|
||||
android:src="@drawable/photo" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@ -5,15 +5,42 @@
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".activity.MainActivity">
|
||||
android:background="#F5F5F5"
|
||||
tools:application=".activity.MainActivity">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Hello World!"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/app_name"
|
||||
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/tabLayout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="@android:color/transparent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/title"
|
||||
app:tabGravity="fill"
|
||||
app:tabIndicatorHeight="0dp"
|
||||
app:tabMode="fixed" />
|
||||
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/viewPager"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="8dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tabLayout" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
48
app/src/main/res/layout/activity_splash.xml
Normal file
@ -0,0 +1,48 @@
|
||||
<?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.SplashActivity">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/splash_image"
|
||||
android:layout_width="150dp"
|
||||
android:layout_height="150dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.388" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/splash_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="32dp"
|
||||
android:text="@string/app_name"
|
||||
android:textSize="25sp"
|
||||
android:textStyle="bold"
|
||||
android: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_gradient"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
28
app/src/main/res/layout/fragment_favorite.xml
Normal file
@ -0,0 +1,28 @@
|
||||
<?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:application=".fragment.FavoriteFragment">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="16dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="There's nothing here yet"
|
||||
android:textColor="@color/gray"
|
||||
android:textSize="18sp"
|
||||
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>
|
||||
28
app/src/main/res/layout/fragment_home.xml
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
tools:application=".fragment.HomeFragment">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="16dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="There's nothing here yet"
|
||||
android:textColor="@color/gray"
|
||||
android:textSize="18sp"
|
||||
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>
|
||||
61
app/src/main/res/layout/fragment_import.xml
Normal file
@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
tools:application=".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/upload"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="There's nothing here yet"
|
||||
android:textColor="@color/gray"
|
||||
android:textSize="18sp"
|
||||
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/upload"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginBottom="25dp"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:background="@drawable/rounded_rectangle"
|
||||
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/upload" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:text="UPLOAD"
|
||||
android:textColor="@color/black" />
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
69
app/src/main/res/layout/item_space.xml
Normal file
@ -0,0 +1,69 @@
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="200dp"
|
||||
android:background="@drawable/layout_background">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/item_image"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="@android:color/white"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@+id/title_container"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/like"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:src="@drawable/un_like"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:elevation="4dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/title_container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/delete">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:padding="8dp"
|
||||
android:gravity="center"
|
||||
android:background="@drawable/text_background"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/delete"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:src="@drawable/delete"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:elevation="4dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:layout_marginEnd="16dp" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
31
app/src/main/res/layout/tab_custom.xml
Normal file
@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_view"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/title"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="15dp"
|
||||
android:textStyle="bold"
|
||||
android:gravity="center"
|
||||
android:text="@string/app_name"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/image_view" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
BIN
app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 982 B |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/placeholder.png
Normal file
|
After Width: | Height: | Size: 341 KiB |
@ -2,4 +2,5 @@
|
||||
<resources>
|
||||
<color name="black">#FF000000</color>
|
||||
<color name="white">#FFFFFFFF</color>
|
||||
<color name="gray">#C0C0C0</color>
|
||||
</resources>
|
||||
@ -1,3 +1,5 @@
|
||||
<resources>
|
||||
<string name="app_name">AR Drawing Space</string>
|
||||
<!-- TODO: Remove or change this placeholder text -->
|
||||
<string name="hello_blank_fragment">Hello blank fragment</string>
|
||||
</resources>
|
||||
6
keystore.properties
Normal file
@ -0,0 +1,6 @@
|
||||
app_name=AR Drawing Space
|
||||
package_name=com.ardrawing.ardrawingspace
|
||||
keystoreFile=app/ARDrawingSpace.jks
|
||||
key_alias=ARDrawingSpacekey0
|
||||
key_store_password=ARDrawingSpace
|
||||
key_password=ARDrawingSpace
|
||||