投稿画面で添付メディアを並べ替え
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.FeaturedTagCache
|
||||||
import jp.juggler.subwaytooter.actpost.addAttachment
|
import jp.juggler.subwaytooter.actpost.addAttachment
|
||||||
import jp.juggler.subwaytooter.actpost.applyMushroomText
|
import jp.juggler.subwaytooter.actpost.applyMushroomText
|
||||||
|
import jp.juggler.subwaytooter.actpost.rearrangeAttachments
|
||||||
import jp.juggler.subwaytooter.actpost.onPickCustomThumbnailImpl
|
import jp.juggler.subwaytooter.actpost.onPickCustomThumbnailImpl
|
||||||
import jp.juggler.subwaytooter.actpost.onPostAttachmentCompleteImpl
|
import jp.juggler.subwaytooter.actpost.onPostAttachmentCompleteImpl
|
||||||
import jp.juggler.subwaytooter.actpost.openAttachment
|
import jp.juggler.subwaytooter.actpost.openAttachment
|
||||||
|
@ -314,7 +315,7 @@ class ActPost : AppCompatActivity(),
|
||||||
R.id.btnFeaturedTag -> completionHelper.openFeaturedTagList(
|
R.id.btnFeaturedTag -> completionHelper.openFeaturedTagList(
|
||||||
featuredTagCache[account?.acct?.ascii ?: ""]?.list
|
featuredTagCache[account?.acct?.ascii ?: ""]?.list
|
||||||
)
|
)
|
||||||
|
R.id.btnAttachmentsRearrange -> rearrangeAttachments()
|
||||||
R.id.ibSchedule -> performSchedule()
|
R.id.ibSchedule -> performSchedule()
|
||||||
R.id.ibScheduleReset -> resetSchedule()
|
R.id.ibScheduleReset -> resetSchedule()
|
||||||
}
|
}
|
||||||
|
@ -445,6 +446,7 @@ class ActPost : AppCompatActivity(),
|
||||||
views.btnEmojiPicker,
|
views.btnEmojiPicker,
|
||||||
views.btnMore,
|
views.btnMore,
|
||||||
views.ivAccount,
|
views.ivAccount,
|
||||||
|
views.btnAttachmentsRearrange,
|
||||||
).forEach { it.setOnClickListener(this) }
|
).forEach { it.setOnClickListener(this) }
|
||||||
|
|
||||||
ivMedia.forEach { it.setOnClickListener(this) }
|
ivMedia.forEach { it.setOnClickListener(this) }
|
||||||
|
|
|
@ -5,6 +5,7 @@ import android.net.Uri
|
||||||
import android.text.InputType
|
import android.text.InputType
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import jp.juggler.subwaytooter.ActPost
|
import jp.juggler.subwaytooter.ActPost
|
||||||
import jp.juggler.subwaytooter.R
|
import jp.juggler.subwaytooter.R
|
||||||
import jp.juggler.subwaytooter.api.ApiTask
|
import jp.juggler.subwaytooter.api.ApiTask
|
||||||
|
@ -20,6 +21,7 @@ import jp.juggler.subwaytooter.calcIconRound
|
||||||
import jp.juggler.subwaytooter.defaultColorIcon
|
import jp.juggler.subwaytooter.defaultColorIcon
|
||||||
import jp.juggler.subwaytooter.dialog.actionsDialog
|
import jp.juggler.subwaytooter.dialog.actionsDialog
|
||||||
import jp.juggler.subwaytooter.dialog.decodeAttachmentBitmap
|
import jp.juggler.subwaytooter.dialog.decodeAttachmentBitmap
|
||||||
|
import jp.juggler.subwaytooter.dialog.dialogArrachmentRearrange
|
||||||
import jp.juggler.subwaytooter.dialog.focusPointDialog
|
import jp.juggler.subwaytooter.dialog.focusPointDialog
|
||||||
import jp.juggler.subwaytooter.dialog.showTextInputDialog
|
import jp.juggler.subwaytooter.dialog.showTextInputDialog
|
||||||
import jp.juggler.subwaytooter.pref.PrefB
|
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.network.toPutRequestBuilder
|
||||||
import jp.juggler.util.ui.isLiveActivity
|
import jp.juggler.util.ui.isLiveActivity
|
||||||
import jp.juggler.util.ui.vg
|
import jp.juggler.util.ui.vg
|
||||||
|
import kotlinx.coroutines.CancellationException
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
private val log = LogCategory("ActPostAttachment")
|
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() {
|
fun ActPost.showMediaAttachment() {
|
||||||
if (isFinishing) return
|
if (isFinishing) return
|
||||||
views.llAttachment.vg(attachmentList.isNotEmpty())
|
views.llAttachment.vg(attachmentList.isNotEmpty())
|
||||||
ivMedia.forEachIndexed { i, v -> showMediaAttachmentOne(v, i) }
|
ivMedia.forEachIndexed { i, v -> showMediaAttachmentOne(v, i) }
|
||||||
|
showAttachmentRearrangeButton()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ActPost.showMediaAttachmentProgress() {
|
fun ActPost.showMediaAttachmentProgress() {
|
||||||
|
if (isFinishing) return
|
||||||
|
showAttachmentRearrangeButton()
|
||||||
val mergedProgress = attachmentList
|
val mergedProgress = attachmentList
|
||||||
.mapNotNull { it.progress.notEmpty() }
|
.mapNotNull { it.progress.notEmpty() }
|
||||||
.joinToString("\n")
|
.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" />
|
android:textAllCaps="false" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<com.google.android.flexbox.FlexboxLayout
|
||||||
android:id="@+id/llAttachment"
|
android:id="@+id/llAttachment"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="4dp"
|
android:layout_marginTop="4dp"
|
||||||
android:baselineAligned="false"
|
android:baselineAligned="false"
|
||||||
android:gravity="top|start"
|
app:flexWrap="wrap">
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<jp.juggler.subwaytooter.view.MyNetworkImageView
|
<jp.juggler.subwaytooter.view.MyNetworkImageView
|
||||||
android:id="@+id/ivMedia1"
|
android:id="@+id/ivMedia1"
|
||||||
|
@ -161,16 +160,29 @@
|
||||||
android:scaleType="fitCenter"
|
android:scaleType="fitCenter"
|
||||||
tools:src="@drawable/ic_videocam" />
|
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
|
<TextView
|
||||||
android:id="@+id/tvAttachmentProgress"
|
android:id="@+id/tvAttachmentProgress"
|
||||||
android:layout_width="0dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:maxWidth="160dp"
|
||||||
android:textSize="11sp"
|
android:textSize="11sp"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:text="アップロード中です\nアップロード中です\nアップロード中です\nアップロード中です\nアップロード中です"
|
tools:text="アップロード中です\nアップロード中です\nアップロード中です\nアップロード中です\nアップロード中です"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
</LinearLayout>
|
|
||||||
|
</com.google.android.flexbox.FlexboxLayout>
|
||||||
|
|
||||||
<com.google.android.flexbox.FlexboxLayout
|
<com.google.android.flexbox.FlexboxLayout
|
||||||
android:layout_width="match_parent"
|
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="detail">詳細</string>
|
||||||
<string name="emoji_detail">絵文字の詳細</string>
|
<string name="emoji_detail">絵文字の詳細</string>
|
||||||
<string name="post_404_desc">(もしくは、フォロー限定投稿にフォロー外から返信しようとしました)</string>
|
<string name="post_404_desc">(もしくは、フォロー限定投稿にフォロー外から返信しようとしました)</string>
|
||||||
|
<string name="rearrange">並べ替え</string>
|
||||||
|
<string name="attachment_rearrange_desc">ドラッグで並べ替え</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -1302,4 +1302,6 @@
|
||||||
<string name="detail">Detail</string>
|
<string name="detail">Detail</string>
|
||||||
<string name="emoji_detail">Emoji 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="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>
|
</resources>
|
||||||
|
|
|
@ -5,6 +5,7 @@ import android.content.Context
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.res.ColorStateList
|
import android.content.res.ColorStateList
|
||||||
|
import android.content.res.Resources
|
||||||
import android.content.res.TypedArray
|
import android.content.res.TypedArray
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.ColorFilter
|
import android.graphics.ColorFilter
|
||||||
|
@ -19,6 +20,7 @@ import android.media.RingtoneManager
|
||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.text.TextWatcher
|
import android.text.TextWatcher
|
||||||
|
import android.util.DisplayMetrics
|
||||||
import android.util.SparseArray
|
import android.util.SparseArray
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.ImageButton
|
import android.widget.ImageButton
|
||||||
|
@ -389,3 +391,19 @@ fun AppCompatActivity.setNavigationBack(toolbar: Toolbar) =
|
||||||
toolbar.setNavigationOnClickListener {
|
toolbar.setNavigationOnClickListener {
|
||||||
onBackPressedDispatcher.onBackPressed()
|
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