Skip to content

Commit

Permalink
AOSPの設定みたいに、設定項目を色付け点滅させて分かるようにした
Browse files Browse the repository at this point in the history
  • Loading branch information
takusan23 committed Nov 1, 2020
1 parent 4e524ab commit 6e9e5b4
Show file tree
Hide file tree
Showing 4 changed files with 1,019 additions and 51 deletions.
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
package io.github.takusan23.searchpreferencefragment

import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.util.Log
import android.view.View
import androidx.core.view.postDelayed
import androidx.fragment.app.viewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
import androidx.preference.*
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView

/**
* [SearchPreferenceFragment]に置くFragment。設定項目一覧はこのFragmentで表示している
Expand All @@ -18,6 +22,9 @@ class SearchPreferenceChildFragment : PreferenceFragmentCompat() {
/** 最初に表示されるPreferenceのID */
private val defaultPreferenceResId by lazy { arguments?.getInt(PREFERENCE_XML_RESOURCE_ID) }

/** 検索結果を押したときに設定項目をハイライトさせる色 */
var SEARCH_SCROLL_HIGH_LIGHT_COLOR = Color.parseColor("#80ffff00")

companion object {
/** 最初に表示するPreferenceのリソースID */
const val PREFERENCE_XML_RESOURCE_ID = "preference_xml_resource_id"
Expand Down Expand Up @@ -59,31 +66,9 @@ class SearchPreferenceChildFragment : PreferenceFragmentCompat() {
(fragment as? PreferenceFragmentCompat)?.apply {
val scrollTitle = arguments?.getString("scroll_title")
val scrollKey = arguments?.getString("scroll_key")

val pos = getAllPreference(preferenceScreen).indexOfFirst { preference ->
if (scrollKey != null) {
preference.key == scrollKey
} else {
Log.e(javaClass.simpleName, "Preferenceにkeyが設定されていなかったため、同じタイトルの設定項目へスクロールします。")
preference.title == scrollTitle
}
}
// なんか遅延させると動く
view?.postDelayed({
if (isAdded) {
/**
* LayoutManager経由でスクロールする。RecyclerViewにもスクロール関数が生えてるけど、なんか実装空っぽだった
*
* なので、[PreferenceFragmentCompat.scrollToPreference]も、RecyclerViewの実装空っぽスクロール関数を呼んでいるため動かない。
* */
(listView.layoutManager as LinearLayoutManager).apply {
scrollToPositionWithOffset(pos, 0)
}
}
}, 500)

// スクロール
scroll(getAllPreference(preferenceScreen), listView, scrollKey, scrollTitle)
}

}
})
return true
Expand Down Expand Up @@ -115,41 +100,64 @@ class SearchPreferenceChildFragment : PreferenceFragmentCompat() {
}
}

// 表示中のPreferenceを配列にして持っておく
val preferenceList = getAllPreference(preferenceScreen)

// 検索結果Preferenceを押したときのコールバック的なLiveData
viewModel.changePreferenceScreen.observe(viewLifecycleOwner) { result ->
// 同じリソースIDなら
if (result.resId == defaultPreferenceResId) {
// スクロール
val pos = getAllPreference(preferenceScreen).indexOfFirst { preference ->
if (result.preference.key != null) {
preference.key == result.preference.key
} else {
Log.e(javaClass.simpleName, "Preferenceにkeyが設定されていなかったため、同じタイトルの設定項目へスクロールします。")
preference.title == result.preferenceTitle
}
}
// なんか遅延させると動く
view.postDelayed({
if (isAdded) {
/**
* LayoutManager経由でスクロールする。RecyclerViewにもスクロール関数が生えてるけど、なんか実装空っぽだった
*
* なので、[PreferenceFragmentCompat.scrollToPreference]も、RecyclerViewの実装空っぽスクロール関数を呼んでいるため動かない。
* */
(listView.layoutManager as LinearLayoutManager).apply {
scrollToPositionWithOffset(pos, 0)
scroll(preferenceList, listView, result.preference.key, result.preferenceTitle)
}
}

}

private fun scroll(preferenceList: ArrayList<Preference>, listView: RecyclerView, preferenceKey: String?, preferenceTitle: String?) {
// スクロール
val pos = preferenceList.indexOfFirst { preference ->
if (preferenceKey != null) {
preference.key == preferenceKey
} else {
Log.e(javaClass.simpleName, "Preferenceにkeyが設定されていなかったため、同じタイトルの設定項目へスクロールします。")
preference.title == preferenceTitle
}
}
// なんか遅延させると動く
listView.postDelayed(500) {
/**
* LayoutManager経由でスクロールする。RecyclerViewにもスクロール関数が生えてるけど、なんか実装空っぽだった
*
* なので、[PreferenceFragmentCompat.scrollToPreference]も、RecyclerViewの実装空っぽスクロール関数を呼んでいるため動かない。
* */
val visibleItem = (listView.layoutManager as LinearLayoutManager).let {
// 真ん中へスクロールさせたいので
(it.findLastCompletelyVisibleItemPosition() - it.findFirstVisibleItemPosition()) / 2
}
listView.smoothScrollToPosition(pos + visibleItem)
// リピートさせる
var delayTime = 200L
repeat(9) { // 奇数回だと色ついて終わる
// コルーチンだともっときれいにかけそう
listView.postDelayed(delayTime) {
// RecyclerViewの指定した位置のViewを取得して背景色を変更
(listView.layoutManager as LinearLayoutManager).findViewByPosition(pos)?.apply {
background = if (background == null) {
ColorDrawable(SEARCH_SCROLL_HIGH_LIGHT_COLOR)
} else {
null
}
}
}, 500)
}
delayTime += 500
}
}

}

/** Preferenceをすべて見つけて配列にして返す関数 */
private fun getAllPreference(preferenceScreen: PreferenceScreen): ArrayList<Preference> {
// 設定項目を配列にしまう
val preferenceList = arrayListOf<Preference>().apply {
return arrayListOf<Preference>().apply {
// 再帰的に呼び出す
fun getChildPreference(group: PreferenceGroup) {
val preferenceCount = group.preferenceCount
Expand All @@ -163,7 +171,6 @@ class SearchPreferenceChildFragment : PreferenceFragmentCompat() {
}
getChildPreference(preferenceScreen)
}
return preferenceList
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,10 @@ class SearchPreferenceViewModel(application: Application, private val preference

// PreferenceCategoryなら名前を控える。
if (parser.name == "PreferenceCategory" && isCategoryShow) {
val attrs = Xml.asAttributeSet(parser)
val categoryPreference = Preference(context, attrs) // ローカライズに対応させるため
if (eventType == XmlPullParser.START_TAG) {
categoryName = title // 囲いはじめ
categoryName = categoryPreference.title.toString() // 囲いはじめ
}
if (eventType == XmlPullParser.END_TAG) {
categoryName = null // 終了タグ
Expand All @@ -94,8 +96,10 @@ class SearchPreferenceViewModel(application: Application, private val preference
} else {
pref.summary
}
// 属性の方を優先して登録する。なければ遷移先Fragment
pref.fragment = fragmentAttr ?: fragmentName
// もしdependencyが設定されている場合は剥がす(表示できないエラーを回避)
pref.dependency = null
// 階層Fragmentが指定されていればそれを、なければnull
pref.fragment = fragmentName
val data = SearchPreferenceParseData(
preference = pref,
resId = xmlResId,
Expand Down
Loading

0 comments on commit 6e9e5b4

Please sign in to comment.