ActionMode selection in manga lists
parent
f2175b40c0
commit
76a9a0d1ab
@ -0,0 +1,111 @@
|
|||||||
|
package org.koitharu.kotatsu.base.ui.list.decor
|
||||||
|
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.Rect
|
||||||
|
import android.graphics.RectF
|
||||||
|
import android.view.View
|
||||||
|
import androidx.core.view.children
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import androidx.recyclerview.widget.RecyclerView.NO_ID
|
||||||
|
|
||||||
|
abstract class AbstractSelectionItemDecoration : RecyclerView.ItemDecoration() {
|
||||||
|
|
||||||
|
private val bounds = Rect()
|
||||||
|
private val boundsF = RectF()
|
||||||
|
private val selection = HashSet<Long>()
|
||||||
|
|
||||||
|
protected var hasBackground: Boolean = true
|
||||||
|
protected var hasForeground: Boolean = false
|
||||||
|
protected var isIncludeDecorAndMargins: Boolean = true
|
||||||
|
|
||||||
|
val checkedItemsCount: Int
|
||||||
|
get() = selection.size
|
||||||
|
|
||||||
|
val checkedItemsIds: Set<Long>
|
||||||
|
get() = selection
|
||||||
|
|
||||||
|
fun toggleItemChecked(id: Long) {
|
||||||
|
if (!selection.remove(id)) {
|
||||||
|
selection.add(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setItemIsChecked(id: Long, isChecked: Boolean) {
|
||||||
|
if (isChecked) {
|
||||||
|
selection.add(id)
|
||||||
|
} else {
|
||||||
|
selection.remove(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkAll(ids: Collection<Long>) {
|
||||||
|
selection.addAll(ids)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clearSelection() {
|
||||||
|
selection.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDraw(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) {
|
||||||
|
if (hasBackground) {
|
||||||
|
doDraw(canvas, parent, state, false)
|
||||||
|
} else {
|
||||||
|
super.onDraw(canvas, parent, state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDrawOver(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) {
|
||||||
|
if (hasForeground) {
|
||||||
|
doDraw(canvas, parent, state, true)
|
||||||
|
} else {
|
||||||
|
super.onDrawOver(canvas, parent, state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doDraw(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State, isOver: Boolean) {
|
||||||
|
val checkpoint = canvas.save()
|
||||||
|
if (parent.clipToPadding) {
|
||||||
|
canvas.clipRect(
|
||||||
|
parent.paddingLeft, parent.paddingTop, parent.width - parent.paddingRight,
|
||||||
|
parent.height - parent.paddingBottom
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (child in parent.children) {
|
||||||
|
val itemId = getItemId(parent, child)
|
||||||
|
if (itemId != NO_ID && itemId in selection) {
|
||||||
|
if (isIncludeDecorAndMargins) {
|
||||||
|
parent.getDecoratedBoundsWithMargins(child, bounds)
|
||||||
|
} else {
|
||||||
|
bounds.set(child.left, child.top, child.right, child.bottom)
|
||||||
|
}
|
||||||
|
boundsF.set(bounds)
|
||||||
|
boundsF.offset(child.translationX, child.translationY)
|
||||||
|
if (isOver) {
|
||||||
|
onDrawForeground(canvas, parent, child, boundsF, state)
|
||||||
|
} else {
|
||||||
|
onDrawBackground(canvas, parent, child, boundsF, state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
canvas.restoreToCount(checkpoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun getItemId(parent: RecyclerView, child: View) = parent.getChildItemId(child)
|
||||||
|
|
||||||
|
protected open fun onDrawBackground(
|
||||||
|
canvas: Canvas,
|
||||||
|
parent: RecyclerView,
|
||||||
|
child: View,
|
||||||
|
bounds: RectF,
|
||||||
|
state: RecyclerView.State,
|
||||||
|
) = Unit
|
||||||
|
|
||||||
|
protected open fun onDrawForeground(
|
||||||
|
canvas: Canvas,
|
||||||
|
parent: RecyclerView,
|
||||||
|
child: View,
|
||||||
|
bounds: RectF,
|
||||||
|
state: RecyclerView.State,
|
||||||
|
) = Unit
|
||||||
|
}
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
package org.koitharu.kotatsu.base.ui.util
|
||||||
|
|
||||||
|
import androidx.appcompat.view.ActionMode
|
||||||
|
import androidx.lifecycle.DefaultLifecycleObserver
|
||||||
|
import androidx.lifecycle.LifecycleOwner
|
||||||
|
|
||||||
|
class ActionModeDelegate {
|
||||||
|
|
||||||
|
private var activeActionMode: ActionMode? = null
|
||||||
|
private var listeners: MutableList<ActionModeListener>? = null
|
||||||
|
|
||||||
|
val isActionModeStarted: Boolean
|
||||||
|
get() = activeActionMode != null
|
||||||
|
|
||||||
|
fun onSupportActionModeStarted(mode: ActionMode) {
|
||||||
|
activeActionMode = mode
|
||||||
|
listeners?.forEach { it.onActionModeStarted(mode) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onSupportActionModeFinished(mode: ActionMode) {
|
||||||
|
activeActionMode = null
|
||||||
|
listeners?.forEach { it.onActionModeFinished(mode) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addListener(listener: ActionModeListener) {
|
||||||
|
if (listeners == null) {
|
||||||
|
listeners = ArrayList()
|
||||||
|
}
|
||||||
|
checkNotNull(listeners).add(listener)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun removeListener(listener: ActionModeListener) {
|
||||||
|
listeners?.remove(listener)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addListener(listener: ActionModeListener, owner: LifecycleOwner) {
|
||||||
|
addListener(listener)
|
||||||
|
owner.lifecycle.addObserver(ListenerLifecycleObserver(listener))
|
||||||
|
}
|
||||||
|
|
||||||
|
private inner class ListenerLifecycleObserver(
|
||||||
|
private val listener: ActionModeListener,
|
||||||
|
) : DefaultLifecycleObserver {
|
||||||
|
|
||||||
|
override fun onDestroy(owner: LifecycleOwner) {
|
||||||
|
super.onDestroy(owner)
|
||||||
|
removeListener(listener)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
package org.koitharu.kotatsu.base.ui.util
|
||||||
|
|
||||||
|
import androidx.appcompat.view.ActionMode
|
||||||
|
|
||||||
|
interface ActionModeListener {
|
||||||
|
|
||||||
|
fun onActionModeStarted(mode: ActionMode)
|
||||||
|
|
||||||
|
fun onActionModeFinished(mode: ActionMode)
|
||||||
|
}
|
||||||
@ -0,0 +1,71 @@
|
|||||||
|
package org.koitharu.kotatsu.list.ui
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.Paint
|
||||||
|
import android.graphics.RectF
|
||||||
|
import android.view.View
|
||||||
|
import androidx.cardview.widget.CardView
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.graphics.ColorUtils
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import androidx.recyclerview.widget.RecyclerView.NO_ID
|
||||||
|
import org.koitharu.kotatsu.R
|
||||||
|
import org.koitharu.kotatsu.base.ui.list.decor.AbstractSelectionItemDecoration
|
||||||
|
import org.koitharu.kotatsu.list.ui.model.MangaItemModel
|
||||||
|
import org.koitharu.kotatsu.utils.ext.getItem
|
||||||
|
import org.koitharu.kotatsu.utils.ext.getThemeColor
|
||||||
|
import com.google.android.material.R as materialR
|
||||||
|
|
||||||
|
class MangaSelectionDecoration(context: Context) : AbstractSelectionItemDecoration() {
|
||||||
|
|
||||||
|
private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
|
||||||
|
private val checkIcon = ContextCompat.getDrawable(context, materialR.drawable.ic_mtrl_checked_circle)
|
||||||
|
private val iconOffset = context.resources.getDimensionPixelOffset(R.dimen.grid_spacing_outer)
|
||||||
|
private val strokeColor = context.getThemeColor(materialR.attr.colorPrimary, Color.RED)
|
||||||
|
private val fillColor = ColorUtils.setAlphaComponent(
|
||||||
|
ColorUtils.blendARGB(strokeColor, context.getThemeColor(materialR.attr.colorSurface), 0.8f),
|
||||||
|
0x74
|
||||||
|
)
|
||||||
|
|
||||||
|
init {
|
||||||
|
hasBackground = false
|
||||||
|
hasForeground = true
|
||||||
|
isIncludeDecorAndMargins = false
|
||||||
|
|
||||||
|
paint.strokeWidth = context.resources.getDimension(R.dimen.selection_stroke_width)
|
||||||
|
checkIcon?.setTint(strokeColor)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemId(parent: RecyclerView, child: View): Long {
|
||||||
|
val holder = parent.getChildViewHolder(child) ?: return NO_ID
|
||||||
|
val item = holder.getItem<MangaItemModel>() ?: return NO_ID
|
||||||
|
return item.id
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDrawForeground(
|
||||||
|
canvas: Canvas,
|
||||||
|
parent: RecyclerView,
|
||||||
|
child: View,
|
||||||
|
bounds: RectF,
|
||||||
|
state: RecyclerView.State,
|
||||||
|
) {
|
||||||
|
val radius = (child as? CardView)?.radius ?: 0f
|
||||||
|
paint.color = fillColor
|
||||||
|
paint.style = Paint.Style.FILL
|
||||||
|
canvas.drawRoundRect(bounds, radius, radius, paint)
|
||||||
|
paint.color = strokeColor
|
||||||
|
paint.style = Paint.Style.STROKE
|
||||||
|
canvas.drawRoundRect(bounds, radius, radius, paint)
|
||||||
|
checkIcon?.run {
|
||||||
|
setBounds(
|
||||||
|
(bounds.left + iconOffset).toInt(),
|
||||||
|
(bounds.top + iconOffset).toInt(),
|
||||||
|
(bounds.left + iconOffset + intrinsicWidth).toInt(),
|
||||||
|
(bounds.top + iconOffset + intrinsicHeight).toInt(),
|
||||||
|
)
|
||||||
|
draw(canvas)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
package org.koitharu.kotatsu.list.ui.model
|
||||||
|
|
||||||
|
import org.koitharu.kotatsu.parsers.model.Manga
|
||||||
|
|
||||||
|
sealed interface MangaItemModel : ListModel {
|
||||||
|
|
||||||
|
val id: Long
|
||||||
|
val manga: Manga
|
||||||
|
}
|
||||||
@ -1,62 +1,82 @@
|
|||||||
package org.koitharu.kotatsu.utils
|
package org.koitharu.kotatsu.utils
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import androidx.core.app.ShareCompat
|
||||||
import androidx.core.content.FileProvider
|
import androidx.core.content.FileProvider
|
||||||
|
import java.io.File
|
||||||
import org.koitharu.kotatsu.BuildConfig
|
import org.koitharu.kotatsu.BuildConfig
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
import org.koitharu.kotatsu.parsers.model.Manga
|
import org.koitharu.kotatsu.parsers.model.Manga
|
||||||
import java.io.File
|
|
||||||
|
private const val TYPE_TEXT = "text/plain"
|
||||||
|
private const val TYPE_IMAGE = "image/*"
|
||||||
|
private const val TYPE_CBZ = "application/x-cbz"
|
||||||
|
|
||||||
class ShareHelper(private val context: Context) {
|
class ShareHelper(private val context: Context) {
|
||||||
|
|
||||||
fun shareMangaLink(manga: Manga) {
|
fun shareMangaLink(manga: Manga) {
|
||||||
val intent = Intent(Intent.ACTION_SEND)
|
val text = buildString {
|
||||||
intent.type = "text/plain"
|
|
||||||
intent.putExtra(Intent.EXTRA_TEXT, buildString {
|
|
||||||
append(manga.title)
|
append(manga.title)
|
||||||
append("\n \n")
|
append("\n \n")
|
||||||
append(manga.publicUrl)
|
append(manga.publicUrl)
|
||||||
})
|
}
|
||||||
val shareIntent =
|
ShareCompat.IntentBuilder(context)
|
||||||
Intent.createChooser(intent, context.getString(R.string.share_s, manga.title))
|
.setText(text)
|
||||||
context.startActivity(shareIntent)
|
.setType(TYPE_TEXT)
|
||||||
|
.setChooserTitle(context.getString(R.string.share_s, manga.title))
|
||||||
|
.startChooser()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun shareCbz(file: File) {
|
fun shareMangaLinks(manga: Collection<Manga>) {
|
||||||
val uri = FileProvider.getUriForFile(context, "${BuildConfig.APPLICATION_ID}.files", file)
|
if (manga.isEmpty()) {
|
||||||
val intent = Intent(Intent.ACTION_SEND)
|
return
|
||||||
intent.setDataAndType(uri, context.contentResolver.getType(uri))
|
}
|
||||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
if (manga.size == 1) {
|
||||||
val shareIntent =
|
shareMangaLink(manga.first())
|
||||||
Intent.createChooser(intent, context.getString(R.string.share_s, file.name))
|
return
|
||||||
context.startActivity(shareIntent)
|
}
|
||||||
|
val text = manga.joinToString("\n \n") {
|
||||||
|
"${it.title} - ${it.publicUrl}"
|
||||||
|
}
|
||||||
|
ShareCompat.IntentBuilder(context)
|
||||||
|
.setText(text)
|
||||||
|
.setType(TYPE_TEXT)
|
||||||
|
.setChooserTitle(R.string.share)
|
||||||
|
.startChooser()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun shareBackup(file: File) {
|
fun shareCbz(files: Collection<File>) {
|
||||||
val uri = FileProvider.getUriForFile(context, "${BuildConfig.APPLICATION_ID}.files", file)
|
if (files.isEmpty()) {
|
||||||
val intent = Intent(Intent.ACTION_SEND)
|
return
|
||||||
intent.setDataAndType(uri, context.contentResolver.getType(uri))
|
}
|
||||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
val intentBuilder = ShareCompat.IntentBuilder(context)
|
||||||
val shareIntent =
|
.setType(TYPE_CBZ)
|
||||||
Intent.createChooser(intent, context.getString(R.string.share_s, file.name))
|
for (file in files) {
|
||||||
context.startActivity(shareIntent)
|
val uri = FileProvider.getUriForFile(context, "${BuildConfig.APPLICATION_ID}.files", file)
|
||||||
|
intentBuilder.addStream(uri)
|
||||||
|
}
|
||||||
|
files.singleOrNull()?.let {
|
||||||
|
intentBuilder.setChooserTitle(context.getString(R.string.share_s, it.name))
|
||||||
|
} ?: run {
|
||||||
|
intentBuilder.setChooserTitle(R.string.share)
|
||||||
|
}
|
||||||
|
intentBuilder.startChooser()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun shareImage(uri: Uri) {
|
fun shareImage(uri: Uri) {
|
||||||
val intent = Intent(Intent.ACTION_SEND)
|
ShareCompat.IntentBuilder(context)
|
||||||
intent.setDataAndType(uri, context.contentResolver.getType(uri) ?: "image/*")
|
.setStream(uri)
|
||||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
.setType(context.contentResolver.getType(uri) ?: TYPE_IMAGE)
|
||||||
val shareIntent = Intent.createChooser(intent, context.getString(R.string.share_image))
|
.setChooserTitle(R.string.share_image)
|
||||||
context.startActivity(shareIntent)
|
.startChooser()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun shareText(text: String) {
|
fun shareText(text: String) {
|
||||||
val intent = Intent(Intent.ACTION_SEND)
|
ShareCompat.IntentBuilder(context)
|
||||||
intent.type = "text/plain"
|
.setText(text)
|
||||||
intent.putExtra(Intent.EXTRA_TEXT, text)
|
.setType(TYPE_TEXT)
|
||||||
val shareIntent = Intent.createChooser(intent, context.getString(R.string.share))
|
.setChooserTitle(R.string.share)
|
||||||
context.startActivity(shareIntent)
|
.startChooser()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:tint="?attr/colorControlNormal"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#000"
|
||||||
|
android:pathData="M9,3V4H4V6H5V19A2,2 0 0,0 7,21H17A2,2 0 0,0 19,19V6H20V4H15V3H9M7,6H17V19H7V6M9,8V17H11V8H9M13,8V17H15V8H13Z" />
|
||||||
|
</vector>
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_share"
|
||||||
|
android:icon="?actionModeShareDrawable"
|
||||||
|
android:title="@string/share"
|
||||||
|
app:showAsAction="ifRoom|withText" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_remove"
|
||||||
|
android:icon="@drawable/ic_delete"
|
||||||
|
android:title="@string/remove"
|
||||||
|
app:showAsAction="ifRoom|withText" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_select_all"
|
||||||
|
android:icon="?actionModeSelectAllDrawable"
|
||||||
|
android:title="@android:string/selectAll"
|
||||||
|
app:showAsAction="ifRoom|withText" />
|
||||||
|
|
||||||
|
</menu>
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_share"
|
||||||
|
android:icon="?actionModeShareDrawable"
|
||||||
|
android:title="@string/share"
|
||||||
|
app:showAsAction="ifRoom|withText" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_favourite"
|
||||||
|
android:icon="@drawable/ic_heart_outline"
|
||||||
|
android:title="@string/add_to_favourites"
|
||||||
|
app:showAsAction="ifRoom|withText" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_remove"
|
||||||
|
android:icon="@drawable/ic_delete"
|
||||||
|
android:title="@string/remove"
|
||||||
|
app:showAsAction="ifRoom|withText" />
|
||||||
|
|
||||||
|
</menu>
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_share"
|
||||||
|
android:icon="?actionModeShareDrawable"
|
||||||
|
android:title="@string/share"
|
||||||
|
app:showAsAction="ifRoom|withText" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_remove"
|
||||||
|
android:icon="@drawable/ic_delete"
|
||||||
|
android:title="@string/delete"
|
||||||
|
app:showAsAction="ifRoom|withText" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_select_all"
|
||||||
|
android:icon="?actionModeSelectAllDrawable"
|
||||||
|
android:title="@android:string/selectAll"
|
||||||
|
app:showAsAction="ifRoom|withText" />
|
||||||
|
</menu>
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_share"
|
||||||
|
android:icon="?actionModeShareDrawable"
|
||||||
|
android:title="@string/share"
|
||||||
|
app:showAsAction="ifRoom|withText" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_favourite"
|
||||||
|
android:icon="@drawable/ic_heart_outline"
|
||||||
|
android:title="@string/add_to_favourites"
|
||||||
|
app:showAsAction="ifRoom|withText" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_save"
|
||||||
|
android:icon="@drawable/ic_save"
|
||||||
|
android:title="@string/save"
|
||||||
|
app:showAsAction="ifRoom|withText" />
|
||||||
|
|
||||||
|
</menu>
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_create"
|
||||||
|
android:icon="@drawable/ic_list_add"
|
||||||
|
android:title="@string/add_new_category"
|
||||||
|
android:titleCondensed="@string/add"
|
||||||
|
app:showAsAction="ifRoom|withText" />
|
||||||
|
|
||||||
|
</menu>
|
||||||
@ -1,9 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<menu
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/action_remove"
|
|
||||||
android:title="@string/remove" />
|
|
||||||
|
|
||||||
</menu>
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<menu
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/action_remove"
|
|
||||||
android:title="@string/remove" />
|
|
||||||
|
|
||||||
</menu>
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<menu
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/action_delete"
|
|
||||||
android:title="@string/delete" />
|
|
||||||
|
|
||||||
</menu>
|
|
||||||
Loading…
Reference in New Issue