Commit aa4eb488 authored by wanglei's avatar wanglei

重复图片数据比对和UI展示

parent edd06204
...@@ -8,7 +8,6 @@ import android.net.Uri ...@@ -8,7 +8,6 @@ import android.net.Uri
* 重复图片数据 * 重复图片数据
*/ */
data class DupImageData( data class DupImageData(
val name: String = "Image", val dupList: List<MediaDataC>,
val path: String = "", var select: Boolean = false,
val Uri: Uri = android.net.Uri.EMPTY,
) )
\ No newline at end of file
package com.zxhy.hfilemanagermaster.duplicate package com.zxhy.hfilemanagermaster.duplicate
import android.annotation.SuppressLint
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.example.hfilemanagermaster.R
import com.example.hfilemanagermaster.databinding.ItemDupImageSelectBinding
import com.example.hfilemanagermaster.databinding.ItemImageSelect2Binding
import com.zxhy.hfilemanagermaster.data.DupImageData
import com.zxhy.hfilemanagermaster.data.MediaDataC
import com.zxhy.hfilemanagermaster.glide.loadIntoImageView
import com.zxhy.hfilemanagermaster.knife.inflate
class DupImageAdapter : RecyclerView.Adapter<DupImageAdapter.DupImageVideHolder>() { class DupImageAdapter : RecyclerView.Adapter<DupImageAdapter.DupImageVideHolder>() {
class DupImageVideHolder(view: View) : RecyclerView.ViewHolder(view) {}
private val dupImageList = arrayListOf<DupImageData>()
class DupImageVideHolder(view: View) : RecyclerView.ViewHolder(view) {
val binding = ItemDupImageSelectBinding.bind(view)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DupImageVideHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DupImageVideHolder {
TODO("Not yet implemented") val root = R.layout.item_dup_image_select.inflate(parent)
return DupImageVideHolder(root)
} }
override fun getItemCount(): Int { override fun getItemCount(): Int {
TODO("Not yet implemented") return dupImageList.size
} }
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: DupImageVideHolder, position: Int) { override fun onBindViewHolder(holder: DupImageVideHolder, position: Int) {
TODO("Not yet implemented") val context = holder.binding.root.context
val data = dupImageList[position]
holder.binding.apply {
ivSelector.isSelected = data.select
tvNum.text = "${data.dupList.size} items"
val adapter = DupImageItemAdapter()
rvDup.adapter = adapter
adapter.setData(data.dupList)
}
}
@SuppressLint("NotifyDataSetChanged")
fun setData(data: List<DupImageData>) {
dupImageList.clear()
dupImageList.addAll(data)
notifyDataSetChanged()
}
}
private class DupImageItemAdapter :
RecyclerView.Adapter<DupImageItemAdapter.DupImageItemViewHolder>() {
private val mediaList = arrayListOf<MediaDataC>()
class DupImageItemViewHolder(view: View) : ViewHolder(view) {
val binding = ItemImageSelect2Binding.bind(view)
} }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DupImageItemViewHolder {
val root = R.layout.item_image_select_2.inflate(parent)
return DupImageItemViewHolder(root)
}
override fun getItemCount(): Int {
return mediaList.size
}
override fun onBindViewHolder(holder: DupImageItemViewHolder, position: Int) {
val context = holder.binding.root.context
val data = mediaList[position]
holder.binding.apply {
loadIntoImageView(context, data.uri, ivImage)
ivSelector.isSelected = data.select
}
}
@SuppressLint("NotifyDataSetChanged")
fun setData(data: List<MediaDataC>) {
mediaList.clear()
mediaList.addAll(data)
notifyDataSetChanged()
}
} }
\ No newline at end of file
...@@ -9,12 +9,15 @@ import androidx.core.view.WindowInsetsCompat ...@@ -9,12 +9,15 @@ import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.example.hfilemanagermaster.R import com.example.hfilemanagermaster.R
import com.example.hfilemanagermaster.databinding.ActivityDupPictureBinding import com.example.hfilemanagermaster.databinding.ActivityDupPictureBinding
import com.zxhy.hfilemanagermaster.data.DupImageData
import com.zxhy.hfilemanagermaster.knife.dupImage import com.zxhy.hfilemanagermaster.knife.dupImage
import com.zxhy.hfilemanagermaster.knife.getDupImageList
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class DupPictureActivity : AppCompatActivity() { class DupPictureActivity : AppCompatActivity() {
private lateinit var binding: ActivityDupPictureBinding private lateinit var binding: ActivityDupPictureBinding
private lateinit var adapter: DupImageAdapter
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
enableEdgeToEdge() enableEdgeToEdge()
...@@ -30,12 +33,24 @@ class DupPictureActivity : AppCompatActivity() { ...@@ -30,12 +33,24 @@ class DupPictureActivity : AppCompatActivity() {
finish() finish()
} }
binding.tvDelete.setOnClickListener { binding.tvDelete.setOnClickListener {
lifecycleScope.launch(Dispatchers.IO) {
val list = dupImage()
println(list)
lifecycleScope.launch(Dispatchers.Main) {
} }
adapter = DupImageAdapter()
binding.rv.adapter = adapter
loadData()
}
private fun loadData() {
lifecycleScope.launch(Dispatchers.IO) {
val list = dupImage()
val dupDataList = arrayListOf<DupImageData>()
val dupList = getDupImageList(list)
dupList.forEach {
dupDataList.add(DupImageData(dupList = it))
}
lifecycleScope.launch(Dispatchers.Main) {
adapter.setData(dupDataList)
} }
} }
} }
......
...@@ -8,6 +8,7 @@ import android.view.ViewGroup ...@@ -8,6 +8,7 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.example.hfilemanagermaster.R import com.example.hfilemanagermaster.R
import com.example.hfilemanagermaster.databinding.ItemImageBinding import com.example.hfilemanagermaster.databinding.ItemImageBinding
import com.zxhy.hfilemanagermaster.knife.inflate
class ImageAdapter : RecyclerView.Adapter<ImageAdapter.ImageViewHolder>() { class ImageAdapter : RecyclerView.Adapter<ImageAdapter.ImageViewHolder>() {
...@@ -32,15 +33,7 @@ class ImageAdapter : RecyclerView.Adapter<ImageAdapter.ImageViewHolder>() { ...@@ -32,15 +33,7 @@ class ImageAdapter : RecyclerView.Adapter<ImageAdapter.ImageViewHolder>() {
holder.binding.iv.setImageURI(data) holder.binding.iv.setImageURI(data)
} }
/**
* 解析xml布局
*
* @param parent 父布局
* @param attachToRoot 是否依附到父布局
*/
fun Int.inflate(parent: ViewGroup, attachToRoot: Boolean = false): View {
return LayoutInflater.from(parent.context).inflate(this, parent, attachToRoot)
}
@SuppressLint("NotifyDataSetChanged") @SuppressLint("NotifyDataSetChanged")
fun setData(data: List<Uri>) { fun setData(data: List<Uri>) {
......
...@@ -7,6 +7,8 @@ import android.database.Cursor ...@@ -7,6 +7,8 @@ import android.database.Cursor
import android.provider.MediaStore import android.provider.MediaStore
import com.zxhy.hfilemanagermaster.data.MediaDataC import com.zxhy.hfilemanagermaster.data.MediaDataC
import java.io.File import java.io.File
import java.text.SimpleDateFormat
import java.util.Locale
fun Context.dupImage(): ArrayList<MediaDataC> { fun Context.dupImage(): ArrayList<MediaDataC> {
val list = arrayListOf<MediaDataC>() val list = arrayListOf<MediaDataC>()
...@@ -14,10 +16,13 @@ fun Context.dupImage(): ArrayList<MediaDataC> { ...@@ -14,10 +16,13 @@ fun Context.dupImage(): ArrayList<MediaDataC> {
// 查询照片的Uri和字段 // 查询照片的Uri和字段
val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
val projection = arrayOf(MediaStore.Images.Media._ID, MediaStore.Images.Media.DISPLAY_NAME) val projection = arrayOf(MediaStore.Images.Media._ID, MediaStore.Images.Media.DISPLAY_NAME)
//DESC 降列
//ASC 升序
val sortOrder = MediaStore.Images.ImageColumns._ID + " DESC"
try { try {
// 执行查询 // 执行查询
val contentResolver: ContentResolver = contentResolver val contentResolver: ContentResolver = contentResolver
cursor = contentResolver.query(uri, projection, null, null, null) cursor = contentResolver.query(uri, projection, null, null, sortOrder)
// 遍历结果 // 遍历结果
if (cursor != null && cursor.moveToFirst()) { if (cursor != null && cursor.moveToFirst()) {
...@@ -31,11 +36,13 @@ fun Context.dupImage(): ArrayList<MediaDataC> { ...@@ -31,11 +36,13 @@ fun Context.dupImage(): ArrayList<MediaDataC> {
val photoUri = ContentUris.withAppendedId(uri, id) val photoUri = ContentUris.withAppendedId(uri, id)
val filePath = getFilePathByUri(this, photoUri) ?: "" val filePath = getFilePathByUri(this, photoUri) ?: ""
val md5 = File(filePath).digestMd5().byteArrayToHexString() val md5 = File(filePath).digestMd5().byteArrayToHexString()
val time = File(filePath).lastModified()
val timeE = SimpleDateFormat("MMM dd, yyyy", Locale.ENGLISH).format(time)
// println(photoUri) // println(photoUri)
list.add(MediaDataC(uri = photoUri, path = filePath, md5 = md5)) list.add(MediaDataC(uri = photoUri, path = filePath, time = timeE, md5 = md5))
// 在此处进行照片的操作,例如显示、复制、删除等 // 在此处进行照片的操作,例如显示、复制、删除等
// ... // ...
// if (list.size == 10) { // if (list.size == 30) {
// break // break
// } // }
} while (cursor.moveToNext()) } while (cursor.moveToNext())
...@@ -48,4 +55,20 @@ fun Context.dupImage(): ArrayList<MediaDataC> { ...@@ -48,4 +55,20 @@ fun Context.dupImage(): ArrayList<MediaDataC> {
cursor?.close() cursor?.close()
} }
return list return list
}
//获取重复图片
fun getDupImageList(list: List<MediaDataC>): List<List<MediaDataC>> {
val dupList = arrayListOf<List<MediaDataC>>()
val origList = list.toMutableList()
list.forEach { data ->
val dup = origList.filter { it.md5 == data.md5 }
if (dup.size > 1) {
dupList.add(dup)
origList.removeAll(dup)
}
}
return dupList
} }
\ No newline at end of file
package com.zxhy.hfilemanagermaster.knife
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
/**
* 解析xml布局
*
* @param parent 父布局
* @param attachToRoot 是否依附到父布局
*/
fun Int.inflate(parent: ViewGroup, attachToRoot: Boolean = false): View {
return LayoutInflater.from(parent.context).inflate(this, parent, attachToRoot)
}
...@@ -9,6 +9,7 @@ import com.example.hfilemanagermaster.R ...@@ -9,6 +9,7 @@ import com.example.hfilemanagermaster.R
import com.example.hfilemanagermaster.databinding.ItemMediaSelectBinding import com.example.hfilemanagermaster.databinding.ItemMediaSelectBinding
import com.zxhy.hfilemanagermaster.data.MediaDataC import com.zxhy.hfilemanagermaster.data.MediaDataC
import com.zxhy.hfilemanagermaster.glide.loadIntoImageView import com.zxhy.hfilemanagermaster.glide.loadIntoImageView
import com.zxhy.hfilemanagermaster.knife.inflate
class LagerFileSelectorAdapter( class LagerFileSelectorAdapter(
private val selectAction: ((flag: Boolean) -> Unit)? = null private val selectAction: ((flag: Boolean) -> Unit)? = null
...@@ -90,15 +91,6 @@ class LagerFileSelectorAdapter( ...@@ -90,15 +91,6 @@ class LagerFileSelectorAdapter(
notifyDataSetChanged() notifyDataSetChanged()
} }
/**
* 解析xml布局
*
* @param parent 父布局
* @param attachToRoot 是否依附到父布局
*/
fun Int.inflate(parent: ViewGroup, attachToRoot: Boolean = false): View {
return LayoutInflater.from(parent.context).inflate(this, parent, attachToRoot)
}
@SuppressLint("NotifyDataSetChanged") @SuppressLint("NotifyDataSetChanged")
fun setToggleSelect(): Boolean { fun setToggleSelect(): Boolean {
......
...@@ -9,6 +9,7 @@ import com.example.hfilemanagermaster.R ...@@ -9,6 +9,7 @@ import com.example.hfilemanagermaster.R
import com.example.hfilemanagermaster.databinding.ItemImageSelectBinding import com.example.hfilemanagermaster.databinding.ItemImageSelectBinding
import com.zxhy.hfilemanagermaster.data.MediaDataC import com.zxhy.hfilemanagermaster.data.MediaDataC
import com.zxhy.hfilemanagermaster.glide.loadIntoImageView import com.zxhy.hfilemanagermaster.glide.loadIntoImageView
import com.zxhy.hfilemanagermaster.knife.inflate
class LargeImageSelectorAdapter( class LargeImageSelectorAdapter(
private val selectAction: ((flag: Boolean) -> Unit)? = null private val selectAction: ((flag: Boolean) -> Unit)? = null
...@@ -75,15 +76,6 @@ class LargeImageSelectorAdapter( ...@@ -75,15 +76,6 @@ class LargeImageSelectorAdapter(
} }
} }
/**
* 解析xml布局
*
* @param parent 父布局
* @param attachToRoot 是否依附到父布局
*/
fun Int.inflate(parent: ViewGroup, attachToRoot: Boolean = false): View {
return LayoutInflater.from(parent.context).inflate(this, parent, attachToRoot)
}
@SuppressLint("NotifyDataSetChanged") @SuppressLint("NotifyDataSetChanged")
fun setData(data: List<MediaDataC>) { fun setData(data: List<MediaDataC>) {
......
...@@ -9,6 +9,7 @@ import com.example.hfilemanagermaster.R ...@@ -9,6 +9,7 @@ import com.example.hfilemanagermaster.R
import com.example.hfilemanagermaster.databinding.ItemVideoSelectBinding import com.example.hfilemanagermaster.databinding.ItemVideoSelectBinding
import com.zxhy.hfilemanagermaster.data.MediaDataC import com.zxhy.hfilemanagermaster.data.MediaDataC
import com.zxhy.hfilemanagermaster.glide.loadIntoImageView import com.zxhy.hfilemanagermaster.glide.loadIntoImageView
import com.zxhy.hfilemanagermaster.knife.inflate
class LargeVideoSelectorAdapter( class LargeVideoSelectorAdapter(
private val selectAction: ((flag: Boolean) -> Unit)? = null private val selectAction: ((flag: Boolean) -> Unit)? = null
...@@ -71,15 +72,6 @@ class LargeVideoSelectorAdapter( ...@@ -71,15 +72,6 @@ class LargeVideoSelectorAdapter(
} }
/**
* 解析xml布局
*
* @param parent 父布局
* @param attachToRoot 是否依附到父布局
*/
fun Int.inflate(parent: ViewGroup, attachToRoot: Boolean = false): View {
return LayoutInflater.from(parent.context).inflate(this, parent, attachToRoot)
}
@SuppressLint("NotifyDataSetChanged") @SuppressLint("NotifyDataSetChanged")
fun setData(data: List<MediaDataC>) { fun setData(data: List<MediaDataC>) {
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded" /> tools:ignore="ContentDescription,RtlHardcoded" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
...@@ -60,14 +60,16 @@ ...@@ -60,14 +60,16 @@
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toLeftOf="@id/tv_all" app:layout_constraintRight_toLeftOf="@id/tv_all"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded" /> tools:ignore="ContentDescription,RtlHardcoded" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv" android:id="@+id/rv"
tools:listitem="@layout/item_dup_image_select"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:layout_marginHorizontal="20dp" android:layout_marginHorizontal="20dp"
android:layout_marginVertical="16dp" android:layout_marginVertical="16dp"
app:layout_constraintBottom_toTopOf="@id/tv_delete" app:layout_constraintBottom_toTopOf="@id/tv_delete"
......
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView 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="115dp"
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="12dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_num"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="12dp"
android:layout_marginTop="8dp"
android:text="2 items"
android:textColor="#333333"
android:textSize="15sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText,RtlHardcoded" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_dup"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="2dp"
android:orientation="horizontal"
android:paddingHorizontal="6dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_num"
tools:listitem="@layout/item_image_select_2" />
<ImageView
android:id="@+id/iv_selector"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_margin="8dp"
android:src="@drawable/bg_media_selector"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView 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="70dp"
android:layout_height="70dp"
android:layout_margin="6dp"
app:cardCornerRadius="8dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:ignore="ContentDescription" />
<ImageView
android:src="@drawable/bg_circle_selector_c2f300"
android:id="@+id/iv_selector"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_marginHorizontal="2dp"
android:layout_marginVertical="2dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
tools:ignore="ContentDescription" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
\ 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