Implemented drag-and-drop reordering ability in quote recycler view; refactored project structure

This commit is contained in:
denizk0461
2023-05-15 14:16:48 +02:00
parent 252c69a3ef
commit e0e7a4cbe0
15 changed files with 121 additions and 115 deletions
+1 -2
View File
@@ -8,10 +8,9 @@
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme" android:theme="@style/AppTheme"
android:backupAgent=".DriveAgent"
android:restoreAnyVersion="true"> android:restoreAnyVersion="true">
<activity <activity
android:name=".MainActivity" android:name=".activity.MainActivity"
android:exported="true" android:exported="true"
android:windowSoftInputMode="adjustPan"> android:windowSoftInputMode="adjustPan">
<intent-filter> <intent-filter>
@@ -1,14 +0,0 @@
package com.denizd.textbasic
import android.app.backup.*
class DriveAgent : BackupAgentHelper() {
override fun onCreate() {
super.onCreate()
SharedPreferencesBackupHelper(this, QuoteStorage.PREF_NAME).also {
addHelper(QuoteStorage.PREF_BACKUP_KEY, it)
}
}
}
@@ -1,69 +0,0 @@
package com.denizd.textbasic
import android.app.PendingIntent
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.Context
import android.content.Intent
import android.util.TypedValue
import android.view.Gravity
import android.widget.RemoteViews
class TextWidget : AppWidgetProvider() {
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
val remoteViews = configureViews(context, appWidgetIds)
// Perform this loop procedure for each App Widget that belongs to this provider
appWidgetIds.forEach { appWidgetId ->
// Tell the AppWidgetManager to perform an update on the current app widget
appWidgetManager.updateAppWidget(appWidgetId, remoteViews)
}
}
private fun configureViews(context: Context, appWidgetIds: IntArray): RemoteViews =
RemoteViews(context.packageName, R.layout.widget_text).apply {
val storage = QuoteStorage(context)
val quote = if (storage.isOrderRandom()) {
storage.getRandomQuote()
} else {
storage.getNextQuote()
}
setTextViewText(R.id.widget_text, quote.ifBlank { context.getString(R.string.info_add_text) })
setTextViewTextSize(R.id.widget_text, TypedValue.COMPLEX_UNIT_SP, storage.getTextSize().toFloat())
val colours = storage.getColours(context = context)
setTextColor(R.id.widget_text, colours.first)
setInt(R.id.background, "setBackgroundColor", colours.second)
val gravity = when (storage.getWidgetGravity()) {
0 -> Gravity.START or Gravity.TOP
1 -> Gravity.CENTER_HORIZONTAL or Gravity.TOP
2 -> Gravity.END or Gravity.TOP
3 -> Gravity.START or Gravity.CENTER_VERTICAL
4 -> Gravity.CENTER
5 -> Gravity.END or Gravity.CENTER_VERTICAL
6 -> Gravity.START or Gravity.BOTTOM
7 -> Gravity.CENTER_HORIZONTAL or Gravity.BOTTOM
8 -> Gravity.END or Gravity.BOTTOM
else -> Gravity.CENTER
}
setInt(R.id.root_layout, "setGravity", gravity)
setOnClickPendingIntent(
R.id.root_layout,
Intent(context, TextWidget::class.java).let { intent ->
intent.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds)
PendingIntent.getBroadcast(
context, 0, intent, PendingIntent.FLAG_IMMUTABLE
)
}
)
}
}
@@ -1,4 +1,4 @@
package com.denizd.textbasic package com.denizd.textbasic.activity
import android.app.backup.BackupManager import android.app.backup.BackupManager
import android.appwidget.AppWidgetManager import android.appwidget.AppWidgetManager
@@ -7,6 +7,7 @@ import android.content.Intent
import android.os.Bundle import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import com.denizd.textbasic.R
import com.denizd.textbasic.databinding.ActivityMainBinding import com.denizd.textbasic.databinding.ActivityMainBinding
import com.denizd.textbasic.fragment.GuideFragment import com.denizd.textbasic.fragment.GuideFragment
import com.denizd.textbasic.fragment.QuoteFragment import com.denizd.textbasic.fragment.QuoteFragment
@@ -1,4 +1,4 @@
package com.denizd.textbasic package com.denizd.textbasic.adapter
import android.text.Editable import android.text.Editable
import android.text.TextWatcher import android.text.TextWatcher
@@ -8,8 +8,13 @@ import android.view.ViewGroup
import android.widget.ImageButton import android.widget.ImageButton
import android.widget.TextView import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.denizd.textbasic.R
import java.util.Collections
class QuoteAdapter(quotes: List<String>) : RecyclerView.Adapter<QuoteAdapter.QuoteViewHolder>() { class QuoteAdapter(
quotes: List<String>,
) : RecyclerView.Adapter<QuoteAdapter.QuoteViewHolder>(),
RecyclerRowMoveCallback.RecyclerViewTouchHelperContract {
private var mutableQuotes: MutableList<String> = quotes.toMutableList() private var mutableQuotes: MutableList<String> = quotes.toMutableList()
@@ -19,9 +24,9 @@ class QuoteAdapter(quotes: List<String>) : RecyclerView.Adapter<QuoteAdapter.Quo
val delete: ImageButton = view.findViewById(R.id.delete_button) val delete: ImageButton = view.findViewById(R.id.delete_button)
} }
override fun getItemViewType(position: Int): Int { // override fun getItemViewType(position: Int): Int {
return /*if (position == itemCount - 1) 1 else*/ 0 // return /*if (position == itemCount - 1) 1 else*/ 0
} // }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QuoteViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QuoteViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.quote_entry, parent, false) val v = LayoutInflater.from(parent.context).inflate(R.layout.quote_entry, parent, false)
@@ -49,11 +54,6 @@ class QuoteAdapter(quotes: List<String>) : RecyclerView.Adapter<QuoteAdapter.Quo
override fun getItemCount(): Int = mutableQuotes.size override fun getItemCount(): Int = mutableQuotes.size
fun setQuotes(quotes: List<String>) {
this.mutableQuotes = quotes.toMutableList()
notifyDataSetChanged()
}
fun addNewQuote() { fun addNewQuote() {
mutableQuotes.add("") mutableQuotes.add("")
notifyItemInserted(mutableQuotes.size + 1) notifyItemInserted(mutableQuotes.size + 1)
@@ -62,4 +62,22 @@ class QuoteAdapter(quotes: List<String>) : RecyclerView.Adapter<QuoteAdapter.Quo
fun getAllQuotes(): Array<String> { fun getAllQuotes(): Array<String> {
return mutableQuotes.filter { s -> s.isNotBlank() }.toTypedArray() return mutableQuotes.filter { s -> s.isNotBlank() }.toTypedArray()
} }
override fun onRowMoved(from: Int, to: Int) {
if (from < to) for (i in from until to) {
Collections.swap(mutableQuotes, i, i + 1)
} else for (i in to downTo from - 1) {
Collections.swap(mutableQuotes, i, i - 1)
}
notifyItemMoved(from, to)
}
override fun onRowSelected(viewHolder: QuoteViewHolder) {
// TODO
}
override fun onRowClear(viewHolder: QuoteViewHolder) {
// TODO
}
} }
@@ -0,0 +1,55 @@
package com.denizd.textbasic.adapter
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
class RecyclerRowMoveCallback(
private val touchHelperContract: RecyclerViewTouchHelperContract,
) : ItemTouchHelper.Callback() {
override fun isLongPressDragEnabled(): Boolean {
return true
}
override fun isItemViewSwipeEnabled(): Boolean {
return false
}
override fun getMovementFlags(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
): Int = makeMovementFlags(ItemTouchHelper.UP or ItemTouchHelper.DOWN, 0)
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
touchHelperContract.onRowMoved(viewHolder.adapterPosition, target.adapterPosition)
return false
}
override fun onSelectedChanged(
viewHolder: RecyclerView.ViewHolder?,
actionState: Int,
) {
if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
touchHelperContract.onRowSelected(viewHolder as QuoteAdapter.QuoteViewHolder)
}
super.onSelectedChanged(viewHolder, actionState)
}
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
super.clearView(recyclerView, viewHolder)
touchHelperContract.onRowClear(viewHolder as QuoteAdapter.QuoteViewHolder)
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {}
interface RecyclerViewTouchHelperContract {
fun onRowMoved(from: Int, to: Int)
fun onRowSelected(viewHolder: QuoteAdapter.QuoteViewHolder)
fun onRowClear(viewHolder: QuoteAdapter.QuoteViewHolder)
}
}
@@ -1,8 +1,10 @@
package com.denizd.textbasic package com.denizd.textbasic.db
import android.content.Context import android.content.Context
import android.graphics.Color import android.graphics.Color
import android.graphics.Typeface import android.graphics.Typeface
import com.denizd.textbasic.util.ColorTransparentUtils
import com.denizd.textbasic.R
class QuoteStorage(context: Context) { class QuoteStorage(context: Context) {
@@ -82,8 +84,18 @@ class QuoteStorage(context: Context) {
} }
return Pair( return Pair(
Color.parseColor(ColorTransparentUtils.transparentColor(context.getColor(colours.first), textTransparency * 5)),//Color.parseColor(ColorTransparentUtils.transparentColor(colours.first, 10)), Color.parseColor(
Color.parseColor(ColorTransparentUtils.transparentColor(context.getColor(colours.second), bgTransparency * 5)) ColorTransparentUtils.transparentColor(
context.getColor(colours.first),
textTransparency * 5
)
),//Color.parseColor(ColorTransparentUtils.transparentColor(colours.first, 10)),
Color.parseColor(
ColorTransparentUtils.transparentColor(
context.getColor(colours.second),
bgTransparency * 5
)
)
) )
} }
@@ -3,11 +3,13 @@ package com.denizd.textbasic.fragment
import android.animation.LayoutTransition import android.animation.LayoutTransition
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.denizd.textbasic.QuoteAdapter import com.denizd.textbasic.adapter.QuoteAdapter
import com.denizd.textbasic.QuoteStorage import com.denizd.textbasic.db.QuoteStorage
import com.denizd.textbasic.util.viewBinding import com.denizd.textbasic.util.viewBinding
import com.denizd.textbasic.R import com.denizd.textbasic.R
import com.denizd.textbasic.adapter.RecyclerRowMoveCallback
import com.denizd.textbasic.databinding.FragmentQuoteBinding import com.denizd.textbasic.databinding.FragmentQuoteBinding
import com.google.android.material.transition.MaterialSharedAxis import com.google.android.material.transition.MaterialSharedAxis
@@ -38,6 +40,7 @@ class QuoteFragment : BaseFragment(R.layout.fragment_quote) {
binding.quoteScroller.let { s -> binding.quoteScroller.let { s ->
s.layoutManager = LinearLayoutManager(context) s.layoutManager = LinearLayoutManager(context)
ItemTouchHelper(RecyclerRowMoveCallback(quoteAdapter)).attachToRecyclerView(s)
s.adapter = quoteAdapter s.adapter = quoteAdapter
} }
@@ -7,8 +7,8 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.* import android.widget.*
import androidx.annotation.ColorInt import androidx.annotation.ColorInt
import com.denizd.textbasic.ColorTransparentUtils import com.denizd.textbasic.util.ColorTransparentUtils
import com.denizd.textbasic.QuoteStorage import com.denizd.textbasic.db.QuoteStorage
import com.denizd.textbasic.R import com.denizd.textbasic.R
import com.denizd.textbasic.databinding.FragmentSettingsBinding import com.denizd.textbasic.databinding.FragmentSettingsBinding
import com.denizd.textbasic.util.viewBinding import com.denizd.textbasic.util.viewBinding
@@ -248,7 +248,8 @@ class SettingsFragment : BaseFragment(R.layout.fragment_settings) {
} }
binding.textPreviewBackgroundDark.setBackgroundColor( binding.textPreviewBackgroundDark.setBackgroundColor(
Color.parseColor(ColorTransparentUtils.transparentColor( Color.parseColor(
ColorTransparentUtils.transparentColor(
context.getColor(R.color.md_theme_dark_background), context.getColor(R.color.md_theme_dark_background),
if (storage.isInvertedEnabled()) { if (storage.isInvertedEnabled()) {
abs((storage.getBackgroundTransparency() * 5)) abs((storage.getBackgroundTransparency() * 5))
@@ -1,4 +1,4 @@
package com.denizd.textbasic package com.denizd.textbasic.model
/** /**
* Stores a single quote. For potential use with a Room database. * Stores a single quote. For potential use with a Room database.
@@ -1,4 +1,4 @@
package com.denizd.textbasic package com.denizd.textbasic.util
import java.util.* import java.util.*
import kotlin.math.roundToInt import kotlin.math.roundToInt
@@ -14,7 +14,7 @@ object ColorTransparentUtils {
/** /**
* This method convert number into hex number or we can say transparent code * This method convert number into hex number or we can say transparent code
* *
* @param trans number of transparency you want * @param trans number of transparency you want 🏳
* @return hex decimal number or transparency code * @return hex decimal number or transparency code
*/ */
fun convert(trans: Int): String { fun convert(trans: Int): String {
@@ -1,4 +1,4 @@
package com.denizd.textbasic package com.denizd.textbasic.view
import android.content.Context import android.content.Context
import android.graphics.Canvas import android.graphics.Canvas
@@ -4,7 +4,7 @@ import android.content.Context
import android.graphics.* import android.graphics.*
import android.text.StaticLayout import android.text.StaticLayout
import android.text.TextPaint import android.text.TextPaint
import com.denizd.textbasic.QuoteStorage import com.denizd.textbasic.db.QuoteStorage
import com.denizd.textbasic.R import com.denizd.textbasic.R
class CanvasText { class CanvasText {
+1 -1
View File
@@ -7,7 +7,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginHorizontal="8dp" android:layout_marginHorizontal="8dp"
android:layout_marginVertical="8dp" android:layout_marginVertical="8dp"
tools:context=".MainActivity" tools:context=".activity.MainActivity"
android:orientation="vertical" android:orientation="vertical"
android:backgroundTint="?attr/colorTintBackground"> android:backgroundTint="?attr/colorTintBackground">
@@ -25,7 +25,7 @@
android:gravity="center" android:gravity="center"
android:animateLayoutChanges="true"> android:animateLayoutChanges="true">
<com.denizd.textbasic.VerticalTextView <com.denizd.textbasic.view.VerticalTextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/text_size" android:text="@string/text_size"
@@ -40,7 +40,7 @@
android:layout_marginHorizontal="4dp"/> android:layout_marginHorizontal="4dp"/>
<!-- TODO the following 4 elements are hidden but must be removed once their features are implemented custom --> <!-- TODO the following 4 elements are hidden but must be removed once their features are implemented custom -->
<com.denizd.textbasic.VerticalTextView <com.denizd.textbasic.view.VerticalTextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/text_opacity" android:text="@string/text_opacity"
@@ -56,7 +56,7 @@
android:visibility="gone" android:visibility="gone"
android:layout_marginHorizontal="4dp"/> android:layout_marginHorizontal="4dp"/>
<com.denizd.textbasic.VerticalTextView <com.denizd.textbasic.view.VerticalTextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/bg_opacity" android:text="@string/bg_opacity"
@@ -72,7 +72,7 @@
android:visibility="gone" android:visibility="gone"
android:layout_marginHorizontal="4dp"/> android:layout_marginHorizontal="4dp"/>
<com.denizd.textbasic.VerticalTextView <com.denizd.textbasic.view.VerticalTextView
android:id="@+id/outline_textview" android:id="@+id/outline_textview"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -396,7 +396,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<com.denizd.textbasic.VerticalTextView <com.denizd.textbasic.view.VerticalTextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/position" android:text="@string/position"