Commit edd06204 authored by wanglei's avatar wanglei

图片获取md5计算重复

parent 4ffd508f
package com.zxhy.hfilemanagermaster.data
import android.net.Uri
/**
* 重复图片数据
*/
data class DupImageData(
val name: String = "Image",
val path: String = "",
val Uri: Uri = android.net.Uri.EMPTY,
)
\ No newline at end of file
...@@ -12,5 +12,6 @@ data class MediaDataC( ...@@ -12,5 +12,6 @@ data class MediaDataC(
val type: Int = MediaDataC_TYPE_IMAGE, val type: Int = MediaDataC_TYPE_IMAGE,
val uri: Uri = Uri.EMPTY, val uri: Uri = Uri.EMPTY,
val path: String = "", val path: String = "",
val md5: String = "",
var select: Boolean = false, var select: Boolean = false,
) )
package com.zxhy.hfilemanagermaster.duplicate
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
class DupImageAdapter : RecyclerView.Adapter<DupImageAdapter.DupImageVideHolder>() {
class DupImageVideHolder(view: View) : RecyclerView.ViewHolder(view) {}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DupImageVideHolder {
TODO("Not yet implemented")
}
override fun getItemCount(): Int {
TODO("Not yet implemented")
}
override fun onBindViewHolder(holder: DupImageVideHolder, position: Int) {
TODO("Not yet implemented")
}
}
\ No newline at end of file
...@@ -6,8 +6,12 @@ import androidx.appcompat.app.AppCompatActivity ...@@ -6,8 +6,12 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
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.knife.dupImage
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class DupPictureActivity : AppCompatActivity() { class DupPictureActivity : AppCompatActivity() {
private lateinit var binding: ActivityDupPictureBinding private lateinit var binding: ActivityDupPictureBinding
...@@ -25,5 +29,14 @@ class DupPictureActivity : AppCompatActivity() { ...@@ -25,5 +29,14 @@ class DupPictureActivity : AppCompatActivity() {
binding.ivArrow.setOnClickListener { binding.ivArrow.setOnClickListener {
finish() finish()
} }
binding.tvDelete.setOnClickListener {
lifecycleScope.launch(Dispatchers.IO) {
val list = dupImage()
println(list)
lifecycleScope.launch(Dispatchers.Main) {
}
}
}
} }
} }
\ No newline at end of file
...@@ -15,5 +15,6 @@ fun loadIntoImageView(context: Context, uri: String, imageView: ImageView) { ...@@ -15,5 +15,6 @@ fun loadIntoImageView(context: Context, uri: String, imageView: ImageView) {
fun loadIntoImageView(context: Context, uri: Uri, imageView: ImageView) { fun loadIntoImageView(context: Context, uri: Uri, imageView: ImageView) {
Glide.with(context) Glide.with(context)
.load(uri) .load(uri)
.centerCrop()
.into(imageView) .into(imageView)
} }
\ No newline at end of file
package com.zxhy.hfilemanagermaster.knife
import android.content.ContentResolver
import android.content.ContentUris
import android.content.Context
import android.database.Cursor
import android.provider.MediaStore
import com.zxhy.hfilemanagermaster.data.MediaDataC
import java.io.File
fun Context.dupImage(): ArrayList<MediaDataC> {
val list = arrayListOf<MediaDataC>()
var cursor: Cursor? = null
// 查询照片的Uri和字段
val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
val projection = arrayOf(MediaStore.Images.Media._ID, MediaStore.Images.Media.DISPLAY_NAME)
try {
// 执行查询
val contentResolver: ContentResolver = contentResolver
cursor = contentResolver.query(uri, projection, null, null, null)
// 遍历结果
if (cursor != null && cursor.moveToFirst()) {
do {
// 获取照片的ID和名称
val id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID))
val name =
cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME))
// 根据ID构建照片的Uri
val photoUri = ContentUris.withAppendedId(uri, id)
val filePath = getFilePathByUri(this, photoUri) ?: ""
val md5 = File(filePath).digestMd5().byteArrayToHexString()
// println(photoUri)
list.add(MediaDataC(uri = photoUri, path = filePath, md5 = md5))
// 在此处进行照片的操作,例如显示、复制、删除等
// ...
// if (list.size == 10) {
// break
// }
} while (cursor.moveToNext())
} else {
println("无数据")
}
} catch (e: Exception) {
e.printStackTrace()
} finally {
cursor?.close()
}
return list
}
\ No newline at end of file
package com.zxhy.hfilemanagermaster.knife
import java.io.File
import java.nio.channels.FileChannel
import java.security.MessageDigest
//生成、查看文件的MD5、SHA1、SHA2、SHA3值
//https://blog.csdn.net/COCO56/article/details/106161207
//根据加密类型获取具体的值
fun File.digestMd5(): ByteArray {
val byteBuffer = inputStream().channel.map(FileChannel.MapMode.READ_ONLY, 0, length())
val digest = MessageDigest.getInstance("MD5")
digest.update(byteBuffer)
return digest.digest()
}
private const val HEXES = "0123456789ABCDEF"
/**
* ByteArray转Hex码
*/
fun ByteArray.byteArrayToHexString(): String {
val hex = StringBuilder(2 * this.size)
for (element in this) {
val high = element.toInt().and(0xFF).shr(4)
val low = element.toInt().and(0x0F)
hex.append(HEXES[high]).append(HEXES[low])
}
return hex.toString()
}
...@@ -60,6 +60,47 @@ fun Context.testPhoto(): ArrayList<Uri> { ...@@ -60,6 +60,47 @@ fun Context.testPhoto(): ArrayList<Uri> {
return list return list
} }
fun Context.largePhoto(): ArrayList<MediaDataC> {
val list = arrayListOf<MediaDataC>()
var cursor: Cursor? = null
// 查询照片的Uri和字段
val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
val projection = arrayOf(MediaStore.Images.Media._ID, MediaStore.Images.Media.DISPLAY_NAME)
try {
// 执行查询
val contentResolver: ContentResolver = contentResolver
cursor = contentResolver.query(uri, projection, null, null, null)
// 遍历结果
if (cursor != null && cursor.moveToFirst()) {
do {
// 获取照片的ID和名称
val id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID))
val name =
cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME))
// 根据ID构建照片的Uri
val photoUri = ContentUris.withAppendedId(uri, id)
// println(photoUri)
list.add(MediaDataC(uri = photoUri))
// 在此处进行照片的操作,例如显示、复制、删除等
// ...
if (list.size == 10) {
break
}
} while (cursor.moveToNext())
} else {
println("无数据")
}
} catch (e: Exception) {
e.printStackTrace()
} finally {
cursor?.close()
}
return list
}
@SuppressLint("SimpleDateFormat") @SuppressLint("SimpleDateFormat")
fun Context.largeVideo(): ArrayList<MediaDataC> { fun Context.largeVideo(): ArrayList<MediaDataC> {
val list = arrayListOf<MediaDataC>() val list = arrayListOf<MediaDataC>()
......
...@@ -10,9 +10,9 @@ import com.example.hfilemanagermaster.databinding.ItemMediaSelectBinding ...@@ -10,9 +10,9 @@ 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
class MediaSelectAdapter( class LagerFileSelectorAdapter(
val selectAction: ((flag: Boolean) -> Unit)? = null private val selectAction: ((flag: Boolean) -> Unit)? = null
) : RecyclerView.Adapter<MediaSelectAdapter.MediaSelectViewHolder>() { ) : RecyclerView.Adapter<LagerFileSelectorAdapter.MediaSelectViewHolder>() {
private val mediaList = arrayListOf<MediaDataC>() private val mediaList = arrayListOf<MediaDataC>()
class MediaSelectViewHolder(view: View) : RecyclerView.ViewHolder(view) { class MediaSelectViewHolder(view: View) : RecyclerView.ViewHolder(view) {
...@@ -57,7 +57,7 @@ class MediaSelectAdapter( ...@@ -57,7 +57,7 @@ class MediaSelectAdapter(
val data = mediaList[position] val data = mediaList[position]
//判断是做局部刷新还是单条刷新 //判断是做局部刷新还是单条刷新
if (payloads.isEmpty()) { if (payloads.isEmpty()) {//局部刷新
holder.binding.apply { holder.binding.apply {
loadIntoImageView(context, data.uri, iv) loadIntoImageView(context, data.uri, iv)
...@@ -108,4 +108,8 @@ class MediaSelectAdapter( ...@@ -108,4 +108,8 @@ class MediaSelectAdapter(
return !flag return !flag
} }
fun getSelectSize(): Int {
return mediaList.count { it.select }
}
} }
\ No newline at end of file
...@@ -7,15 +7,22 @@ import androidx.core.content.ContextCompat ...@@ -7,15 +7,22 @@ import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.hfilemanagermaster.R import com.example.hfilemanagermaster.R
import com.example.hfilemanagermaster.databinding.ActivityLargeFileBinding import com.example.hfilemanagermaster.databinding.ActivityLargeFileBinding
import com.zxhy.hfilemanagermaster.knife.largePhoto
import com.zxhy.hfilemanagermaster.knife.largeVideo import com.zxhy.hfilemanagermaster.knife.largeVideo
import com.zxhy.hfilemanagermaster.permission.alert
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class LargeFileActivity : AppCompatActivity() { class LargeFileActivity : AppCompatActivity() {
private lateinit var binding: ActivityLargeFileBinding private lateinit var binding: ActivityLargeFileBinding
private lateinit var mediaSelectAdapter: MediaSelectAdapter private lateinit var mediaSelectAdapter: LagerFileSelectorAdapter
private lateinit var imageSelectorAdapter: LargeImageSelectorAdapter
private lateinit var videoSelectorAdapter: LargeVideoSelectorAdapter
private var currentMode = 0//0 文件 1图片 2视频
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
...@@ -31,20 +38,63 @@ class LargeFileActivity : AppCompatActivity() { ...@@ -31,20 +38,63 @@ class LargeFileActivity : AppCompatActivity() {
binding.ivArrow.setOnClickListener { binding.ivArrow.setOnClickListener {
finish() finish()
} }
mediaSelectAdapter = MediaSelectAdapter {
binding.ivAll.isSelected = it
}
binding.rv.adapter = mediaSelectAdapter
binding.tvDelete.setOnClickListener { binding.tvDelete.setOnClickListener {
val num = when (currentMode) {
0 -> mediaSelectAdapter.getSelectSize()
1 -> imageSelectorAdapter.getSelectSize()
2 -> videoSelectorAdapter.getSelectSize()
else -> 0
}
this.alert("当前选中${num}项,是否确认删除", "删除确认") {
positiveButton("确定") { dialog ->
dialog.dismiss()
}
negativeButton("取消") { dialog ->
dialog.dismiss()
}
//禁止取消
isCancel(false)
}
} }
binding.ivAll.setOnClickListener { view -> binding.ivAll.setOnClickListener { view ->
view.isSelected = mediaSelectAdapter.setToggleSelect() when (currentMode) {
0 -> view.isSelected = mediaSelectAdapter.setToggleSelect()
1 -> view.isSelected = imageSelectorAdapter.setToggleSelect()
2 -> view.isSelected = videoSelectorAdapter.setToggleSelect()
}
} }
loadData() fileMode()
binding.tvFile.setOnClickListener {
fileMode()
}
binding.tvImage.setOnClickListener {
imageMode()
}
binding.tvVideo.setOnClickListener {
videoMode()
} }
}
private fun fileMode() {
currentMode = 0
binding.tvFile.setTextColor(ContextCompat.getColor(this, R.color.color_333333))
binding.tvImage.setTextColor(ContextCompat.getColor(this, R.color.color_999999))
binding.tvVideo.setTextColor(ContextCompat.getColor(this, R.color.color_999999))
private fun loadData() { mediaSelectAdapter = LagerFileSelectorAdapter {
binding.ivAll.isSelected = it
}
binding.rv.layoutManager = LinearLayoutManager(this)
binding.rv.adapter = mediaSelectAdapter
loadLargeFileData()
}
private fun loadLargeFileData() {
lifecycleScope.launch(Dispatchers.IO) { lifecycleScope.launch(Dispatchers.IO) {
val list = this@LargeFileActivity.largeVideo() val list = this@LargeFileActivity.largeVideo()
lifecycleScope.launch(Dispatchers.Main) { lifecycleScope.launch(Dispatchers.Main) {
...@@ -52,4 +102,52 @@ class LargeFileActivity : AppCompatActivity() { ...@@ -52,4 +102,52 @@ class LargeFileActivity : AppCompatActivity() {
} }
} }
} }
private fun imageMode() {
currentMode = 1
binding.tvFile.setTextColor(ContextCompat.getColor(this, R.color.color_999999))
binding.tvImage.setTextColor(ContextCompat.getColor(this, R.color.color_333333))
binding.tvVideo.setTextColor(ContextCompat.getColor(this, R.color.color_999999))
imageSelectorAdapter = LargeImageSelectorAdapter {
binding.ivAll.isSelected = it
}
binding.rv.layoutManager = GridLayoutManager(this, 3)
binding.rv.adapter = imageSelectorAdapter
loadLargeImageData()
}
private fun loadLargeImageData() {
lifecycleScope.launch(Dispatchers.IO) {
val list = this@LargeFileActivity.largePhoto()
lifecycleScope.launch(Dispatchers.Main) {
imageSelectorAdapter.setData(list)
}
}
}
private fun videoMode() {
currentMode = 2
binding.tvFile.setTextColor(ContextCompat.getColor(this, R.color.color_999999))
binding.tvImage.setTextColor(ContextCompat.getColor(this, R.color.color_999999))
binding.tvVideo.setTextColor(ContextCompat.getColor(this, R.color.color_333333))
videoSelectorAdapter = LargeVideoSelectorAdapter {
binding.ivAll.isSelected = it
}
binding.rv.layoutManager = GridLayoutManager(this, 3)
binding.rv.adapter = videoSelectorAdapter
loadLargeVideoData()
}
private fun loadLargeVideoData() {
lifecycleScope.launch(Dispatchers.IO) {
val list = this@LargeFileActivity.largeVideo()
lifecycleScope.launch(Dispatchers.Main) {
videoSelectorAdapter.setData(list)
}
}
}
} }
\ No newline at end of file
package com.zxhy.hfilemanagermaster.largefile
import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.hfilemanagermaster.R
import com.example.hfilemanagermaster.databinding.ItemImageSelectBinding
import com.zxhy.hfilemanagermaster.data.MediaDataC
import com.zxhy.hfilemanagermaster.glide.loadIntoImageView
class LargeImageSelectorAdapter(
private val selectAction: ((flag: Boolean) -> Unit)? = null
) : RecyclerView.Adapter<LargeImageSelectorAdapter.ImageSelectorViewHolder>() {
private val mediaList = arrayListOf<MediaDataC>()
class ImageSelectorViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val binding = ItemImageSelectBinding.bind(view)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ImageSelectorViewHolder {
val root = R.layout.item_image_select.inflate(parent)
return ImageSelectorViewHolder(root)
}
override fun getItemCount(): Int {
return mediaList.size
}
override fun onBindViewHolder(holder: ImageSelectorViewHolder, position: Int) {
val context = holder.binding.root.context
val data = mediaList[position]
holder.binding.apply {
loadIntoImageView(context, data.uri, ivImage)
ivSelector.isSelected = data.select
ivSelector.setOnClickListener {
data.select = !data.select
notifyItemChanged(position, "单条刷新")
}
if (data == mediaList.last()) {
selectAction?.invoke(mediaList.all { it.select })
}
}
}
override fun onBindViewHolder(
holder: ImageSelectorViewHolder,
position: Int,
payloads: MutableList<Any>
) {
val context = holder.binding.root.context
val data = mediaList[position]
//判断是做局部刷新还是单条刷新
if (payloads.isEmpty()) {//局部刷新
holder.binding.apply {
loadIntoImageView(context, data.uri, ivImage)
ivSelector.isSelected = data.select
ivSelector.setOnClickListener {
data.select = !data.select
notifyItemChanged(position, "单条刷新")
}
if (data == mediaList.last()) {
selectAction?.invoke(mediaList.all { it.select })
}
}
} else { // 单条刷新
holder.binding.apply {
ivSelector.isSelected = data.select
}
super.onBindViewHolder(holder, position, payloads)
selectAction?.invoke(mediaList.all { it.select })
}
}
/**
* 解析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")
fun setData(data: List<MediaDataC>) {
mediaList.clear()
mediaList.addAll(data)
notifyDataSetChanged()
}
@SuppressLint("NotifyDataSetChanged")
fun setToggleSelect(): Boolean {
val flag = mediaList.all { it.select }
mediaList.forEach { it.select = !flag }
notifyDataSetChanged()
return !flag
}
fun getSelectSize(): Int {
return mediaList.count { it.select }
}
}
\ No newline at end of file
package com.zxhy.hfilemanagermaster.largefile
import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.hfilemanagermaster.R
import com.example.hfilemanagermaster.databinding.ItemVideoSelectBinding
import com.zxhy.hfilemanagermaster.data.MediaDataC
import com.zxhy.hfilemanagermaster.glide.loadIntoImageView
class LargeVideoSelectorAdapter(
private val selectAction: ((flag: Boolean) -> Unit)? = null
) : RecyclerView.Adapter<LargeVideoSelectorAdapter.VideoSelectorViewHolder>() {
private val mediaList = arrayListOf<MediaDataC>()
class VideoSelectorViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val binding = ItemVideoSelectBinding.bind(view)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VideoSelectorViewHolder {
val root = R.layout.item_video_select.inflate(parent)
return VideoSelectorViewHolder(root)
}
override fun getItemCount(): Int {
return mediaList.size
}
override fun onBindViewHolder(holder: VideoSelectorViewHolder, position: Int) {
val context = holder.binding.root.context
val data = mediaList[position]
holder.binding.apply {
loadIntoImageView(context, data.uri, ivImage)
ivSelector.isSelected = data.select
}
}
override fun onBindViewHolder(
holder: VideoSelectorViewHolder,
position: Int,
payloads: MutableList<Any>
) {
val context = holder.binding.root.context
val data = mediaList[position]
//判断是做局部刷新还是单条刷新
if (payloads.isEmpty()) {//局部刷新
holder.binding.apply {
loadIntoImageView(context, data.uri, ivImage)
ivSelector.isSelected = data.select
ivSelector.setOnClickListener {
data.select = !data.select
notifyItemChanged(position, "单条刷新")
}
if (data == mediaList.last()) {
selectAction?.invoke(mediaList.all { it.select })
}
}
} else {// 单条刷新
holder.binding.apply {
ivSelector.isSelected = data.select
}
super.onBindViewHolder(holder, position, payloads)
selectAction?.invoke(mediaList.all { it.select })
}
}
/**
* 解析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")
fun setData(data: List<MediaDataC>) {
mediaList.clear()
mediaList.addAll(data)
notifyDataSetChanged()
}
@SuppressLint("NotifyDataSetChanged")
fun setToggleSelect(): Boolean {
val flag = mediaList.all { it.select }
mediaList.forEach { it.select = !flag }
notifyDataSetChanged()
return !flag
}
fun getSelectSize(): Int {
return mediaList.count { it.select }
}
}
\ No newline at end of file
...@@ -74,7 +74,7 @@ class ManagerFragment : Fragment() { ...@@ -74,7 +74,7 @@ class ManagerFragment : Fragment() {
binding.ivPdf.setOnClickListener { } binding.ivPdf.setOnClickListener { }
binding.ivPpt.setOnClickListener { } binding.ivPpt.setOnClickListener { }
binding.cardView1.setOnClickListener { binding.cardView1.setOnClickListener {
// findNavController().navigate(R.id.dupPictureActivity) findNavController().navigate(R.id.dupPictureActivity)
} }
binding.cardView2.setOnClickListener { binding.cardView2.setOnClickListener {
......
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/qw_00856" android:state_selected="true" />
<item android:drawable="@mipmap/zsd_0979" android:state_selected="false" />
</selector>
\ No newline at end of file
...@@ -112,7 +112,7 @@ ...@@ -112,7 +112,7 @@
android:id="@+id/rv" android:id="@+id/rv"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_marginHorizontal="12dp" android:layout_marginHorizontal="0dp"
android:layout_marginVertical="16dp" android:layout_marginVertical="16dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
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="100dp"
android:layout_margin="12dp"
android:layout_height="100dp"
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="24dp"
android:layout_height="24dp"
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
<?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="100dp"
android:layout_height="100dp"
android:layout_margin="12dp"
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:id="@+id/iv_play"
android:layout_width="32dp"
android:layout_height="32dp"
android:src="@mipmap/dda_0979"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/iv_selector"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginHorizontal="2dp"
android:layout_marginVertical="2dp"
android:src="@drawable/bg_circle_selector_c2f300"
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
...@@ -5,4 +5,6 @@ ...@@ -5,4 +5,6 @@
<color name="color_B7FF03">#B7FF03</color> <color name="color_B7FF03">#B7FF03</color>
<color name="color_C2F300">#C2F300</color> <color name="color_C2F300">#C2F300</color>
<color name="color_DCFE86">#DCFE86</color> <color name="color_DCFE86">#DCFE86</color>
<color name="color_333333">#333333</color>
<color name="color_999999">#999999</color>
</resources> </resources>
\ 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