Commit ce010dc7 authored by jyx's avatar jyx

相册清理

parent 0505771a
......@@ -159,6 +159,7 @@ dependencies {
implementation Deps.banner
implementation Deps.glide
kapt Deps.glide_compiler
implementation Deps.photoView
implementation Deps.livedata_ktx
implementation Deps.viewPager2
......
......@@ -2,6 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mints.cleaner">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
......@@ -14,8 +15,16 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".ui.setting.SettingActivity"></activity>
<activity android:name=".ui.albumClean.AlbumCleanActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!--屏幕适配-->
<!-- 屏幕适配 -->
<meta-data
android:name="android.max_aspect"
android:value="2.4" />
......@@ -23,11 +32,7 @@
<activity android:name=".ui.login.LoginActivity" />
<activity android:name=".ui.splash.SplashActivity" />
<activity android:name=".ui.NavigationActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
......
package com.mints.cleaner.adapter
import android.widget.ImageView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.request.RequestOptions
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.BaseViewHolder
import com.mints.cleaner.R
import com.mints.cleaner.model.bean.Image
import com.mints.cleaner.util.VersionUtils
import com.mints.cleaner.widget.RoundCheckBox
class AlbumCleanAdapter(layoutResId: Int, data: List<Image>) :
BaseQuickAdapter<Image, BaseViewHolder>(layoutResId, data) {
// 选中图片数据
private var mSelectImages = arrayListOf<Image>()
// 复选框选中状态
private var mCheckBoxTags = arrayListOf<Int>()
private var mSelectListener: OnImageSelectListener? = null
private var mItemClickListener: OnItemClickListener? = null
private val isViewImage = false
private val isAndroidQ: Boolean = VersionUtils.isAndroidQ()
override fun convert(helper: BaseViewHolder, item: Image) {
helper.getView<ImageView>(R.id.iv_item_album).run {
Glide.with(mContext).load(if (isAndroidQ) item.uri else item.path)
.apply(RequestOptions().diskCacheStrategy(DiskCacheStrategy.NONE))
.into(this)
setOnClickListener {
mItemClickListener?.let {
it.onItemClick(item, helper.adapterPosition)
}
}
}
helper.getView<RoundCheckBox>(R.id.cb_item).run {
setOnCheckedChangeListener(null)
tag = helper.adapterPosition
isChecked = mCheckBoxTags.contains(helper.adapterPosition)
setOnCheckedChangeListener { _, _ ->
if (mSelectImages.contains(item)) {
unSelectImage(item)
} else {
selectImage(item)
}
if (isChecked) {
mCheckBoxTags.add(helper.adapterPosition)
} else {
mCheckBoxTags.remove(helper.adapterPosition)
}
}
}
}
fun setOnImageSelectListener(listener: OnImageSelectListener?) {
mSelectListener = listener
}
fun setOnItemClickListener1(listener: OnItemClickListener?) {
mItemClickListener = listener
}
fun getSelectImageList(): List<Image> {
return mSelectImages
}
// 更新数据
fun refreshData(data: List<Image>) {
mData = data
notifyDataSetChanged()
}
// 清空复选框标识
fun cleanSelectImage() {
mSelectImages = arrayListOf()
mCheckBoxTags = arrayListOf()
mSelectListener?.let {
it.onImageSelect(mSelectImages.size)
}
notifyDataSetChanged()
}
// 全选
fun fullSelectImage() {
for (index in 0 until mData.size) {
mCheckBoxTags.add(index)
mSelectImages.add(mData[index])
}
mSelectListener?.let {
it.onImageSelect(mSelectImages.size)
}
notifyDataSetChanged()
}
// 取消全选
fun cancelFullSelectImage() {
// 取消全选
mSelectImages = arrayListOf()
mCheckBoxTags = arrayListOf()
mSelectListener?.let {
it.onImageSelect(mSelectImages.size)
}
notifyDataSetChanged()
}
/**
* 选中图片
*/
private fun selectImage(image: Image) {
mSelectImages.add(image)
mSelectListener?.let {
it.onImageSelect(mSelectImages.size)
}
}
/**
* 取消选中图片
*/
private fun unSelectImage(image: Image) {
mSelectImages.remove(image)
mSelectListener?.let {
it.onImageSelect(mSelectImages.size)
}
}
interface OnImageSelectListener {
fun onImageSelect(
selectCount: Int
)
}
interface OnItemClickListener {
fun onItemClick(image: Image?, position: Int)
}
}
\ No newline at end of file
......@@ -8,9 +8,6 @@ import com.mints.cleaner.R
class CleanAdapter : BaseMultiItemQuickAdapter<CleanMultiItem, BaseViewHolder> {
private val names = arrayOf("手机加速", "微信清理", "QQ清理", "软件管理", "相册清理", "视频清理")
constructor(data: List<CleanMultiItem>) : super(data) {
addItemType(CleanMultiItem.ITEM_TOP, R.layout.item_clean_top)
addItemType(CleanMultiItem.ITEM_MID, R.layout.item_clean_mid)
......@@ -24,21 +21,13 @@ class CleanAdapter : BaseMultiItemQuickAdapter<CleanMultiItem, BaseViewHolder> {
}
CleanMultiItem.ITEM_MID -> {
val listitem: MutableList<Map<String, Any>> =
ArrayList()
for (i in names.indices) {
val item: MutableMap<String, Any> = HashMap()
item["item_gv_text"] = names[i]
listitem.add(item)
}
val gridView = helper.getView<GridView>(R.id.gv_clean)
val simpleAdapter = SimpleAdapter(
gridView.context,
listitem,
item?.gvDataList,
R.layout.item_gv_clean,
arrayOf("item_gv_text"),
intArrayOf(R.id.item_gv_text)
arrayOf("item_gv_icon", "item_gv_text"),
intArrayOf(R.id.item_gv_img, R.id.item_gv_text)
)
gridView.adapter = simpleAdapter
gridView.setOnItemClickListener { _, _, position, _ ->
......
......@@ -5,15 +5,16 @@ import com.chad.library.adapter.base.entity.MultiItemEntity
class CleanMultiItem : MultiItemEntity {
private var itemType: Int = 0
private var itemIndex: Int = 0
var gvDataList: MutableList<Map<String, Any>> = ArrayList()
constructor(itemType: Int) {
this.itemType = itemType
}
constructor(itemType: Int, itemIndex: Int) {
constructor(itemType: Int, gvDataList: MutableList<Map<String, Any>>) {
this.itemType = itemType
this.itemIndex = itemIndex
this.gvDataList = gvDataList
}
companion object {
......
......@@ -2,12 +2,10 @@ package com.mints.cleaner.model.api.client
import com.mints.cleaner.model.api.neterror.CashException
import com.mints.cleaner.model.api.neterror.ServerException
import com.mints.cleaner.model.api.neterror.Throwable
import com.mints.cleaner.model.repository.BaseResponse
import com.mints.core.Result
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.coroutineScope
import java.io.IOException
import java.lang.Exception
open class BaseRepository {
......
package com.mints.cleaner.model.bean
class CleanHeaderTitle(
// 标题内容
var title: Int,
// 左边图标
var leftIcon: Int,
// 左边图标点击事件
var leftAction: () -> Unit,
// 右边文字是否显示
val rightInfoVisible: Int,
// 右边文字内容
val rightInfo: String,
// 右边文字点击事件
val rightInfoAction: () -> Unit,
// 背景颜色
val background: Int
)
\ No newline at end of file
package com.mints.cleaner.model.bean
class Folder {
var name: String
var images: ArrayList<Image> = arrayListOf()
constructor(name: String) {
this.name = name
}
constructor(name: String, images: ArrayList<Image>) {
this.name = name
this.images = images
}
fun addImage(image: Image?) {
if (image != null && image.path.isEmpty()) {
if (images == null) {
images = ArrayList()
}
images.add(image)
}
}
}
\ No newline at end of file
package com.mints.cleaner.model.bean
data class HeaderTitle(
class HeaderTitle(
// 标题内容
val title: Int,
var title: Int,
// 返回箭头是否显示
val backArrowVisible: Int,
// 右边图标
val rightIcon: Int,
var leftIconVisible: Int,
// 左边图标
var leftIcon: Int,
// 左边图标点击事件
var leftAction: () -> Unit,
// 背景颜色
val background: Int
)
\ No newline at end of file
package com.mints.cleaner.model.bean
import android.net.Uri
data class Image(
val path: String,
val time: Long,
val name: String,
val mimeType: String,
val uri: Uri,
val size: Long
)
\ No newline at end of file
package com.mints.cleaner.model.repository
import com.mints.cleaner.R
import com.mints.cleaner.adapter.clean.CleanMultiItem
import com.mints.cleaner.model.api.ApiService
import com.mints.cleaner.model.api.client.BaseRepository
class MainRepository(val service: ApiService) : BaseRepository() {
// 网格布局data
private val gvNames = arrayOf("手机加速", "微信清理", "QQ清理", "软件管理", "相册清理", "视频清理")
private val gvIcons = arrayOf(
R.mipmap.ic_launcher,
R.mipmap.ic_launcher,
R.mipmap.ic_launcher,
R.mipmap.ic_launcher,
R.mipmap.ic_launcher,
R.mipmap.ic_launcher
)
private var multiItemList: ArrayList<CleanMultiItem> = arrayListOf()
private val gvDataList: MutableList<Map<String, Any>> = ArrayList()
fun getHomeData(): ArrayList<CleanMultiItem> {
for (i in gvNames.indices) {
val item: MutableMap<String, Any> = HashMap()
item["item_gv_icon"] = gvIcons[i]
item["item_gv_text"] = gvNames[i]
gvDataList.add(item)
}
multiItemList = arrayListOf(
CleanMultiItem(CleanMultiItem.ITEM_TOP),
CleanMultiItem(CleanMultiItem.ITEM_MID, gvDataList),
CleanMultiItem(CleanMultiItem.ITEM_BOTTOM),
CleanMultiItem(CleanMultiItem.ITEM_BOTTOM),
CleanMultiItem(CleanMultiItem.ITEM_BOTTOM),
CleanMultiItem(CleanMultiItem.ITEM_BOTTOM)
)
return multiItemList
}
}
\ No newline at end of file
package com.mints.cleaner.ui.albumClean
import android.content.Intent
import android.net.Uri
import android.view.View
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.GridLayoutManager
import com.mints.cleaner.R
import com.mints.cleaner.adapter.AlbumCleanAdapter
import com.mints.cleaner.databinding.ActivityAlbumCleanBinding
import com.mints.cleaner.model.bean.CleanHeaderTitle
import com.mints.cleaner.model.bean.Folder
import com.mints.cleaner.model.bean.HeaderTitle
import com.mints.cleaner.model.bean.Image
import com.mints.cleaner.util.FileUtils
import com.mints.cleaner.util.LogUtil
import com.mints.core.base.BaseVMActivity
import kotlinx.android.synthetic.main.activity_album_clean.*
import java.io.File
import java.util.*
class AlbumCleanActivity : BaseVMActivity(), AlbumCleanAdapter.OnImageSelectListener,
AlbumCleanAdapter.OnItemClickListener {
private val binding by binding<ActivityAlbumCleanBinding>(R.layout.activity_album_clean)
private val dataList = arrayListOf<Image>()
// 是否全选
private var flag = false
private var rightInfo = "全选"
private val albumAdapter: AlbumCleanAdapter by lazy {
AlbumCleanAdapter(
R.layout.item_album_clean,
dataList
)
}
override fun initView() {
binding.run {
title = CleanHeaderTitle(
R.string.app_name,
R.mipmap.ic_activity_arrow,
{
onBackPressed()
},
View.VISIBLE,
rightInfo,
{
rightInfo = if (!flag) {
albumAdapter.fullSelectImage()
"取消全选"
} else {
albumAdapter.cancelFullSelectImage()
"全选"
}
flag = !flag
},
R.color.theme
)
}
initRecyclerView()
btn_clean.setOnClickListener {
val selectImageList = albumAdapter.getSelectImageList()
if (selectImageList.isEmpty()) return@setOnClickListener
for (element in selectImageList) {
FileUtils.deleteImage(element.path, this)
updateAlbum(element.path)
}
dataList.removeAll(selectImageList)
albumAdapter.cleanSelectImage()
albumAdapter.notifyDataSetChanged()
}
}
private fun initRecyclerView() {
recyclerview_album.run {
layoutManager = GridLayoutManager(this@AlbumCleanActivity, 3)
adapter = albumAdapter
albumAdapter.setOnImageSelectListener(this@AlbumCleanActivity)
albumAdapter.setOnItemClickListener1(this@AlbumCleanActivity)
}
}
override fun initData() {
AlbumCleanModel.loadImageForSDCard(this, object : AlbumCleanModel.DataCallback {
override fun onSuccess(folders: ArrayList<Folder>?) {
folders?.let {
for (index in 0 until folders.size) {
dataList.addAll(folders[index].images)
}
}
runOnUiThread {
albumAdapter.notifyDataSetChanged()
}
}
})
}
override fun startObserve() {
}
override fun onImageSelect(selectCount: Int) {
// 改变 删除按钮数据
updateBtnText(selectCount)
}
override fun onItemClick(image: Image?, position: Int) {
LogUtil.d("onItemClick: $position")
}
// 删除图片后更新图库
private fun updateAlbum(imgPath: String) {
val intent = Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE)
intent.data = Uri.fromFile(File(imgPath))
sendBroadcast(intent)
}
private fun updateBtnText(selectCount: Int) {
// 若有选中图片,改变删除按钮样式,更新数据
if (selectCount > 0) {
btn_clean.background = ContextCompat.getDrawable(this, R.drawable.btn_clean_selected)
var selectSize = 0L
val selectImageList = albumAdapter.getSelectImageList()
for (element in selectImageList) {
selectSize += element.size
}
val selectSizeStr = FileUtils.formatFileSize(selectSize)
btn_clean.text = "删除($selectSizeStr)"
} else {
btn_clean.background = ContextCompat.getDrawable(this, R.drawable.btn_clean_unselected)
btn_clean.text = "删除(0KB)"
}
}
}
\ No newline at end of file
package com.mints.cleaner.ui.home
import android.graphics.Color
import android.view.LayoutInflater
import android.view.View
import android.widget.Toast
import com.mints.cleaner.R
import com.mints.cleaner.adapter.clean.CleanAdapter
import com.mints.cleaner.adapter.clean.CleanMultiItem
import com.mints.cleaner.databinding.FragmentCleanBinding
import com.mints.cleaner.model.bean.HeaderTitle
import com.mints.cleaner.ui.main.MainViewModel
......@@ -20,29 +18,21 @@ import org.koin.androidx.viewmodel.ext.android.viewModel
class HomeFragment : BaseVMFragment<FragmentCleanBinding>(R.layout.fragment_clean) {
private val mainViewModel by viewModel<MainViewModel>()
private val cleanAdapter by lazy { CleanAdapter(multiItemList) }
private val multiItemList =
arrayListOf(
CleanMultiItem(CleanMultiItem.ITEM_TOP),
CleanMultiItem(CleanMultiItem.ITEM_MID),
CleanMultiItem(CleanMultiItem.ITEM_BOTTOM, 0),
CleanMultiItem(CleanMultiItem.ITEM_BOTTOM, 1),
CleanMultiItem(CleanMultiItem.ITEM_BOTTOM, 2),
CleanMultiItem(CleanMultiItem.ITEM_BOTTOM, 3)
)
private val cleanAdapter by lazy { CleanAdapter(mainViewModel.repository.getHomeData()) }
override fun initView() {
binding.run {
viewModel = mainViewModel
adapter = cleanAdapter
title = HeaderTitle(
R.string.app_name,
View.GONE,
R.mipmap.ic_activity_arrow,
{},
R.color.theme
)
}
initRecyclerView()
......@@ -53,7 +43,7 @@ class HomeFragment : BaseVMFragment<FragmentCleanBinding>(R.layout.fragment_clea
addFooterView(LayoutInflater.from(activity).inflate(R.layout.home_footer, null))
// 一键清理
setOnItemChildClickListener { adapter, view, position ->
setOnItemChildClickListener { _, _, _ ->
// 一键清理
activity?.let { toast(it, "一键清理", Toast.LENGTH_SHORT) }
}
......
package com.mints.cleaner.ui.setting
import android.view.View
import com.mints.cleaner.R
import com.mints.cleaner.databinding.ActivitySettingBinding
import com.mints.cleaner.model.bean.HeaderTitle
import com.mints.core.base.BaseVMActivity
import kotlinx.android.synthetic.main.header_bar.*
class SettingActivity : BaseVMActivity() {
private val binding by binding<ActivitySettingBinding>(R.layout.activity_setting)
override fun initView() {
binding.run {
title = HeaderTitle(
R.string.app_name,
View.GONE,
R.mipmap.ic_activity_arrow,
{},
R.color.theme
)
}
iv_header_left.setOnClickListener {
onBackPressed()
}
}
override fun initData() {
}
override fun startObserve() {
}
}
\ No newline at end of file
package com.mints.cleaner.util
import android.content.ContentResolver
import android.content.ContentUris
import android.content.Context
import android.database.Cursor
import android.net.Uri
import android.provider.MediaStore
import java.text.DecimalFormat
object FileUtils {
//定义GB的计算常量
private const val GB = 1024 * 1024 * 1024
//定义MB的计算常量
private const val MB = 1024 * 1024
//定义KB的计算常量
private const val KB = 1024
fun formatFileSize(bytes: Long): String {
//格式化小数
val format = DecimalFormat("###.0")
return when {
bytes / GB >= 1 -> {
format.format(bytes.toDouble() / GB) + "GB"
}
bytes / MB >= 1 -> {
format.format(bytes.toDouble() / MB) + "MB"
}
bytes / KB >= 1 -> {
format.format(bytes.toDouble() / KB) + "KB"
}
else -> {
bytes.toString() + "B"
}
}
}
fun deleteImage(imgPath: String, context: Context): Boolean {
val resolver: ContentResolver = context.contentResolver
val cursor: Cursor = MediaStore.Images.Media.query(
resolver,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
arrayOf(MediaStore.Images.Media._ID),
MediaStore.Images.Media.DATA + "=?",
arrayOf(imgPath),
null
)
var result = false
var uri: Uri?
if (cursor.moveToFirst()) {
val id = cursor.getLong(0)
val contentUri: Uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
uri = ContentUris.withAppendedId(contentUri, id)
val count: Int = context.contentResolver.delete(uri, null, null)
result = count == 1
} else {
val cursor2 = MediaStore.Images.Media.query(
resolver,
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
arrayOf(MediaStore.Images.Media._ID),
MediaStore.Images.Media.DATA + "=?",
arrayOf(imgPath),
null
)
if (cursor2.moveToFirst()) {
val id = cursor2.getLong(0)
val contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
uri = ContentUris.withAppendedId(contentUri, id)
val count: Int = context.contentResolver.delete(uri, null, null)
result = count == 1
}
}
return result
}
}
\ No newline at end of file
package com.mints.cleaner.util;
import android.annotation.SuppressLint;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.util.Log;
import java.io.File;
/**
* @Author teach-梁任彦
* @Description
* @Date 2019-09-11
*/
public class UriUtils {
@SuppressLint("NewApi")
public static String getPathForUri(Context context,Uri uri){
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
if (VersionUtils.INSTANCE.isAndroidQ()) {
return context.getExternalFilesDir(Environment.DIRECTORY_PICTURES) + "/" + split[1];
} else {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
}
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[]{
split[1]
};
return getDataColumn(context, contentUri, selection, selectionArgs);
}
}
// MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme())) {
// Return the remote address
if (isGooglePhotosUri(uri)) {
return uri.getLastPathSegment();
}
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
public static String getDataColumn(Context context, Uri uri, String selection,
String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = {
column
};
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
null);
if (cursor != null && cursor.moveToFirst()) {
final int column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
}
} catch (IllegalArgumentException ex) {
} finally {
if (cursor != null) {
cursor.close();
}
}
return null;
}
/**
* @param uri
* The Uri to check.
* @return Whether the Uri authority is ExternalStorageProvider.
*/
private static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
/**
* @param uri
* The Uri to check.
* @return Whether the Uri authority is DownloadsProvider.
*/
private static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
/**
* @param uri
* The Uri to check.
* @return Whether the Uri authority is MediaProvider.
*/
private static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
/**
* 判断是否是Google相册的图片,类似于content://com.google.android.apps.photos.content/...
**/
public static boolean isGooglePhotosUri(Uri uri) {
return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}
/**
* 判断是否是Google相册的图片,类似于content://com.google.android.apps.photos.contentprovider/0/1/mediakey:/local%3A821abd2f-9f8c-4931-bbe9-a975d1f5fabc/ORIGINAL/NONE/1075342619
**/
public static boolean isGooglePlayPhotosUri(Uri uri) {
return "com.google.android.apps.photos.contentprovider".equals(uri.getAuthority());
}
/**
* 图片路径转uri
* @param context
* @param path
* @return
*/
public static Uri getImageContentUri(Context context, String path) {
Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
new String[] { MediaStore.Images.Media._ID }, MediaStore.Images.Media.DATA + "=? ",
new String[] { path }, null);
if (cursor != null && cursor.moveToFirst()) {
int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
Uri baseUri = Uri.parse("content://media/external/images/media");
return Uri.withAppendedPath(baseUri, "" + id);
} else {
if (new File(path).exists()) {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DATA, path);
return context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
} else {
return null;
}
}
}
}
package com.mints.cleaner.util
import android.os.Build
object VersionUtils {
/**
* 判断是否是Android L版本
*
* @return
*/
fun isAndroidL(): Boolean {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
}
/**
* 判断是否是Android N版本
*
* @return
*/
fun isAndroidN(): Boolean {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
}
/**
* 判断是否是Android P版本
*
* @return
*/
fun isAndroidP(): Boolean {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.P
}
/**
* 判断是否是Android Q版本
*
* @return
*/
fun isAndroidQ(): Boolean {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
}
}
\ No newline at end of file
package com.mints.cleaner.widget
import android.content.Context
import android.util.AttributeSet
class RoundCheckBox : androidx.appcompat.widget.AppCompatCheckBox {
constructor(context: Context, attrs: AttributeSet?, defStyle: Int) : super(context, attrs, defStyle)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, androidx.appcompat.R.attr.radioButtonStyle)
constructor(context: Context) : this(context, null)
}
\ No newline at end of file
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/green" />
<corners android:radius="6dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/gray" />
<corners android:radius="6dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="title"
type="com.mints.cleaner.model.bean.CleanHeaderTitle" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
layout="@layout/clean_header_bar"
title="title" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview_album"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<View style="@style/line_3" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btn_clean"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="20dp"
android:layout_marginBottom="10dp"
android:background="@drawable/btn_clean_unselected"
android:text="删除(0KB)"
android:textColor="@color/white"
android:textSize="18sp" />
</LinearLayout>
</LinearLayout>
</layout>
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="title"
type="com.mints.cleaner.model.bean.HeaderTitle" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
layout="@layout/header_bar"
app:title="@{title}" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="20dp">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/feature_set"
android:textColor="@color/black"
android:textSize="18sp" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_activity_arrow" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="20dp">
<TextView
android:id="@+id/tv_title2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/about_us"
android:textColor="@color/black"
android:textSize="18sp" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_activity_arrow" />
</LinearLayout>
</LinearLayout>
</layout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="title"
type="com.mints.cleaner.model.bean.CleanHeaderTitle" />
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@{title.background}"
android:paddingTop="30dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp">
<ImageView
android:id="@+id/iv_header_left_clean"
onClick="@{title.leftAction}"
icon="@{title.leftIcon}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="10dp"
android:scaleType="center" />
<TextView
android:id="@+id/tv_activity_title_clean"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="10dp"
android:layout_toEndOf="@id/iv_header_left_clean"
android:text="@{title.title}"
android:textColor="@color/product_net_text"
android:textSize="18sp" />
<TextView
android:id="@+id/tv_activity_right_clean"
onClick="@{title.rightInfoAction}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="10dp"
android:text="@{title.rightInfo}"
android:textColor="@color/product_net_text"
android:textSize="18sp"
android:visibility="@{title.rightInfoVisible}" />
</RelativeLayout>
</FrameLayout>
</layout>
\ No newline at end of file
......@@ -8,44 +8,40 @@
type="com.mints.cleaner.model.bean.HeaderTitle" />
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@{title.background}"
android:paddingTop="30dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="80dp"
android:background="@{title.background}">
android:layout_height="50dp">
<ImageView
android:id="@+id/iv_header_left"
onClick="@{title.leftAction}"
icon="@{title.leftIcon}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="40dp"
android:layout_centerVertical="true"
android:layout_marginStart="10dp"
android:scaleType="center"
android:src="@mipmap/ic_activity_arrow"
android:visibility="@{title.backArrowVisible}" />
android:visibility="@{title.leftIconVisible}" />
<TextView
android:id="@+id/tv_activity_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="40dp"
android:layout_centerVertical="true"
android:layout_marginStart="10dp"
android:layout_toEndOf="@id/iv_header_left"
android:text="@{title.title}"
android:textColor="@color/product_net_text"
android:textSize="18sp" />
<ImageView
android:id="@+id/iv_header_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_marginTop="40dp"
android:layout_marginEnd="20dp"
android:scaleType="center"
android:src="@{title.rightIcon}" />
<View
style="@style/line_3"
android:layout_alignParentBottom="true" />
</RelativeLayout>
</FrameLayout>
</layout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="4dp">
<ImageView
android:id="@+id/iv_item_album"
android:layout_width="match_parent"
android:layout_height="150dp"
android:scaleType="centerCrop" />
<com.mints.cleaner.widget.RoundCheckBox
android:id="@+id/cb_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|bottom" />
</FrameLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="20dp">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_activity_arrow" />
</LinearLayout>
\ No newline at end of file
......@@ -14,6 +14,7 @@
<color name="gray">#999999</color>
<color name="gray_01">#F5F5F5</color>
<color name="gray_02">#E8E8F0</color>
<color name="green">#00FF00</color>
<color name="status_bg">#002444</color>
<color name="product_net_text">#121B32</color>
......
......@@ -28,4 +28,11 @@
<string name="music_clean_info">清理不喜欢的音乐</string>
<string name="zip_clean_info">清理无用的压缩包</string>
<string name="about">清理无用的压缩包</string>
<string name="feature_set">功能设置</string>
<string name="about_us">关于我们</string>
<string name="selector_all_image">全部图片</string>
</resources>
\ No newline at end of file
......@@ -2,9 +2,9 @@
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<!-- <item name="colorPrimary">@color/colorPrimary</item>-->
<!-- <item name="colorPrimaryDark">@color/colorPrimaryDark</item>-->
<!-- <item name="colorAccent">@color/colorAccent</item>-->
<item name="drawerArrowStyle">@style/DrawerArrowStyle</item>
</style>
......
......@@ -27,6 +27,7 @@ object Versions {
const val banner = "1.4.10"
const val glide = "4.11.0"
const val glide_compiler = "4.11.0"
const val photoView = "2.0.0"
const val cardView = "1.0.0"
const val verticalTabLayout = "1.2.5"
const val flowLayout = "1.1.2"
......@@ -75,6 +76,7 @@ object Deps {
const val orhanobut_logger = "com.orhanobut:logger:${Versions.orhanobut_logger}"
// third
const val photoView = "com.github.chrisbanes:PhotoView:${Versions.photoView}"
const val circleimageview = "de.hdodenhof:circleimageview:${Versions.circleImageview}"
const val leakCanary = "com.squareup.leakcanary:leakcanary-android:${Versions.leakcanary}"
const val baseRecyclerViewAdapterHelper = "com.github.CymChad:BaseRecyclerViewAdapterHelper:${Versions.baseRecyclerViewAdapterHelper}"
......
package com.mints.core.binding
import android.widget.ImageView
import androidx.databinding.BindingAdapter
@BindingAdapter("icon", requireAll = false)
fun ImageView.init(iconResId: Int) {
setImageResource(iconResId)
}
\ No newline at end of file
package com.mints.core.binding
import android.view.View
import androidx.databinding.BindingAdapter
@BindingAdapter("onClick", requireAll = false)
fun View.init(action: () -> Unit) {
setOnClickListener { action() }
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment