feat:完成保存图片
This commit is contained in:
4
.idea/deploymentTargetDropDown.xml
generated
4
.idea/deploymentTargetDropDown.xml
generated
@@ -10,12 +10,12 @@
|
||||
<deviceKey>
|
||||
<Key>
|
||||
<type value="VIRTUAL_DEVICE_PATH" />
|
||||
<value value="$USER_HOME$/.android/avd/Card_Pixel_XL_API_27.avd" />
|
||||
<value value="$USER_HOME$/.android/avd/Card_Pixel_3a_XL_API_34.avd" />
|
||||
</Key>
|
||||
</deviceKey>
|
||||
</Target>
|
||||
</targetSelectedWithDropDown>
|
||||
<timeTargetWasSelectedWithDropDown value="2024-03-07T08:47:00.360478Z" />
|
||||
<timeTargetWasSelectedWithDropDown value="2024-03-08T06:17:13.921598Z" />
|
||||
</State>
|
||||
</entry>
|
||||
</value>
|
||||
|
@@ -17,12 +17,33 @@ android {
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
signingConfigs {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
storeFile file('../card.jks')
|
||||
storePassword "card2024"
|
||||
keyAlias "card"
|
||||
keyPassword "card2024"
|
||||
v2SigningEnabled true
|
||||
v1SigningEnabled true
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled true
|
||||
shrinkResources true // 开了混淆的时候才能开启 是否去除无效的资源文件
|
||||
zipAlignEnabled true // 开了混淆的时候才能开启 是否进行压缩并重排列
|
||||
crunchPngs true // 启用 PNG 压缩
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
debug{
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
@@ -33,6 +54,23 @@ android {
|
||||
buildFeatures {
|
||||
viewBinding = true
|
||||
}
|
||||
|
||||
android.applicationVariants.configureEach { variant ->
|
||||
variant.outputs.configureEach { output ->
|
||||
def date = new Date().format("MMddHHmm", TimeZone.getTimeZone("GMT+08"))
|
||||
|
||||
def outputFile = output.outputFile
|
||||
if (outputFile == null || !outputFile.name.endsWith('.apk')) {
|
||||
return
|
||||
}
|
||||
|
||||
def abi = output.getFilter(com.android.build.OutputFile.ABI)
|
||||
if (abi == null) {
|
||||
abi = "universal"
|
||||
}
|
||||
outputFileName = "card_${buildType.name}_v${defaultConfig.versionName}_${defaultConfig.versionCode}_${abi}_${date}.apk"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
@@ -2,10 +2,7 @@ package com.heeeeka.card.support
|
||||
|
||||
import android.animation.Animator
|
||||
|
||||
/**
|
||||
* Created by Max on 2024/3/6 11:43
|
||||
* Desc:
|
||||
**/
|
||||
|
||||
interface DefAnimListener : Animator.AnimatorListener {
|
||||
override fun onAnimationStart(animation: Animator) {
|
||||
}
|
||||
|
@@ -12,10 +12,6 @@ import com.heeeeka.card.R
|
||||
import com.heeeeka.card.databinding.CardBgDialogBinding
|
||||
import com.heeeeka.card.utils.ILog
|
||||
|
||||
/**
|
||||
* Created by Max on 2024/3/6 14:14
|
||||
* Desc:
|
||||
**/
|
||||
class CardBgDialog(
|
||||
context: Context,
|
||||
private val lifecycle: Lifecycle,
|
||||
|
@@ -6,9 +6,9 @@ import android.graphics.Bitmap
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.ViewGroup
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.view.drawToBitmap
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleEventObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
@@ -20,16 +20,24 @@ import com.heeeeka.card.support.CardEngine
|
||||
import com.heeeeka.card.utils.ILog
|
||||
import com.heeeeka.card.utils.UiUtils
|
||||
import com.heeeeka.card.utils.roundCorner
|
||||
import com.heeeeka.card.utils.saveToAlbum
|
||||
import com.heeeeka.card.utils.toast
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class CardDisplayDialog(
|
||||
private val activity: FragmentActivity,
|
||||
private val activity: ComponentActivity,
|
||||
private val cardInfo: CardInfo,
|
||||
private val launcherCompat: ActivityResultLauncherCompat<Array<String>, Map<String, Boolean>>
|
||||
) : Dialog(activity, R.style.base_dialog), LifecycleEventObserver, ILog {
|
||||
|
||||
private var binding: CardDisplayDialogBinding? = null
|
||||
private var cardEngine: CardEngine? = null
|
||||
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -42,7 +50,6 @@ class CardDisplayDialog(
|
||||
binding.layoutCard.roundCorner(UiUtils.dip2px(context, 12f))
|
||||
(binding.layoutCard.layoutParams as? ConstraintLayout.LayoutParams)?.let {
|
||||
it.dimensionRatio = "${cardInfo.width}:${cardInfo.height}"
|
||||
logD("dimensionRatio:${it.dimensionRatio}")
|
||||
binding.layoutCard.layoutParams = it
|
||||
}
|
||||
binding.layoutCard.post {
|
||||
@@ -86,13 +93,28 @@ class CardDisplayDialog(
|
||||
}
|
||||
|
||||
private fun saveImageImpl(bitmap: Bitmap) {
|
||||
logD("saveImageImpl thread:${Thread.currentThread().name}")
|
||||
logD("MAAAX", "saveImageImpl end")
|
||||
binding?.tvSave?.isEnabled = false
|
||||
binding?.progressbar?.animate()?.alpha(1f)?.start()
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val fileName = "card_${System.currentTimeMillis()}.jpg"
|
||||
bitmap.saveToAlbum(
|
||||
context = context,
|
||||
fileName = fileName,
|
||||
relativePath = null,
|
||||
quality = 100
|
||||
)
|
||||
withContext(Dispatchers.Main) {
|
||||
binding?.progressbar?.animate()?.alpha(0f)?.start()
|
||||
context.toast(R.string.save_successfully)
|
||||
binding?.tvSave?.isEnabled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun dismiss() {
|
||||
super.dismiss()
|
||||
activity.lifecycle.removeObserver(this)
|
||||
scope.cancel()
|
||||
}
|
||||
|
||||
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
|
||||
|
@@ -2,10 +2,7 @@ package com.heeeeka.card.utils
|
||||
|
||||
import android.util.Log
|
||||
|
||||
/**
|
||||
* Created by Max on 2024/3/6 15:43
|
||||
* Desc:
|
||||
**/
|
||||
|
||||
interface ILog {
|
||||
fun logD(message: String) {
|
||||
Log.d(getLogTag(), message)
|
||||
|
@@ -5,7 +5,7 @@ import android.widget.Toast
|
||||
|
||||
|
||||
fun Context.toast(message: Int, isLong: Boolean = false) {
|
||||
toast(getString(message))
|
||||
toast(getString(message), isLong)
|
||||
}
|
||||
|
||||
fun Context.toast(message: CharSequence, isLong: Boolean = false) {
|
||||
|
@@ -27,13 +27,15 @@
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/layout_card"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginHorizontal="28dp"
|
||||
android:layout_marginTop="12dp"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="0dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_title"
|
||||
app:layout_constraintWidth_percent="0.81"
|
||||
tools:layout_constraintDimensionRatio="750:1624">
|
||||
|
||||
<ImageView
|
||||
@@ -80,15 +82,31 @@
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintDimensionRatio="110:44"
|
||||
app:layout_constraintEnd_toStartOf="@id/tv_cancel"
|
||||
app:layout_constraintStart_toStartOf="@id/layout_card"
|
||||
app:layout_constraintTop_toBottomOf="@id/layout_card" />
|
||||
app:layout_constraintTop_toBottomOf="@id/layout_card"
|
||||
app:layout_constraintWidth_percent="0.372" />
|
||||
|
||||
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||
android:id="@+id/progressbar"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_gravity="center"
|
||||
android:alpha="0"
|
||||
android:indeterminate="true"
|
||||
app:indicatorColor="#9E3A30"
|
||||
app:layout_constraintBottom_toBottomOf="@id/tv_save"
|
||||
app:layout_constraintDimensionRatio="1:1"
|
||||
app:layout_constraintEnd_toEndOf="@id/tv_save"
|
||||
app:layout_constraintStart_toStartOf="@id/tv_save"
|
||||
app:layout_constraintTop_toTopOf="@id/tv_save"
|
||||
app:layout_constraintWidth_percent="0.1"
|
||||
tools:alpha="1"
|
||||
tools:trackColor="#00FFFF" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_cancel"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="19dp"
|
||||
android:background="@drawable/shape_e5e3e0_8dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/cancel"
|
||||
@@ -96,8 +114,8 @@
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintDimensionRatio="110:44"
|
||||
app:layout_constraintEnd_toEndOf="@id/layout_card"
|
||||
app:layout_constraintStart_toEndOf="@id/tv_save"
|
||||
app:layout_constraintTop_toTopOf="@id/tv_save" />
|
||||
app:layout_constraintTop_toTopOf="@id/tv_save"
|
||||
app:layout_constraintWidth_percent="0.372" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</FrameLayout>
|
@@ -11,5 +11,6 @@
|
||||
<string name="save_photo_album">保存相冊</string>
|
||||
<string name="select_firework">選擇煙花類型</string>
|
||||
<string name="card_text_length_tips">祝福語太長</string>
|
||||
<string name="permission_external_storage_denied">存储权限被禁止,为了正常使用该功能,请前往系统设置页手动开启</string>
|
||||
<string name="permission_external_storage_denied">存儲權限被禁止,為了正常使用該功能,請前往系統設置頁手動開啟</string>
|
||||
<string name="save_successfully">保存成功</string>
|
||||
</resources>
|
@@ -14,6 +14,7 @@
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
<item name="colorAccent">#9E3A30</item>
|
||||
</style>
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user