スクロール周りの細かいバグ修正

This commit is contained in:
tateisu 2018-01-19 18:27:35 +09:00
parent a4cc7c2f10
commit 8016879f7a
11 changed files with 726 additions and 418 deletions

View File

@ -61,6 +61,7 @@
<w>unmute</w>
<w>unreblog</w>
<w>utoken</w>
<w>workarea</w>
</words>
</dictionary>
</component>

View File

@ -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"

View File

@ -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

View File

@ -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()
}
}

View File

@ -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)
}
}

View File

@ -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

View File

@ -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
}

View File

@ -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) }
}
}

View File

@ -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)
}
}
}

View File

@ -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