Home > OS >  Android Studio: autoSize of EditText doesn't work
Android Studio: autoSize of EditText doesn't work

Time:07-21

in my current project there's an EditText with fixed layout_width and layout_height, called exercise that is expanded downwards programmatically: One line of text (String) "\n" is added to the EditText.

Sometimes the line added to the EditText, let's call it element, is too long to fit inside the full width of the object so it's splitted into a new line. The thing is I would either like the lines' text size in exercise to be resized to fit the EditText's width or have a clear visible distance between each line (element), but just not inside the newline due to not fitting inside the exercise's width.

Therefore I googled as much as I could and tried out every possible solution I could find today. What I tried:

  • Using either EditText as the object and android:autoSizeTextType="uniform" & android:inputType="textMultiLine|textCapSentences"as attributes or androidx.appcompat.widget.AppCompatEditText, accompanied by the attributes app:autoSizeMaxTextSize="28sp", app:autoSizeMinTextSize="8sp"and app:autoSizeStepGranularity="1sp" (with a device that supports just exactly API 26)
  • using other types of text objects
  • using lineSpacingExtra to insert some spacing. This unfortunately also inserted the spacing between the wrapped/ splitted line so the original element's line that got splitted by wrapping inside the EditText had the spacing aswell.

That's where I am now. I can't get the text size be reduced automatically when the line would be too wide for the EditText's width.

I could supply the full XML, if needed.

I'm grateful for any hint that could help here. Thanks in advance!

CodePudding user response:

you can try something like this

if(et.getText().length()>10) {
        et.setTextSize(newValue)

CodePudding user response:

Here's a really basic RecyclerView implementation (using view binding, let me know if you're not familiar with that - you can just findViewById all the things instead):

A picture of the result, with multiple lines at different sizes

class MainFragment : Fragment(R.layout.fragment_main) {

    lateinit var binding: FragmentMainBinding

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        binding = FragmentMainBinding.bind(view)
        with(binding) {
            val adapter = MyAdapter()
            recyclerView.adapter = adapter
            recyclerView.layoutManager = LinearLayoutManager(requireContext())

            addButton.setOnClickListener {
                val item = textEntry.text.toString()
                if (item.isNotBlank()) {
                    adapter.addItem(item)
                    textEntry.text.clear()
                }
            }
        }
    }


}

class MyAdapter : RecyclerView.Adapter<MyAdapter.ViewHolder>() {

    private var data: List<String> = emptyList()

    fun addItem(item: String) {
        data = data   item
        notifyItemInserted(data.lastIndex)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = ItemViewBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.binding.textView.text = data[position]
    }

    override fun getItemCount(): Int = data.size

    class ViewHolder(val binding: ItemViewBinding) : RecyclerView.ViewHolder(binding.root)
}
fragment_main.xml


<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:gravity="center"
    android:padding="10dp">

<androidx.recyclerview.widget.RecyclerView
    android:id="@ id/recyclerView"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_marginBottom="8dp"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toTopOf="@id/textEntry"
    />

    <EditText
        android:id="@ id/textEntry"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:singleLine="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toStartOf="@id/addButton"
        />

    <Button
        android:id="@ id/addButton"
        android:text="ADD"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        />


</androidx.constraintlayout.widget.ConstraintLayout>
item_view.xml


<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingHorizontal="16dp"
    >
    <TextView
        android:id="@ id/textView"
        app:autoSizeTextType="uniform"
        android:layout_width="match_parent"
        android:layout_height="48sp"
        android:maxLines="1"
        android:gravity="center_vertical"
        />

</FrameLayout>

It's pretty simple - you have a text entry field and a button to add the contents as a new line. The button passes the contents to addItem on the adapter, which appends it to the list of lines in data. The RecyclerView just displays all the items in data, using a ViewHolder layout that has an auto-sizing TextView to scale each item.

Ideally you'd want to persist data somehow (e.g. the Add button passes the new data to a ViewModel, stores it somehow, updates the current list which the adapter has observed so it updates whenever there's a change) - I just left it as a basic proof of concept. Also, it's easier to store separate items if they're kept separate - you can always serialise it by joining them into a single string if you really want! But generally you wouldn't want to do that

  • Related