2013-03-13 108 views
14

我希望能够拥有多个RelativeLayouts的屏幕,并且我希望顶部布局和底部布局具有圆角,所以顶部布局将具有顶部2角落圆角,底部布局将有底部2角落圆角。Android围绕布局背景图像,只有顶部或底部的角落

我的问题是,我在网上找到的所有例子都使用shape.xml来创建一个圆角,并给它一个渐变,这是不够好,因为我想给relativeLayout一个背景图像,并有那个形象圆润了,我似乎无法做到这一点。

任何帮助将不胜感激!

编辑 - 赏金开始

好吧,我一直在敲打我的头靠在墙上的这一个年龄段。目前我正在使用名为UITableView的第三方工具,主要是测试一些东西。

https://github.com/thiagolocatelli/android-uitableview

它建立的tableView方式类似于iPhone表是的,我希望能够给每一行的背景图像,并有弯曲的顶部和底部行。在这种的UITableView类,下提交,该代码被称为

public void commit() 
    { 
     mIndexController = 0; 

     if (mItemList.size() > 1) 
     { 
      // when the list has more than one item 
      for (IListItem obj : mItemList) 
      { 
       View tempItemView; 
       if (mIndexController == 0) 
       { 
        //tempItemView = new RoundedView(context_i, this); 
        tempItemView = mInflater.inflate(R.layout.list_item_top,null); 


     } 
      else if (mIndexController == mItemList.size() - 1) 
      { 
       tempItemView = mInflater.inflate(R.layout.list_item_bottom,null); 
      } 
      else 
      { 
       tempItemView = mInflater.inflate(R.layout.list_item_middle,null); 
      } 
      setupItem(tempItemView, obj, mIndexController); 
      tempItemView.setClickable(obj.isClickable()); 
      mListContainer.addView(tempItemView); 
      mIndexController++; 

     } 
    } 
    else if (mItemList.size() == 1) 
    { 
     // when the list has only one item 
     View tempItemView = mInflater.inflate(R.layout.list_item_single, 
       null); 
     IListItem obj = mItemList.get(0); 
     setupItem(tempItemView, obj, mIndexController); 
     tempItemView.setClickable(obj.isClickable()); 
     mListContainer.addView(tempItemView); 
    } 
} 

他为顶部中间和底部行,顶部和底部的布局风格圆润使用XML,但问题是,我想给每一行图片。因此,我已将此代码

tempItemView.setBackgroundResource(R.drawable.background); 

但问题是,这消除了对顶部和底部行作为拐角处的弯曲角是使用XML,并使用白色梯度,而不是一个图像变圆。我需要能够膨胀布局,然后弯曲顶部和底部的角落。我已经看过很多裁剪角落的例子,甚至尝试了不同的第三方工具,但还没有找到一个例子,它显示了将一个背景图像应用于一个容器,然后将角落四舍五入。

有没有人有任何想法如何做到这一点?

编辑:

在iPhone上,你可以做这样的事情

UIColor *color = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:@"image.png"]]; 

当你将图像转换成彩色。 Android是否具有相同的功能?

编辑:

感谢ACheese的答案,我修改了代码,并分离成3种方法,一个顶级圆角,一个完全圆角,还有一个底部圆角,又上来与此

public void setBackgroundRounded(int resID, int w, int h, View v) 
    { 
     DisplayMetrics metrics = getResources().getDisplayMetrics(); 
     double dH = (metrics.heightPixels/100) * 1.5; 
     int iHeight = (int)dH; 

     Bitmap bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); 
     Canvas c = new Canvas(bmp); 
     Shader shader = new BitmapShader(BitmapFactory.decodeResource(
       getResources(), resID), Shader.TileMode.MIRROR, 
       Shader.TileMode.MIRROR); 

     Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG); 
     paint.setAntiAlias(true); 
     paint.setShader(shader); 
     RectF rec = new RectF(0, 0, w, h); 
     c.drawRoundRect(rec, iHeight, iHeight, paint); 

     v.setBackgroundDrawable(new BitmapDrawable(getResources(), bmp)); 
    } 

    public void setTopRounded(int resID, int w, int h, View v) 
    { 
     Bitmap bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); 
     Canvas c = new Canvas(bmp); 
     Shader shader = new BitmapShader(BitmapFactory.decodeResource(
       getResources(), resID), Shader.TileMode.MIRROR, 
       Shader.TileMode.MIRROR); 

     Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG); 
     paint.setAntiAlias(true); 
     paint.setShader(shader); 
     RectF rec = new RectF(0, 0, w, h - 20); 
     c.drawRect(new RectF(0, 20, w, h), paint); 
     c.drawRoundRect(rec, 20, 20, paint); 
     v.setBackgroundDrawable(new BitmapDrawable(getResources(), bmp)); 
    } 

    public void setBottomRounded(int id, int w, int h, View v) 
    { 
     DisplayMetrics metrics = getResources().getDisplayMetrics(); 
     double dH = (metrics.heightPixels/100) * 1.5; 
     int iHeight = (int)dH; 

     Bitmap bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); 
     Canvas c = new Canvas(bmp); 
     Shader shader = new BitmapShader(BitmapFactory.decodeResource(
       getResources(), id), Shader.TileMode.MIRROR, 
       Shader.TileMode.MIRROR); 
     Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG); 
     paint.setAntiAlias(true); 
     paint.setShader(shader); 
     RectF rec = new RectF(0, 0, w, h); 
     c.drawRoundRect(rec, iHeight, iHeight, paint); 
     c.drawRect(new RectF(0, 0, w, h-iHeight), paint); 

     v.setBackgroundDrawable(new BitmapDrawable(getResources(), bmp)); 
    } 

我使用指标设置多少舍入视图,因此它随着不同的屏幕尺寸缩放。

希望能帮助有这个问题的人!

+0

因此,您需要为您的活动中的主布局设置圆角背景,是否正确..或甚至它不在活动中,以容纳其他视图的主容器? – hardartcore 2013-03-13 12:12:38

+0

正确的,我需要能够给该容器一个背景图像,并有该容器的角落2圆角,无论是顶部2角落或底部2角落 – AdamM 2013-03-13 12:15:18

+0

如果你想活动的背景有圆角,那么这活动应首先透明化。然后,将您的圆形图像设置为底部视图的背景。 – Lumis 2013-03-19 23:13:41

回答

2

检查我的解决方案是否适用于您的案例: 通过扩展RelativeLayout来定义您自己的布局。您只需添加以下代码

@SuppressWarnings("deprecation") 
public void setBackground(int id){ 
    Bitmap bmp = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888); 
    Canvas c = new Canvas(bmp); 
    Shader shader = new BitmapShader(BitmapFactory.decodeResource(getResources(), id), Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); 

    Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG); 
    paint.setAntiAlias(true); 
    paint.setShader(shader); 
    RectF rec = new RectF(0, 0, getMeasuredWidth(), getMeasuredHeight()); 
// you may need this for only top round corner 
// RectF rec = new RectF(0, 0, getMeasuredWidth(), getMeasuredHeight()-20); 
// c.drawRect(new RectF(0, 20, getMeasuredWidth(), getMeasuredHeight()),  paint); 
    c.drawRoundRect(rec, 20, 20, paint); 
    this.setBackgroundDrawable(new BitmapDrawable(getResources(), bmp)); 

} 

从您的活动中调用此方法。你不能从onCreate()调用,因为getMeasuredWidth()和getMeasuredHeight()没有准备好。通过设置您自己的可绘制ID,覆盖并调用onWindowFocusChanged(boolean hasFocused)。这将重复设置您的图像作为背景与圆角。

+0

你的方法似乎是迄今为止最成功的。会接受答案。我对这些方法唯一的问题是,Androids画布模式似乎是相当耗费资源的,如果在屏幕上有几个视图,当从一个屏幕转换到另一个包含几个这些方法调用的屏幕时,它可能导致显着的UI滞后。将不得不将它设置为屏幕过渡,然后调用此方法。你有没有注意到这一点?不要以为你有任何解决办法?再次感谢您的帮助 – AdamM 2013-03-26 11:03:57

+0

哦,对于决定使用此方法的其他人,请确保将Shader.TileMode.Repeat更改为Shader.TileMode.MIRROR,以防止图像被重复使用(如果您有相当大的视图) – AdamM 2013-03-26 11:50:51

+0

我使用此方法为背景,但为一些自定义的ImageView。我没有注意到任何显着的UI滞后。你有没有在onDraw()或onMeasure()中调用它?我认为几个电话都很好。但是,如果情况确实如此,大量Bitmaps实例太多肯定会占用大量内存,从而导致UI滞后。 – Acheese 2013-03-26 15:10:39

2

那你有没有尝试过这样的事情:

例如,这是你的主要布局:

RelativeLayout myMainRelLAyout = (RelativeLayout) findViewById(R.id.my_layout); 

,做MyMainRelLAyout.setBackgroundResource(R.drawable.mydrawable);

其中mydrawable.xml是这样的:

<?xml version="1.0" encoding="utf-8"?> 
    <shape xmlns:android="http://schemas.android.com/apk/res/android" > 

    <solid android:color="@android:color/white" /> 

    <corners 
     android:bottomLeftRadius="0dip" 
     android:bottomRightRadius="0dip" 
     android:topLeftRadius="5dip" 
     android:topRightRadius="5dip" /> 
    </shape> 

根据下面的评论,我可以建议你这个链接:Romain Guy - image with rounded corners,在那里你可以找到一个答案,我认为这将帮助你如何做到这一点。

这是另一个使用ImageView的有用库,但您可以更改它并将其用于任何种类的View,链接:RoundedImageView

+0

所有将要做的是给它一个背景颜色,我知道如何做到这一点,但我希望能够传递一个图像,所以图像是圆形的 – AdamM 2013-03-13 12:18:30

+0

你需要添加一个自定义的圆形图像,而不仅仅是一种颜色? – hardartcore 2013-03-13 12:19:05

+0

我拥有的图像将是矩形图像,我希望能够传入任何图像以用作背景图像,并使用代码绕过传入的任何图像的角点。上面的代码将设置背景颜色的容器是白色的 – AdamM 2013-03-13 12:20:08

0

如何使用LayerList设置位图,将其四舍五入,然后将其设置为相对布局背景?

该文档包括一步一步如何做到这一点。

+0

我的问题与该代码是否意味着无论何时我想更改容器的背景图像,我都需要3个图像,一个用于图像中心,一个用于顶角一个用于底角。我希望能够使用这一个图像,并使用代码绕过顶角或底角 – AdamM 2013-03-13 12:25:44

+0

可以引用一个图像,但有3种不同的样式并将它们切换出来。因此,创建一个包含三个不同角度圆角的xml样式,并在需要时应用它们。 http://developer.android.com/guide/topics/resources/style-resource.html – Hrafn 2013-03-13 12:27:45

1

好的,我终于找到了解决方案。为了圆顶部边角,用这种方法

public Bitmap getTopRoundedCorner(Bitmap bitmap, DisplayMetrics metrics) { 

    //Using this so it scales with different screen sizes 
    double dH = (metrics.heightPixels/100.0) * 3; 
    int iHeight = (int) dH; 

    //Subtract this from bitmap height 
    Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), 
       bitmap.getHeight()-iHeight, Config.ARGB_8888); 

    Canvas canvas = new Canvas(output); 

    final int color = 0xff424242; 
    final Paint paint = new Paint(); 
    final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); 

    //Again used so it scales with diff screen sizes 
    //Can play around with this value, depending on how rounded you wanted the corner 
    dH = (metrics.heightPixels/100.0) * 3.5; 
    iHeight = (int) dH; 

    final RectF rectF = new RectF(rect); 
    final float roundPx = iHeight; 

    paint.setAntiAlias(true); 
    canvas.drawARGB(0, 0, 0, 0); 
    paint.setColor(color); 
    canvas.drawRoundRect(rectF, roundPx, roundPx, paint); 
    paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); 
    canvas.drawBitmap(bitmap, rect, rect, paint); 

    return output; 
    } 

如果你只想圆底角落,用这种方法

public Bitmap getBottomRoundedCorner(Bitmap bitmap) { 
     Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), 
        bitmap.getHeight(), Config.ARGB_8888); 
     Canvas canvas = new Canvas(output); 

     final int color = 0xff424242; 
     final Paint paint = new Paint(); 
     final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); 
     final RectF rectF = new RectF(rect); 

     //Again play around with this to get the rounded value you require 
     double dH = (metrics.heightPixels/100.0) * 2.5; 
     int iHeight = (int) dH; 
     final float roundPx = iHeight; 

     paint.setAntiAlias(true); 
     canvas.drawARGB(0, 0, 0, 0); 
     paint.setColor(color); 
     canvas.drawRoundRect(rectF, roundPx, roundPx, paint); 
     paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); 
     canvas.drawBitmap(bitmap, rect, rect, paint); 

     //Draw second rectangle over the top of the first one 
     //So it hides the top rounded corners 
     iHeight = (int) dH; 

     final int color2 = 0xff424242; 
     final Paint paint2 = new Paint(); 
     Canvas canvas2 = new Canvas(output); 
     final Rect testRect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()-iHeight); 
     final RectF testF = new RectF(testRect); 

     paint2.setAntiAlias(true); 
     canvas2.drawARGB(0, 0, 0, 0); 
     paint2.setColor(color2); 
     canvas2.drawRoundRect(testF, roundPx, roundPx, paint2); 
     paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); 
     canvas2.drawBitmap(bitmap, testRect, testRect, paint2); 
     return output; 
     } 

此外,如果你在不同尺寸不同的图像传递,我会推荐使用此方法第一

public Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) { 
     int width = bm.getWidth(); 
     int height = bm.getHeight(); 
     float scaleWidth = ((float) newWidth)/width; 
     float scaleHeight = ((float) newHeight)/height; 
     // CREATE A MATRIX FOR THE MANIPULATION 
     Matrix matrix = new Matrix(); 
     // RESIZE THE BIT MAP 
     matrix.postScale(scaleWidth, scaleHeight); 

     // "RECREATE" THE NEW BITMAP 
     Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false); 
     return resizedBitmap; 
    } 

缩放图像向上施加圆角方法之前是相同的大小,否则如果在不同的图像与通过不同的宽度/高度,根据传入图像的不同,圆角会显得截然不同。如果您先将图像放大,这意味着无论您传入哪张图像,都应该看起来相当一致。

然后,你可以做这样的事情

Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.tablebackground); 
     bmp = getResizedBitmap(bmp, 200, 300); 
     bmp = getTopRoundedCorner(bmp); 
     BitmapDrawable backgroundDrawable = new BitmapDrawable(getResources(),bmp); 
     subLayout = (RelativeLayout) findViewById(R.id.subLayout); 
     subLayout.setBackgroundDrawable(backgroundDrawable); 

希望帮助谁是有同样的问题任何人!

+0

应该指出,这些方法可能会造成相当大的内存密集,这可能会导致问题。试图改进这些方法 – AdamM 2013-03-25 09:12:13

+0

当试图使用上面的方法getTopRoundedCorners时,我无法解决“metrics.heightPixels”上的变量错误。有什么遗漏吗? – Phil 2014-08-08 14:44:34

+0

没关系,我通过在方法顶部添加'DisplayMetrics指标=新的DisplayMetrics'得到它 – Phil 2014-08-08 14:46:21

相关问题