Android вокруг фонового изображения макетов, только верхние или нижние углы - программирование
Подтвердить что ты не робот

Android вокруг фонового изображения макетов, только верхние или нижние углы

Я хочу иметь экран с несколькими RelativeLayouts, и я хочу, чтобы верхний макет и нижний макет имели закругленные углы, поэтому верхняя компоновка имела бы верхние 2 угловые закругления, а нижняя компоновка имела бы нижние 2 угловые закругленные,

Моя проблема заключается в том, что все примеры, которые я нахожу в Интернете, используют shape.xml для создания закругленного угла и дают ему градиент, и это недостаточно хорошо, потому что я хочу дать relativeLayout фоновое изображение и изображение округлено, и я не могу сделать оба.

Любая помощь будет очень благодарна!

РЕДАКТИРОВАТЬ - Bounty Started

Хорошо, я много лет стучал головой о стену. В настоящий момент я использую сторонний инструмент под названием UITableView, в основном просто проверяя что-то.

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

Он устанавливает tableView аналогично тому, как выглядит таблица iPhone, и я хочу, чтобы каждая строка имела фоновое изображение и имела верхнюю и нижнюю строки изогнутыми. В этом классе 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);
    }
}

У него стиль макета для верхних средних и нижних строк, верхний и нижний округленные используются XML, но проблема в том, что я хочу дать каждой строке изображение. Поэтому я добавил этот код

tempItemView.setBackgroundResource(R.drawable.background);

Но проблема в том, что это удаляет изогнутые углы для верхней и нижней строк, поскольку углы округляются с использованием XML и используют белые градиенты, а не изображение. Мне нужно уметь раздувать макет, а затем наклонять верхний и нижний углы. Я просмотрел так много примеров углов обрезки и даже опробовал различные сторонние инструменты, но еще не нашел один пример, который показывает применение фонового изображения к контейнеру, а затем округление углов.

Есть ли у кого-нибудь идеи о том, как это сделать?

Edit:

На iPhone вы можете сделать что-то вроде этого

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

Где вы конвертируете изображение в цвет. Есть ли у Android эквивалент?

Edit:

Спасибо 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));
    }

Я использую метрики, чтобы настроить, насколько обойти обзор, поэтому он масштабируется с разными размерами экрана.

Надеюсь, что это поможет другим, у кого была эта проблема!

4b9b3361

Ответ 1

Проверьте, работает ли мое решение для вашего дела: Определите свой собственный макет, расширив 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() не готовы. Переопределите и вызовите из onWindowFocusChanged (boolean hasFocused), установив свой собственный идентификатор. Это повторит настройку вашего изображения в качестве фона с круглыми углами.

Ответ 2

Так вы пробовали что-то вроде этого:

Например, это ваш основной макет:

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

и do 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 - изображение с закругленными углами, где вы можете найти ответ, который я думаю, поможет вам, как это сделать.

И вот еще одна полезная библиотека, которая использует ImageView, но вы можете ее изменить и использовать для любого вида View, link: RoundedImageView.

Ответ 3

Хорошо, я нашел решение наконец. Чтобы закруглить верхние углы, используйте этот метод

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

Надеюсь, что это поможет любому другому, у кого была такая же проблема!

Ответ 4

Как насчет использования LayerList, где вы устанавливаете растровое изображение, округление его угла и затем устанавливаете его в качестве фона Relative layouts?

В документации есть шаг за шагом, как это сделать.