mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
Disable animator in edit mode (#947)
This commit is contained in:
parent
8a2d01c0db
commit
720d20e1be
10 changed files with 388 additions and 16 deletions
|
@ -9,27 +9,27 @@
|
|||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
|
||||
<application
|
||||
android:name="com.anytypeio.anytype.sample.SampleApp"
|
||||
android:name=".SampleApp"
|
||||
android:allowBackup="true"
|
||||
android:fullBackupContent="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:usesCleartextTraffic="true"
|
||||
android:theme="@style/AppTheme"
|
||||
android:usesCleartextTraffic="true"
|
||||
tools:ignore="GoogleAppIndexingWarning">
|
||||
<activity android:name="com.anytypeio.anytype.sample.ScrollAndMove" />
|
||||
<activity android:name="com.anytypeio.anytype.sample.StyleActivity">
|
||||
<activity android:name=".DisabledAnimationActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="com.anytypeio.anytype.sample.MainActivity" />
|
||||
<activity android:name=".ScrollAndMove" />
|
||||
<activity android:name=".StyleActivity" />
|
||||
<activity android:name=".MainActivity" />
|
||||
<activity
|
||||
android:name="com.anytypeio.anytype.sample.KeyboardActivity"
|
||||
android:name=".KeyboardActivity"
|
||||
android:windowSoftInputMode="adjustResize" />
|
||||
</application>
|
||||
|
||||
|
|
|
@ -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<Mock>
|
||||
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<Mock>
|
||||
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<Mock>) : AbstractAdapter<Mock>(items) {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AbstractHolder<Mock> {
|
||||
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<Mock>) {
|
||||
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<Mock>(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<Mock>(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<Mock>,
|
||||
private val new: List<Mock>
|
||||
) : 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<EditText>(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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.anytypeio.anytype.sample.adapter
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
|
||||
abstract class AbstractAdapter<T>(
|
||||
private var items: List<T>
|
||||
) : RecyclerView.Adapter<AbstractHolder<T>>() {
|
||||
|
||||
override fun getItemCount(): Int = items.size
|
||||
|
||||
override fun onBindViewHolder(holder: AbstractHolder<T>, position: Int) {
|
||||
holder.bind(items[position])
|
||||
}
|
||||
|
||||
abstract fun update(update: List<T>)
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package com.anytypeio.anytype.sample.adapter
|
||||
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
|
||||
abstract class AbstractHolder<T>(view: View) : RecyclerView.ViewHolder(view) {
|
||||
abstract fun bind(item: T)
|
||||
}
|
54
sample/src/main/res/layout/activity_disabled_animation.xml
Normal file
54
sample/src/main/res/layout/activity_disabled_animation.xml
Normal file
|
@ -0,0 +1,54 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".DisabledAnimationActivity">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/startButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="@drawable/rectangle_debug"
|
||||
android:fontFamily="monospace"
|
||||
android:gravity="center"
|
||||
android:padding="32dp"
|
||||
android:text="START"
|
||||
android:textColor="@color/orange"
|
||||
app:layout_constraintEnd_toStartOf="@+id/endButton"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/endButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="@drawable/rectangle_debug"
|
||||
android:fontFamily="monospace"
|
||||
android:gravity="center"
|
||||
android:padding="32dp"
|
||||
android:text="END"
|
||||
android:textColor="@color/orange"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/startButton"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="32dp"
|
||||
android:padding="32dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/startButton" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
12
sample/src/main/res/layout/item_editable.xml
Normal file
12
sample/src/main/res/layout/item_editable.xml
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<EditText
|
||||
android:fontFamily="monospace"
|
||||
android:id="@+id/input"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</FrameLayout>
|
|
@ -5,7 +5,7 @@
|
|||
<!-- Customize your theme here. -->
|
||||
<item name="colorPrimary">@color/orange</item>
|
||||
<item name="colorPrimaryDark">@color/anytype_text_teal</item>
|
||||
<item name="colorAccent">@color/anytype_text_blue</item>
|
||||
<item name="colorAccent">@color/orange</item>
|
||||
<!-- <item name="android:dialogTheme">@style/AppBottomSheetDialogTheme</item>-->
|
||||
<item name="alertDialogTheme">@style/DialogTheme</item>
|
||||
<!-- <item name="android:alertDialogTheme">?alertDialogTheme</item>-->
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue