简体   繁体   English

Android围绕一个Layouts背景图片,只有顶角或底角

[英]Android round a Layouts background image, only top or bottom corners

I want to be able to have a screen with multiple RelativeLayouts, and I want the top layout and the bottom layout to have rounded corners, so top layout would have top 2 corners rounded, and bottom layout would have bottom 2 corners rounded. 我希望能够拥有一个具有多个RelativeLayouts的屏幕,并且我希望顶部布局和底部布局具有圆角,因此顶部布局将具有圆角的前2个角,并且底部布局将具有圆形的底部2个角。

My issue is, all the examples I find online are using shape.xml to create a rounded corner and gave it a gradient and that is not good enough, because I want to to give the relativeLayout a background image, and have that image rounded, and I can't seem to do both. 我的问题是,我在网上找到的所有例子都使用shape.xml来创建一个圆角并给它一个渐变,这还不够好,因为我想给relativeLayout一个背景图像,并将该图像舍入,我似乎无法做到这两点。

Any help would be much appreciated!! 任何帮助将非常感激!!

EDIT - Bounty Started 编辑 - 赏金开始

Okay, I have been banging my head against the wall for ages on this one. 好吧,在这个问题上,我多年来一直在撞墙。 I am using a 3rd party tool called UITableView at the moment, mainly just testing something out. 我目前正在使用名为UITableView的第三方工具,主要是测试一些东西。

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

It sets up tableView similar to the way iPhone table is, and I want to be able to give each row a background image, and have the top and bottom rows curved. 它设置tableView类似于iPhone表格的方式,我希望能够为每一行提供背景图像,并使顶部和底部行弯曲。 In this UITableView class, under commit, this code is called 在这个UITableView类中,在commit下,调用此代码

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);
    }
}

He has a layout style for top middle and bottom rows, top and bottom rounded used XML, but the problem is, I want to give each row an image. 他有一个顶部中间和底部行的布局样式,顶部和底部圆形使用XML,但问题是,我想给每一行一个图像。 So I added this code 所以我添加了这段代码

tempItemView.setBackgroundResource(R.drawable.background);

But the problem is, this removes the curved corners for the top and bottom rows as the corners are rounded using XML and using white gradients, not an image. 但问题是,这会消除顶部和底部行的弯曲角落,因为角落使用XML并使用白色渐变而不是图像。 I need to be able to inflate the layout, then curve the top and bottom corners. 我需要能够给布局充气,然后弯曲顶角和底角。 I have looked at so many examples of cropping corners, and even tried out different 3rd party tools, but have yet to find a single example which shows applying a background image to a container, and then rounding the corners. 我看了很多裁剪角落的例子,甚至尝试了不同的第三方工具,但还没有找到一个例子,它显示了将背景图像应用到容器,然后将角落四舍五入。

Does anyone have any ideas on how to do this?? 有没有人对如何做到这一点有任何想法?

Edit: 编辑:

On iPhone, you can do something like this 在iPhone上,你可以做这样的事情

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

Where you convert an image into a colour. 将图像转换为颜色的位置。 Does Android have an equivalent? Android有相同的功能吗?

Edit: 编辑:

Thanks to ACheese for the answer, I modified his code and separated it into 3 methods, one for top rounded corners, one for fully rounded corners, and one for bottom rounded corners, and came up with this 感谢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));
    }

I use metrics to set up how much to round the view, so it scales with different screen sizes. 我使用指标来设置视图的四舍五入,因此它可以根据不同的屏幕尺寸进行缩放。

Hope that helps others who were having this issue!! 希望能帮助其他人解决这个问题!!

So did you tried something like this : 所以你尝试过这样的事情:

For example this is your main layout : 例如,这是您的主要布局:

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

and do MyMainRelLAyout.setBackgroundResource(R.drawable.mydrawable); 并做MyMainRelLAyout.setBackgroundResource(R.drawable.mydrawable);

where mydrawable.xml look like this : 其中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>

Depending on the comments below I can suggest you this link : Romain Guy - image with rounded corners , where you can find an answer which I think will help you how to do this. 根据下面的评论,我可以建议你这个链接: Romain Guy - 带圆角的图像 ,在那里你可以找到答案,我认为这将有助于你如何做到这一点。

And here is another useful library which is using ImageView, but you can change it and use it for any kind of View, link : RoundedImageView . 这是另一个使用ImageView的有用库,但您可以更改它并将其用于任何类型的View,链接: RoundedImageView

Check if my solution work for your case : Define your own layout by extending RelativeLayout. 检查我的解决方案是否适用于您的案例:通过扩展RelativeLayout来定义您自己的布局。 You only need to add the following code 您只需添加以下代码

@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));

}

call this method from your activity. 从您的活动中调用此方法。 You cannot call from onCreate() because getMeasuredWidth() and getMeasuredHeight() are not ready. 您无法从onCreate()调用,因为getMeasuredWidth()和getMeasuredHeight()尚未就绪。 Override and call from onWindowFocusChanged(boolean hasFocused) by setting your own drawable id. 通过设置自己的drawable id覆盖并调用onWindowFocusChanged(boolean hasFocused)。 This will repeating setting your image as the background with round corners. 这将重复将您的图像设置为带圆角的背景。

Okay, I found a solution at long last. 好的,我终于找到了解决方案。 In order to round top corners, use this method 要使圆角变圆,请使用此方法

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;
  }

If you only want to round bottom corner, use this method 如果您只想圆角,请使用此方法

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;
      }

Also if you passing in different images which are different sizes, I would recommend you use this method first 此外,如果您传入不同大小的不同图像,我建议您先使用此方法

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;
    }

Scale the images up to be the same size before applying the rounded corners method, otherwise if you pass in a different image with different width/height, the rounded corners will look quite different depending on what image is passed in. If you scale the image up first, it means no matter what image you pass in, should look fairly consistent. 在应用圆角方法之前将图像缩放到相同的大小,否则如果传入具有不同宽度/高度的不同图像,则圆角将根据传入的图像看起来完全不同。如果缩放图像首先,这意味着无论你传入什么样的图像,都应该看起来相当一致。

Then you can just do something like this 然后你可以做这样的事情

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);

Hope that helps any others who were having the same issue!! 希望能帮助其他有同样问题的人!

What about using a LayerList where you set the bitmap, its corner rounding, and then set it as your Relative layouts background? 如何使用LayerList设置位图,其圆角,然后将其设置为相对布局背景?

The documentation includes a step by step of how to do it. 该文档包括如何执行此操作的一步一步。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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