スクロール周りの細かいバグ修正
This commit is contained in:
parent
a4cc7c2f10
commit
8016879f7a
|
@ -61,6 +61,7 @@
|
|||
<w>unmute</w>
|
||||
<w>unreblog</w>
|
||||
<w>utoken</w>
|
||||
<w>workarea</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
</component>
|
|
@ -12,8 +12,8 @@ android {
|
|||
minSdkVersion 21
|
||||
targetSdkVersion 27
|
||||
|
||||
versionCode 207
|
||||
versionName "2.0.7"
|
||||
versionCode 208
|
||||
versionName "2.0.8"
|
||||
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
|
||||
|
|
|
@ -213,7 +213,10 @@ class ActMain : AppCompatActivity()
|
|||
if(tag is ItemViewHolder) {
|
||||
column = tag.column
|
||||
break
|
||||
} else if(tag is ViewHolderHeaderProfile) {
|
||||
}else if(tag is ViewHolderItem ) {
|
||||
column = tag.ivh.column
|
||||
break
|
||||
} else if(tag is ViewHolderHeaderBase) {
|
||||
column = tag.column
|
||||
break
|
||||
} else if(tag is TabletColumnViewHolder) {
|
||||
|
@ -336,7 +339,16 @@ class ActMain : AppCompatActivity()
|
|||
)
|
||||
|
||||
// 新しいカラムをどこに挿入するか
|
||||
val defaultInsertPosition : Int
|
||||
fun nextPosition(column : Column?) : Int {
|
||||
if(column != null) {
|
||||
val pos = app_state.column_list.indexOf(column)
|
||||
if(pos != - 1) return pos + 1
|
||||
}
|
||||
return defaultInsertPosition
|
||||
}
|
||||
|
||||
// 新しいカラムをどこに挿入するか
|
||||
private val defaultInsertPosition : Int
|
||||
get() = phoneTab(
|
||||
{ pe -> pe.pager.currentItem + 1 },
|
||||
{ _ -> Integer.MAX_VALUE }
|
||||
|
@ -371,7 +383,7 @@ class ActMain : AppCompatActivity()
|
|||
// 前回最後に表示していたカラムの位置にスクロールする
|
||||
val column_pos = Pref.ipLastColumnPos(pref)
|
||||
if(column_pos >= 0 && column_pos < app_state.column_list.size) {
|
||||
scrollToColumn(column_pos, true)
|
||||
scrollToColumn(column_pos, false)
|
||||
}
|
||||
|
||||
// 表示位置に合わせたイベントを発行
|
||||
|
@ -687,7 +699,7 @@ class ActMain : AppCompatActivity()
|
|||
if(! app_state.column_list.isEmpty()) {
|
||||
val select = data.getIntExtra(ActColumnList.EXTRA_SELECTION, - 1)
|
||||
if(0 <= select && select < app_state.column_list.size) {
|
||||
scrollToColumn(select, false)
|
||||
scrollToColumn(select)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1267,7 +1279,7 @@ class ActMain : AppCompatActivity()
|
|||
val ivIcon = viewRoot.findViewById<ImageView>(R.id.ivIcon)
|
||||
|
||||
viewRoot.tag = i
|
||||
viewRoot.setOnClickListener { v -> scrollToColumn(v.tag as Int, false) }
|
||||
viewRoot.setOnClickListener { v -> scrollToColumn(v.tag as Int) }
|
||||
viewRoot.contentDescription = column.getColumnName(true)
|
||||
//
|
||||
|
||||
|
@ -1808,7 +1820,7 @@ class ActMain : AppCompatActivity()
|
|||
|
||||
if(! app_state.column_list.isEmpty() && page_delete > 0 && page_showing == page_delete) {
|
||||
val idx = page_delete - 1
|
||||
scrollToColumn(idx, false)
|
||||
scrollToColumn(idx)
|
||||
val c = app_state.column_list[idx]
|
||||
if(! c.bFirstInitialized) {
|
||||
c.startLoading()
|
||||
|
@ -1820,7 +1832,7 @@ class ActMain : AppCompatActivity()
|
|||
|
||||
if(! app_state.column_list.isEmpty() && page_delete > 0) {
|
||||
val idx = page_delete - 1
|
||||
scrollToColumn(idx, false)
|
||||
scrollToColumn(idx)
|
||||
val c = app_state.column_list[idx]
|
||||
if(! c.bFirstInitialized) {
|
||||
c.startLoading()
|
||||
|
@ -1838,7 +1850,7 @@ class ActMain : AppCompatActivity()
|
|||
for(column in app_state.column_list) {
|
||||
if(column.isSameSpec(ai, type, params)) {
|
||||
index = app_state.column_list.indexOf(column)
|
||||
scrollToColumn(index, false)
|
||||
scrollToColumn(index)
|
||||
return column
|
||||
}
|
||||
}
|
||||
|
@ -1846,7 +1858,7 @@ class ActMain : AppCompatActivity()
|
|||
//
|
||||
val col = Column(app_state, ai, this, type, *params)
|
||||
index = addColumn(col, index)
|
||||
scrollToColumn(index, false)
|
||||
scrollToColumn(index)
|
||||
if(! col.bFirstInitialized) {
|
||||
col.startLoading()
|
||||
}
|
||||
|
@ -2047,13 +2059,7 @@ class ActMain : AppCompatActivity()
|
|||
return false
|
||||
}
|
||||
|
||||
fun nextPosition(column : Column?) : Int {
|
||||
if(column != null) {
|
||||
val pos = app_state.column_list.indexOf(column)
|
||||
if(pos != - 1) return pos + 1
|
||||
}
|
||||
return defaultInsertPosition
|
||||
}
|
||||
|
||||
|
||||
private fun addColumn(column : Column, indexArg : Int) : Int {
|
||||
var index = indexArg
|
||||
|
@ -2187,20 +2193,15 @@ class ActMain : AppCompatActivity()
|
|||
env.tablet_pager_adapter.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
private fun scrollToColumn(index : Int, bAlign : Boolean) {
|
||||
private fun scrollToColumn(index : Int, smoothScroll:Boolean = true ) {
|
||||
scrollColumnStrip(index)
|
||||
|
||||
phoneTab(
|
||||
{ env -> env.pager.setCurrentItem(index, true) },
|
||||
{ env ->
|
||||
if(! bAlign) {
|
||||
// 指定したカラムが画面内に表示されるように動いてくれるようだ
|
||||
env.tablet_pager.smoothScrollToPosition(index)
|
||||
} else {
|
||||
// 指定位置が表示範囲の左端にくるようにスクロール
|
||||
env.tablet_pager.scrollToPosition(index)
|
||||
}
|
||||
}
|
||||
|
||||
// スマホはスムーススクロール基本ありだがたまにしない
|
||||
{ env -> env.pager.setCurrentItem(index, smoothScroll) },
|
||||
|
||||
// タブレットでスムーススクロールさせると頻繁にオーバーランするので絶対しない
|
||||
{ env -> env.tablet_pager.scrollToPosition(index) }
|
||||
)
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -32,6 +32,7 @@ import android.support.v7.widget.ListRecyclerView
|
|||
import android.support.v7.widget.LinearLayoutManager
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import jp.juggler.subwaytooter.view.ListDivider
|
||||
import java.io.Closeable
|
||||
import java.lang.reflect.Field
|
||||
|
||||
class ColumnViewHolder(
|
||||
|
@ -48,13 +49,13 @@ class ColumnViewHolder(
|
|||
v.visibility = if(visible) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
val fieldRecycler : Field by lazy{
|
||||
val fieldRecycler : Field by lazy {
|
||||
val field = RecyclerView::class.java.getDeclaredField("mRecycler")
|
||||
field.isAccessible = true
|
||||
field
|
||||
}
|
||||
|
||||
val fieldState :Field by lazy{
|
||||
val fieldState : Field by lazy {
|
||||
val field = RecyclerView::class.java.getDeclaredField("mState")
|
||||
field.isAccessible = true
|
||||
field
|
||||
|
@ -72,7 +73,7 @@ class ColumnViewHolder(
|
|||
val listView : ListRecyclerView
|
||||
val refreshLayout : SwipyRefreshLayout
|
||||
lateinit var listLayoutManager : LinearLayoutManager
|
||||
|
||||
|
||||
private val llColumnHeader : View
|
||||
private val tvColumnIndex : TextView
|
||||
private val tvColumnContext : TextView
|
||||
|
@ -190,8 +191,8 @@ class ColumnViewHolder(
|
|||
|
||||
tvLoading = root.findViewById(R.id.tvLoading)
|
||||
listView = root.findViewById(R.id.listView)
|
||||
|
||||
if(Pref.bpShareViewPool(activity.pref)){
|
||||
|
||||
if(Pref.bpShareViewPool(activity.pref)) {
|
||||
listView.recycledViewPool = activity.viewPool
|
||||
}
|
||||
|
||||
|
@ -260,7 +261,13 @@ class ColumnViewHolder(
|
|||
|
||||
// 入力の追跡
|
||||
etRegexFilter.addTextChangedListener(object : TextWatcher {
|
||||
override fun beforeTextChanged(s : CharSequence, start : Int, count : Int, after : Int) {}
|
||||
override fun beforeTextChanged(
|
||||
s : CharSequence,
|
||||
start : Int,
|
||||
count : Int,
|
||||
after : Int
|
||||
) {
|
||||
}
|
||||
|
||||
override fun onTextChanged(s : CharSequence, start : Int, before : Int, count : Int) {}
|
||||
|
||||
|
@ -317,7 +324,11 @@ class ColumnViewHolder(
|
|||
}
|
||||
|
||||
if(column.hasMultipleViewHolder()) {
|
||||
log.d("restoreScrollPosition [%d] %s , column has multiple view holder. retry later.", page_idx, column.getColumnName(true))
|
||||
log.d(
|
||||
"restoreScrollPosition [%d] %s , column has multiple view holder. retry later.",
|
||||
page_idx,
|
||||
column.getColumnName(true)
|
||||
)
|
||||
|
||||
// タブレットモードでカラムを追加/削除した際に発生する。
|
||||
// このタイミングでスクロール位置を復元してもうまくいかないので延期する
|
||||
|
@ -326,16 +337,26 @@ class ColumnViewHolder(
|
|||
}
|
||||
|
||||
val sp = column.scroll_save ?: //復元後にもここを通るがこれは正常である
|
||||
// log.d( "restoreScrollPosition [%d] %s , column has no saved scroll position.", page_idx, column.getColumnName( true ) );
|
||||
return
|
||||
// log.d( "restoreScrollPosition [%d] %s , column has no saved scroll position.", page_idx, column.getColumnName( true ) );
|
||||
return
|
||||
|
||||
column.scroll_save = null
|
||||
|
||||
if(listView.visibility != View.VISIBLE) {
|
||||
log.d("restoreScrollPosition [%d] %s , listView is not visible. saved position %s,%s is dropped.", page_idx, column.getColumnName(true), sp.pos, sp.top
|
||||
log.d(
|
||||
"restoreScrollPosition [%d] %s , listView is not visible. saved position %s,%s is dropped.",
|
||||
page_idx,
|
||||
column.getColumnName(true),
|
||||
sp.adapterIndex,
|
||||
sp.offset
|
||||
)
|
||||
} else {
|
||||
log.d("restoreScrollPosition [%d] %s , listView is visible. resume %s,%s", page_idx, column.getColumnName(true), sp.pos, sp.top
|
||||
log.d(
|
||||
"restoreScrollPosition [%d] %s , listView is visible. resume %s,%s",
|
||||
page_idx,
|
||||
column.getColumnName(true),
|
||||
sp.adapterIndex,
|
||||
sp.offset
|
||||
)
|
||||
sp.restore(this@ColumnViewHolder)
|
||||
}
|
||||
|
@ -367,7 +388,8 @@ class ColumnViewHolder(
|
|||
|
||||
log.d("onPageCreate [%d] %s", page_idx, column.getColumnName(true))
|
||||
|
||||
val bSimpleList = column.column_type != Column.TYPE_CONVERSATION && Pref.bpSimpleList(activity.pref)
|
||||
val bSimpleList =
|
||||
column.column_type != Column.TYPE_CONVERSATION && Pref.bpSimpleList(activity.pref)
|
||||
|
||||
tvColumnIndex.text = activity.getString(R.string.column_index, page_idx + 1, page_count)
|
||||
|
||||
|
@ -376,7 +398,6 @@ class ColumnViewHolder(
|
|||
val status_adapter = ItemListAdapter(activity, column, this, bSimpleList)
|
||||
this.status_adapter = status_adapter
|
||||
|
||||
|
||||
// status_adapter.header = when(column.column_type) {
|
||||
// Column.TYPE_PROFILE -> ViewHolderHeaderProfile(activity, column, listView)
|
||||
// Column.TYPE_SEARCH -> ViewHolderHeaderSearch(activity, column, listView, activity.getString(R.string.search_desc_mastodon_api))
|
||||
|
@ -436,7 +457,8 @@ class ColumnViewHolder(
|
|||
|
||||
when(column.column_type) {
|
||||
|
||||
Column.TYPE_CONVERSATION, Column.TYPE_INSTANCE_INFORMATION -> refreshLayout.isEnabled = false
|
||||
Column.TYPE_CONVERSATION, Column.TYPE_INSTANCE_INFORMATION -> refreshLayout.isEnabled =
|
||||
false
|
||||
|
||||
Column.TYPE_SEARCH -> {
|
||||
refreshLayout.isEnabled = true
|
||||
|
@ -476,27 +498,48 @@ class ColumnViewHolder(
|
|||
if(c == 0) {
|
||||
llColumnHeader.setBackgroundResource(R.drawable.btn_bg_ddd)
|
||||
} else {
|
||||
ViewCompat.setBackground(llColumnHeader, Styler.getAdaptiveRippleDrawable(
|
||||
c,
|
||||
if(column.header_fg_color != 0)
|
||||
column.header_fg_color
|
||||
else
|
||||
Styler.getAttributeColor(activity, R.attr.colorRippleEffect)
|
||||
))
|
||||
ViewCompat.setBackground(
|
||||
llColumnHeader, Styler.getAdaptiveRippleDrawable(
|
||||
c,
|
||||
if(column.header_fg_color != 0)
|
||||
column.header_fg_color
|
||||
else
|
||||
Styler.getAttributeColor(activity, R.attr.colorRippleEffect)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
c = column.header_fg_color
|
||||
if(c == 0) {
|
||||
tvColumnIndex.setTextColor(Styler.getAttributeColor(activity, R.attr.colorColumnHeaderPageNumber))
|
||||
tvColumnName.setTextColor(Styler.getAttributeColor(activity, android.R.attr.textColorPrimary))
|
||||
Styler.setIconDefaultColor(activity, ivColumnIcon, column.getIconAttrId(column.column_type))
|
||||
tvColumnIndex.setTextColor(
|
||||
Styler.getAttributeColor(
|
||||
activity,
|
||||
R.attr.colorColumnHeaderPageNumber
|
||||
)
|
||||
)
|
||||
tvColumnName.setTextColor(
|
||||
Styler.getAttributeColor(
|
||||
activity,
|
||||
android.R.attr.textColorPrimary
|
||||
)
|
||||
)
|
||||
Styler.setIconDefaultColor(
|
||||
activity,
|
||||
ivColumnIcon,
|
||||
column.getIconAttrId(column.column_type)
|
||||
)
|
||||
Styler.setIconDefaultColor(activity, btnColumnSetting, R.attr.ic_tune)
|
||||
Styler.setIconDefaultColor(activity, btnColumnReload, R.attr.btn_refresh)
|
||||
Styler.setIconDefaultColor(activity, btnColumnClose, R.attr.btn_close)
|
||||
} else {
|
||||
tvColumnIndex.setTextColor(c)
|
||||
tvColumnName.setTextColor(c)
|
||||
Styler.setIconCustomColor(activity, ivColumnIcon, c, column.getIconAttrId(column.column_type))
|
||||
Styler.setIconCustomColor(
|
||||
activity,
|
||||
ivColumnIcon,
|
||||
c,
|
||||
column.getIconAttrId(column.column_type)
|
||||
)
|
||||
Styler.setIconCustomColor(activity, btnColumnSetting, c, R.attr.ic_tune)
|
||||
Styler.setIconCustomColor(activity, btnColumnReload, c, R.attr.btn_refresh)
|
||||
Styler.setIconCustomColor(activity, btnColumnClose, c, R.attr.btn_close)
|
||||
|
@ -513,7 +556,7 @@ class ColumnViewHolder(
|
|||
|
||||
loadBackgroundImage(ivColumnBackgroundImage, column.column_bg_image)
|
||||
|
||||
status_adapter?.getHeaderViewHolder(listView)?.showColor()
|
||||
status_adapter?.findHeaderViewHolder(listView)?.showColor()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -737,15 +780,20 @@ class ColumnViewHolder(
|
|||
column.startLoading()
|
||||
}
|
||||
|
||||
R.id.llColumnHeader ->{
|
||||
if(status_adapter.itemCount > 0){
|
||||
listLayoutManager.scrollToPositionWithOffset(0,0)
|
||||
R.id.llColumnHeader -> {
|
||||
if(status_adapter.itemCount > 0) {
|
||||
listLayoutManager.scrollToPositionWithOffset(0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
R.id.btnColumnSetting -> llColumnSetting.visibility = if(llColumnSetting.visibility == View.VISIBLE) View.GONE else View.VISIBLE
|
||||
R.id.btnColumnSetting -> llColumnSetting.visibility =
|
||||
if(llColumnSetting.visibility == View.VISIBLE) View.GONE else View.VISIBLE
|
||||
|
||||
R.id.btnDeleteNotification -> Action_Notification.deleteAll(activity, column.access_info, false)
|
||||
R.id.btnDeleteNotification -> Action_Notification.deleteAll(
|
||||
activity,
|
||||
column.access_info,
|
||||
false
|
||||
)
|
||||
|
||||
R.id.btnColor -> {
|
||||
val idx = activity.app_state.column_list.indexOf(column)
|
||||
|
@ -774,11 +822,9 @@ class ColumnViewHolder(
|
|||
}
|
||||
|
||||
private fun showColumnCloseButton() {
|
||||
val column = this@ColumnViewHolder.column ?: return
|
||||
|
||||
// カラム保護の状態
|
||||
btnColumnClose.isEnabled = ! column.dont_close
|
||||
btnColumnClose.alpha = if(column.dont_close) 0.3f else 1f
|
||||
val dont_close = column ?.dont_close ?: return
|
||||
btnColumnClose.isEnabled = ! dont_close
|
||||
btnColumnClose.alpha = if(dont_close) 0.3f else 1f
|
||||
}
|
||||
|
||||
// カラムヘッダなど、負荷が低い部分の表示更新
|
||||
|
@ -794,7 +840,12 @@ class ColumnViewHolder(
|
|||
var c : Int
|
||||
|
||||
c = ac.color_fg
|
||||
tvColumnContext.setTextColor(if(c != 0) c else Styler.getAttributeColor(activity, R.attr.colorTimeSmall))
|
||||
tvColumnContext.setTextColor(
|
||||
if(c != 0) c else Styler.getAttributeColor(
|
||||
activity,
|
||||
R.attr.colorTimeSmall
|
||||
)
|
||||
)
|
||||
|
||||
c = ac.color_bg
|
||||
if(c == 0) {
|
||||
|
@ -857,7 +908,7 @@ class ColumnViewHolder(
|
|||
|
||||
refreshLayout.visibility = View.VISIBLE
|
||||
|
||||
status_adapter.getHeaderViewHolder(listView)?.bindData(column)
|
||||
status_adapter.findHeaderViewHolder(listView)?.bindData(column)
|
||||
|
||||
if(! column.bRefreshLoading) {
|
||||
refreshLayout.isRefreshing = false
|
||||
|
@ -878,27 +929,33 @@ class ColumnViewHolder(
|
|||
val column = this.column
|
||||
when {
|
||||
column == null -> log.d("saveScrollPosition [%d] , column==null", page_idx)
|
||||
column.is_dispose.get() -> log.d("saveScrollPosition [%d] , column is disposed", page_idx)
|
||||
|
||||
column.is_dispose.get() -> log.d(
|
||||
"saveScrollPosition [%d] , column is disposed",
|
||||
page_idx
|
||||
)
|
||||
|
||||
listView.visibility != View.VISIBLE -> {
|
||||
val scroll_save = ScrollPosition(0, 0)
|
||||
column.scroll_save = scroll_save
|
||||
log.d("saveScrollPosition [%d] %s , listView is not visible, save %s,%s"
|
||||
log.d(
|
||||
"saveScrollPosition [%d] %s , listView is not visible, save %s,%s"
|
||||
, page_idx
|
||||
, column.getColumnName(true)
|
||||
, scroll_save.pos
|
||||
, scroll_save.top
|
||||
, scroll_save.adapterIndex
|
||||
, scroll_save.offset
|
||||
)
|
||||
}
|
||||
|
||||
else -> {
|
||||
val scroll_save = ScrollPosition(this)
|
||||
column.scroll_save = scroll_save
|
||||
log.d("saveScrollPosition [%d] %s , listView is visible, save %s,%s"
|
||||
log.d(
|
||||
"saveScrollPosition [%d] %s , listView is visible, save %s,%s"
|
||||
, page_idx
|
||||
, column.getColumnName(true)
|
||||
, scroll_save.pos
|
||||
, scroll_save.top
|
||||
, scroll_save.adapterIndex
|
||||
, scroll_save.offset
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -910,43 +967,111 @@ class ColumnViewHolder(
|
|||
|
||||
sp.restore(this)
|
||||
|
||||
val dy = (deltaDp * activity.density +0.5f).toInt()
|
||||
val dy = (deltaDp * activity.density + 0.5f).toInt()
|
||||
if(dy != 0) listView.postDelayed(Runnable {
|
||||
if(column == null || listView.adapter !== last_adapter) return@Runnable
|
||||
|
||||
try {
|
||||
val recycler = fieldRecycler.get(listView) as RecyclerView.Recycler
|
||||
val state = fieldState.get(listView) as RecyclerView.State
|
||||
listLayoutManager.scrollVerticallyBy(dy, recycler,state)
|
||||
}catch(ex:Throwable){
|
||||
listLayoutManager.scrollVerticallyBy(dy, recycler, state)
|
||||
} catch(ex : Throwable) {
|
||||
log.trace(ex)
|
||||
log.e("can't access field in class %s",RecyclerView::class.java.simpleName)
|
||||
log.e("can't access field in class %s", RecyclerView::class.java.simpleName)
|
||||
}
|
||||
}, 20L)
|
||||
}
|
||||
|
||||
inner class AdapterItemHeightWorkarea internal constructor(val adapter:ItemListAdapter) : Closeable {
|
||||
|
||||
private val item_width : Int
|
||||
private val widthSpec : Int
|
||||
private var lastViewType : Int = - 1
|
||||
private var lastViewHolder : RecyclerView.ViewHolder? = null
|
||||
init {
|
||||
this.item_width = listView.width - listView.paddingLeft - listView.paddingRight
|
||||
this.widthSpec = View.MeasureSpec.makeMeasureSpec(item_width, View.MeasureSpec.EXACTLY)
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
val childViewHolder = lastViewHolder
|
||||
if(childViewHolder != null) {
|
||||
adapter.onViewRecycled(childViewHolder)
|
||||
lastViewHolder = null
|
||||
}
|
||||
}
|
||||
|
||||
fun getAdapterItemHeight(adapterIndex : Int) : Int {
|
||||
|
||||
var childViewHolder = listView.findViewHolderForAdapterPosition(adapterIndex)
|
||||
if(childViewHolder != null) {
|
||||
childViewHolder.itemView.measure(widthSpec, heightSpec)
|
||||
return childViewHolder.itemView.measuredHeight
|
||||
}
|
||||
|
||||
|
||||
log.d("getAdapterItemHeight idx=$adapterIndex createView")
|
||||
|
||||
val viewType = adapter.getItemViewType(adapterIndex)
|
||||
|
||||
childViewHolder = lastViewHolder
|
||||
if(childViewHolder == null || lastViewType != viewType) {
|
||||
if(childViewHolder != null) {
|
||||
adapter.onViewRecycled(childViewHolder)
|
||||
}
|
||||
childViewHolder = adapter.onCreateViewHolder(listView, viewType)
|
||||
lastViewHolder = childViewHolder
|
||||
lastViewType = viewType
|
||||
}
|
||||
adapter.onBindViewHolder(childViewHolder, adapterIndex)
|
||||
childViewHolder.itemView.measure(widthSpec, heightSpec)
|
||||
return childViewHolder.itemView.measuredHeight
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun getListItemHeight( idx : Int) : Int {
|
||||
val item_width = listView.width - listView.paddingLeft - listView.paddingRight
|
||||
val widthSpec = View.MeasureSpec.makeMeasureSpec(item_width, View.MeasureSpec.EXACTLY)
|
||||
|
||||
var childViewHolder = listView.findViewHolderForAdapterPosition(idx)
|
||||
if( childViewHolder != null ) {
|
||||
childViewHolder.itemView.measure(widthSpec, heightSpec)
|
||||
return childViewHolder.itemView.measuredHeight
|
||||
}
|
||||
|
||||
// 特定の要素が特定の位置に来るようにスクロール位置を調整する
|
||||
fun setListItemTop(listIndex : Int, yArg : Int) {
|
||||
var adapterIndex = column?.toAdapterIndex(listIndex) ?: return
|
||||
|
||||
val adapter = status_adapter
|
||||
if( adapter != null) {
|
||||
log.d("getListItemHeight idx=$idx createView")
|
||||
val viewType = adapter.getItemViewType(idx)
|
||||
childViewHolder = adapter.createViewHolder(listView, viewType)
|
||||
adapter.bindViewHolder(childViewHolder, idx)
|
||||
childViewHolder.itemView.measure(widthSpec, heightSpec)
|
||||
return childViewHolder.itemView.measuredHeight
|
||||
if( adapter == null) {
|
||||
log.e("setListItemTop: missing status adapter")
|
||||
return
|
||||
}
|
||||
log.e("getListItemHeight: missing status adapter")
|
||||
return 0
|
||||
|
||||
var y = yArg
|
||||
AdapterItemHeightWorkarea(adapter).use { workarea ->
|
||||
while(y > 0 && adapterIndex > 0) {
|
||||
-- adapterIndex
|
||||
y -= workarea.getAdapterItemHeight(adapterIndex)
|
||||
y -= ListDivider.height
|
||||
}
|
||||
}
|
||||
|
||||
if(adapterIndex == 0 && y > 0) y = 0
|
||||
listLayoutManager.scrollToPositionWithOffset(adapterIndex, y)
|
||||
}
|
||||
|
||||
fun getListItemTop(listIndex : Int) : Int {
|
||||
|
||||
val adapterIndex = column?.toAdapterIndex(listIndex)
|
||||
?: return 0
|
||||
|
||||
val childView = listLayoutManager.findViewByPosition(adapterIndex)
|
||||
?: throw IndexOutOfBoundsException("findViewByPosition($adapterIndex) returns null.")
|
||||
|
||||
return childView.top
|
||||
}
|
||||
|
||||
fun findFirstVisibleListItem() : Int {
|
||||
|
||||
val adapterIndex = listLayoutManager.findFirstVisibleItemPosition()
|
||||
|
||||
if(adapterIndex == RecyclerView.NO_POSITION)
|
||||
throw IndexOutOfBoundsException()
|
||||
|
||||
return column?.toListIndex(adapterIndex)
|
||||
?: throw IndexOutOfBoundsException()
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -508,7 +508,7 @@ internal class DlgContextMenu(
|
|||
if( who_host?.isEmpty() != false || who_host == "?" ) {
|
||||
// 何もしない
|
||||
} else {
|
||||
Action_Instance.timelineLocal(activity, who_host)
|
||||
Action_Instance.timelineLocal(activity, pos,who_host)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,10 +21,7 @@ internal class ItemListAdapter(
|
|||
}
|
||||
|
||||
override fun getItemCount() : Int {
|
||||
return when(column.getHeaderType()){
|
||||
null-> column.list_data.size
|
||||
else-> column.list_data.size +1
|
||||
}
|
||||
return column.toAdapterIndex(column.list_data.size)
|
||||
}
|
||||
|
||||
private fun getItemIdForListIndex(position : Int):Long{
|
||||
|
@ -38,7 +35,7 @@ internal class ItemListAdapter(
|
|||
}
|
||||
|
||||
override fun getItemId(position : Int) : Long {
|
||||
val headerType = column.getHeaderType()
|
||||
val headerType = column.headerType
|
||||
if( headerType != null){
|
||||
if(position==0) return 0
|
||||
return getItemIdForListIndex(position-1)
|
||||
|
@ -47,7 +44,7 @@ internal class ItemListAdapter(
|
|||
}
|
||||
|
||||
override fun getItemViewType(position : Int) : Int {
|
||||
val headerType = column.getHeaderType()
|
||||
val headerType = column.headerType
|
||||
if( headerType == null || position>0 ) return 0
|
||||
return headerType.viewType
|
||||
}
|
||||
|
@ -81,15 +78,15 @@ internal class ItemListAdapter(
|
|||
}
|
||||
}
|
||||
|
||||
fun getHeaderViewHolder(listView:RecyclerView): ViewHolderHeaderBase?{
|
||||
return when(column.getHeaderType()){
|
||||
fun findHeaderViewHolder(listView:RecyclerView): ViewHolderHeaderBase?{
|
||||
return when(column.headerType){
|
||||
null-> null
|
||||
else-> listView.findViewHolderForAdapterPosition(0) as? ViewHolderHeaderBase
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder : RecyclerView.ViewHolder, positionArg : Int) {
|
||||
val headerType = column.getHeaderType()
|
||||
val headerType = column.headerType
|
||||
if(holder is ViewHolderItem) {
|
||||
val position = if(headerType != null) positionArg - 1 else positionArg
|
||||
val o = if(position >= 0 && position < list.size) list[position] else null
|
||||
|
|
|
@ -54,14 +54,14 @@ object Styler {
|
|||
|
||||
fun getAttributeDrawable(context : Context, attrId : Int) : Drawable {
|
||||
val drawableId = getAttributeResourceId(context, attrId)
|
||||
return ContextCompat.getDrawable(context, drawableId)
|
||||
?: throw RuntimeException(
|
||||
String.format(
|
||||
Locale.JAPAN,
|
||||
"getDrawable failed. drawableId=0x%x",
|
||||
drawableId
|
||||
)
|
||||
val d = ContextCompat.getDrawable(context, drawableId)
|
||||
return d ?: throw RuntimeException(
|
||||
String.format(
|
||||
Locale.JAPAN,
|
||||
"getDrawable failed. drawableId=0x%x",
|
||||
drawableId
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// ImageViewにアイコンを設定する
|
||||
|
@ -250,13 +250,12 @@ object Styler {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// ActMainの初期化時に更新される
|
||||
var round_ratio :Float = 0.33f * 0.5f
|
||||
var round_ratio : Float = 0.33f * 0.5f
|
||||
|
||||
fun calcIconRound(wh:Int) =wh.toFloat() * round_ratio
|
||||
|
||||
fun calcIconRound(lp:ViewGroup.LayoutParams)
|
||||
=Math.min(lp.width,lp.height).toFloat() * round_ratio
|
||||
fun calcIconRound(wh : Int) = wh.toFloat() * round_ratio
|
||||
|
||||
fun calcIconRound(lp : ViewGroup.LayoutParams) =
|
||||
Math.min(lp.width, lp.height).toFloat() * round_ratio
|
||||
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ object Action_Instance {
|
|||
|
||||
// 指定タンスのローカルタイムラインを開く
|
||||
fun timelineLocal(
|
||||
activity : ActMain, host : String
|
||||
activity : ActMain, pos:Int,host : String
|
||||
) {
|
||||
// 指定タンスのアカウントを持ってるか?
|
||||
val account_list = ArrayList<SavedAccount>()
|
||||
|
@ -40,7 +40,7 @@ object Action_Instance {
|
|||
// 持ってないなら疑似アカウントを追加する
|
||||
val ai = addPseudoAccount(activity, host)
|
||||
if(ai != null) {
|
||||
activity.addColumn(activity.defaultInsertPosition, ai, Column.TYPE_LOCAL)
|
||||
activity.addColumn(pos, ai, Column.TYPE_LOCAL)
|
||||
}
|
||||
} else {
|
||||
// 持ってるならアカウントを選んで開く
|
||||
|
@ -51,7 +51,7 @@ object Action_Instance {
|
|||
bAuto = false,
|
||||
message = activity.getString(R.string.account_picker_add_timeline_of, host),
|
||||
accountListArg = account_list
|
||||
) { ai -> activity.addColumn(activity.defaultInsertPosition, ai, Column.TYPE_LOCAL) }
|
||||
) { ai -> activity.addColumn(pos, ai, Column.TYPE_LOCAL) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,47 +3,32 @@ package jp.juggler.subwaytooter.util
|
|||
import android.support.v7.widget.RecyclerView
|
||||
import jp.juggler.subwaytooter.ColumnViewHolder
|
||||
|
||||
class ScrollPosition{
|
||||
|
||||
var pos : Int = 0
|
||||
val top : Int
|
||||
class ScrollPosition {
|
||||
|
||||
constructor(pos : Int, top : Int) {
|
||||
this.pos = pos
|
||||
this.top = top
|
||||
var adapterIndex : Int
|
||||
val offset : Int
|
||||
|
||||
constructor(adapterIndex : Int, top : Int) {
|
||||
this.adapterIndex = adapterIndex
|
||||
this.offset = top
|
||||
}
|
||||
|
||||
// constructor(listView : MyListView) {
|
||||
// if(listView.childCount == 0) {
|
||||
// top = 0
|
||||
// pos = top
|
||||
// } else {
|
||||
// pos = listView.firstVisiblePosition
|
||||
// top = listView.getChildAt(0).top
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fun restore(listView : MyListView) {
|
||||
// if(0 <= pos && pos < listView.adapter.count) {
|
||||
// listView.setSelectionFromTop(pos, top)
|
||||
// }
|
||||
// }
|
||||
|
||||
constructor(holder:ColumnViewHolder) {
|
||||
val findPosition = holder.listLayoutManager.findFirstVisibleItemPosition()
|
||||
if( findPosition == RecyclerView.NO_POSITION){
|
||||
top = 0
|
||||
pos = top
|
||||
}else{
|
||||
pos = findPosition
|
||||
val firstItemView = holder.listLayoutManager.findViewByPosition(findPosition)
|
||||
top = firstItemView?.top ?: 0
|
||||
constructor(holder : ColumnViewHolder) {
|
||||
val layoutManager = holder.listLayoutManager
|
||||
val findPosition = layoutManager.findFirstVisibleItemPosition()
|
||||
if(findPosition == RecyclerView.NO_POSITION) {
|
||||
adapterIndex = 0
|
||||
offset = 0
|
||||
} else {
|
||||
adapterIndex = findPosition
|
||||
val firstItemView = layoutManager.findViewByPosition(findPosition)
|
||||
offset = firstItemView?.top ?: 0
|
||||
}
|
||||
}
|
||||
|
||||
fun restore(holder:ColumnViewHolder) {
|
||||
if(0 <= pos && pos < holder.listView.adapter.itemCount) {
|
||||
holder.listLayoutManager.scrollToPositionWithOffset(pos,top)
|
||||
fun restore(holder : ColumnViewHolder) {
|
||||
if(adapterIndex in 0 until holder.listView.adapter.itemCount) {
|
||||
holder.listLayoutManager.scrollToPositionWithOffset(adapterIndex, offset)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,17 +111,20 @@ class MyNetworkImageView : AppCompatImageView {
|
|||
return null
|
||||
}
|
||||
|
||||
private fun cancelLoading() {
|
||||
private fun cancelLoading(defaultDrawable: Drawable?) {
|
||||
|
||||
val d = drawable
|
||||
if(d is Animatable) {
|
||||
if(d.isRunning) {
|
||||
//log.d("cancelLoading: Animatable.stop()")
|
||||
d.stop()
|
||||
}
|
||||
}
|
||||
|
||||
setImageDrawable(defaultDrawable)
|
||||
|
||||
val target = mTarget
|
||||
if(target != null) {
|
||||
val d = drawable
|
||||
if(d is Animatable) {
|
||||
if(d.isRunning) {
|
||||
//log.d("cancelLoading: Animatable.stop()")
|
||||
d.stop()
|
||||
}
|
||||
}
|
||||
setImageDrawable(null)
|
||||
try {
|
||||
getGlide()?.clear(target)
|
||||
} catch(ex : Throwable) {
|
||||
|
@ -133,21 +136,12 @@ class MyNetworkImageView : AppCompatImageView {
|
|||
|
||||
}
|
||||
|
||||
// デフォルト画像かnullを表示する
|
||||
private fun setDefaultImageOrNull() {
|
||||
|
||||
val d = drawable
|
||||
if(d is Animatable) {
|
||||
if(d.isRunning) {
|
||||
log.d("setDefaultImageOrNull: Animatable.stop()")
|
||||
d.stop()
|
||||
}
|
||||
}
|
||||
|
||||
if(mDefaultImageId != 0) {
|
||||
setImageResource(mDefaultImageId)
|
||||
} else {
|
||||
setImageDrawable(null)
|
||||
// デフォルト画像かnull
|
||||
private fun getDefaultDrawable(context:Context?):Drawable? {
|
||||
return if(context!= null && mDefaultImageId != 0) {
|
||||
ContextCompat.getDrawable(context, mDefaultImageId)
|
||||
}else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,21 +152,19 @@ class MyNetworkImageView : AppCompatImageView {
|
|||
if(url?.isEmpty() != false) {
|
||||
// if the URL to be loaded in this view is empty,
|
||||
// cancel any old requests and clear the currently loaded image.
|
||||
cancelLoading()
|
||||
setDefaultImageOrNull()
|
||||
cancelLoading(getDefaultDrawable(context))
|
||||
return
|
||||
}
|
||||
|
||||
// すでにリクエストが発行済みで、リクエストされたURLが同じなら何もしない
|
||||
if((mTarget as? UrlTarget)?.urlLoading == url) return
|
||||
|
||||
// if there is a pre-existing request, cancel it if it's fetching a different URL.
|
||||
cancelLoading(getDefaultDrawable(context))
|
||||
|
||||
// 非表示状態ならロードを延期する
|
||||
if(!isShown) return
|
||||
|
||||
// if there is a pre-existing request, cancel it if it's fetching a different URL.
|
||||
cancelLoading()
|
||||
setDefaultImageOrNull()
|
||||
|
||||
var wrapWidth = false
|
||||
var wrapHeight = false
|
||||
val lp = layoutParams
|
||||
|
@ -288,7 +280,7 @@ class MyNetworkImageView : AppCompatImageView {
|
|||
override fun onLoadFailed(errorDrawable : Drawable?) = onLoadFailed(urlLoading)
|
||||
|
||||
override fun onResourceReady(
|
||||
resource : Drawable,
|
||||
drawable : Drawable,
|
||||
transition : Transition<in Drawable>?
|
||||
) {
|
||||
try {
|
||||
|
@ -300,18 +292,18 @@ class MyNetworkImageView : AppCompatImageView {
|
|||
when {
|
||||
mCornerRadius <= 0f -> {
|
||||
// 角丸でないならそのまま使う
|
||||
resource
|
||||
drawable
|
||||
}
|
||||
|
||||
// GidDrawableを置き換える
|
||||
resource is GifDrawable -> replaceGifDrawable(resource)
|
||||
drawable is GifDrawable -> replaceGifDrawable(drawable)
|
||||
|
||||
// Glide 4.xから、静止画はBitmapDrawableになった
|
||||
resource is BitmapDrawable -> replaceBitmapDrawable(resource)
|
||||
drawable is BitmapDrawable -> replaceBitmapDrawable(drawable)
|
||||
|
||||
else -> {
|
||||
log.d("onResourceReady: drawable class=%s", resource.javaClass)
|
||||
resource
|
||||
log.d("onResourceReady: drawable class=%s", drawable.javaClass)
|
||||
drawable
|
||||
}
|
||||
}
|
||||
)
|
||||
|
@ -321,10 +313,10 @@ class MyNetworkImageView : AppCompatImageView {
|
|||
|
||||
}
|
||||
|
||||
private fun afterResourceReady(transition : Transition<in Drawable>?, resource : Drawable) {
|
||||
super.onResourceReady(resource, transition)
|
||||
private fun afterResourceReady(transition : Transition<in Drawable>?, drawable : Drawable) {
|
||||
super.onResourceReady(drawable, transition)
|
||||
|
||||
// if( ! resource.isAnimated() ){
|
||||
// if( ! drawable.isAnimated() ){
|
||||
// //XXX: Try to generalize this to other sizes/shapes.
|
||||
// // This is a dirty hack that tries to make loading square thumbnails and then square full images less costly
|
||||
// // by forcing both the smaller thumb and the larger version to have exactly the same intrinsic dimensions.
|
||||
|
@ -332,26 +324,26 @@ class MyNetworkImageView : AppCompatImageView {
|
|||
// // the ImageView requests a layout. Scrolling rapidly while replacing thumbs with larger images triggers
|
||||
// // lots of these calls and causes significant amounts of jank.
|
||||
// float viewRatio = view.getWidth() / (float) view.getHeight();
|
||||
// float drawableRatio = resource.getIntrinsicWidth() / (float) resource.getIntrinsicHeight();
|
||||
// float drawableRatio = drawable.getIntrinsicWidth() / (float) drawable.getIntrinsicHeight();
|
||||
// if( Math.abs( viewRatio - 1f ) <= SQUARE_RATIO_MARGIN
|
||||
// && Math.abs( drawableRatio - 1f ) <= SQUARE_RATIO_MARGIN ){
|
||||
// resource = new SquaringDrawable( resource, view.getWidth() );
|
||||
// drawable = new SquaringDrawable( drawable, view.getWidth() );
|
||||
// }
|
||||
// }
|
||||
|
||||
this.glide_drawable = resource
|
||||
if(resource is GifDrawable) {
|
||||
resource.setLoopCount(GifDrawable.LOOP_FOREVER)
|
||||
resource.start()
|
||||
} else if(resource is MyGifDrawable) {
|
||||
resource.setLoopCount(GifDrawable.LOOP_FOREVER)
|
||||
resource.start()
|
||||
this.glide_drawable = drawable
|
||||
if(drawable is GifDrawable) {
|
||||
drawable.setLoopCount(GifDrawable.LOOP_FOREVER)
|
||||
drawable.start()
|
||||
} else if(drawable is MyGifDrawable) {
|
||||
drawable.setLoopCount(GifDrawable.LOOP_FOREVER)
|
||||
drawable.start()
|
||||
}
|
||||
}
|
||||
|
||||
// super.onResourceReady から呼ばれる
|
||||
override fun setResource(resource : Drawable?) {
|
||||
setImageDrawable(resource)
|
||||
override fun setResource(drawable : Drawable?) {
|
||||
setImageDrawable(drawable)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
|
@ -388,7 +380,7 @@ class MyNetworkImageView : AppCompatImageView {
|
|||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
cancelLoading()
|
||||
cancelLoading(null)
|
||||
super.onDetachedFromWindow()
|
||||
}
|
||||
|
||||
|
@ -421,13 +413,14 @@ class MyNetworkImageView : AppCompatImageView {
|
|||
|
||||
override fun onDraw(canvas : Canvas) {
|
||||
|
||||
// bitmapがrecycledされた場合でもそのまま描画する
|
||||
// bitmapがrecycledされた場合に例外をキャッチする
|
||||
try {
|
||||
super.onDraw(canvas)
|
||||
} catch(ex : Throwable) {
|
||||
log.trace(ex)
|
||||
}
|
||||
|
||||
|
||||
// media type の描画
|
||||
val media_type_drawable = this.media_type_drawable
|
||||
if(media_type_drawable != null) {
|
||||
val drawable_w = media_type_drawable.intrinsicWidth
|
||||
|
|
Loading…
Reference in New Issue