投稿画面で添付メディアを並べ替え
This commit is contained in:
parent
b93d912336
commit
729b10143f
|
@ -22,6 +22,7 @@ import jp.juggler.subwaytooter.actpost.CompletionHelper
|
|||
import jp.juggler.subwaytooter.actpost.FeaturedTagCache
|
||||
import jp.juggler.subwaytooter.actpost.addAttachment
|
||||
import jp.juggler.subwaytooter.actpost.applyMushroomText
|
||||
import jp.juggler.subwaytooter.actpost.rearrangeAttachments
|
||||
import jp.juggler.subwaytooter.actpost.onPickCustomThumbnailImpl
|
||||
import jp.juggler.subwaytooter.actpost.onPostAttachmentCompleteImpl
|
||||
import jp.juggler.subwaytooter.actpost.openAttachment
|
||||
|
@ -314,7 +315,7 @@ class ActPost : AppCompatActivity(),
|
|||
R.id.btnFeaturedTag -> completionHelper.openFeaturedTagList(
|
||||
featuredTagCache[account?.acct?.ascii ?: ""]?.list
|
||||
)
|
||||
|
||||
R.id.btnAttachmentsRearrange -> rearrangeAttachments()
|
||||
R.id.ibSchedule -> performSchedule()
|
||||
R.id.ibScheduleReset -> resetSchedule()
|
||||
}
|
||||
|
@ -445,6 +446,7 @@ class ActPost : AppCompatActivity(),
|
|||
views.btnEmojiPicker,
|
||||
views.btnMore,
|
||||
views.ivAccount,
|
||||
views.btnAttachmentsRearrange,
|
||||
).forEach { it.setOnClickListener(this) }
|
||||
|
||||
ivMedia.forEach { it.setOnClickListener(this) }
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.net.Uri
|
|||
import android.text.InputType
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import jp.juggler.subwaytooter.ActPost
|
||||
import jp.juggler.subwaytooter.R
|
||||
import jp.juggler.subwaytooter.api.ApiTask
|
||||
|
@ -20,6 +21,7 @@ import jp.juggler.subwaytooter.calcIconRound
|
|||
import jp.juggler.subwaytooter.defaultColorIcon
|
||||
import jp.juggler.subwaytooter.dialog.actionsDialog
|
||||
import jp.juggler.subwaytooter.dialog.decodeAttachmentBitmap
|
||||
import jp.juggler.subwaytooter.dialog.dialogArrachmentRearrange
|
||||
import jp.juggler.subwaytooter.dialog.focusPointDialog
|
||||
import jp.juggler.subwaytooter.dialog.showTextInputDialog
|
||||
import jp.juggler.subwaytooter.pref.PrefB
|
||||
|
@ -40,6 +42,8 @@ import jp.juggler.util.log.withCaption
|
|||
import jp.juggler.util.network.toPutRequestBuilder
|
||||
import jp.juggler.util.ui.isLiveActivity
|
||||
import jp.juggler.util.ui.vg
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.math.min
|
||||
|
||||
private val log = LogCategory("ActPostAttachment")
|
||||
|
@ -64,13 +68,23 @@ fun ActPost.decodeAttachments(sv: String) {
|
|||
}
|
||||
}
|
||||
|
||||
fun ActPost.showAttachmentRearrangeButton() {
|
||||
views.btnAttachmentsRearrange.vg(
|
||||
attachmentList.size >= 2 &&
|
||||
attachmentList.none { it.status == PostAttachment.Status.Progress }
|
||||
)
|
||||
}
|
||||
|
||||
fun ActPost.showMediaAttachment() {
|
||||
if (isFinishing) return
|
||||
views.llAttachment.vg(attachmentList.isNotEmpty())
|
||||
ivMedia.forEachIndexed { i, v -> showMediaAttachmentOne(v, i) }
|
||||
showAttachmentRearrangeButton()
|
||||
}
|
||||
|
||||
fun ActPost.showMediaAttachmentProgress() {
|
||||
if (isFinishing) return
|
||||
showAttachmentRearrangeButton()
|
||||
val mergedProgress = attachmentList
|
||||
.mapNotNull { it.progress.notEmpty() }
|
||||
.joinToString("\n")
|
||||
|
@ -436,3 +450,32 @@ fun ActPost.onPickCustomThumbnailImpl(pa: PostAttachment, src: GetContentResultE
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun ActPost.rearrangeAttachments() = lifecycleScope.launch {
|
||||
try {
|
||||
val rearranged = dialogArrachmentRearrange(attachmentList)
|
||||
// 入れ替え中にアップロード失敗などで要素が消えることがあるので
|
||||
// 最新のattachmentListを指定順に並べ替える
|
||||
val remain = ArrayList(attachmentList)
|
||||
val newList = buildList {
|
||||
rearranged.map { a ->
|
||||
val pa = remain.find { it === a }
|
||||
if (pa != null) {
|
||||
add(pa)
|
||||
remain.remove(pa)
|
||||
}
|
||||
}
|
||||
addAll(remain)
|
||||
}
|
||||
// attachmentListを更新して表示し直す
|
||||
attachmentList.clear()
|
||||
attachmentList.addAll(newList)
|
||||
showMediaAttachment()
|
||||
showMediaAttachmentProgress()
|
||||
} catch (ex: Throwable) {
|
||||
log.e(ex, "attachmentRearrange failed.")
|
||||
if (ex !is CancellationException) {
|
||||
dialogOrToast(ex.withCaption("attachmentRearrange failed."))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,205 @@
|
|||
package jp.juggler.subwaytooter.dialog
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Dialog
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MotionEvent
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bumptech.glide.Glide
|
||||
import jp.juggler.subwaytooter.ActPost
|
||||
import jp.juggler.subwaytooter.R
|
||||
import jp.juggler.subwaytooter.databinding.AttachmentRearrangeDialogBinding
|
||||
import jp.juggler.subwaytooter.databinding.AttachmentsRearrangeItemBinding
|
||||
import jp.juggler.subwaytooter.defaultColorIcon
|
||||
import jp.juggler.subwaytooter.util.PostAttachment
|
||||
import jp.juggler.util.data.ellipsizeDot3
|
||||
import jp.juggler.util.ui.attrColor
|
||||
import jp.juggler.util.ui.dismissSafe
|
||||
import jp.juggler.util.ui.dp
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
import org.jetbrains.anko.backgroundColor
|
||||
import kotlin.coroutines.resumeWithException
|
||||
|
||||
suspend fun ActPost.dialogArrachmentRearrange(
|
||||
initialList: List<PostAttachment>,
|
||||
): List<PostAttachment> = suspendCancellableCoroutine { cont ->
|
||||
val views = AttachmentRearrangeDialogBinding.inflate(layoutInflater)
|
||||
val dialog = Dialog(this)
|
||||
dialog.setContentView(views.root)
|
||||
|
||||
cont.invokeOnCancellation { dialog.dismissSafe() }
|
||||
|
||||
dialog.setOnDismissListener {
|
||||
if (cont.isActive) cont.resumeWithException(CancellationException())
|
||||
}
|
||||
|
||||
val rearrangeAdapter = RearrangeAdapter(layoutInflater, initialList)
|
||||
|
||||
views.btnCancel.setOnClickListener {
|
||||
dialog.dismissSafe()
|
||||
}
|
||||
|
||||
views.btnOk.setOnClickListener {
|
||||
if (cont.isActive) {
|
||||
cont.resume(rearrangeAdapter.list) {}
|
||||
}
|
||||
dialog.dismissSafe()
|
||||
}
|
||||
|
||||
views.listView.apply {
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
adapter = rearrangeAdapter
|
||||
rearrangeAdapter.itemTouchHelper.attachToRecyclerView(this)
|
||||
}
|
||||
|
||||
dialog.window?.setLayout(dp(300), dp(440))
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
private class RearrangeAdapter(
|
||||
private val inflater: LayoutInflater,
|
||||
initialList: List<PostAttachment>,
|
||||
) : RecyclerView.Adapter<RearrangeAdapter.MyViewHolder>(),
|
||||
MyDragCallback.Changer {
|
||||
|
||||
val list = ArrayList(initialList)
|
||||
|
||||
private var lastStateViewHolder: MyViewHolder? = null
|
||||
private var draggingItem: PostAttachment? = null
|
||||
|
||||
val itemTouchHelper by lazy {
|
||||
ItemTouchHelper(MyDragCallback(this))
|
||||
}
|
||||
|
||||
override fun getItemCount() = list.size
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
|
||||
MyViewHolder(parent)
|
||||
|
||||
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
|
||||
holder.bind(list.elementAtOrNull(position))
|
||||
}
|
||||
|
||||
override fun onMove(posFrom: Int, posTo: Int): Boolean {
|
||||
val item = list.removeAt(posFrom)
|
||||
list.add(posTo, item)
|
||||
notifyItemMoved(posFrom, posTo)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onState(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
|
||||
val holder = (viewHolder as? MyViewHolder)
|
||||
holder?.let { lastStateViewHolder = it }
|
||||
val pa = holder?.lastItem
|
||||
draggingItem = when {
|
||||
pa != null && actionState == ItemTouchHelper.ACTION_STATE_DRAG -> pa
|
||||
else -> null
|
||||
}
|
||||
holder?.bind()
|
||||
lastStateViewHolder?.takeIf { it != holder }?.bind()
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
inner class MyViewHolder(
|
||||
parent: ViewGroup,
|
||||
val views: AttachmentsRearrangeItemBinding =
|
||||
AttachmentsRearrangeItemBinding.inflate(inflater, parent, false),
|
||||
) : RecyclerView.ViewHolder(views.root) {
|
||||
|
||||
var lastItem: PostAttachment? = null
|
||||
|
||||
init {
|
||||
views.root.setOnTouchListener { _, event ->
|
||||
if (event.actionMasked == MotionEvent.ACTION_DOWN) {
|
||||
itemTouchHelper.startDrag(this)
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fun bind(pa: PostAttachment? = lastItem) {
|
||||
pa ?: return
|
||||
lastItem = pa
|
||||
|
||||
val context = views.root.context
|
||||
|
||||
views.root.apply {
|
||||
when {
|
||||
draggingItem === pa -> backgroundColor =
|
||||
context.attrColor(R.attr.colorSearchFormBackground)
|
||||
|
||||
else -> background = null
|
||||
}
|
||||
}
|
||||
|
||||
views.ivThumbnail.apply {
|
||||
val imageUrl = pa.attachment?.preview_url
|
||||
if (imageUrl.isNullOrEmpty()) {
|
||||
val imageId = when (pa.status) {
|
||||
PostAttachment.Status.Progress -> R.drawable.ic_upload
|
||||
PostAttachment.Status.Error -> R.drawable.ic_error
|
||||
else -> R.drawable.ic_clip
|
||||
}
|
||||
Glide.with(context).clear(this)
|
||||
setImageDrawable(defaultColorIcon(context, imageId))
|
||||
} else {
|
||||
Glide.with(context)
|
||||
.load(imageUrl)
|
||||
.placeholder(defaultColorIcon(context, R.drawable.ic_hourglass))
|
||||
.error(defaultColorIcon(context, R.drawable.ic_error))
|
||||
.fallback(defaultColorIcon(context, R.drawable.ic_clip))
|
||||
.into(this)
|
||||
}
|
||||
}
|
||||
views.tvText.text = pa.attachment?.run {
|
||||
"$type ${description?.ellipsizeDot3(40) ?: ""}"
|
||||
} ?: context.getString(R.string.attachment_uploading)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MyDragCallback(
|
||||
private val changer: Changer,
|
||||
) : ItemTouchHelper.SimpleCallback(
|
||||
ItemTouchHelper.UP or ItemTouchHelper.DOWN,
|
||||
0 // no swipe
|
||||
) {
|
||||
interface Changer {
|
||||
fun onMove(posFrom: Int, posTo: Int): Boolean
|
||||
fun onState(viewHolder: RecyclerView.ViewHolder?, actionState: Int)
|
||||
}
|
||||
|
||||
override fun isLongPressDragEnabled() = false
|
||||
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) = Unit
|
||||
|
||||
override fun onMove(
|
||||
recyclerView: RecyclerView,
|
||||
viewHolder: RecyclerView.ViewHolder,
|
||||
target: RecyclerView.ViewHolder,
|
||||
): Boolean = changer.onMove(
|
||||
// position of drag from
|
||||
viewHolder.bindingAdapterPosition,
|
||||
// position of drag to
|
||||
target.bindingAdapterPosition,
|
||||
)
|
||||
|
||||
override fun onSelectedChanged(
|
||||
viewHolder: RecyclerView.ViewHolder?,
|
||||
actionState: Int,
|
||||
) {
|
||||
super.onSelectedChanged(viewHolder, actionState)
|
||||
changer.onState(viewHolder, actionState)
|
||||
}
|
||||
|
||||
override fun clearView(
|
||||
recyclerView: RecyclerView,
|
||||
viewHolder: RecyclerView.ViewHolder,
|
||||
) {
|
||||
super.clearView(recyclerView, viewHolder)
|
||||
changer.onState(null, ItemTouchHelper.ACTION_STATE_IDLE)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M280,800L80,600L280,400L336,457L233,560L520,560L520,640L233,640L336,743L280,800ZM680,560L624,503L727,400L440,400L440,320L727,320L624,217L680,160L880,360L680,560Z"/>
|
||||
</vector>
|
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M320,520L320,233L217,336L160,280L360,80L560,280L503,336L400,233L400,520L320,520ZM600,880L400,680L457,624L560,727L560,440L640,440L640,727L743,624L800,680L600,880Z"/>
|
||||
</vector>
|
|
@ -116,14 +116,13 @@
|
|||
android:textAllCaps="false" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
<com.google.android.flexbox.FlexboxLayout
|
||||
android:id="@+id/llAttachment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:baselineAligned="false"
|
||||
android:gravity="top|start"
|
||||
android:orientation="horizontal">
|
||||
app:flexWrap="wrap">
|
||||
|
||||
<jp.juggler.subwaytooter.view.MyNetworkImageView
|
||||
android:id="@+id/ivMedia1"
|
||||
|
@ -161,16 +160,29 @@
|
|||
android:scaleType="fitCenter"
|
||||
tools:src="@drawable/ic_videocam" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btnAttachmentsRearrange"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:background="@drawable/btn_bg_transparent_round6dp"
|
||||
android:contentDescription="@string/rearrange"
|
||||
android:src="@drawable/swap_horiz_24px"
|
||||
android:visibility="gone"
|
||||
app:tint="?attr/colorTextContent"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvAttachmentProgress"
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:maxWidth="160dp"
|
||||
android:textSize="11sp"
|
||||
android:visibility="gone"
|
||||
tools:text="アップロード中です\nアップロード中です\nアップロード中です\nアップロード中です\nアップロード中です"
|
||||
tools:visibility="visible" />
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.flexbox.FlexboxLayout>
|
||||
|
||||
<com.google.android.flexbox.FlexboxLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout 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="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="?attr/colorTextContent"
|
||||
android:padding="8dp"
|
||||
android:text="@string/attachment_rearrange_desc"
|
||||
/>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/listView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:padding="8dp"
|
||||
android:clipToPadding="false"
|
||||
/>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?attr/colorSettingDivider"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
<Button
|
||||
android:background="@drawable/btn_bg_transparent_round6dp"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:id="@+id/btnCancel"
|
||||
android:text="@string/cancel"/>
|
||||
<View
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/colorSettingDivider"/>
|
||||
<Button
|
||||
android:background="@drawable/btn_bg_transparent_round6dp"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:id="@+id/btnOk"
|
||||
android:text="@string/ok"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout 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:id="@+id/llColumn"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:baselineAligned="false"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:paddingVertical="3dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivThumbnail"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="80dp"
|
||||
android:background="#80808080"
|
||||
android:importantForAccessibility="no"
|
||||
android:scaleType="fitCenter"
|
||||
tools:src="@drawable/ic_face" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvText"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="4dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="60dp"
|
||||
android:textColor="?attr/colorTextContent"
|
||||
tools:text="aaa" />
|
||||
</LinearLayout>
|
|
@ -1290,4 +1290,6 @@
|
|||
<string name="detail">詳細</string>
|
||||
<string name="emoji_detail">絵文字の詳細</string>
|
||||
<string name="post_404_desc">(もしくは、フォロー限定投稿にフォロー外から返信しようとしました)</string>
|
||||
<string name="rearrange">並べ替え</string>
|
||||
<string name="attachment_rearrange_desc">ドラッグで並べ替え</string>
|
||||
</resources>
|
||||
|
|
|
@ -1302,4 +1302,6 @@
|
|||
<string name="detail">Detail</string>
|
||||
<string name="emoji_detail">Emoji detail</string>
|
||||
<string name="post_404_desc">(Or, you reply to follower-only post from other account)</string>
|
||||
<string name="rearrange">rearrange</string>
|
||||
<string name="attachment_rearrange_desc">Drag to rearrange.</string>
|
||||
</resources>
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.content.Context
|
|||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.content.res.ColorStateList
|
||||
import android.content.res.Resources
|
||||
import android.content.res.TypedArray
|
||||
import android.graphics.Color
|
||||
import android.graphics.ColorFilter
|
||||
|
@ -19,6 +20,7 @@ import android.media.RingtoneManager
|
|||
import android.os.SystemClock
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.util.DisplayMetrics
|
||||
import android.util.SparseArray
|
||||
import android.view.View
|
||||
import android.widget.ImageButton
|
||||
|
@ -389,3 +391,19 @@ fun AppCompatActivity.setNavigationBack(toolbar: Toolbar) =
|
|||
toolbar.setNavigationOnClickListener {
|
||||
onBackPressedDispatcher.onBackPressed()
|
||||
}
|
||||
|
||||
|
||||
val Float.roundPixels get()= (this+0.5f).toInt()
|
||||
fun DisplayMetrics.dpFloat(src:Float) = (density* src)
|
||||
fun DisplayMetrics.dpFloat(src:Int) = (density*src.toFloat())
|
||||
fun Resources.dpFloat(src:Float) = displayMetrics.dpFloat(src)
|
||||
fun Resources.dpFloat(src:Int) = displayMetrics.dpFloat(src)
|
||||
fun Context.dpFloat(src:Float) = resources.dpFloat(src)
|
||||
fun Context.dpFloat(src:Int) = resources.dpFloat(src)
|
||||
|
||||
fun DisplayMetrics.dp(src:Float) = (density* src).roundPixels
|
||||
fun DisplayMetrics.dp(src:Int) = (density*src.toFloat()).roundPixels
|
||||
fun Resources.dp(src:Float) = displayMetrics.dp(src)
|
||||
fun Resources.dp(src:Int) = displayMetrics.dp(src)
|
||||
fun Context.dp(src:Float) = resources.dp(src)
|
||||
fun Context.dp(src:Int) = resources.dp(src)
|
||||
|
|
Loading…
Reference in New Issue