Я хочу создать кнопки, как на картинке. Внутри круга (который прозрачен в png) я хочу разместить изображения профиля игроков. Также должен быть текст на синей полосе. У меня это работает, но это кажется слишком сложным. Я думаю, что легче понять, что я сделал, не давая кода, но если он вам нужен, я могу его добавить. Вот макет:

  • RelativeLayout
    • LinearLayout (горизонтальная ориентация)
      • Пустой вид с весом 0,7
      • Изображение профиля толщиной 0,2
      • Пустое представление с весом 0,1
    • накладываемое изображение, которое я разместил ниже.
    • LinearLayout (горизонтальная ориентация)
      • RelativeLayout с весом 0,7 (пространство, где может размещаться весь текст)
      • пустой вид с весом 0,3

enter image description here

Кстати: справа от круга png не прозрачный, а белый!

Это хорошо работает, но должен быть способ лучше! Все эти пустые виды просто для того, чтобы выровнять картинку по правильному положению, некрасиво. И тот факт, что накладываемое изображение должно находиться между изображением профиля и текстом, делает его еще более уродливым.

Я бы предпочел сделать это без png в качестве наложения, но с простыми формами (чтобы он хорошо смотрелся на каждом экране), но я не знаю, как это сделать. Вы бы порекомендовали это? И если да, то как это можно было сделать?

Или у вас есть идея, как улучшить макет xml или как это сделать иначе.

Огромное спасибо

3
DominicM 4 Фев 2015 в 15:22

3 ответа

Лучший ответ

Вы можете использовать простой LinearLayout, если ограничите фоновое изображение областью профиля с правой стороны. Вы можете определить область содержимого в самом изображении, если вы используете рисование с девятью патчами, как показано ниже:

  1. Извлеките часть профиля из файла фонового изображения.
  2. Создайте из него девять патчей, которые можно вытянуть, определяя всю область как растягиваемую (левая и верхняя граничные линии), а пустой кружок как область содержимого (правая и нижняя линии).
  3. Поскольку в идеале у вас должно быть изображение на переднем плане, чтобы гарантировать, что фотография не будет нарисована за пределами круга, вы можете использовать FrameLayout с возможностью рисования переднего плана, чтобы содержать ImageView фотографии вашего профиля. Также потребуется еще одно фиктивное дочернее представление, чтобы обойти ошибку в FrameLayout, которая вызывает один дочерний элемент с размерами match_parent будет размещен неправильно.

Вот как должен выглядеть макет в конце:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/text"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:background="#00f" />

    <FrameLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:foreground="@drawable/profile_bg">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

        <ImageView
            android:id="@+id/photo"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </FrameLayout>
</LinearLayout>
1
corsair992 7 Фев 2015 в 00:14

Теперь я готов представить свой ответ.

  • Портрет:

    введите описание изображения здесь

  • Пейзаж:

    введите описание изображения здесь

Layout.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:shape="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <!--This is the CustomView which include -->
    <!--own attributes: -->
    <!--circle_radius is the radius of image, -->
    <!--content_padding is the padding,-->
    <!--and background_color is the color of shape.-->

    <CustomShape
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        shape:circle_radius="40dp"
        shape:content_padding="8dp"
        shape:background_color="#FF983493">

        <!--There must be two Views:-->
        <!--TextView and ImageView and only in this order.-->
        <!--Set-->
        <!--android:layout_width="wrap_content"-->
        <!--android:layout_height="wrap_content"-->
        <!--to bot of them, because in CustomShape it will be-->
        <!--resized for you. There also don`t need to set -->
        <!--any kind of margin or location attributes.-->

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/txt"
            android:padding="5dp"
            android:textColor="@android:color/white"
            android:text="sdsfkjsdkfhsdk flsdkfjkls asdfasd fklasdjl fkjasdklfjasd k "
            android:background="@android:color/transparent"/>

        <!--For RoundImage I use custom class which round the drawable,-->
        <!--not a View. Look down.-->

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/img"
            android:src="@drawable/img"
            android:scaleType="fitCenter"
            android:background="@android:color/transparent" />

    </CustomShape>

</RelativeLayout>

CustomShape класс:

public class CustomShape extends RelativeLayout {
    Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);

    int circleRadius; // image radius
    int diameter; // image diameter
    int contentPadding;
    int semiPadding;
    int rectRightSide;

    int backgroundColor;
    int viewWidth; // width of parent(CustomShape layout)

    public CustomShape(Context context) {
        super(context);
        this.setWillNotDraw(false);
    }

    public CustomShape(Context context, AttributeSet attrs) {
        super(context, attrs);

        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CustomShape, 0, 0);
        try {
            this.circleRadius = (int) ta.getDimension(R.styleable.CustomShape_circle_radius, 40);
            this.contentPadding = (int) ta.getDimension(R.styleable.CustomShape_content_padding, 8);
            this.backgroundColor = ta.getColor(R.styleable.CustomShape_background_color, 0);

            this.semiPadding = contentPadding / 2;
            this.diameter = circleRadius * 2;
        } finally {
            ta.recycle();
        }

        this.setWillNotDraw(false);
    }

    public CustomShape(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.setWillNotDraw(false);
    }

    @Override
    protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld) {
        super.onSizeChanged(xNew, yNew, xOld, yOld);

        viewWidth = xNew;

        this.rectRightSide = viewWidth - circleRadius - (circleRadius / 2); // get position for image
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        ImageView img = (ImageView) this.getChildAt(1);
        RelativeLayout.LayoutParams imgParams = new LayoutParams(diameter - contentPadding, diameter - contentPadding);
        imgParams.leftMargin = rectRightSide - circleRadius + semiPadding;
        imgParams.topMargin = semiPadding;
        img.setLayoutParams(imgParams);

        //Create custom RoundImage and set to image

        try {
            Drawable drawable = img.getDrawable();
            Bitmap bm = ((BitmapDrawable) drawable).getBitmap();
            RoundImage resultImage = new RoundImage(bm);
            img.setImageDrawable(resultImage);
        } catch (ClassCastException e) {
        }

        //Positioning and resizing TextView

        View txt = this.getChildAt(0);
        RelativeLayout.LayoutParams txtParams = new LayoutParams(rectRightSide - circleRadius - semiPadding, diameter - contentPadding);
        txtParams.topMargin = semiPadding;
        txtParams.leftMargin = semiPadding;
        txt.setLayoutParams(txtParams);

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int parentWidth = MeasureSpec.getSize(widthMeasureSpec);

        this.setMeasuredDimension(parentWidth, diameter); // set correct height
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        paint.setColor(backgroundColor);
        canvas.drawRect(0, 0, rectRightSide, diameter, paint);

        //Draw circle

        paint.setDither(true);
        canvas.drawCircle(rectRightSide, circleRadius, circleRadius, paint);
    }
}

Attr.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CustomShape">
        <attr name="circle_radius" format="dimension" />
        <attr name="content_padding" format="dimension" />
        <attr name="background_color" format="color" />
    </declare-styleable>
</resources>

RoundImage класс:

public class RoundImage extends Drawable {
    private final Bitmap mBitmap;
    private final Paint mPaint;
    private final RectF mRectF;
    private final int mBitmapWidth;
    private final int mBitmapHeight;

    public RoundImage(Bitmap bitmap) {
        mBitmap = bitmap;
        mRectF = new RectF();
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        final BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        mPaint.setShader(shader);

        mBitmapWidth = mBitmap.getWidth();
        mBitmapHeight = mBitmap.getHeight();
    }

    @Override
    public void draw(Canvas canvas) {
        canvas.drawOval(mRectF, mPaint);
    }

    @Override
    protected void onBoundsChange(Rect bounds) {
        super.onBoundsChange(bounds);
        mRectF.set(bounds);
    }

    @Override
    public void setAlpha(int alpha) {
        if (mPaint.getAlpha() != alpha) {
            mPaint.setAlpha(alpha);
            invalidateSelf();
        }
    }

    @Override
    public void setColorFilter(ColorFilter cf) {
        mPaint.setColorFilter(cf);
    }

    @Override
    public int getOpacity() {
        return PixelFormat.TRANSLUCENT;
    }

    @Override
    public int getIntrinsicWidth() {
        return mBitmapWidth;
    }

    @Override
    public int getIntrinsicHeight() {
        return mBitmapHeight;
    }

    public void setAntiAlias(boolean aa) {
        mPaint.setAntiAlias(aa);
        invalidateSelf();
    }

    @Override
    public void setFilterBitmap(boolean filter) {
        mPaint.setFilterBitmap(filter);
        invalidateSelf();
    }

    @Override
    public void setDither(boolean dither) {
        mPaint.setDither(dither);
        invalidateSelf();
    }

    public Bitmap getBitmap() {
        return mBitmap;
    }

}

Надеюсь, это поможет тебе.

-2
GIGAMOLE 7 Фев 2015 в 21:29

Вы можете сделать это без изображения:

Макет:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:weightSum="1.0">
    <TextView
        android:layout_weight="0.7"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:text="New Text"
        android:id="@+id/textView"
        android:background="#0073ff"/>
    <ImageView
        android:layout_weight="0.2"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:background="@drawable/half_round_drawable"
        android:src="@drawable/profile"/>
    </LinearLayout>
</LinearLayout>

Half_round_drawable:

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

    <item>
        <shape android:shape="oval">
            <corners android:radius="16dp" />
            <solid android:color="#0073ff" />
        </shape>
    </item>
    <item
        android:bottom="0dp"
        android:right="32dp"> <!-- radius *2 -->
        <shape>
            <solid android:color="#0073ff" />
        </shape>
    </item>

</layer-list>

Чтобы сделать изображение профиля круглым, вы должны использовать что-то вроде этого: Как создать круговой ImageView в Android?

2
Community 23 Май 2017 в 12:23