2013-03-13 49 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