fix #212, アプリ設定画面のListViewが過剰に更新されるのを防ぐ
This commit is contained in:
parent
3df1fde938
commit
b12b834d11
|
@ -18,15 +18,19 @@ import android.widget.*
|
|||
import androidx.annotation.ColorInt
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.widget.SwitchCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.FileProvider
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.jrummyapps.android.colorpicker.ColorPickerDialog
|
||||
import com.jrummyapps.android.colorpicker.ColorPickerDialogListener
|
||||
import jp.juggler.subwaytooter.appsetting.AppDataExporter
|
||||
import jp.juggler.subwaytooter.appsetting.AppSettingItem
|
||||
import jp.juggler.subwaytooter.appsetting.SettingType
|
||||
import jp.juggler.subwaytooter.appsetting.appSettingRoot
|
||||
import jp.juggler.subwaytooter.databinding.ActAppSettingBinding
|
||||
import jp.juggler.subwaytooter.databinding.LvSettingItemBinding
|
||||
import jp.juggler.subwaytooter.dialog.DlgAppPicker
|
||||
import jp.juggler.subwaytooter.notification.restartAllWorker
|
||||
import jp.juggler.subwaytooter.pref.impl.BooleanPref
|
||||
|
@ -47,8 +51,10 @@ import java.io.File
|
|||
import java.io.FileOutputStream
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStreamWriter
|
||||
import java.lang.ref.WeakReference
|
||||
import java.text.NumberFormat
|
||||
import java.util.*
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipOutputStream
|
||||
|
@ -79,9 +85,14 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
|
||||
lateinit var pref: SharedPreferences
|
||||
lateinit var handler: Handler
|
||||
private lateinit var lvList: ListView
|
||||
private lateinit var adapter: MyAdapter
|
||||
private lateinit var etSearch: EditText
|
||||
|
||||
val views by lazy {
|
||||
ActAppSettingBinding.inflate(layoutInflater)
|
||||
}
|
||||
|
||||
private val adapter by lazy {
|
||||
MyAdapter()
|
||||
}
|
||||
|
||||
private val arNoop = ActivityResultHandler(log) { }
|
||||
|
||||
|
@ -108,6 +119,18 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
}
|
||||
}
|
||||
|
||||
private var pendingQuery: String? = null
|
||||
|
||||
private val procQuery: Runnable = Runnable {
|
||||
if (pendingQuery != null) load(null, pendingQuery)
|
||||
}
|
||||
|
||||
private val divider = Any()
|
||||
|
||||
private var lastSection: AppSettingItem? = null
|
||||
private var lastQuery: String? = null
|
||||
private var colorTarget: AppSettingItem? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
backPressed {
|
||||
|
@ -151,17 +174,15 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
}
|
||||
|
||||
private fun initUi() {
|
||||
setContentView(R.layout.act_app_setting)
|
||||
setContentView(views.root)
|
||||
App1.initEdgeToEdge(this)
|
||||
|
||||
Styler.fixHorizontalPadding0(findViewById(R.id.llContent))
|
||||
lvList = findViewById(R.id.lvList)
|
||||
Styler.fixHorizontalPadding0(views.llContent)
|
||||
|
||||
adapter = MyAdapter()
|
||||
lvList.adapter = adapter
|
||||
views.lvList.layoutManager = LinearLayoutManager(this)
|
||||
views.lvList.adapter = adapter
|
||||
|
||||
etSearch = findViewById<EditText>(R.id.etSearch).apply {
|
||||
addTextChangedListener(object : TextWatcher {
|
||||
views.etSearch.addTextChangedListener(object : TextWatcher {
|
||||
override fun afterTextChanged(p0: Editable?) {
|
||||
pendingQuery = p0?.toString()
|
||||
this@ActAppSetting.handler.removeCallbacks(procQuery)
|
||||
|
@ -184,9 +205,8 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
findViewById<View>(R.id.btnSearchReset).setOnClickListener(this@ActAppSetting)
|
||||
views.btnSearchReset.setOnClickListener(this)
|
||||
}
|
||||
|
||||
private fun removeDefaultPref() {
|
||||
|
@ -215,34 +235,18 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
when (v.id) {
|
||||
R.id.btnSearchReset -> {
|
||||
handler.removeCallbacks(procQuery)
|
||||
etSearch.setText("")
|
||||
etSearch.hideKeyboard()
|
||||
views.etSearch.setText("")
|
||||
views.etSearch.hideKeyboard()
|
||||
load(lastSection, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
private var pendingQuery: String? = null
|
||||
|
||||
private val procQuery: Runnable = Runnable {
|
||||
if (pendingQuery != null) load(null, pendingQuery)
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
private val divider = Any()
|
||||
private val list = ArrayList<Any>()
|
||||
|
||||
private var lastSection: AppSettingItem? = null
|
||||
private var lastQuery: String? = null
|
||||
|
||||
private fun load(section: AppSettingItem?, query: String?) {
|
||||
list.clear()
|
||||
|
||||
adapter.items = buildList {
|
||||
var lastPath: String? = null
|
||||
fun addParentPath(item: AppSettingItem) {
|
||||
list.add(divider)
|
||||
add(divider)
|
||||
|
||||
val pathList = ArrayList<String>()
|
||||
var parent = item.parent
|
||||
|
@ -253,12 +257,14 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
val path = pathList.joinToString("/")
|
||||
if (path != lastPath) {
|
||||
lastPath = path
|
||||
list.add(path)
|
||||
list.add(divider)
|
||||
add(path)
|
||||
add(divider)
|
||||
}
|
||||
}
|
||||
|
||||
if (query?.isNotEmpty() == true) {
|
||||
when {
|
||||
// 検索キーワードあり
|
||||
query?.isNotBlank() == true -> {
|
||||
lastQuery = query
|
||||
fun scanGroup(level: Int, item: AppSettingItem) {
|
||||
if (item.caption == 0) return
|
||||
|
@ -267,7 +273,9 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
if (item.type == SettingType.Group) {
|
||||
for (child in item.items) {
|
||||
if (child.caption == 0) continue
|
||||
if (getString(item.caption).contains(query, ignoreCase = true)) {
|
||||
if (getString(item.caption).contains(query,
|
||||
ignoreCase = true)
|
||||
) {
|
||||
match = true
|
||||
break
|
||||
}
|
||||
|
@ -275,17 +283,15 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
if (match) {
|
||||
// put entire group
|
||||
addParentPath(item)
|
||||
list.add(item)
|
||||
for (child in item.items) {
|
||||
list.add(child)
|
||||
}
|
||||
add(item)
|
||||
addAll(item.items)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (match) {
|
||||
addParentPath(item)
|
||||
list.add(item)
|
||||
add(item)
|
||||
}
|
||||
}
|
||||
for (child in item.items) {
|
||||
|
@ -293,31 +299,29 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
}
|
||||
}
|
||||
scanGroup(0, appSettingRoot)
|
||||
if (list.isNotEmpty()) list.add(divider)
|
||||
} else if (section == null) {
|
||||
}
|
||||
// show root page
|
||||
section == null -> {
|
||||
val root = appSettingRoot
|
||||
lastQuery = null
|
||||
lastSection = null
|
||||
for (child in root.items) {
|
||||
list.add(divider)
|
||||
list.add(child)
|
||||
add(divider)
|
||||
add(child)
|
||||
}
|
||||
}
|
||||
list.add(divider)
|
||||
} else {
|
||||
// show section page
|
||||
else -> {
|
||||
lastSection = section
|
||||
lastQuery = null
|
||||
fun scanGroup(level: Int, parent: AppSettingItem?) {
|
||||
parent ?: return
|
||||
for (item in parent.items) {
|
||||
list.add(divider)
|
||||
list.add(item)
|
||||
add(divider)
|
||||
add(item)
|
||||
if (item.items.isNotEmpty()) {
|
||||
if (item.type == SettingType.Group) {
|
||||
for (child in item.items) {
|
||||
list.add(child)
|
||||
}
|
||||
addAll(item.items)
|
||||
} else {
|
||||
scanGroup(level + 1, item)
|
||||
}
|
||||
|
@ -325,41 +329,11 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
}
|
||||
}
|
||||
scanGroup(0, section.cast())
|
||||
if (list.isNotEmpty()) list.add(divider)
|
||||
}
|
||||
adapter.notifyDataSetChanged()
|
||||
lvList.setSelectionFromTop(0, 0)
|
||||
}
|
||||
|
||||
inner class MyAdapter : BaseAdapter() {
|
||||
|
||||
override fun getCount(): Int = list.size
|
||||
override fun getItemId(position: Int): Long = 0
|
||||
override fun getItem(position: Int): Any = list[position]
|
||||
override fun getViewTypeCount(): Int = SettingType.values().maxByOrNull { it.id }!!.id + 1
|
||||
|
||||
override fun getItemViewType(position: Int): Int =
|
||||
when (val item = list[position]) {
|
||||
is AppSettingItem -> item.type.id
|
||||
is String -> SettingType.Path.id
|
||||
divider -> SettingType.Divider.id
|
||||
else -> error("can't generate view for type $item")
|
||||
}
|
||||
|
||||
// true if the item at the specified position is not a separator.
|
||||
// (A separator is a non-selectable, non-clickable item).
|
||||
override fun areAllItemsEnabled(): Boolean = false
|
||||
|
||||
override fun isEnabled(position: Int): Boolean = list[position] is AppSettingItem
|
||||
|
||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View =
|
||||
when (val item = list[position]) {
|
||||
is AppSettingItem ->
|
||||
getViewSettingItem(item, convertView, parent)
|
||||
is String -> getViewPath(item, convertView)
|
||||
divider -> getViewDivider(convertView)
|
||||
else -> error("can't generate view for type $item")
|
||||
if (isNotEmpty()) add(divider)
|
||||
}
|
||||
views.lvList.scrollToPosition(0)
|
||||
}
|
||||
|
||||
private fun dip(dp: Float): Int =
|
||||
|
@ -367,62 +341,6 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
|
||||
private fun dip(dp: Int): Int = dip(dp.toFloat())
|
||||
|
||||
private fun getViewDivider(convertView: View?): View =
|
||||
convertView ?: FrameLayout(this@ActAppSetting).apply {
|
||||
layoutParams = AbsListView.LayoutParams(
|
||||
AbsListView.LayoutParams.MATCH_PARENT,
|
||||
AbsListView.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
addView(View(this@ActAppSetting).apply {
|
||||
layoutParams = FrameLayout.LayoutParams(
|
||||
AbsListView.LayoutParams.MATCH_PARENT,
|
||||
dip(1)
|
||||
).apply {
|
||||
val marginX = 0
|
||||
val marginY = dip(6)
|
||||
setMargins(marginX, marginY, marginX, marginY)
|
||||
}
|
||||
setBackgroundColor(context.attrColor(R.attr.colorSettingDivider))
|
||||
})
|
||||
}
|
||||
|
||||
private fun getViewPath(path: String, convertView: View?): View {
|
||||
val tv: MyTextView =
|
||||
convertView.cast() ?: MyTextView(this@ActAppSetting).apply {
|
||||
layoutParams = AbsListView.LayoutParams(
|
||||
AbsListView.LayoutParams.MATCH_PARENT,
|
||||
AbsListView.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
val padX = 0
|
||||
val padY = dip(3)
|
||||
setTypeface(typeface, Typeface.BOLD)
|
||||
setPaddingRelative(padX, padY, padX, padY)
|
||||
}
|
||||
tv.text = path
|
||||
return tv
|
||||
}
|
||||
|
||||
private fun getViewSettingItem(
|
||||
item: AppSettingItem,
|
||||
convertView: View?,
|
||||
parent: ViewGroup?,
|
||||
): View {
|
||||
val view: View
|
||||
val holder: ViewHolderSettingItem
|
||||
if (convertView != null) {
|
||||
view = convertView
|
||||
holder = convertView.tag.cast()!!
|
||||
} else {
|
||||
view = layoutInflater.inflate(R.layout.lv_setting_item, parent, false)
|
||||
holder = ViewHolderSettingItem(view)
|
||||
view.tag = holder
|
||||
}
|
||||
holder.bind(item)
|
||||
return view
|
||||
}
|
||||
|
||||
private var colorTarget: AppSettingItem? = null
|
||||
|
||||
override fun onDialogDismissed(dialogId: Int) {
|
||||
}
|
||||
|
||||
|
@ -438,40 +356,146 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
colorTarget.changed(this)
|
||||
}
|
||||
|
||||
inner class ViewHolderSettingItem(viewRoot: View) :
|
||||
inner class MyAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
var items: List<Any> = emptyList()
|
||||
set(newItems) {
|
||||
val oldItems = field
|
||||
field = newItems
|
||||
DiffUtil.calculateDiff(object : DiffUtil.Callback() {
|
||||
override fun getOldListSize() = oldItems.size
|
||||
override fun getNewListSize() = newItems.size
|
||||
override fun areItemsTheSame(
|
||||
oldItemPosition: Int,
|
||||
newItemPosition: Int,
|
||||
) = oldItems.elementAtOrNull(oldItemPosition) == newItems.elementAtOrNull(
|
||||
newItemPosition)
|
||||
|
||||
override fun areContentsTheSame(
|
||||
oldItemPosition: Int,
|
||||
newItemPosition: Int,
|
||||
) = oldItems.elementAtOrNull(oldItemPosition) == newItems.elementAtOrNull(
|
||||
newItemPosition)
|
||||
}, true).dispatchUpdatesTo(this)
|
||||
}
|
||||
|
||||
private val settingHolderList =
|
||||
ConcurrentHashMap<AppSettingItem, WeakReference<VhSettingItem>>()
|
||||
|
||||
override fun getItemCount() = items.size
|
||||
|
||||
override fun getItemViewType(position: Int) =
|
||||
when (val item = items.elementAtOrNull(position)) {
|
||||
divider -> SettingType.Divider.id
|
||||
is String -> SettingType.Path.id
|
||||
is AppSettingItem -> item.type.id
|
||||
else -> error("can't generate view for type $item")
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
|
||||
when (SettingType.map[viewType]) {
|
||||
SettingType.Divider -> VhDivider()
|
||||
SettingType.Path -> VhPath(parent)
|
||||
else -> VhSettingItem(this@ActAppSetting, parent)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) {
|
||||
when (val item = items.elementAtOrNull(position)) {
|
||||
divider -> viewHolder.cast<VhDivider>()
|
||||
is String -> viewHolder.cast<VhPath>()?.bind(item)
|
||||
is AppSettingItem -> if (viewHolder is VhSettingItem) {
|
||||
viewHolder.bind(item)
|
||||
// 古い紐付けを削除
|
||||
settingHolderList.entries.filter {
|
||||
when (it.value.get()) {
|
||||
null, viewHolder -> true
|
||||
else -> false
|
||||
}
|
||||
}.forEach { settingHolderList.remove(it.key) }
|
||||
// 新しい紐付けを覚える
|
||||
settingHolderList[item] = WeakReference(viewHolder)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun findVhSetting(item: AppSettingItem) = settingHolderList[item]?.get()
|
||||
}
|
||||
|
||||
private inner class VhDivider(
|
||||
viewRoot: FrameLayout = FrameLayout(this@ActAppSetting).apply {
|
||||
layoutParams = RecyclerView.LayoutParams(
|
||||
RecyclerView.LayoutParams.MATCH_PARENT,
|
||||
RecyclerView.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
addView(View(this@ActAppSetting).apply {
|
||||
layoutParams = FrameLayout.LayoutParams(
|
||||
FrameLayout.LayoutParams.MATCH_PARENT,
|
||||
dip(1)
|
||||
).apply {
|
||||
val marginX = 0
|
||||
val marginY = dip(6)
|
||||
setMargins(marginX, marginY, marginX, marginY)
|
||||
}
|
||||
setBackgroundColor(context.attrColor(R.attr.colorSettingDivider))
|
||||
})
|
||||
},
|
||||
) : RecyclerView.ViewHolder(viewRoot)
|
||||
|
||||
private inner class VhPath(
|
||||
val parent: ViewGroup,
|
||||
val viewRoot: MyTextView = MyTextView(this@ActAppSetting).apply {
|
||||
layoutParams = RecyclerView.LayoutParams(
|
||||
RecyclerView.LayoutParams.MATCH_PARENT,
|
||||
RecyclerView.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
val padX = 0
|
||||
val padY = dip(3)
|
||||
setTypeface(typeface, Typeface.BOLD)
|
||||
setPaddingRelative(padX, padY, padX, padY)
|
||||
},
|
||||
) : RecyclerView.ViewHolder(viewRoot) {
|
||||
fun bind(path: String) {
|
||||
viewRoot.text = path
|
||||
}
|
||||
}
|
||||
|
||||
// not private
|
||||
class VhSettingItem(
|
||||
val activity: ActAppSetting,
|
||||
parent: ViewGroup,
|
||||
private val views: LvSettingItemBinding = LvSettingItemBinding
|
||||
.inflate(activity.layoutInflater, parent, false),
|
||||
) : RecyclerView.ViewHolder(views.root),
|
||||
TextWatcher,
|
||||
AdapterView.OnItemSelectedListener,
|
||||
CompoundButton.OnCheckedChangeListener {
|
||||
|
||||
private val tvCaption: TextView = viewRoot.findViewById(R.id.tvCaption)
|
||||
private val btnAction: Button = viewRoot.findViewById(R.id.btnAction)
|
||||
private val btnAction = views.btnAction
|
||||
|
||||
private val checkBox: CheckBox = viewRoot.findViewById<CheckBox>(R.id.checkBox)
|
||||
private val checkBox = views.checkBox
|
||||
.also { it.setOnCheckedChangeListener(this) }
|
||||
|
||||
private val swSwitch: SwitchCompat = viewRoot.findViewById<SwitchCompat>(R.id.swSwitch)
|
||||
private val swSwitch = views.swSwitch
|
||||
.also { it.setOnCheckedChangeListener(this) }
|
||||
|
||||
val llExtra: LinearLayout = viewRoot.findViewById(R.id.llExtra)
|
||||
val llExtra = views.llExtra
|
||||
|
||||
val textView1: TextView = viewRoot.findViewById(R.id.textView1)
|
||||
val textView1 = views.textView1
|
||||
|
||||
private val llButtonBar: LinearLayout = viewRoot.findViewById(R.id.llButtonBar)
|
||||
private val vColor: View = viewRoot.findViewById(R.id.vColor)
|
||||
private val btnEdit: Button = viewRoot.findViewById(R.id.btnEdit)
|
||||
private val btnReset: Button = viewRoot.findViewById(R.id.btnReset)
|
||||
private val llButtonBar = views.llButtonBar
|
||||
private val vColor = views.vColor
|
||||
private val btnEdit = views.btnEdit
|
||||
private val btnReset = views.btnReset
|
||||
|
||||
private val spSpinner: Spinner = viewRoot.findViewById<Spinner>(R.id.spSpinner)
|
||||
private val spSpinner = views.spSpinner
|
||||
.also { it.onItemSelectedListener = this }
|
||||
|
||||
private val etEditText: EditText = viewRoot.findViewById<EditText>(R.id.etEditText)
|
||||
private val etEditText = views.etEditText
|
||||
.also { it.addTextChangedListener(this) }
|
||||
|
||||
private val tvDesc: TextView = viewRoot.findViewById(R.id.tvDesc)
|
||||
private val tvError: TextView = viewRoot.findViewById(R.id.tvError)
|
||||
private val tvDesc = views.tvDesc
|
||||
private val tvError = views.tvError
|
||||
|
||||
val activity: ActAppSetting
|
||||
get() = this@ActAppSetting
|
||||
private val pref = activity.pref
|
||||
|
||||
var item: AppSettingItem? = null
|
||||
|
||||
|
@ -482,7 +506,7 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
try {
|
||||
this.item = item
|
||||
|
||||
tvCaption.vg(false)
|
||||
views.tvCaption.vg(false)
|
||||
btnAction.vg(false)
|
||||
checkBox.vg(false)
|
||||
swSwitch.vg(false)
|
||||
|
@ -495,11 +519,11 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
tvDesc.vg(false)
|
||||
tvError.vg(false)
|
||||
|
||||
val name = if (item.caption == 0) "" else getString(item.caption)
|
||||
val name = if (item.caption == 0) "" else activity.getString(item.caption)
|
||||
|
||||
if (item.desc != 0) {
|
||||
tvDesc.vg(true)
|
||||
tvDesc.text = getString(item.desc)
|
||||
tvDesc.text = activity.getString(item.desc)
|
||||
if (item.descClickSet) {
|
||||
tvDesc.background = ContextCompat.getDrawable(
|
||||
activity,
|
||||
|
@ -520,7 +544,7 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
btnAction.text = name
|
||||
btnAction.isEnabledAlpha = item.enabled
|
||||
btnAction.setOnClickListener {
|
||||
load(item.cast()!!, null)
|
||||
activity.load(item.cast()!!, null)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -539,7 +563,7 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
checkBox.vg(false) // skip animation
|
||||
checkBox.text = name
|
||||
checkBox.isEnabledAlpha = item.enabled
|
||||
checkBox.isChecked = bp(pref)
|
||||
checkBox.isChecked = bp(activity.pref)
|
||||
checkBox.vg(true)
|
||||
}
|
||||
|
||||
|
@ -548,9 +572,9 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
item.pref.cast() ?: error("$name has no boolean pref")
|
||||
showCaption(name)
|
||||
swSwitch.vg(false) // skip animation
|
||||
setSwitchColor(swSwitch)
|
||||
activity.setSwitchColor(swSwitch)
|
||||
swSwitch.isEnabledAlpha = item.enabled
|
||||
swSwitch.isChecked = bp(pref)
|
||||
swSwitch.isChecked = bp(activity.pref)
|
||||
swSwitch.vg(true)
|
||||
}
|
||||
|
||||
|
@ -561,7 +585,7 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
SettingType.Sample -> {
|
||||
llExtra.vg(true)
|
||||
llExtra.removeAllViews()
|
||||
layoutInflater.inflate(item.sampleLayoutId, llExtra, true)
|
||||
activity.layoutInflater.inflate(item.sampleLayoutId, llExtra, true)
|
||||
item.sampleUpdate(activity, llExtra)
|
||||
}
|
||||
|
||||
|
@ -570,12 +594,12 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
showCaption(name)
|
||||
llButtonBar.vg(true)
|
||||
vColor.vg(true)
|
||||
vColor.setBackgroundColor(ip(pref))
|
||||
vColor.setBackgroundColor(ip(activity.pref))
|
||||
btnEdit.isEnabledAlpha = item.enabled
|
||||
btnReset.isEnabledAlpha = item.enabled
|
||||
btnEdit.setOnClickListener {
|
||||
colorTarget = item
|
||||
val color = ip(pref)
|
||||
activity.colorTarget = item
|
||||
val color = ip(activity.pref)
|
||||
val builder = ColorPickerDialog.newBuilder()
|
||||
.setDialogType(ColorPickerDialog.TYPE_CUSTOM)
|
||||
.setAllowPresets(true)
|
||||
|
@ -585,7 +609,7 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
builder.show(activity)
|
||||
}
|
||||
btnReset.setOnClickListener {
|
||||
pref.edit().remove(ip).apply()
|
||||
activity.pref.edit().remove(ip).apply()
|
||||
showColor()
|
||||
item.changed.invoke(activity)
|
||||
}
|
||||
|
@ -602,11 +626,12 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
// 整数型の設定のSpinnerは全て選択肢を単純に覚える
|
||||
val argsInt = item.spinnerArgs
|
||||
if (argsInt != null) {
|
||||
initSpinner(spSpinner, argsInt.map { getString(it) })
|
||||
activity.initSpinner(spSpinner,
|
||||
argsInt.map { activity.getString(it) })
|
||||
} else {
|
||||
initSpinner(spSpinner, item.spinnerArgsProc(activity))
|
||||
activity.initSpinner(spSpinner, item.spinnerArgsProc(activity))
|
||||
}
|
||||
spSpinner.setSelection(pi.invoke(pref))
|
||||
spSpinner.setSelection(pi.invoke(activity.pref))
|
||||
} else {
|
||||
item.spinnerInitializer.invoke(activity, spSpinner)
|
||||
}
|
||||
|
@ -615,18 +640,13 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
SettingType.EditText -> {
|
||||
showCaption(name)
|
||||
etEditText.vg(true)
|
||||
|
||||
?: error("EditText must have preference.")
|
||||
etEditText.inputType = item.inputType
|
||||
val text = when (val pi = item.pref) {
|
||||
is FloatPref -> {
|
||||
item.fromFloat.invoke(activity, pi(pref))
|
||||
}
|
||||
|
||||
is StringPref -> {
|
||||
pi(pref)
|
||||
}
|
||||
|
||||
is FloatPref ->
|
||||
item.fromFloat.invoke(activity, pi(activity.pref))
|
||||
is StringPref ->
|
||||
pi(activity.pref)
|
||||
else -> error("EditText han incorrect pref $pi")
|
||||
}
|
||||
etEditText.setText(text)
|
||||
|
@ -662,8 +682,7 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
|
||||
private fun showCaption(caption: String) {
|
||||
if (caption.isNotEmpty()) {
|
||||
tvCaption.vg(true)
|
||||
tvCaption.text = caption
|
||||
views.tvCaption.vg(true)?.text = caption
|
||||
updateCaption()
|
||||
}
|
||||
}
|
||||
|
@ -672,16 +691,16 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
val item = item ?: return
|
||||
val key = item.pref?.key ?: return
|
||||
|
||||
val sample: TextView = tvCaption
|
||||
var defaultExtra = defaultLineSpacingExtra[key]
|
||||
val sample = views.tvCaption
|
||||
var defaultExtra = activity.defaultLineSpacingExtra[key]
|
||||
if (defaultExtra == null) {
|
||||
defaultExtra = sample.lineSpacingExtra
|
||||
defaultLineSpacingExtra[key] = defaultExtra
|
||||
activity.defaultLineSpacingExtra[key] = defaultExtra
|
||||
}
|
||||
var defaultMultiplier = defaultLineSpacingMultiplier[key]
|
||||
var defaultMultiplier = activity.defaultLineSpacingMultiplier[key]
|
||||
if (defaultMultiplier == null) {
|
||||
defaultMultiplier = sample.lineSpacingMultiplier
|
||||
defaultLineSpacingMultiplier[key] = defaultMultiplier
|
||||
activity.defaultLineSpacingMultiplier[key] = defaultMultiplier
|
||||
}
|
||||
|
||||
val size = item.captionFontSize.invoke(activity)
|
||||
|
@ -705,7 +724,7 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
fun showColor() {
|
||||
val item = item ?: return
|
||||
val ip = item.pref.cast<IntPref>() ?: return
|
||||
val c = ip(pref)
|
||||
val c = ip(activity.pref)
|
||||
vColor.setBackgroundColor(c)
|
||||
}
|
||||
|
||||
|
@ -724,15 +743,15 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
when (val pi = item.pref) {
|
||||
|
||||
is StringPref -> {
|
||||
pref.edit().put(pi, sv).apply()
|
||||
activity.pref.edit().put(pi, sv).apply()
|
||||
}
|
||||
|
||||
is FloatPref -> {
|
||||
val fv = item.toFloat.invoke(activity, sv)
|
||||
if (fv.isFinite()) {
|
||||
pref.edit().put(pi, fv).apply()
|
||||
activity.pref.edit().put(pi, fv).apply()
|
||||
} else {
|
||||
pref.edit().remove(pi.key).apply()
|
||||
activity.pref.edit().remove(pi.key).apply()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -756,7 +775,7 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
if (bindingBusy) return
|
||||
val item = item ?: return
|
||||
when (val pi = item.pref) {
|
||||
is IntPref -> pref.edit().put(pi, spSpinner.selectedItemPosition).apply()
|
||||
is IntPref -> activity.pref.edit().put(pi, spSpinner.selectedItemPosition).apply()
|
||||
else -> item.spinnerOnSelected.invoke(activity, spSpinner, position)
|
||||
}
|
||||
item.changed.invoke(activity)
|
||||
|
@ -865,13 +884,9 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
finish()
|
||||
}
|
||||
|
||||
fun findItemViewHolder(item: AppSettingItem?): ViewHolderSettingItem? {
|
||||
fun findItemViewHolder(item: AppSettingItem?): VhSettingItem? {
|
||||
if (item != null) {
|
||||
for (i in 0 until lvList.childCount) {
|
||||
val view = lvList.getChildAt(i)
|
||||
val holder: ViewHolderSettingItem? = view?.tag?.cast()
|
||||
if (holder?.item == item) return holder
|
||||
}
|
||||
adapter.findVhSetting(item)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
@ -884,8 +899,7 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
}
|
||||
|
||||
// リスト内部のSwitchCompat全ての色を更新する
|
||||
fun setSwitchColor() =
|
||||
setSwitchColor(lvList)
|
||||
fun setSwitchColor() = setSwitchColor(views.lvList)
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
|
@ -914,8 +928,8 @@ class ActAppSetting : AppCompatActivity(), ColorPickerDialogListener, View.OnCli
|
|||
return Float.NaN
|
||||
}
|
||||
|
||||
private val defaultLineSpacingExtra = HashMap<String, Float>()
|
||||
private val defaultLineSpacingMultiplier = HashMap<String, Float>()
|
||||
val defaultLineSpacingExtra = HashMap<String, Float>()
|
||||
val defaultLineSpacingMultiplier = HashMap<String, Float>()
|
||||
|
||||
private fun handleFontResult(item: AppSettingItem?, data: Intent, fileName: String) {
|
||||
item ?: error("handleFontResult : setting item is null")
|
||||
|
|
|
@ -18,6 +18,7 @@ import jp.juggler.subwaytooter.util.CustomShareTarget
|
|||
import jp.juggler.subwaytooter.util.openBrowser
|
||||
import jp.juggler.util.*
|
||||
import org.jetbrains.anko.backgroundDrawable
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
enum class SettingType(val id: Int) {
|
||||
Path(0),
|
||||
|
@ -33,6 +34,12 @@ enum class SettingType(val id: Int) {
|
|||
TextWithSelector(10),
|
||||
CheckBox(11),
|
||||
Section(12)
|
||||
|
||||
;
|
||||
|
||||
companion object {
|
||||
val map = values().associateBy { it.id }
|
||||
}
|
||||
}
|
||||
|
||||
class AppSettingItem(
|
||||
|
@ -41,6 +48,7 @@ class AppSettingItem(
|
|||
@StringRes val caption: Int,
|
||||
val pref: BasePref<*>? = null,
|
||||
) {
|
||||
val id = idSeed.incrementAndGet()
|
||||
|
||||
@StringRes
|
||||
var desc: Int = 0
|
||||
|
@ -191,7 +199,11 @@ class AppSettingItem(
|
|||
for (item in items) item.scan(block)
|
||||
}
|
||||
|
||||
override fun hashCode() = id
|
||||
override fun equals(other: Any?) = (other as? AppSettingItem)?.id == this.id
|
||||
|
||||
companion object {
|
||||
var idSeed = AtomicInteger(0)
|
||||
|
||||
var SAMPLE_CCD_HEADER: AppSettingItem? = null
|
||||
var SAMPLE_CCD_BODY: AppSettingItem? = null
|
||||
|
@ -467,7 +479,7 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett
|
|||
|
||||
spinner(PrefI.ipMediaBackground, R.string.background_pattern) {
|
||||
MediaBackgroundDrawable.Kind.values()
|
||||
.filter{it.isMediaBackground}
|
||||
.filter { it.isMediaBackground }
|
||||
.map { it.name }
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<ListView
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/lvList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
|
|
Loading…
Reference in New Issue