Compare commits
3 Commits
gallery-v1
...
gallery-v1
| Author | SHA1 | Date | |
|---|---|---|---|
| 262d35fb4e | |||
| 5b0bb599bb | |||
| 3955de100d |
@@ -1,8 +1,8 @@
|
|||||||
#Created by .winboll/winboll_app_build.gradle
|
#Created by .winboll/winboll_app_build.gradle
|
||||||
#Sun Apr 26 10:16:07 HKT 2026
|
#Sun Apr 26 11:32:37 HKT 2026
|
||||||
stageCount=5
|
stageCount=6
|
||||||
libraryProject=
|
libraryProject=
|
||||||
baseVersion=15.0
|
baseVersion=15.0
|
||||||
publishVersion=15.0.4
|
publishVersion=15.0.5
|
||||||
buildCount=0
|
buildCount=0
|
||||||
baseBetaVersion=15.0.5
|
baseBetaVersion=15.0.6
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public class AlbumActivity extends AppCompatActivity {
|
|||||||
private String albumPath;
|
private String albumPath;
|
||||||
private String albumName;
|
private String albumName;
|
||||||
private FloatingActionButton fabScrollTop;
|
private FloatingActionButton fabScrollTop;
|
||||||
private RecyclerView.OnScrollListener scrollListener;
|
private Preferences prefs;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
@@ -49,10 +49,13 @@ public class AlbumActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
getSupportActionBar().setTitle(albumName);
|
getSupportActionBar().setTitle(albumName);
|
||||||
|
|
||||||
|
prefs = new Preferences(this);
|
||||||
|
|
||||||
recyclerView = findViewById(R.id.recycler_view);
|
recyclerView = findViewById(R.id.recycler_view);
|
||||||
recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
|
recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
|
||||||
adapter = new ImageAdapter();
|
adapter = new ImageAdapter();
|
||||||
adapter.setContext(this);
|
adapter.setContext(this);
|
||||||
|
adapter.setAlbumPath(albumPath);
|
||||||
recyclerView.setAdapter(adapter);
|
recyclerView.setAdapter(adapter);
|
||||||
|
|
||||||
fabScrollTop = findViewById(R.id.fab_scroll_top);
|
fabScrollTop = findViewById(R.id.fab_scroll_top);
|
||||||
@@ -63,7 +66,7 @@ public class AlbumActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
scrollListener = new RecyclerView.OnScrollListener() {
|
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
|
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
|
||||||
super.onScrolled(recyclerView, dx, dy);
|
super.onScrolled(recyclerView, dx, dy);
|
||||||
@@ -77,8 +80,7 @@ public class AlbumActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
recyclerView.addOnScrollListener(scrollListener);
|
|
||||||
|
|
||||||
adapter.setOnImageClickListener(new OnImageClickListener() {
|
adapter.setOnImageClickListener(new OnImageClickListener() {
|
||||||
@Override
|
@Override
|
||||||
@@ -122,6 +124,20 @@ public class AlbumActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getSortOrder(int sortMode) {
|
||||||
|
switch (sortMode) {
|
||||||
|
case Preferences.SORT_TIME_ASC:
|
||||||
|
return android.provider.MediaStore.Images.Media.DATE_ADDED + " ASC";
|
||||||
|
case Preferences.SORT_NAME_DESC:
|
||||||
|
return android.provider.MediaStore.Images.Media.DISPLAY_NAME + " DESC";
|
||||||
|
case Preferences.SORT_NAME_ASC:
|
||||||
|
return android.provider.MediaStore.Images.Media.DISPLAY_NAME + " ASC";
|
||||||
|
case Preferences.SORT_TIME_DESC:
|
||||||
|
default:
|
||||||
|
return android.provider.MediaStore.Images.Media.DATE_ADDED + " DESC";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void loadImages() {
|
private void loadImages() {
|
||||||
LogUtils.d(TAG, "loadImages");
|
LogUtils.d(TAG, "loadImages");
|
||||||
ArrayList<Uri> imageUrls = new ArrayList<>();
|
ArrayList<Uri> imageUrls = new ArrayList<>();
|
||||||
@@ -131,7 +147,8 @@ public class AlbumActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
String selection = android.provider.MediaStore.Images.Media.DATA + " LIKE ?";
|
String selection = android.provider.MediaStore.Images.Media.DATA + " LIKE ?";
|
||||||
String[] selectionArgs = new String[]{albumPath + "%"};
|
String[] selectionArgs = new String[]{albumPath + "%"};
|
||||||
String sortOrder = android.provider.MediaStore.Images.Media.DATE_ADDED + " DESC";
|
int sortMode = prefs.getAlbumSortMode();
|
||||||
|
String sortOrder = getSortOrder(sortMode);
|
||||||
|
|
||||||
try (Cursor cursor = contentResolver.query(collection, null, selection, selectionArgs, sortOrder)) {
|
try (Cursor cursor = contentResolver.query(collection, null, selection, selectionArgs, sortOrder)) {
|
||||||
if (cursor != null) {
|
if (cursor != null) {
|
||||||
@@ -155,7 +172,64 @@ public class AlbumActivity extends AppCompatActivity {
|
|||||||
adapter.setData(imageUrls, imagePaths);
|
adapter.setData(imageUrls, imagePaths);
|
||||||
LogUtils.d(TAG, "Loaded " + imageUrls.size() + " images");
|
LogUtils.d(TAG, "Loaded " + imageUrls.size() + " images");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
getMenuInflater().inflate(R.menu.menu_album, menu);
|
||||||
|
int sortMode = prefs.getAlbumSortMode();
|
||||||
|
int menuId = getSortMenuId(sortMode);
|
||||||
|
MenuItem item = menu.findItem(menuId);
|
||||||
|
if (item != null) {
|
||||||
|
item.setChecked(true);
|
||||||
|
}
|
||||||
|
MenuItem sortItem = menu.findItem(R.id.action_sort);
|
||||||
|
if (sortItem != null && sortItem.getSubMenu() != null) {
|
||||||
|
sortItem.getSubMenu().setGroupCheckable(0, true, true);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getSortMenuId(int sortMode) {
|
||||||
|
switch (sortMode) {
|
||||||
|
case Preferences.SORT_TIME_ASC:
|
||||||
|
return R.id.sort_time_asc;
|
||||||
|
case Preferences.SORT_NAME_DESC:
|
||||||
|
return R.id.sort_name_desc;
|
||||||
|
case Preferences.SORT_NAME_ASC:
|
||||||
|
return R.id.sort_name_asc;
|
||||||
|
case Preferences.SORT_TIME_DESC:
|
||||||
|
default:
|
||||||
|
return R.id.sort_time_desc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
||||||
|
int itemId = item.getItemId();
|
||||||
|
if (itemId == R.id.sort_time_desc) {
|
||||||
|
prefs.setAlbumSortMode(Preferences.SORT_TIME_DESC);
|
||||||
|
item.setChecked(true);
|
||||||
|
loadImages();
|
||||||
|
return true;
|
||||||
|
} else if (itemId == R.id.sort_time_asc) {
|
||||||
|
prefs.setAlbumSortMode(Preferences.SORT_TIME_ASC);
|
||||||
|
item.setChecked(true);
|
||||||
|
loadImages();
|
||||||
|
return true;
|
||||||
|
} else if (itemId == R.id.sort_name_desc) {
|
||||||
|
prefs.setAlbumSortMode(Preferences.SORT_NAME_DESC);
|
||||||
|
item.setChecked(true);
|
||||||
|
loadImages();
|
||||||
|
return true;
|
||||||
|
} else if (itemId == R.id.sort_name_asc) {
|
||||||
|
prefs.setAlbumSortMode(Preferences.SORT_NAME_ASC);
|
||||||
|
item.setChecked(true);
|
||||||
|
loadImages();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
package cc.winboll.studio.gallery;
|
||||||
|
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
|
import cc.winboll.studio.libappbase.LogUtils;
|
||||||
|
|
||||||
|
public class AlbumCoverDbHelper extends SQLiteOpenHelper {
|
||||||
|
public static final String TAG = "AlbumCoverDbHelper";
|
||||||
|
private static final String DB_NAME = "album_cover.db";
|
||||||
|
private static final int DB_VERSION = 1;
|
||||||
|
private static final String TABLE_NAME = "album_covers";
|
||||||
|
private static final String COLUMN_ALBUM_PATH = "album_path";
|
||||||
|
private static final String COLUMN_IMAGE_PATH = "image_path";
|
||||||
|
|
||||||
|
private static final String SQL_CREATE = "CREATE TABLE " + TABLE_NAME + " ("
|
||||||
|
+ COLUMN_ALBUM_PATH + " TEXT PRIMARY KEY, "
|
||||||
|
+ COLUMN_IMAGE_PATH + " TEXT)";
|
||||||
|
|
||||||
|
private static AlbumCoverDbHelper dbHelper;
|
||||||
|
|
||||||
|
public static AlbumCoverDbHelper getInstance(Context context) {
|
||||||
|
if (dbHelper == null) {
|
||||||
|
dbHelper = new AlbumCoverDbHelper(context.getApplicationContext());
|
||||||
|
}
|
||||||
|
return dbHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AlbumCoverDbHelper(Context context) {
|
||||||
|
super(context, DB_NAME, null, DB_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(SQLiteDatabase db) {
|
||||||
|
db.execSQL(SQL_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||||
|
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
|
||||||
|
onCreate(db);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCover(String albumPath, String imagePath) {
|
||||||
|
SQLiteDatabase db = getWritableDatabase();
|
||||||
|
ContentValues values = new ContentValues();
|
||||||
|
values.put(COLUMN_ALBUM_PATH, albumPath);
|
||||||
|
values.put(COLUMN_IMAGE_PATH, imagePath);
|
||||||
|
db.insertWithOnConflict(TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_REPLACE);
|
||||||
|
LogUtils.d(TAG, "setCover: album=" + albumPath + ", image=" + imagePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCover(String albumPath) {
|
||||||
|
SQLiteDatabase db = getReadableDatabase();
|
||||||
|
Cursor cursor = db.query(TABLE_NAME, new String[]{COLUMN_IMAGE_PATH},
|
||||||
|
COLUMN_ALBUM_PATH + " = ?", new String[]{albumPath}, null, null, null);
|
||||||
|
String coverPath = null;
|
||||||
|
if (cursor != null) {
|
||||||
|
if (cursor.moveToFirst()) {
|
||||||
|
coverPath = cursor.getString(0);
|
||||||
|
}
|
||||||
|
cursor.close();
|
||||||
|
}
|
||||||
|
return coverPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearCover(String albumPath) {
|
||||||
|
SQLiteDatabase db = getWritableDatabase();
|
||||||
|
db.delete(TABLE_NAME, COLUMN_ALBUM_PATH + " = ?", new String[]{albumPath});
|
||||||
|
LogUtils.d(TAG, "clearCover: " + albumPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,6 +24,8 @@ public class ImageAdapter extends RecyclerView.Adapter<ImageAdapter.ViewHolder>
|
|||||||
private int bgType = 0;
|
private int bgType = 0;
|
||||||
private Preferences prefs;
|
private Preferences prefs;
|
||||||
private PinnedImageDbHelper pinnedDbHelper;
|
private PinnedImageDbHelper pinnedDbHelper;
|
||||||
|
private AlbumCoverDbHelper coverDbHelper;
|
||||||
|
private String albumPath;
|
||||||
|
|
||||||
private int getBgRes() {
|
private int getBgRes() {
|
||||||
switch (bgType) {
|
switch (bgType) {
|
||||||
@@ -58,51 +60,38 @@ public class ImageAdapter extends RecyclerView.Adapter<ImageAdapter.ViewHolder>
|
|||||||
if (pinnedDbHelper == null || imagePaths.isEmpty()) {
|
if (pinnedDbHelper == null || imagePaths.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
ArrayList<Uri> pinnedUrls = new ArrayList<>();
|
||||||
ArrayList<String> pinnedPaths = new ArrayList<>();
|
ArrayList<String> pinnedPaths = new ArrayList<>();
|
||||||
|
ArrayList<Uri> unpinnedUrls = new ArrayList<>();
|
||||||
ArrayList<String> unpinnedPaths = new ArrayList<>();
|
ArrayList<String> unpinnedPaths = new ArrayList<>();
|
||||||
for (String path : imagePaths) {
|
for (int i = 0; i < imagePaths.size(); i++) {
|
||||||
|
String path = imagePaths.get(i);
|
||||||
if (pinnedDbHelper.isPinned(path)) {
|
if (pinnedDbHelper.isPinned(path)) {
|
||||||
|
pinnedUrls.add(imageUrls.get(i));
|
||||||
pinnedPaths.add(path);
|
pinnedPaths.add(path);
|
||||||
} else {
|
} else {
|
||||||
|
unpinnedUrls.add(imageUrls.get(i));
|
||||||
unpinnedPaths.add(path);
|
unpinnedPaths.add(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Comparator<String> pathComparator = new Comparator<String>() {
|
|
||||||
@Override
|
|
||||||
public int compare(String p1, String p2) {
|
|
||||||
return p1.compareToIgnoreCase(p2);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Collections.sort(pinnedPaths, pathComparator);
|
|
||||||
Collections.sort(unpinnedPaths, pathComparator);
|
|
||||||
|
|
||||||
ArrayList<Uri> newUrls = new ArrayList<>();
|
|
||||||
ArrayList<String> newPaths = new ArrayList<>();
|
|
||||||
for (String path : pinnedPaths) {
|
|
||||||
int index = imagePaths.indexOf(path);
|
|
||||||
if (index >= 0) {
|
|
||||||
newUrls.add(imageUrls.get(index));
|
|
||||||
newPaths.add(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (String path : unpinnedPaths) {
|
|
||||||
int index = imagePaths.indexOf(path);
|
|
||||||
if (index >= 0) {
|
|
||||||
newUrls.add(imageUrls.get(index));
|
|
||||||
newPaths.add(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
imageUrls.clear();
|
imageUrls.clear();
|
||||||
imagePaths.clear();
|
imagePaths.clear();
|
||||||
imageUrls.addAll(newUrls);
|
imageUrls.addAll(pinnedUrls);
|
||||||
imagePaths.addAll(newPaths);
|
imageUrls.addAll(unpinnedUrls);
|
||||||
|
imagePaths.addAll(pinnedPaths);
|
||||||
|
imagePaths.addAll(unpinnedPaths);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setContext(android.content.Context context) {
|
public void setContext(android.content.Context context) {
|
||||||
prefs = new Preferences(context);
|
prefs = new Preferences(context);
|
||||||
bgType = prefs.getBgType();
|
bgType = prefs.getBgType();
|
||||||
pinnedDbHelper = PinnedImageDbHelper.getInstance(context);
|
pinnedDbHelper = PinnedImageDbHelper.getInstance(context);
|
||||||
|
coverDbHelper = AlbumCoverDbHelper.getInstance(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAlbumPath(String albumPath) {
|
||||||
|
this.albumPath = albumPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refreshBg() {
|
public void refreshBg() {
|
||||||
@@ -125,17 +114,24 @@ public class ImageAdapter extends RecyclerView.Adapter<ImageAdapter.ViewHolder>
|
|||||||
android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(view.getContext());
|
android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(view.getContext());
|
||||||
builder.setTitle("Image");
|
builder.setTitle("Image");
|
||||||
boolean isPinned = pinnedDbHelper != null && pinnedDbHelper.isPinned(imagePath);
|
boolean isPinned = pinnedDbHelper != null && pinnedDbHelper.isPinned(imagePath);
|
||||||
String[] items = isPinned ? new String[]{"取消置顶"} : new String[]{"置顶"};
|
String[] items = isPinned ? new String[]{"取消置顶", "设置为封面"} : new String[]{"置顶", "设置为封面"};
|
||||||
builder.setItems(items, new android.content.DialogInterface.OnClickListener() {
|
builder.setItems(items, new android.content.DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(android.content.DialogInterface dialog, int which) {
|
public void onClick(android.content.DialogInterface dialog, int which) {
|
||||||
if (pinnedDbHelper != null && which == 0) {
|
if (which == 0) {
|
||||||
if (isPinned) {
|
if (pinnedDbHelper != null) {
|
||||||
pinnedDbHelper.unpinImage(imagePath);
|
if (isPinned) {
|
||||||
} else {
|
pinnedDbHelper.unpinImage(imagePath);
|
||||||
pinnedDbHelper.pinImage(imagePath);
|
} else {
|
||||||
|
pinnedDbHelper.pinImage(imagePath);
|
||||||
|
}
|
||||||
|
refreshPinned();
|
||||||
|
}
|
||||||
|
} else if (which == 1) {
|
||||||
|
if (coverDbHelper != null && albumPath != null) {
|
||||||
|
coverDbHelper.setCover(albumPath, imagePath);
|
||||||
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
refreshPinned();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -166,6 +162,9 @@ public class ImageAdapter extends RecyclerView.Adapter<ImageAdapter.ViewHolder>
|
|||||||
boolean isPinned = pinnedDbHelper != null && pinnedDbHelper.isPinned(imagePath);
|
boolean isPinned = pinnedDbHelper != null && pinnedDbHelper.isPinned(imagePath);
|
||||||
holder.pinIcon.setVisibility(isPinned ? View.VISIBLE : View.GONE);
|
holder.pinIcon.setVisibility(isPinned ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
|
boolean isCover = coverDbHelper != null && albumPath != null && imagePath.equals(coverDbHelper.getCover(albumPath));
|
||||||
|
holder.coverIcon.setVisibility(isCover ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
holder.itemView.setOnClickListener(new OnClickListener() {
|
holder.itemView.setOnClickListener(new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
@@ -192,10 +191,12 @@ public class ImageAdapter extends RecyclerView.Adapter<ImageAdapter.ViewHolder>
|
|||||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
ImageView imageView;
|
ImageView imageView;
|
||||||
ImageView pinIcon;
|
ImageView pinIcon;
|
||||||
|
ImageView coverIcon;
|
||||||
ViewHolder(View itemView) {
|
ViewHolder(View itemView) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
imageView = itemView.findViewById(R.id.image);
|
imageView = itemView.findViewById(R.id.image);
|
||||||
pinIcon = itemView.findViewById(R.id.pin_icon);
|
pinIcon = itemView.findViewById(R.id.pin_icon);
|
||||||
|
coverIcon = itemView.findViewById(R.id.cover_icon);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -159,7 +159,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadAlbums() {
|
private void loadAlbums() {
|
||||||
LogUtils.d(TAG, "loadAlbums");
|
LogUtils.d(TAG, "loadAlbums");
|
||||||
String folderPath = prefs.getFolderPath();
|
String folderPath = prefs.getFolderPath();
|
||||||
File baseFolder = new File(folderPath);
|
File baseFolder = new File(folderPath);
|
||||||
@@ -176,6 +176,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AlbumCoverDbHelper coverDbHelper = AlbumCoverDbHelper.getInstance(this);
|
||||||
ArrayList<Album> albums = new ArrayList<>();
|
ArrayList<Album> albums = new ArrayList<>();
|
||||||
|
|
||||||
FileFilter directoryFilter = new FileFilter() {
|
FileFilter directoryFilter = new FileFilter() {
|
||||||
@@ -189,11 +190,26 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
if (subfolders != null) {
|
if (subfolders != null) {
|
||||||
for (File subfolder : subfolders) {
|
for (File subfolder : subfolders) {
|
||||||
LogUtils.d(TAG, "scanning folder: " + subfolder.getName());
|
LogUtils.d(TAG, "scanning folder: " + subfolder.getName());
|
||||||
ArrayList<Uri> images = getImagesInFolder(subfolder.getAbsolutePath());
|
String albumPath = subfolder.getAbsolutePath();
|
||||||
if (!images.isEmpty()) {
|
String coverPath = coverDbHelper.getCover(albumPath);
|
||||||
Uri latestImage = images.get(0);
|
Uri coverUri = null;
|
||||||
albums.add(new Album(subfolder.getName(), subfolder.getAbsolutePath(), latestImage, images.size()));
|
if (coverPath != null) {
|
||||||
LogUtils.d(TAG, "album added: " + subfolder.getName() + ", " + images.size() + " images");
|
coverUri = getUriFromPath(coverPath);
|
||||||
|
}
|
||||||
|
if (coverUri == null) {
|
||||||
|
ArrayList<Uri> images = getImagesInFolder(albumPath);
|
||||||
|
if (!images.isEmpty()) {
|
||||||
|
coverUri = images.get(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ArrayList<Uri> allImages = getImagesInFolder(albumPath);
|
||||||
|
if (coverUri != null || !allImages.isEmpty()) {
|
||||||
|
if (coverUri == null && !allImages.isEmpty()) {
|
||||||
|
coverUri = allImages.get(0);
|
||||||
|
}
|
||||||
|
int imageCount = allImages.size();
|
||||||
|
albums.add(new Album(subfolder.getName(), albumPath, coverUri, imageCount));
|
||||||
|
LogUtils.d(TAG, "album added: " + subfolder.getName() + ", " + imageCount + " images");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -205,7 +221,24 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
adapter.setData(albums);
|
adapter.setData(albums);
|
||||||
LogUtils.d(TAG, "Loaded " + albums.size() + " albums");
|
LogUtils.d(TAG, "Loaded " + albums.size() + " albums");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Uri getUriFromPath(String path) {
|
||||||
|
String[] projection = { MediaStore.Images.Media._ID };
|
||||||
|
String selection = MediaStore.Images.Media.DATA + " = ?";
|
||||||
|
String[] selectionArgs = { path };
|
||||||
|
try (Cursor cursor = getContentResolver().query(
|
||||||
|
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
|
||||||
|
projection, selection, selectionArgs, null)) {
|
||||||
|
if (cursor != null) {
|
||||||
|
if (cursor.moveToFirst()) {
|
||||||
|
long id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID));
|
||||||
|
return Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, String.valueOf(id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private ArrayList<Uri> getImagesInFolder(String folderPath) {
|
private ArrayList<Uri> getImagesInFolder(String folderPath) {
|
||||||
ArrayList<Uri> imageUrls = new ArrayList<>();
|
ArrayList<Uri> imageUrls = new ArrayList<>();
|
||||||
ContentResolver contentResolver = getContentResolver();
|
ContentResolver contentResolver = getContentResolver();
|
||||||
|
|||||||
@@ -9,9 +9,16 @@ public class Preferences {
|
|||||||
private static final String PREF_NAME = "gallery_prefs";
|
private static final String PREF_NAME = "gallery_prefs";
|
||||||
private static final String KEY_FOLDER_PATH = "folder_path";
|
private static final String KEY_FOLDER_PATH = "folder_path";
|
||||||
private static final String KEY_BG_TYPE = "bg_type";
|
private static final String KEY_BG_TYPE = "bg_type";
|
||||||
|
private static final String KEY_ALBUM_SORT_MODE = "album_sort_mode";
|
||||||
private static final int DEFAULT_BG_TYPE = 0;
|
private static final int DEFAULT_BG_TYPE = 0;
|
||||||
|
private static final int DEFAULT_SORT_MODE = 0;
|
||||||
private static final String DEFAULT_PATH = "/storage/emulated/0/Pictures/Gallery/owner";
|
private static final String DEFAULT_PATH = "/storage/emulated/0/Pictures/Gallery/owner";
|
||||||
|
|
||||||
|
public static final int SORT_TIME_DESC = 0;
|
||||||
|
public static final int SORT_TIME_ASC = 1;
|
||||||
|
public static final int SORT_NAME_DESC = 2;
|
||||||
|
public static final int SORT_NAME_ASC = 3;
|
||||||
|
|
||||||
public static String getDefaultPath() {
|
public static String getDefaultPath() {
|
||||||
return DEFAULT_PATH;
|
return DEFAULT_PATH;
|
||||||
}
|
}
|
||||||
@@ -41,4 +48,13 @@ public class Preferences {
|
|||||||
LogUtils.d(TAG, "setBgType: " + type);
|
LogUtils.d(TAG, "setBgType: " + type);
|
||||||
prefs.edit().putInt(KEY_BG_TYPE, type).apply();
|
prefs.edit().putInt(KEY_BG_TYPE, type).apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getAlbumSortMode() {
|
||||||
|
return prefs.getInt(KEY_ALBUM_SORT_MODE, DEFAULT_SORT_MODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAlbumSortMode(int mode) {
|
||||||
|
LogUtils.d(TAG, "setAlbumSortMode: " + mode);
|
||||||
|
prefs.edit().putInt(KEY_ALBUM_SORT_MODE, mode).apply();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
13
gallery/src/main/res/drawable/ic_cover.xml
Normal file
13
gallery/src/main/res/drawable/ic_cover.xml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#000000"
|
||||||
|
android:pathData="M21,3H3C1.9,3 1,3.9 1,5v14c0,1.1 0.9,2 2,2h18c1.1,0 2,-0.9 2,-2V5C23,3.9 22.1,3 21,3zM21,19H3V5h18V19z"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#000000"
|
||||||
|
android:pathData="M9,12l2,2l4,-4l1.5,1.5L11,17l-3,-3z"/>
|
||||||
|
</vector>
|
||||||
10
gallery/src/main/res/drawable/ic_sort.xml
Normal file
10
gallery/src/main/res/drawable/ic_sort.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:pathData="M3,18h6v-2H3v2zM3,6v2h18V6H3zM3,13h12v-2H3v2z"/>
|
||||||
|
</vector>
|
||||||
@@ -25,4 +25,17 @@
|
|||||||
app:tint="@color/black"
|
app:tint="@color/black"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"/>
|
xmlns:app="http://schemas.android.com/apk/res-auto"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/cover_icon"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_gravity="bottom|end"
|
||||||
|
android:layout_margin="4dp"
|
||||||
|
android:background="@drawable/bg_circle_white"
|
||||||
|
android:padding="4dp"
|
||||||
|
android:src="@drawable/ic_cover"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:tint="@color/black"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"/>
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
26
gallery/src/main/res/menu/menu_album.xml
Normal file
26
gallery/src/main/res/menu/menu_album.xml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_sort"
|
||||||
|
android:icon="@drawable/ic_sort"
|
||||||
|
android:title="排序"
|
||||||
|
app:showAsAction="ifRoom">
|
||||||
|
<menu>
|
||||||
|
<group android:checkableBehavior="single">
|
||||||
|
<item
|
||||||
|
android:id="@+id/sort_time_desc"
|
||||||
|
android:title="时间倒序"/>
|
||||||
|
<item
|
||||||
|
android:id="@+id/sort_time_asc"
|
||||||
|
android:title="时间正序"/>
|
||||||
|
<item
|
||||||
|
android:id="@+id/sort_name_desc"
|
||||||
|
android:title="名称倒序"/>
|
||||||
|
<item
|
||||||
|
android:id="@+id/sort_name_asc"
|
||||||
|
android:title="名称正序"/>
|
||||||
|
</group>
|
||||||
|
</menu>
|
||||||
|
</item>
|
||||||
|
</menu>
|
||||||
Reference in New Issue
Block a user