diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0a654706c6..ed499e3616 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,19 @@
# Change log for Android @Anytype app.
+## Version 0.1.1 (WIP)
+
+### New features & enhancements 🚀
+
+* Disable animation for edit-mode in order to increase editor performance (#884)
+
+### Design & UX 🔳
+
+*
+
+### Fixes & tech 🚒
+
+*
+
## Version 0.1.0
### New features 🚀
diff --git a/app/src/main/java/com/anytypeio/anytype/ui/page/PageFragment.kt b/app/src/main/java/com/anytypeio/anytype/ui/page/PageFragment.kt
index 3abf557661..ce459a03d1 100644
--- a/app/src/main/java/com/anytypeio/anytype/ui/page/PageFragment.kt
+++ b/app/src/main/java/com/anytypeio/anytype/ui/page/PageFragment.kt
@@ -29,6 +29,7 @@ import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding
import androidx.lifecycle.ViewModelProviders
import androidx.lifecycle.lifecycleScope
+import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.transition.ChangeBounds
import androidx.transition.Fade
@@ -370,7 +371,7 @@ open class PageFragment :
recycler.apply {
layoutManager = LinearLayoutManager(requireContext())
setHasFixedSize(true)
- //itemAnimator = null
+ itemAnimator = null
adapter = pageAdapter
addOnScrollListener(titleVisibilityDetector)
}
@@ -824,7 +825,7 @@ open class PageFragment :
}
bottomMenu.update(count)
if (!bottomMenu.isShowing) {
- //recycler.apply { itemAnimator = DefaultItemAnimator() }
+ recycler.apply { itemAnimator = DefaultItemAnimator() }
hideSoftInput()
Timber.d("Hiding top menu")
topToolbar.invisible()
@@ -835,7 +836,7 @@ open class PageFragment :
}
}
} else {
- //recycler.apply { itemAnimator = null }
+ recycler.apply { itemAnimator = null }
bottomMenu.hideWithAnimation()
hideSelectButton()
}
diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/interface/TextHolder.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/interface/TextHolder.kt
index 9efeb5badc..8352ddb790 100644
--- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/interface/TextHolder.kt
+++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/interface/TextHolder.kt
@@ -1,6 +1,5 @@
package com.anytypeio.anytype.core_ui.features.editor.holders.`interface`
-import android.text.Editable
import android.view.Gravity
import android.view.View
import android.view.inputmethod.InputMethodManager
@@ -74,10 +73,11 @@ interface TextHolder {
}
fun setFocus(item: Focusable) {
- if (item.isFocused)
+ if (item.isFocused) {
focus()
- else
+ } else {
content.clearFocus()
+ }
}
fun focus() {
@@ -86,12 +86,13 @@ interface TextHolder {
post {
if (!hasFocus()) {
if (requestFocus()) {
- context.imm().showSoftInput(this, InputMethodManager.SHOW_IMPLICIT)
+ context.imm().showSoftInput(this, InputMethodManager.SHOW_FORCED)
} else {
Timber.d("Couldn't gain focus")
}
- } else
+ } else {
Timber.d("Already had focus")
+ }
}
}
}
diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml
index ea2657e825..f83febf038 100644
--- a/sample/src/main/AndroidManifest.xml
+++ b/sample/src/main/AndroidManifest.xml
@@ -9,27 +9,27 @@
-
-
+
-
-
+
+
+
diff --git a/sample/src/main/java/com/anytypeio/anytype/sample/DisabledAnimationActivity.kt b/sample/src/main/java/com/anytypeio/anytype/sample/DisabledAnimationActivity.kt
new file mode 100644
index 0000000000..892750881e
--- /dev/null
+++ b/sample/src/main/java/com/anytypeio/anytype/sample/DisabledAnimationActivity.kt
@@ -0,0 +1,266 @@
+package com.anytypeio.anytype.sample
+
+import android.content.Context
+import android.graphics.Color
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.view.inputmethod.InputMethodManager
+import android.widget.EditText
+import androidx.appcompat.app.AppCompatActivity
+import androidx.recyclerview.widget.DiffUtil
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.anytypeio.anytype.core_utils.ext.imm
+import com.anytypeio.anytype.core_utils.ui.ViewType
+import com.anytypeio.anytype.sample.adapter.AbstractAdapter
+import com.anytypeio.anytype.sample.adapter.AbstractHolder
+import kotlinx.android.synthetic.main.activity_disabled_animation.*
+import kotlinx.android.synthetic.main.item_editable.view.*
+import timber.log.Timber
+
+class DisabledAnimationActivity : AppCompatActivity(R.layout.activity_disabled_animation) {
+
+ private val start: List
+ get() = mutableListOf(
+ Mock(
+ id = 0,
+ text = "TITLE",
+ type = 0,
+ isFocused = false
+ ),
+ Mock(
+ id = 0,
+ text = "BULLETED",
+ type = 0,
+ isFocused = true
+ ),
+ Mock(
+ id = 1,
+ text = "PARAGRAPH 2",
+ type = 0,
+ isFocused = false
+ )
+ )
+
+ private val end: List
+ get() = listOf(
+ Mock(
+ id = 0,
+ text = "TITLE",
+ type = 0,
+ isFocused = false
+ ),
+ Mock(
+ id = 0,
+ text = "PARAGRAPH",
+ type = 1,
+ isFocused = true
+ ),
+ Mock(
+ id = 1,
+ text = "PARAGRAPH 2",
+ type = 0,
+ isFocused = false
+ )
+ )
+
+ private val mockAdapter = MockAdapter(
+ items = start.toMutableList()
+ )
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ recycler.apply {
+ layoutManager = CustomLinearLayoutManager(context)
+ adapter = mockAdapter
+ itemAnimator = null
+ }
+ startButton.setOnClickListener {
+ Timber.d("Start button clicked")
+ mockAdapter.update(
+ update = end
+ )
+ }
+
+ endButton.setOnClickListener {
+ Timber.d("End button clicked")
+ mockAdapter.update(
+ update = start
+ )
+ }
+ }
+
+ class MockAdapter(val items: MutableList) : AbstractAdapter(items) {
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AbstractHolder {
+ return when (viewType) {
+ 0 -> {
+ val inflater = LayoutInflater.from(parent.context)
+ val view = inflater.inflate(R.layout.item_editable, parent, false)
+ MockHolder(view)
+ }
+ 1 -> {
+ val inflater = LayoutInflater.from(parent.context)
+ val view = inflater.inflate(R.layout.item_editable, parent, false)
+ MockHolder2(view)
+ }
+ else -> throw IllegalStateException()
+ }
+ }
+
+ override fun getItemViewType(position: Int): Int {
+ return items[position].getViewType()
+ }
+
+ override fun update(update: List) {
+ val old = ArrayList(items)
+ val cb = Differ(old = old, new = update)
+ val result = DiffUtil.calculateDiff(cb)
+ items.clear()
+ items.addAll(update)
+ result.dispatchUpdatesTo(this)
+ }
+ }
+
+ class MockHolder(view: View) : AbstractHolder(view) {
+
+ override fun bind(item: Mock) {
+ Timber.d("Binding item: $item")
+ itemView.input.setText(item.text)
+ if (item.isFocused)
+ focus()
+ else
+ itemView.input.clearFocus()
+ }
+
+ private fun focus() {
+ itemView.input.apply {
+ post {
+ if (!hasFocus()) {
+ if (requestFocus()) {
+ context.imm().showSoftInput(this, InputMethodManager.SHOW_FORCED)
+ } else {
+ Timber.d("Couldn't gain focus")
+ }
+ } else
+ Timber.d("Already had focus")
+ }
+ }
+ }
+ }
+
+ class MockHolder2(view: View) : AbstractHolder(view) {
+
+ override fun bind(item: Mock) {
+ Timber.d("Binding item: $item")
+ itemView.input.setText(item.text)
+ itemView.input.setTextColor(Color.GREEN)
+ if (item.isFocused) focus()
+ }
+
+ private fun focus() {
+ itemView.input.apply {
+ post {
+ Timber.d("Focusing!")
+ if (!hasFocus()) {
+ if (requestFocus()) {
+ context.imm().showSoftInput(this, InputMethodManager.SHOW_FORCED)
+ } else {
+ Timber.d("Couldn't gain focus")
+ }
+ } else
+ Timber.d("Already had focus")
+ }
+ }
+ }
+ }
+
+ data class Mock(
+ val id: Int,
+ val text: String,
+ val isFocused: Boolean,
+ val type: Int
+ ) : ViewType {
+ override fun getViewType(): Int = type
+ }
+
+ class Differ(
+ private val old: List,
+ private val new: List
+ ) : DiffUtil.Callback() {
+
+ override fun getOldListSize(): Int = old.size
+ override fun getNewListSize(): Int = new.size
+
+ override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
+ val oldItem = old[oldItemPosition]
+ val newItem = new[newItemPosition]
+ Timber.d("areItemsTheSame for: $oldItem \n and \n $newItem")
+ return oldItem.id == newItem.id
+ }
+
+ override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
+ val oldItem = old[oldItemPosition]
+ val newItem = new[newItemPosition]
+ Timber.d("areContentsTheSame for: $oldItem \n and \n $newItem")
+ return oldItem == newItem
+ }
+ }
+
+ class CustomLinearLayoutManager(
+ context: Context,
+ //focus: View
+ ) : LinearLayoutManager(context) {
+
+ override fun onInterceptFocusSearch(focused: View, direction: Int): View? {
+ Timber.d("OnInterceptFocusSearch view with text: ${(focused as EditText).text}")
+ when (direction) {
+ View.FOCUS_UP -> {
+ Timber.d("OnInterceptFocusSearch direction: FOCUS_UP")
+ }
+ View.FOCUS_DOWN -> {
+ Timber.d("OnInterceptFocusSearch direction: FOCUS_DOWN")
+ }
+ }
+ //return super.onInterceptFocusSearch(focused, direction)
+
+ //val v = getChildAt(2)?.findViewById(R.id.input)
+
+ //v?.requestFocus()
+
+ //Timber.d("At position 2 there is a view with text: ${(v as EditText).text}")
+
+ return null
+ }
+
+ override fun removeView(child: View?) {
+ Timber.d("On remove view")
+ super.removeView(child)
+ }
+
+ override fun detachView(child: View) {
+ Timber.d("On detach view")
+ super.detachView(child)
+ }
+
+ override fun onFocusSearchFailed(
+ focused: View,
+ focusDirection: Int,
+ recycler: RecyclerView.Recycler,
+ state: RecyclerView.State
+ ): View? {
+ Timber.d("onFocusSearchFailed for view with text: ${(focused as EditText).text}")
+ when (focusDirection) {
+ View.FOCUS_UP -> {
+ Timber.d("onFocusSearchFailed direction: FOCUS_UP")
+ }
+ View.FOCUS_DOWN -> {
+ Timber.d("onFocusSearchFailed direction: FOCUS_DOWN")
+ }
+ }
+ return super.onFocusSearchFailed(focused, focusDirection, recycler, state)
+ }
+ }
+}
diff --git a/sample/src/main/java/com/anytypeio/anytype/sample/adapter/AbstractAdapter.kt b/sample/src/main/java/com/anytypeio/anytype/sample/adapter/AbstractAdapter.kt
new file mode 100644
index 0000000000..136b5da446
--- /dev/null
+++ b/sample/src/main/java/com/anytypeio/anytype/sample/adapter/AbstractAdapter.kt
@@ -0,0 +1,16 @@
+package com.anytypeio.anytype.sample.adapter
+
+import androidx.recyclerview.widget.RecyclerView
+
+abstract class AbstractAdapter(
+ private var items: List
+) : RecyclerView.Adapter>() {
+
+ override fun getItemCount(): Int = items.size
+
+ override fun onBindViewHolder(holder: AbstractHolder, position: Int) {
+ holder.bind(items[position])
+ }
+
+ abstract fun update(update: List)
+}
\ No newline at end of file
diff --git a/sample/src/main/java/com/anytypeio/anytype/sample/adapter/AbstractHolder.kt b/sample/src/main/java/com/anytypeio/anytype/sample/adapter/AbstractHolder.kt
new file mode 100644
index 0000000000..711bbe37de
--- /dev/null
+++ b/sample/src/main/java/com/anytypeio/anytype/sample/adapter/AbstractHolder.kt
@@ -0,0 +1,8 @@
+package com.anytypeio.anytype.sample.adapter
+
+import android.view.View
+import androidx.recyclerview.widget.RecyclerView
+
+abstract class AbstractHolder(view: View) : RecyclerView.ViewHolder(view) {
+ abstract fun bind(item: T)
+}
\ No newline at end of file
diff --git a/sample/src/main/res/layout/activity_disabled_animation.xml b/sample/src/main/res/layout/activity_disabled_animation.xml
new file mode 100644
index 0000000000..e7b0b87b91
--- /dev/null
+++ b/sample/src/main/res/layout/activity_disabled_animation.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sample/src/main/res/layout/item_editable.xml b/sample/src/main/res/layout/item_editable.xml
new file mode 100644
index 0000000000..40eabe1498
--- /dev/null
+++ b/sample/src/main/res/layout/item_editable.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sample/src/main/res/values/styles.xml b/sample/src/main/res/values/styles.xml
index 2215fe243b..cfa9b62f4a 100644
--- a/sample/src/main/res/values/styles.xml
+++ b/sample/src/main/res/values/styles.xml
@@ -5,7 +5,7 @@
- @color/orange
- @color/anytype_text_teal
- - @color/anytype_text_blue
+ - @color/orange
- @style/DialogTheme