summaryrefslogtreecommitdiff
path: root/java/src
diff options
context:
space:
mode:
author Andrey Epin <ayepin@google.com> 2022-12-19 09:02:11 -0800
committer Andrey Epin <ayepin@google.com> 2022-12-19 09:38:24 -0800
commit68163c09ae1bfd8ebeaabfd21b78650b2ede00df (patch)
tree279d6db5a019c2492e0a5d9ea58ea4be096319ac /java/src
parentdc36b45b534e9f438de69238c8b762b7ff5c8d89 (diff)
A base scrollable action row implementation
A base implementation of the new scrollable action row; the view is added to the codebase but not used. Bug: 262278109 Test: Tested with some debug code injections (base functionality, a11y, unit tests). Change-Id: Ic109440ce9609e73b72fc86c2cd455c42a421103
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/intentresolver/widget/ScrollableActionRow.kt120
1 files changed, 120 insertions, 0 deletions
diff --git a/java/src/com/android/intentresolver/widget/ScrollableActionRow.kt b/java/src/com/android/intentresolver/widget/ScrollableActionRow.kt
new file mode 100644
index 00000000..f3a34985
--- /dev/null
+++ b/java/src/com/android/intentresolver/widget/ScrollableActionRow.kt
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.intentresolver.widget
+
+import android.content.Context
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.android.intentresolver.R
+
+class ScrollableActionRow : RecyclerView, ActionRow {
+ constructor(context: Context) : this(context, null)
+ constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
+ constructor(
+ context: Context, attrs: AttributeSet?, defStyleAttr: Int
+ ) : super(context, attrs, defStyleAttr) {
+ layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
+ adapter = Adapter(context)
+ }
+
+ private val actionsAdapter get() = adapter as Adapter
+
+ override fun setActions(actions: List<ActionRow.Action>) {
+ actionsAdapter.setActions(actions)
+ }
+
+ override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
+ super.onLayout(changed, l, t, r, b)
+ setOverScrollMode(
+ if (areAllChildrenVisible) View.OVER_SCROLL_NEVER else View.OVER_SCROLL_ALWAYS
+ )
+ }
+
+ private val areAllChildrenVisible: Boolean
+ get() {
+ val count = getChildCount()
+ if (count == 0) return true
+ val first = getChildAt(0)
+ val last = getChildAt(count - 1)
+ return getChildAdapterPosition(first) == 0
+ && getChildAdapterPosition(last) == actionsAdapter.itemCount - 1
+ && isFullyVisible(first)
+ && isFullyVisible(last)
+ }
+
+ private fun isFullyVisible(view: View): Boolean =
+ view.left >= paddingLeft && view.right <= width - paddingRight
+
+ private class Adapter(private val context: Context) : RecyclerView.Adapter<ViewHolder>() {
+ private val iconSize: Int =
+ context.resources.getDimensionPixelSize(R.dimen.chooser_action_view_icon_size)
+ private val itemLayout = R.layout.chooser_action_view
+ private var actions: List<ActionRow.Action> = emptyList()
+
+ override fun onCreateViewHolder(parent: ViewGroup, type: Int): ViewHolder =
+ ViewHolder(
+ LayoutInflater.from(context).inflate(itemLayout, null) as TextView,
+ iconSize
+ )
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ holder.bind(actions[position])
+ }
+
+ override fun getItemCount() = actions.size
+
+ override fun onViewRecycled(holder: ViewHolder) {
+ holder.unbind()
+ }
+
+ override fun onFailedToRecycleView(holder: ViewHolder): Boolean {
+ holder.unbind()
+ return super.onFailedToRecycleView(holder)
+ }
+
+ fun setActions(actions: List<ActionRow.Action>) {
+ this.actions = ArrayList(actions)
+ notifyDataSetChanged()
+ }
+ }
+
+ private class ViewHolder(
+ private val view: TextView, private val iconSize: Int
+ ) : RecyclerView.ViewHolder(view) {
+
+ fun bind(action: ActionRow.Action) {
+ if (action.icon != null) {
+ action.icon.setBounds(0, 0, iconSize, iconSize)
+ view.setCompoundDrawablesRelative(null, action.icon, null, null)
+ }
+ view.text = action.label ?: ""
+ view.setOnClickListener {
+ action.onClicked.run()
+ }
+ view.id = action.id
+ }
+
+ fun unbind() {
+ view.setOnClickListener(null)
+ }
+ }
+}