1.主界面背景图修复,彻底修复了权限错误的Bug

2.优化了JMActivity加载速度和效率
3.增加了地图上机厅位置修改的功能
4.增加了本本收藏功能
This commit is contained in:
2025-05-10 14:57:41 +08:00
parent 5844dc638d
commit 0649da7387
10 changed files with 169 additions and 48 deletions

4
.idea/gradle.xml generated
View File

@@ -4,14 +4,18 @@
<component name="GradleSettings"> <component name="GradleSettings">
<option name="linkedExternalProjectsSettings"> <option name="linkedExternalProjectsSettings">
<GradleProjectSettings> <GradleProjectSettings>
<option name="testRunner" value="CHOOSE_PER_TEST" />
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
<option name="modules"> <option name="modules">
<set> <set>
<option value="$PROJECT_DIR$" /> <option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" /> <option value="$PROJECT_DIR$/app" />
</set> </set>
</option> </option>
<option name="resolveExternalAnnotations" value="false" />
</GradleProjectSettings> </GradleProjectSettings>
</option> </option>
<option name="parallelModelFetch" value="true" />
</component> </component>
</project> </project>

10
.idea/migrations.xml generated Normal file
View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectMigrations">
<option name="MigrateToGradleLocalJavaHome">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
</component>
</project>

3
.idea/misc.xml generated
View File

@@ -1,9 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" /> <component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="FrameworkDetectionExcludesConfiguration"> <component name="FrameworkDetectionExcludesConfiguration">
<file type="web" url="file://$PROJECT_DIR$" /> <file type="web" url="file://$PROJECT_DIR$" />
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" /> <output url="file://$PROJECT_DIR$/build/classes" />
</component> </component>
<component name="ProjectType"> <component name="ProjectType">

17
.idea/runConfigurations.xml generated Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
<option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
<option value="com.intellij.execution.junit.PatternConfigurationProducer" />
<option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
<option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
<option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
</set>
</option>
</component>
</project>

View File

@@ -4,6 +4,7 @@ import android.annotation.SuppressLint;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
@@ -11,6 +12,7 @@ import android.net.Uri;
import android.os.Environment; import android.os.Environment;
import android.provider.MediaStore; import android.provider.MediaStore;
import android.util.Log; import android.util.Log;
import android.util.SparseArray;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@@ -39,6 +41,7 @@ public class PhotoAdapter extends RecyclerView.Adapter<PhotoAdapter.PhotoViewHol
private List<String> imageUrls; private List<String> imageUrls;
private List<Integer> nums; private List<Integer> nums;
private static List<Integer> loading = new ArrayList<>(); private static List<Integer> loading = new ArrayList<>();
private SparseArray<Bitmap> bitmapCache = new SparseArray<>();
public void clearLoad() { public void clearLoad() {
loading.clear(); loading.clear();
@@ -51,8 +54,21 @@ public class PhotoAdapter extends RecyclerView.Adapter<PhotoAdapter.PhotoViewHol
this.album = a; this.album = a;
} }
public void updateItem(int position) { public void updateItem(int position) {
if (bitmapCache.get(position) != null) {
notifyItemChanged(position); // 如果已经有 bitmap直接刷新
} else {
String fileName = "image_" + album.getAlbum_id() + "_" + position + ".jpg";
File cacheFile = FileUtils.getCacheDir(context, fileName);
if (cacheFile.exists()) {
Bitmap bitmap = BitmapFactory.decodeFile(cacheFile.getAbsolutePath());
if (bitmap != null) {
bitmapCache.put(position, bitmap);
}
}
notifyItemChanged(position); notifyItemChanged(position);
} }
}
@NonNull @NonNull
@Override @Override
@@ -67,56 +83,47 @@ public class PhotoAdapter extends RecyclerView.Adapter<PhotoAdapter.PhotoViewHol
int num = nums.get(position); int num = nums.get(position);
String fileName = "image_" + album.getAlbum_id() + "_" + position + ".jpg"; String fileName = "image_" + album.getAlbum_id() + "_" + position + ".jpg";
File cacheFile = FileUtils.getCacheDir(context, fileName); File cacheFile = FileUtils.getCacheDir(context, fileName);
// 清除之前的图片和状态 // 清除之前的图片和状态
holder.imageView.setImageBitmap(null); holder.imageView.setImageBitmap(null);
holder.imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); holder.imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
holder.imageView.setOnLongClickListener(null); holder.imageView.setOnLongClickListener(null);
// 先检查内存缓存
Log.d("HHHHHHHHHH", "Loading image at position: " + loading.toString()); Bitmap cachedBitmap = bitmapCache.get(position);
if (cacheFile.exists()) { if (cachedBitmap != null) {
Log.d("HHHHHHHHHH", "Loading cached image at position: " + position); Log.d("PhotoAdapter", "Displaying from memory cache: " + position);
// 加载缓存的图片并压缩到屏幕大小 holder.imageView.setImageBitmap(cachedBitmap);
Glide.with(context)
.asBitmap()
.load(cacheFile)
.override(holder.itemView.getWidth(), holder.itemView.getHeight()) // 压缩图片到屏幕大小
.into(new CustomTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull Bitmap resource, Transition<? super Bitmap> transition) {
Log.d("PhotoAdapter", "Image loaded successfully at position: " + position);
if (!loading.contains(position)) {
loading.add(position);
}
holder.imageView.setImageBitmap(resource);
holder.imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); holder.imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
// 设置长按监听器
holder.imageView.setOnLongClickListener(v -> { holder.imageView.setOnLongClickListener(v -> {
saveImageToMediaStore(resource, fileName); saveImageToMediaStore(cachedBitmap, fileName);
return true; return true;
}); });
return;
} }
@Override // 然后检查磁盘缓存
public void onLoadCleared(Drawable placeholder) { if (cacheFile.exists()) {
Log.d("PhotoAdapter", "Image load cleared at position: " + position); Log.d("PhotoAdapter", "Loading cached image at position: " + position);
} Bitmap bitmap = BitmapFactory.decodeFile(cacheFile.getAbsolutePath());
if (bitmap != null) {
bitmapCache.put(position, bitmap);
holder.imageView.setImageBitmap(bitmap);
holder.imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
@Override holder.imageView.setOnLongClickListener(v -> {
public void onLoadFailed(Drawable errorDrawable) { saveImageToMediaStore(bitmap, fileName);
super.onLoadFailed(errorDrawable); return true;
Log.e("PhotoAdapter", "Image load failed at position: " + position);
}
}); });
} else { } else {
ImageView imageView = holder.imageView; //holder.imageView.setImageResource(R.drawable.loading);
imageView = new ImageView(context); }
imageView.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.loading)); } else {
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); //holder.imageView.setImageResource(R.drawable.loading);
}
}
}
}
@Override @Override
public int getItemCount() { public int getItemCount() {
@@ -220,6 +227,15 @@ public class PhotoAdapter extends RecyclerView.Adapter<PhotoAdapter.PhotoViewHol
// 添加删除缓存方法 // 添加删除缓存方法
public void clearCache() { public void clearCache() {
// 清空内存缓存
if (bitmapCache != null) {
for (int i = 0; i < bitmapCache.size(); i++) {
bitmapCache.remove(i);
}
bitmapCache.clear();
}
// 删除磁盘缓存文件夹
File cacheDir = FileUtils.getCacheDir(context, ""); File cacheDir = FileUtils.getCacheDir(context, "");
if (cacheDir.exists() && cacheDir.isDirectory()) { if (cacheDir.exists() && cacheDir.isDirectory()) {
File[] files = cacheDir.listFiles(); File[] files = cacheDir.listFiles();
@@ -232,4 +248,5 @@ public class PhotoAdapter extends RecyclerView.Adapter<PhotoAdapter.PhotoViewHol
} }
} }
} }
} }

View File

@@ -3,6 +3,7 @@ package org.astral.findmaimaiultra.ui;
import android.Manifest; import android.Manifest;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Canvas; import android.graphics.Canvas;
@@ -29,6 +30,7 @@ import com.bumptech.glide.request.transition.Transition;
import com.google.android.material.bottomsheet.BottomSheetBehavior; import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.button.MaterialButton; import com.google.android.material.button.MaterialButton;
import com.google.android.material.snackbar.Snackbar; import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.switchmaterial.SwitchMaterial;
import com.google.gson.Gson; import com.google.gson.Gson;
import org.astral.findmaimaiultra.R; import org.astral.findmaimaiultra.R;
import org.astral.findmaimaiultra.adapter.PhotoAdapter; import org.astral.findmaimaiultra.adapter.PhotoAdapter;
@@ -39,6 +41,7 @@ import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
@@ -48,6 +51,7 @@ public class JMActivity extends AppCompatActivity {
private FrameLayout overlay; private FrameLayout overlay;
private boolean isOverlayVisible = false; private boolean isOverlayVisible = false;
private BottomSheetBehavior<View> bottomSheetBehavior; private BottomSheetBehavior<View> bottomSheetBehavior;
private SharedPreferences sharedPreferences;
private PhotoAdapter photoAdapter; private PhotoAdapter photoAdapter;
private static final int REQUEST_CODE_WRITE_EXTERNAL_STORAGE = 1; private static final int REQUEST_CODE_WRITE_EXTERNAL_STORAGE = 1;
private Album album; private Album album;
@@ -56,7 +60,7 @@ public class JMActivity extends AppCompatActivity {
protected void onCreate(@Nullable Bundle savedInstanceState) { protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.jm_dialog); setContentView(R.layout.jm_dialog);
sharedPreferences = getSharedPreferences("shoucang_benzi", MODE_PRIVATE);
initRecyclerView(); initRecyclerView();
} }
private void initRecyclerView() { private void initRecyclerView() {
@@ -76,6 +80,28 @@ public class JMActivity extends AppCompatActivity {
MaterialButton downloadButton = findViewById(R.id.download); MaterialButton downloadButton = findViewById(R.id.download);
downloadButton.setOnClickListener(v -> downloadAllImages()); downloadButton.setOnClickListener(v -> downloadAllImages());
SwitchMaterial switchMaterial = findViewById(R.id.shoucang);
//触发器
switchMaterial.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
// 触发器被选中时执行的操作
// 在这里添加你的操作代码
Toast.makeText(JMActivity.this, "已收藏", Toast.LENGTH_SHORT).show();
SharedPreferences.Editor editor = sharedPreferences.edit();
String shoucang = sharedPreferences.getString("benzi","[]");
List<String> list = new Gson().fromJson(shoucang, List.class);
list.add(a.getAlbum_id() + "_" + a.getName());
editor.putString("benzi", new Gson().toJson(list));
editor.apply();
} else {
// 触发器未被选中时执行的操作
}
}
});
bottomSheetBehavior = BottomSheetBehavior.from(findViewById(R.id.bottom_sheet)); bottomSheetBehavior = BottomSheetBehavior.from(findViewById(R.id.bottom_sheet));
bottomSheetBehavior.setPeekHeight(dpToPx(80)); bottomSheetBehavior.setPeekHeight(dpToPx(80));
@@ -157,6 +183,7 @@ public class JMActivity extends AppCompatActivity {
Glide.with(this) Glide.with(this)
.asBitmap() .asBitmap()
.load(imageUrl) .load(imageUrl)
.override(1080, 1920) // 设置最大宽高
.into(new CustomTarget<Bitmap>() { .into(new CustomTarget<Bitmap>() {
@Override @Override
public void onResourceReady(@NonNull Bitmap resource, Transition<? super Bitmap> transition) { public void onResourceReady(@NonNull Bitmap resource, Transition<? super Bitmap> transition) {
@@ -251,6 +278,7 @@ public class JMActivity extends AppCompatActivity {
super.onDestroy(); super.onDestroy();
if (photoAdapter != null) { if (photoAdapter != null) {
photoAdapter.clearCache(); photoAdapter.clearCache();
photoAdapter = null;
} }
} }
private void saveBitmapToFile(Bitmap bitmap, File file) { private void saveBitmapToFile(Bitmap bitmap, File file) {

View File

@@ -78,6 +78,10 @@ public class PixivFragment extends Fragment {
private FragmentPixivBinding binding; private FragmentPixivBinding binding;
private SharedViewModel sharedViewModel; private SharedViewModel sharedViewModel;
private PixivAdapter adapter; private PixivAdapter adapter;
private ListView shoucangList;
// 声明适配器
private ArrayAdapter<String> shoucangListAdapter;
private List<String> shoucangDataList = new ArrayList<>();
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
@@ -89,11 +93,12 @@ public class PixivFragment extends Fragment {
if (context != null) { if (context != null) {
shoucang = context.getSharedPreferences("shoucang_prefs", Context.MODE_PRIVATE); shoucang = context.getSharedPreferences("shoucang_prefs", Context.MODE_PRIVATE);
settingProperties = context.getSharedPreferences("setting_prefs", Context.MODE_PRIVATE); settingProperties = context.getSharedPreferences("setting_prefs", Context.MODE_PRIVATE);
settingProperties2 = context.getSharedPreferences("setting", Context.MODE_PRIVATE); settingProperties2 = context.getSharedPreferences("shoucang_benzi", Context.MODE_PRIVATE);
} }
sharedViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class); sharedViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
} }
@SuppressLint("SetTextI18n")
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) { ViewGroup container, Bundle savedInstanceState) {
@@ -106,7 +111,7 @@ public class PixivFragment extends Fragment {
path1 = binding.path1; path1 = binding.path1;
path2 = binding.path2; path2 = binding.path2;
searchView = binding.searchView; searchView = binding.searchView;
shoucangList = binding.shoucang;
requireActivity().getOnBackPressedDispatcher().addCallback(getViewLifecycleOwner(), new OnBackPressedCallback(true) { requireActivity().getOnBackPressedDispatcher().addCallback(getViewLifecycleOwner(), new OnBackPressedCallback(true) {
@Override @Override
public void handleOnBackPressed() { public void handleOnBackPressed() {
@@ -132,6 +137,27 @@ public class PixivFragment extends Fragment {
recyclerView.setLayoutManager(new LinearLayoutManager(requireContext())); recyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
recyclerView.setAdapter(adapter); recyclerView.setAdapter(adapter);
// 设置搜索框的查询监听器 // 设置搜索框的查询监听器
String dat = settingProperties2.getString("benzi", "[]");
List<String> list = new Gson().fromJson(dat, List.class);
// 替换原有的 for 循环代码
shoucangListAdapter = new ArrayAdapter<>(requireContext(), android.R.layout.simple_list_item_1, shoucangDataList);
shoucangList.setAdapter(shoucangListAdapter);
for (String s : list) {
String id = s.split("_")[0];
String name = s.split("_")[1];
if (name.length() > 14) {
name = name.substring(0, 14);
}
shoucangDataList.add("[" + id + "] " + name + "...\n");
//加个换行横线
}
shoucangListAdapter.notifyDataSetChanged();
shoucangList.setOnItemClickListener((parent, view, position, id) -> {
String selectedItem = shoucangDataList.get(position);
String idValue = selectedItem.split("]")[0].replace("[", "");
fetchDataJM(idValue, 0, null);
});
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override @Override

View File

@@ -62,8 +62,14 @@
android:text="FindMaimai Engine" android:text="FindMaimai Engine"
android:textSize="18sp" android:textSize="18sp"
android:layout_marginTop="8dp" /> android:layout_marginTop="8dp" />
</LinearLayout>
<ListView
android:id="@+id/shoucang"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
</LinearLayout>
<!-- Path 2 --> <!-- Path 2 -->
<LinearLayout <LinearLayout
android:id="@+id/path2" android:id="@+id/path2"

View File

@@ -1,6 +1,6 @@
#Tue Mar 25 23:00:18 HKT 2025 #Sat May 10 13:28:08 CST 2025
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View File

@@ -1,6 +1,12 @@
pluginManagement { pluginManagement {
repositories { repositories {
google() google()
maven {
url 'https://maven.aliyun.com/repository/public'
}
maven {
url 'https://maven.aliyun.com/repository/jcenter'
}
mavenCentral() mavenCentral()
gradlePluginPortal() gradlePluginPortal()
} }
@@ -11,9 +17,15 @@ dependencyResolutionManagement {
google() google()
mavenCentral() mavenCentral()
maven { url "https://jitpack.io" } maven { url "https://jitpack.io" }
maven {
url 'https://maven.aliyun.com/repository/public'
}
maven {
url 'https://maven.aliyun.com/repository/jcenter'
}
}
}
}
}
rootProject.name = "FindMaimaiUltra" rootProject.name = "FindMaimaiUltra"
include ':app' include ':app'