• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.intentresolver.widget
18 
19 import android.content.Context
20 import android.graphics.drawable.Drawable
21 import android.util.AttributeSet
22 import android.view.LayoutInflater
23 import android.view.View
24 import android.view.ViewGroup
25 import android.widget.TextView
26 import androidx.recyclerview.widget.LinearLayoutManager
27 import androidx.recyclerview.widget.RecyclerView
28 import com.android.intentresolver.R
29 
30 class ScrollableActionRow : RecyclerView, ActionRow {
31     constructor(context: Context) : this(context, null)
32     constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
33     constructor(
34         context: Context, attrs: AttributeSet?, defStyleAttr: Int
35     ) : super(context, attrs, defStyleAttr) {
36         layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
37         adapter = Adapter(context)
38     }
39 
40     private val actionsAdapter get() = adapter as Adapter
41 
42     override fun setActions(actions: List<ActionRow.Action>) {
43         actionsAdapter.setActions(actions)
44     }
45 
46     override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
47         super.onLayout(changed, l, t, r, b)
48         setOverScrollMode(
49             if (areAllChildrenVisible) View.OVER_SCROLL_NEVER else View.OVER_SCROLL_ALWAYS
50         )
51     }
52 
53     private class Adapter(private val context: Context) : RecyclerView.Adapter<ViewHolder>() {
54         private val iconSize: Int =
55             context.resources.getDimensionPixelSize(R.dimen.chooser_action_view_icon_size)
56         private val itemLayout = R.layout.chooser_action_view
57         private var actions: List<ActionRow.Action> = emptyList()
58 
59         override fun onCreateViewHolder(parent: ViewGroup, type: Int): ViewHolder =
60             ViewHolder(
61                 LayoutInflater.from(context).inflate(itemLayout, null) as TextView,
62                 iconSize
63             )
64 
65         override fun onBindViewHolder(holder: ViewHolder, position: Int) {
66             holder.bind(actions[position])
67         }
68 
69         override fun getItemCount() = actions.size
70 
71         override fun onViewRecycled(holder: ViewHolder) {
72             holder.unbind()
73         }
74 
75         override fun onFailedToRecycleView(holder: ViewHolder): Boolean {
76             holder.unbind()
77             return super.onFailedToRecycleView(holder)
78         }
79 
80         fun setActions(actions: List<ActionRow.Action>) {
81             this.actions = ArrayList(actions)
82             notifyDataSetChanged()
83         }
84     }
85 
86     private class ViewHolder(
87         private val view: TextView, private val iconSize: Int
88     ) : RecyclerView.ViewHolder(view) {
89 
90         fun bind(action: ActionRow.Action) {
91             action.icon?.let { icon ->
92                 icon.setBounds(0, 0, iconSize, iconSize)
93                 // some drawables (edit) does not gets tinted when set to the top of the text
94                 // with TextView#setCompoundDrawableRelative
95                 tintIcon(icon, view)
96                 view.setCompoundDrawablesRelative(null, icon, null, null)
97             }
98             view.text = action.label ?: ""
99             view.setOnClickListener {
100                 action.onClicked.run()
101             }
102             view.id = action.id
103         }
104 
105         fun unbind() {
106             view.setOnClickListener(null)
107         }
108 
109         private fun tintIcon(drawable: Drawable, view: TextView) {
110             val tintList = view.compoundDrawableTintList ?: return
111             drawable.setTintList(tintList)
112             view.compoundDrawableTintMode?.let { drawable.setTintMode(it) }
113             view.compoundDrawableTintBlendMode?.let { drawable.setTintBlendMode(it) }
114         }
115     }
116 }
117