11package com.yenaly.han1meviewer.ui.fragment.home
22
33import android.annotation.SuppressLint
4+ import android.app.Dialog
5+ import android.content.ContentValues
6+ import android.content.Context
47import android.content.res.ColorStateList
8+ import android.graphics.Bitmap
59import android.graphics.Color
610import android.graphics.RenderEffect
711import android.graphics.Shader
812import android.graphics.drawable.ColorDrawable
913import android.graphics.drawable.GradientDrawable
1014import android.os.Build
1115import android.os.Bundle
16+ import android.os.Environment
17+ import android.provider.MediaStore
18+ import android.text.Spanned
19+ import android.text.method.LinkMovementMethod
1220import android.util.Log
1321import android.view.LayoutInflater
22+ import android.view.View
1423import android.view.ViewGroup
24+ import android.widget.ImageView
25+ import android.widget.TextView
1526import androidx.activity.OnBackPressedCallback
1627import androidx.annotation.RequiresApi
1728import androidx.appcompat.app.AlertDialog
29+ import androidx.core.graphics.drawable.toBitmap
1830import androidx.core.graphics.drawable.toBitmapOrNull
1931import androidx.core.os.bundleOf
2032import androidx.core.view.ViewCompat
@@ -34,8 +46,12 @@ import androidx.palette.graphics.Palette
3446import androidx.recyclerview.widget.ConcatAdapter
3547import androidx.recyclerview.widget.LinearLayoutManager
3648import androidx.recyclerview.widget.RecyclerView
49+ import coil.ImageLoader
3750import coil.load
51+ import coil.request.ImageRequest
52+ import coil.request.SuccessResult
3853import com.google.android.material.dialog.MaterialAlertDialogBuilder
54+ import com.google.android.material.imageview.ShapeableImageView
3955import com.yenaly.han1meviewer.ADVANCED_SEARCH_MAP
4056import com.yenaly.han1meviewer.HAdvancedSearch
4157import com.yenaly.han1meviewer.R
@@ -61,7 +77,12 @@ import com.yenaly.yenaly_libs.utils.application
6177import com.yenaly.yenaly_libs.utils.getSpValue
6278import com.yenaly.yenaly_libs.utils.putSpValue
6379import com.yenaly.yenaly_libs.utils.showShortToast
80+ import kotlinx.coroutines.CoroutineScope
81+ import kotlinx.coroutines.Dispatchers
6482import kotlinx.coroutines.launch
83+ import kotlinx.coroutines.withContext
84+ import java.io.File
85+ import java.io.FileOutputStream
6586import java.io.Serializable
6687
6788/* *
@@ -680,8 +701,17 @@ class HomePageFragment : YenalyFragment<FragmentHomePageBinding>(),
680701 }
681702 announcementCardAdapter = AnnouncementCardAdapter (
682703 sortedList,
683- onClick = {
684- showShortToast(" 点击事件正在绝赞制作中!" )
704+ onClick = { item ->
705+ showAnnouncementDialog(
706+ requireContext(),
707+ title = item.title,
708+ content = item.getHighlightedContent(),
709+ imageUrl = item.imageUrl,
710+ positiveText = item.positiveText,
711+ positiveAction = { },
712+ negativeText = item.negativeText,
713+ negativeAction = { },
714+ )
685715 },
686716 onClose = {
687717 putSpValue(" last_dismiss_time" , System .currentTimeMillis()," setting_pref" )
@@ -701,4 +731,130 @@ class HomePageFragment : YenalyFragment<FragmentHomePageBinding>(),
701731 }
702732 // viewModel.loadAnnouncements()
703733 }
734+ fun showAnnouncementDialog (
735+ context : Context ,
736+ title : String ,
737+ content : Spanned ,
738+ imageUrl : String? = null,
739+ positiveText : String? = null,
740+ positiveAction : (() -> Unit )? = null,
741+ negativeText : String? = null,
742+ negativeAction : (() -> Unit )? = null
743+ ) {
744+ val dialogView = LayoutInflater .from(context)
745+ .inflate(R .layout.dialog_announcement, null , false )
746+
747+ val tvTitle = dialogView.findViewById<TextView >(R .id.dialogTitle)
748+ val tvContent = dialogView.findViewById<TextView >(R .id.dialogContent)
749+ val ivImage = dialogView.findViewById<ShapeableImageView >(R .id.dialogImage)
750+ val positiveText = positiveText ? : context.getString(R .string.i_understand)
751+
752+ tvTitle.text = title
753+ tvTitle.visibility = View .VISIBLE
754+
755+ tvContent.text = content
756+ tvContent.movementMethod = LinkMovementMethod .getInstance()
757+ tvContent.highlightColor = Color .TRANSPARENT
758+
759+ if (! imageUrl.isNullOrBlank()) {
760+ ivImage.visibility = View .VISIBLE
761+ ivImage.load(imageUrl) {
762+ placeholder(R .drawable.akarin)
763+ error(R .drawable.baseline_error_outline_24)
764+ }
765+ ivImage.setOnClickListener {
766+ val fullScreenDialog = Dialog (requireContext(), android.R .style.Theme_Black_NoTitleBar_Fullscreen )
767+ val fullImageView = ImageView (requireContext()).apply {
768+ layoutParams = ViewGroup .LayoutParams (
769+ ViewGroup .LayoutParams .MATCH_PARENT ,
770+ ViewGroup .LayoutParams .MATCH_PARENT
771+ )
772+ scaleType = ImageView .ScaleType .FIT_CENTER
773+ load(imageUrl)
774+ }
775+
776+ fullScreenDialog.setContentView(fullImageView)
777+
778+ fullImageView.scaleX = 0.8f
779+ fullImageView.scaleY = 0.8f
780+ fullImageView.animate()
781+ .scaleX(1f )
782+ .scaleY(1f )
783+ .setDuration(200 )
784+ .start()
785+
786+ fullImageView.setOnClickListener {
787+ fullImageView.animate()
788+ .scaleX(0.8f )
789+ .scaleY(0.8f )
790+ .setDuration(200 )
791+ .withEndAction { fullScreenDialog.dismiss() }
792+ .start()
793+ }
794+
795+ fullImageView.setOnLongClickListener {
796+ MaterialAlertDialogBuilder (context)
797+ .setTitle(getString(R .string.save_image_confirm))
798+ .setPositiveButton(getString(R .string.sure)) { _, _ ->
799+ saveImageToGallery(imageUrl)
800+ }
801+ .setNegativeButton(getString(R .string.cancel)){ dialog, _ -> dialog.dismiss() }
802+ .create()
803+ .show()
804+ true
805+ }
806+
807+ fullScreenDialog.show()
808+ }
809+ }
810+
811+ val builder = MaterialAlertDialogBuilder (context)
812+ .setView(dialogView)
813+ builder.setPositiveButton(positiveText) { _, _ ->
814+ positiveAction?.invoke()
815+ }
816+
817+ if (! negativeText.isNullOrBlank()) {
818+ builder.setNegativeButton(negativeText) { _, _ ->
819+ negativeAction?.invoke()
820+ }
821+ }
822+
823+ builder.show()
824+ }
825+ private fun saveImageToGallery (imageUrl : String ) {
826+ CoroutineScope (Dispatchers .IO ).launch {
827+ val loader = ImageLoader (requireContext())
828+ val request = ImageRequest .Builder (requireContext())
829+ .data(imageUrl)
830+ .allowHardware(false )
831+ .build()
832+ val result = (loader.execute(request) as ? SuccessResult )?.drawable?.toBitmap()
833+ result?.let { bitmap ->
834+ val filename = " IMG_${System .currentTimeMillis()} .jpg"
835+ val fos = if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .Q ) {
836+ val contentValues = ContentValues ().apply {
837+ put(MediaStore .MediaColumns .DISPLAY_NAME , filename)
838+ put(MediaStore .MediaColumns .MIME_TYPE , " image/jpeg" )
839+ put(MediaStore .MediaColumns .RELATIVE_PATH , Environment .DIRECTORY_PICTURES )
840+ }
841+ val uri = requireContext().contentResolver.insert(
842+ MediaStore .Images .Media .EXTERNAL_CONTENT_URI ,
843+ contentValues
844+ )
845+ uri?.let { requireContext().contentResolver.openOutputStream(it) }
846+ } else {
847+ val file = File (
848+ Environment .getExternalStoragePublicDirectory(Environment .DIRECTORY_PICTURES ),
849+ filename
850+ )
851+ FileOutputStream (file)
852+ }
853+ fos?.use { bitmap.compress(Bitmap .CompressFormat .JPEG , 100 , it) }
854+ withContext(Dispatchers .Main ) {
855+ showShortToast(getString(R .string.saved))
856+ }
857+ }
858+ }
859+ }
704860}
0 commit comments