如何添加1dp边框(到图像),以便它可以在所有屏幕上工作?

时间:2013-11-06 12:59:22

标签: android android-layout border android-imageview

我正在寻找一种最简单,最可靠的方法来为元素添加一个瘦(1dp)边框 - 在这种情况下ImageView - 在API级别14 +上。

根据我的理解,图层列表是做这种事情的方法。

所以,我有:

<ImageView
    android:id="@+id/overlay_main_character"
    android:layout_height="72dp"
    android:layout_width="72dp"        
    android:background="@drawable/image_border"
    />

在Java中,ImageView设置为显示this 200x200 px image Wikimedia Commons

res/drawable/image_border.xml

<!-- Adds thin (1dp) border, and nothing else. -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <item>
        <shape android:shape="rectangle" >
            <stroke android:width="1dp" android:color="#FF000000" />
            <solid android:color="@android:color/transparent"/>
        </shape>
    </item>

    <item>
        <shape android:shape="rectangle">
            <padding android:top="1dp" />
            <padding android:bottom="1dp" />
            <padding android:left="1dp" />
            <padding android:right="1dp" />
        </shape>
    </item>

</layer-list>

在测试设备上看起来像什么(Galaxy Note,Android 4.1.2):

enter image description here

缺少左下边框。

我做错了什么?我的图层列表方法是否不正确(或者可以简化)?或者这可以使用除图层列表以外的其他东西来实现吗?

3 个答案:

答案 0 :(得分:5)

您可以为ImageView设置背景颜色,并将填充设置为1dp:

<ImageView
    android:id="@+id/overlay_main_character"
    android:layout_height="72dp"
    android:layout_width="72dp"        
    android:background="#F000"
    android:padding="1dp"
    />

它看起来像你想要的。

答案 1 :(得分:2)

尽管this solution很简单并且通常效果很好,但在通过网络(在后台线程中)获取图像的情况下,它有一个缺点。当图片仍在加载时,会显示大黑方块,这不一定是您想要的。

A colleague of mine指出,在这种情况下,您可以这样做:在边框的图像后面添加FrameLayout“,并将ImageView背景设置为白色(例如),像这样:

<FrameLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@android:color/black"
    android:padding="1dp">

    <ImageView
        android:id="@+id/overlay_main_character"
        android:layout_height="72dp"
        android:layout_width="72dp"
        android:background="@android:color/white" />

</FrameLayout>

在我们的案例中,正在进行的外观更好:

enter image description here


附录:自定义“有边框图像”组件

实际上,除了1dp边框之外,我们还希望动画在网络加载后显示图像(alpha 0 - &gt; 1);类似的东西:

imageView.setAlpha(0f); 
imageView.animate().alpha(1f).setDuration(500).start();

为了让动画看起来不错(至少在我们的应用中),背景应该是白色而不是黑色。

为了支持两者边框和动画,我必须在图像和外部(边框)FrameLayout之间添加另一个 FrameLayout(带有白色背景)。但XML变得非常冗长,因此我们在Java中为此创建了一个自定义可重用组件:“ BorderedImage ”。

package fi.company.product.ui.helpers;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.FrameLayout;
import android.widget.ImageView;

import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;

/**
 * Custom ImageView (technically custom FrameLayout) with black 1dp border, 
 * white background and support for alpha animation (white -> image)
 *
 * @author Jonik, https://stackoverflow.com/a/19818328/56285
 */
public class BorderedImage extends FrameLayout {

    private ImageView imageView;

    public BorderedImage(Context context) {
        super(context);
        init(context);
    }

    public BorderedImage(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public BorderedImage(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    private void init(Context context) {
        // Outer FrameLayout for the black border
        setBackgroundColor(getResources().getColor(android.R.color.black));
        int padding1dp = (int) getResources().getDisplayMetrics().density
        setPadding(padding1dp, padding1dp, padding1dp, padding1dp);

        // Another FrameLayout for the white background 
        FrameLayout middleLayout = new FrameLayout(context);
        middleLayout.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT));
        middleLayout.setBackgroundColor(getResources().getColor(android.R.color.white));
        addView(middleLayout);

        // The actual ImageView
        imageView = new ImageView(context);
        imageView.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT));
        middleLayout.addView(imageView);
    }

    public ImageView getImageView() {
        return imageView;
    }
}

当然,很容易进一步定制这个帮助器:例如,传递边框&amp;背景颜色作为构造函数参数。

现在,在XML中使用BorderedImage非常简单:

<fi.company.product.ui.helpers.BorderedImage
    android:id="@+id/overlay_main_character"
    android:layout_height="72dp"
    android:layout_width="72dp" />

答案 2 :(得分:0)

<LinearLayout
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:orientation="vertical"
   android:padding="1dp" >
   <ImageView
        android:id="@+id/overlay_main_character"
        android:layout_height="72dp"
        android:layout_width="72dp"        
        android:background="@drawable/image_border"
        />