gpt4 book ai didi

android - 每个回收器 View 项目上的 ViewTreeObserver.OnGlobalLayoutListener 自动被动调整 TextView 的大小

转载 作者:行者123 更新时间:2023-11-30 04:54:28 25 4
gpt4 key购买 nike

我有一个普通的基本回收器 View 及其适配器。
在单个回收器 View 行中,我有一个 float 的 textView。
textView 宽度长度应按比例固定,即 30 % 的屏幕。
我想放置 OnGlobalLayoutListener 以在文本超过分隔线时自动向下调整文本大小
以便它适合准备好的 textView 框。
我不想把数字换行

因此,我在每个 ViewHolder 上添加了 OnGlobalLayoutListener,如果 costTextView 与分隔线重叠,我希望检测并跟踪每一行项目。

enter image description here

然而发生的事情是它并没有调整所有行的大小,而是仅调整显示在用户屏幕上的部分项目。示例4-7不受影响,8-12受影响,依此类推。

enter image description here

MainFragment.kt

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.os.bundleOf
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.elliot.financetracker.databinding.MainFragmentBinding

class MainFragment : Fragment() {
companion object {
private val TAG = "HomeFragment"
}

private lateinit var thisView: View
private lateinit var binding: MainFragmentBinding
private var cashList: ArrayList<Cash> = ArrayList()
private lateinit var recyclerView: RecyclerView
private lateinit var mAdapter: CashAdapter

init {
cashList = prepareMovieData()
}

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {

binding =
DataBindingUtil.inflate<MainFragmentBinding>(
inflater,
R.layout.main_fragment, container, false
)
thisView = binding.root
return thisView
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recyclerView = binding.rvCash
mAdapter = CashAdapter(cashList, action)
val mLayoutManager: RecyclerView.LayoutManager = LinearLayoutManager(thisView.context)
recyclerView.layoutManager = mLayoutManager
recyclerView.itemAnimator = DefaultItemAnimator()
recyclerView.adapter = mAdapter
}

private val action = object : CashAdapter.ClickedListener {
override fun onItemClick(cash: Cash) {
val bundle = bundleOf("cash" to cash)
this@MainFragment.findNavController().navigate(R.id.edit_frag, bundle)
}
}

private val actionAddNewRecord = object : View.OnClickListener {
override fun onClick(v: View?) {
val arg = Bundle()
arg.putInt("sss", 43)
this@MainFragment.findNavController().navigate(R.id.edit_frag, arg)
}
}

private fun prepareMovieData(): ArrayList<Cash> {
for (i in 0..29) {
cashList.add(
Cash(
"-2000000000000000000000000.00",
"Action & Adventure $i"
)
)
}

return cashList
}

}

CashAdapter.kt

import android.graphics.Rect
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.elliot.financetracker.CashAdapter.CashViewHolder
import com.elliot.financetracker.databinding.CashListRowBinding
import com.elliot.financetracker.utils.*

//import com.example.recyclerviewbinding.databinding.MovieListRowBinding;
class CashAdapter(
private val cashList: List<Cash>,
private val clickedAction: ClickedListener
) : RecyclerView.Adapter<CashViewHolder>() {

companion object {
private var TAG = "CashAdapter"
}

inner class CashViewHolder(private val binding: CashListRowBinding) :
RecyclerView.ViewHolder(binding.root) {
var positionss: Int = -1
fun bind(cash: Cash, clickedAction: ClickedListener, positionss: Int) {
this.positionss = positionss
binding.cash = cash
binding.cvCashView.setOnClickListener {
clickedAction.onItemClick(binding.cash!!)
}
// ---------- NOTE HERE I ADD GLOBAL LAYOUT LISTENER ---------------------------------------------
this.binding.cvCashView.viewTreeObserver.addOnGlobalLayoutListener(globalObserver)
binding.executePendingBindings()
}

private val globalObserver = object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
val overlapped = isOverlapped(binding.tvItemCost, binding.separatorCost)
if (overlapped) {
Log.d(CashAdapter.TAG, "${CashAdapter.TAG}: isOverlapping : $positionss")
binding.tvItemCost.textSize = resizeTextDown(binding.tvItemCost)
// always assumed values in SP units
} else {
Log.d(CashAdapter.TAG, "${CashAdapter.TAG}: isNotOverlapping : $positionss")
}
}
}

private fun resizeTextDown(target: View): Float {
val t = target as TextView
val z = t.textSize
val a = z.pxToSp()
val b = a - 2.0F
// leave it as SP unit will do**
return b
}
}

interface ClickedListener {
fun onItemClick(cash: Cash)
}

fun isOverlapped(tvItemCost: View, g20: View): Boolean {
val firstPosition = IntArray(2)
val secondPosition = IntArray(2)
tvItemCost.getLocationOnScreen(firstPosition)
g20.getLocationOnScreen(secondPosition)

val rectFirstView = Rect(
firstPosition[0],
firstPosition[1],
firstPosition[0] + tvItemCost.measuredWidth,
firstPosition[1] + tvItemCost.measuredHeight
)
val rectSecondView = Rect(
secondPosition[0],
secondPosition[1],
secondPosition[0] + g20.measuredWidth,
secondPosition[1] + g20.measuredHeight
)

return rectFirstView.intersect(rectSecondView)
}

// plain basic recycler view adapter's methods
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CashViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val binding = CashListRowBinding.inflate(layoutInflater, parent, false)
return CashViewHolder(binding)
}

override fun onBindViewHolder(holder: CashViewHolder, position: Int) {
val cash = cashList[position]
holder.bind(cash, clickedAction, position)
}

override fun getItemCount(): Int {
return cashList.size
}
}

cash_list_row.xml

<?xml version="1.0" encoding="utf-8"?>
<layout 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">

<data>

<variable
name="cash"
type="com.elliot.financetracker.Cash" />
</data>

<androidx.cardview.widget.CardView
android:id="@+id/cv_cash_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="0dp"
android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
app:cardBackgroundColor="@color/colorLightGreen"
app:cardElevation="10dp"
app:cardCornerRadius="@dimen/default_card_corner_radius"
app:cardUseCompatPadding="true">

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp">

<TextView
android:id="@+id/tv_description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="@{cash.description}"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/g_20"
app:layout_constraintTop_toBottomOf="@id/tv_date"
tools:text="Item description Item description Item description Item description" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/g_20"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.7"/>
<View
android:id="@+id/separator_cost"
android:layout_width="1dp"
android:layout_height="0dp"
android:padding="20dp"
android:background="@android:color/darker_gray"
app:layout_constraintLeft_toRightOf="@id/g_20"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<TextView
android:id="@+id/tv_item_cost"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="@{cash.amountString}"
android:gravity="center_vertical"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
tools:text="RM -2000000000.00" />

<!-- removed out ...........-->


</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</layout>

最佳答案

这个可以通过TextView的自动缩放功能完美解决

使用这样的东西

        <TextView
android:layout_width="100dp"
android:layout_height="40dp"
android:maxLines="1"
android:text="hello world google"
app:autoSizeTextType="uniform"
app:autoSizeMinTextSize="1sp"
app:autoSizeMaxTextSize="25sp"
android:gravity="center_vertical"
/>

关于android - 每个回收器 View 项目上的 ViewTreeObserver.OnGlobalLayoutListener 自动被动调整 TextView 的大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59475316/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com