简体   繁体   中英

Having an imageview right aligned to a textview

Looking for a way to align an Imageview which would be in line with the textview and have it be able to adjust if the textview is too long and will extend to the next line. The reason it is an imageView, is I want it to be clickable

I haven't been successful, I have tried image and text spans and also constraintlayout but I can't seem to the get following result below:

Thanks [1]: https://i.stack.imgur.com/onPT9.png

Here is a way to add an image to the end of the text in a TextView whether the text spans one or several lines. The approach is to add a space to the end of each text string and replace that space with an ImageSpan overlaid with a ClickableSpan .

Here is the layout used:

<androidx.appcompat.widget.LinearLayoutCompat
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:background="@android:color/holo_blue_light"
        android:padding="8dp"
        android:text="@string/test_string_1"
        android:textSize="28sp" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:background="@android:color/holo_blue_light"
        android:padding="8dp"
        android:text="@string/test_string_2"
        android:textSize="28sp" />

</androidx.appcompat.widget.LinearLayoutCompat>

And the string resources:

<string name="test_string_1"><b>This</b> is a short string.</string>
<string name="test_string_2"><b>This</b> is some text that spans several lines and is just used as an example.</string>

After waiting for the layout to complete, we can add the images to the end of the text for each TextView .

binding.root.doOnNextLayout {
    // Make the drawables truly clickable.
    binding.textView1.text = addEndImage(binding.textView1)
    binding.textView1.movementMethod = LinkMovementMethod.getInstance()

    binding.textView2.text = addEndImage(binding.textView2)
    binding.textView2.movementMethod = LinkMovementMethod.getInstance()
}

private fun addEndImage(textView: TextView): Spannable {
    // Get out (probable) StaticLayout from the TextView and some of its attributes.
    val size = textView.layout.run {
        val lastLine = lineCount - 1
        -getLineAscent(lastLine) * 2 / 3
    }
    // Get the text and add a space for the spans at the end. If we are certain that the
    // text can be accurately represented by an unspanned String, we could just use
    // "${binding.textView.text} ".toSpannable()
    val text = SpannableStringBuilder(textView.text).append(" ")
    // Get the drawable and size it to fit on our last line.
    val d = AppCompatResources.getDrawable(requireContext(), R.drawable.circle)!!
    d.setBounds(0, 0, size, size)
    // Set the ImageSpan to replace the space we added at the end. Vertical positioning
    // and the size of the image may need to be tweaked.
    val span = ImageSpan(d, ImageSpan.ALIGN_BASELINE)
    text.setSpan(span, text.length - 1, text.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
    // Set the ClickableSpan to overlay the ImageSpan we added at the end.
    val clickableSpan = MyClickableSpan()
    text.setSpan(
        clickableSpan,
        text.length - 1,
        text.length,
        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
    )

    return text
}

class MyClickableSpan : ClickableSpan() {
    override fun onClick(widget: View) {
        Toast.makeText(widget.context, "Clicked", Toast.LENGTH_SHORT).show()
    }

}

在此处输入图像描述



If you need to use an ImageView for accessibility or other reasons, you can do that as follows.

The layout:

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@android:color/holo_blue_light"
        android:padding="8dp"
        android:text="@string/test_string_2"
        android:textSize="28sp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:padding="8dp"
        android:src="@drawable/circle"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

Again, after layout is complete, we can do the following that will give the ImageView top and left margins that will place it at the end of the text.

    binding.root.doOnNextLayout {
        val imageView = binding.imageView
        imageView.setOnClickListener() {
            Toast.makeText(requireContext(), "Clicked", Toast.LENGTH_SHORT).show()
        }
        val textView = binding.textView2
        val layout = textView.layout
        val imageY = textView.bottom
        val shiftX = layout.getLineRight(layout.lineCount - 1)
        val shiftY =
            -(imageView.y - imageY) - imageView.paddingTop - textView.height + layout.getLineBaseline(
                layout.lineCount - 1
            ) - imageView.height / 2
        val lp = (imageView.layoutParams as ViewGroup.MarginLayoutParams)
        lp.marginStart = shiftX.toInt()
        lp.topMargin = shiftY.toInt()
        imageView.layoutParams = lp
    }

在此处输入图像描述

You will have to work with the exact size and placement, but this is a technique that will work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM