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