Align ImageView with EditText horizontally

2020-02-26 12:36发布

I'm trying hard to find a way of aligning an EditText and an ImageView properly on Android. I keep getting this result:

enter image description here

The XML part is quite simple:

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:gravity="center"
        android:scaleType="centerInside"
        android:src="@drawable/android"
        android:visibility="gone" />

    <EditText
        android:id="@+id/edittext"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:singleLine="true" />

</LinearLayout>

I've also tried many of the suggestions below, including PravinCG's (RelativeLayout with alignTop/alignBottom):

<RelativeLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/edittext"
        android:layout_alignTop="@+id/edittext"
        android:scaleType="centerInside"
        android:src="@drawable/android"
        android:visibility="visible" />

    <EditText
        android:id="@+id/edittext"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/image"
        android:hint="@string/username"
        android:singleLine="true" />

</RelativeLayout>

But the result is exactly the same.

I've tried playing with the EditText's background padding, intrinsic height, but to no avail.

The EditText's background drawable is different among Android versions/ROMs, and I want to support them all.

How can I make this alignment pixel perfect on any android version (and style)?

7条回答
地球回转人心会变
2楼-- · 2020-02-26 12:54

You need to use RelativeLayout with android:align_bottom and android:align_Top attribute. I am not writing the code though.

查看更多
Rolldiameter
3楼-- · 2020-02-26 13:00

Have you tried the setCompoundDrawables() methods for the EditText.

You can try setting the intrinsic bounds using the setBounds() method on the Drawable or by using the setCompoundDrawablesWithInstrinsicBounds() method.

This should work on all devices.

查看更多
做自己的国王
4楼-- · 2020-02-26 13:06

Finally found a suitable solution that scales across different Android versions/ROMs/styles.

The main problem is that the EditText's background drawable itself has transparent padding: enter image description here

Also, I've noticed this transparent padding varies a lot between different Android versions/ROMs/styles (stock ICS, for instance, has no transparent padding at all).

In a mid-way conclusion, my original code properly alignes my ImageView with my EditText. However, what I really want is to align my ImageView with the visible part of the EditText's background.

To achieve this, I scan a Bitmap I create from my EditText's background drawable. I scan it top-bottom and bottom-up to find the amount of fully transparent lines and use those values as top/bottom padding for my ImageView. All this consistently takes less than 5ms on my N1. Here's the code:

if(editor.getBackground() != null) {
    int width = editor.getWidth();
    int height = editor.getHeight();
    Drawable backgroundDrawable = editor.getBackground().getCurrent();

    // Paint the editor's background in our bitmap
    Bitmap tempBitmap =  Bitmap.createBitmap(width, height, Config.ARGB_4444);
    backgroundDrawable.draw(new Canvas(tempBitmap));

    // Get the amount of transparent lines at the top and bottom of the bitmap to use as padding
    int topPadding = countTransparentHorizontalLines(0, height, tempBitmap);
    int bottomPadding = countTransparentHorizontalLines(height-1, -1, tempBitmap);

    // Discard the calculated padding if it means hiding the image
    if(topPadding + bottomPadding > height) {
        topPadding = 0;
        bottomPadding = 0;
    }

    tempBitmap.recycle();

    // Apply the padding
    image.setPadding(0, topPadding, 0, bottomPadding);
}

private int countTransparentHorizontalLines(int fromHeight, int toHeight, Bitmap bitmap) {
    int transparentHorizontalLines = 0;
    int width = bitmap.getWidth();
    int currentPixels[] = new int[width];
    boolean fullyTransparentLine = true;

    boolean heightRising = (fromHeight < toHeight);
    int inc =  heightRising ? 1 : -1;

    for(int height = fromHeight; heightRising ? (height < toHeight) : (toHeight < height); height+=inc) {
        bitmap.getPixels(currentPixels, 0, width, 0, height, width, 1);

        for(int currentPixel : currentPixels) {
            if(currentPixel != Color.TRANSPARENT && Color.alpha(currentPixel) != 255) {
                fullyTransparentLine = false;
                break;
            }
        }

        if(fullyTransparentLine)
            transparentHorizontalLines++;
        else
            break;
    }

    return transparentHorizontalLines;
}

And it works like a charm!

it works!

查看更多
孤傲高冷的网名
5楼-- · 2020-02-26 13:08

use android:layout_centerInParent = true for edit text and see weather it works?

查看更多
倾城 Initia
6楼-- · 2020-02-26 13:13

remove editText's and ImageView's properties android:gravity="center" and set gravity property of linearlayout to center_vertically.

查看更多
爱情/是我丢掉的垃圾
7楼-- · 2020-02-26 13:17

To get rid of the padding in the EditText, just use a custom image as background... rectangle with some shadow is enough... or whatever you like... and assign the background to the EditText using

android:background="@drawable/myBackground"
查看更多
登录 后发表回答