둥근 모서리가있는 Android에서보기를 만드는 방법
모서리가 둥근 Android에서보기를 만들려고합니다. 지금까지 찾은 해결책은 모서리가 둥근 모양을 정의하고 해당 뷰의 배경으로 사용하는 것입니다.
내가 한 일은 다음과 같습니다. 아래에 주어진 것처럼 드로어 블을 정의하십시오.
<padding
android:top="2dp"
android:bottom="2dp"/>
<corners android:bottomRightRadius="20dp"
android:bottomLeftRadius="20dp"
android:topLeftRadius="20dp"
android:topRightRadius="20dp"/>
이제 이것을 레이아웃의 배경으로 사용했습니다.
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="10dp"
android:clipChildren="true"
android:background="@drawable/rounded_corner">
이것은 완벽하게 잘 작동하며 뷰에 둥근 모서리가 있음을 알 수 있습니다.
그러나 내 레이아웃에는 ImageView 또는 MapView와 같은 다른 많은 하위 뷰가 있습니다. 위의 레이아웃 안에 ImageView를 배치하면 이미지의 모서리가 잘 리거나 잘리지 않고 전체가 나타납니다.
여기에 설명 된 것처럼 작동하도록 다른 해결 방법을 보았습니다 .
그러나 뷰에 대해 둥근 모서리를 설정하는 방법이 있으며 모든 하위 뷰는 모서리가 둥근 기본 뷰 내에 포함됩니까?
감사.
또 다른 접근 방식은 아래와 같은 사용자 지정 레이아웃 클래스를 만드는 것입니다. 이 레이아웃은 먼저 내용을 오프 스크린 비트 맵에 그리고 둥근 사각형으로 오프 스크린 비트 맵을 마스크 한 다음 실제 캔버스에 오프 스크린 비트 맵을 그립니다.
나는 그것을 시도했고 작동하는 것 같습니다 (적어도 간단한 테스트 케이스에서는). 물론 일반 레이아웃에 비해 성능에 영향을 미칩니다.
package com.example;
import android.content.Context;
import android.graphics.*;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.widget.FrameLayout;
public class RoundedCornerLayout extends FrameLayout {
private final static float CORNER_RADIUS = 40.0f;
private Bitmap maskBitmap;
private Paint paint, maskPaint;
private float cornerRadius;
public RoundedCornerLayout(Context context) {
super(context);
init(context, null, 0);
}
public RoundedCornerLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0);
}
public RoundedCornerLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs, defStyle);
}
private void init(Context context, AttributeSet attrs, int defStyle) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
cornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, CORNER_RADIUS, metrics);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
setWillNotDraw(false);
}
@Override
public void draw(Canvas canvas) {
Bitmap offscreenBitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
Canvas offscreenCanvas = new Canvas(offscreenBitmap);
super.draw(offscreenCanvas);
if (maskBitmap == null) {
maskBitmap = createMask(canvas.getWidth(), canvas.getHeight());
}
offscreenCanvas.drawBitmap(maskBitmap, 0f, 0f, maskPaint);
canvas.drawBitmap(offscreenBitmap, 0f, 0f, paint);
}
private Bitmap createMask(int width, int height) {
Bitmap mask = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8);
Canvas canvas = new Canvas(mask);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.WHITE);
canvas.drawRect(0, 0, width, height, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawRoundRect(new RectF(0, 0, width, height), cornerRadius, cornerRadius, paint);
return mask;
}
}
일반 레이아웃처럼 사용하십시오.
<com.example.RoundedCornerLayout
android:layout_width="200dp"
android:layout_height="200dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/test"/>
<View
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#ff0000"
/>
</com.example.RoundedCornerLayout>
또는 다음 android.support.v7.widget.CardView
과 같이 사용할 수 있습니다 .
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
card_view:cardBackgroundColor="@color/white"
card_view:cardCornerRadius="4dp">
<!--YOUR CONTENT-->
</android.support.v7.widget.CardView>
shape.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#f6eef1" />
<stroke
android:width="2dp"
android:color="#000000" />
<padding
android:bottom="5dp"
android:left="5dp"
android:right="5dp"
android:top="5dp" />
<corners android:radius="5dp" />
</shape>
그리고 내부 레이아웃
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="10dp"
android:clipChildren="true"
android:background="@drawable/shape">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/your image"
android:background="@drawable/shape">
</LinearLayout>
레이아웃에 터치 리스너를 추가하는 동안 문제가 발생하는 경우. 이 레이아웃을 상위 레이아웃으로 사용합니다.
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Region;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;
import android.widget.FrameLayout;
public class RoundedCornerLayout extends FrameLayout {
private final static float CORNER_RADIUS = 6.0f;
private float cornerRadius;
public RoundedCornerLayout(Context context) {
super(context);
init(context, null, 0);
}
public RoundedCornerLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0);
}
public RoundedCornerLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs, defStyle);
}
private void init(Context context, AttributeSet attrs, int defStyle) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
cornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, CORNER_RADIUS, metrics);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
@Override
protected void dispatchDraw(Canvas canvas) {
int count = canvas.save();
final Path path = new Path();
path.addRoundRect(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), cornerRadius, cornerRadius, Path.Direction.CW);
canvas.clipPath(path, Region.Op.REPLACE);
canvas.clipPath(path);
super.dispatchDraw(canvas);
canvas.restoreToCount(count);
}
}
같이
<?xml version="1.0" encoding="utf-8"?>
<com.example.view.RoundedCornerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="@+id/patentItem"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingRight="20dp">
... your child goes here
</RelativeLayout>
</com.example.view.RoundedCornerLayout>
Jaap van Hengstum의 답변 은 훌륭하지만 비용이 많이 들고 예를 들어이 방법을 Button에 적용하면 뷰가 비트 맵으로 렌더링되기 때문에 터치 효과가 손실됩니다.
나에게 가장 좋은 방법과 가장 간단한 방법은 다음과 같이 뷰에 마스크를 적용하는 것입니다.
@Override
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
super.onSizeChanged(width, height, oldWidth, oldHeight);
float cornerRadius = <whatever_you_want>;
this.path = new Path();
this.path.addRoundRect(new RectF(0, 0, width, height), cornerRadius, cornerRadius, Path.Direction.CW);
}
@Override
protected void dispatchDraw(Canvas canvas) {
if (this.path != null) {
canvas.clipPath(this.path);
}
super.dispatchDraw(canvas);
}
라는 XML 파일 만들기 round.xml
에 drawable
폴더를하고이 내용을 붙여 넣기 :
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="#FFFFFF" />
<stroke android:width=".05dp" android:color="#d2d2d2" />
<corners android:topLeftRadius="5dp" android:topRightRadius="5dp" android:bottomRightRadius="5dp" android:bottomLeftRadius="5dp"/>
</shape>
그런 다음 모든 항목에 round.xml
as background
를 사용하십시오 . 그런 다음 둥근 모서리를 제공합니다.
Android L에서는 View.setClipToOutline 을 사용 하여 해당 효과를 얻을 수 있습니다. 이전 버전에서는 임의의 ViewGroup의 내용을 특정 모양으로 자르는 방법이 없었습니다.
비슷한 효과를 줄 수있는 무언가를 생각해야합니다.
ImageView에서 둥근 모서리 만 필요한 경우 셰이더를 사용하여 배경으로 사용중인 모양 위에 이미지를 '페인트'할 수 있습니다. 예를 들어이 라이브러리 를 살펴보십시오 .
정말로 모든 자식을 잘라 내야한다면 레이아웃을 다시 볼 수 있습니까? 어떤 색을 사용하든 배경이 있고 가운데에 둥근 '구멍'이있는 것? 실제로 onDraw 메서드를 재정의하는 모든 자식 위에 해당 모양을 그리는 사용자 지정 ViewGroup을 만들 수 있습니다.
는 CardView
안드로이드 스튜디오 3.0.1 API 27에 나를 위해 일했다. 는 colorPrimary
에서 참조 된 res/values/colors.xml
파일을 그냥 예입니다. 0dp
그것 의 layout_width의 경우 부모의 너비로 늘어납니다. 필요에 따라 제약 조건과 너비 / 높이를 구성해야합니다.
<android.support.v7.widget.CardView
android:id="@+id/cardView"
android:layout_width="0dp"
android:layout_height="200dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:cardCornerRadius="4dp"
app:cardBackgroundColor="@color/colorPrimary">
<!-- put your content here -->
</android.support.v7.widget.CardView>
다음 코드를 사용하여 드로어 블 폴더 아래에 xml 파일을 만듭니다. (내가 만든 파일의 이름은 rounded_corner.xml입니다)
rounded_corner.xml
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- view background color -->
<solid
android:color="#a9c5ac" >
</solid>
<!-- view border color and width -->
<stroke
android:width="3dp"
android:color="#1c1b20" >
</stroke>
<!-- If you want to add some padding -->
<padding
android:left="4dp"
android:top="4dp"
android:right="4dp"
android:bottom="4dp" >
</padding>
<!-- Here is the corner radius -->
<corners
android:radius="10dp" >
</corners>
</shape>
그리고이 드로어 블을 둥근 모서리 테두리를 유지하려는 뷰의 배경으로 유지합니다. LinearLayout을 위해 유지합시다
<LinearLayout android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/rounded_corner"
android:layout_centerInParent="true">
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hi, This layout has rounded corner borders ..."
android:gravity="center"
android:padding="5dp"/>
</LinearLayout>
이 튜토리얼 과 그 아래의 모든 토론을 따르십시오 -http : //www.curious-creature.org/2012/12/11/android-recipe-1-image-with-rounded-corners/
전체 Android UI 툴킷의 주요 개발자 중 한 명인 Guy Romain이 작성한이 게시물에 따르면 둥근 모서리가있는 컨테이너 (및 그의 모든 하위 뷰)를 만들 수 있지만, 그는 너무 비싸다고 설명했습니다. 렌더링 문제).
그의 게시물에 따라 갈 것을 권장하고 둥근 모서리를 원한다면 ImageView
이 게시물에 따라 둥근 모서리를 구현하십시오 . 그런 다음 배경이있는 컨테이너 안에 넣을 수 있으며 원하는 효과를 얻을 수 있습니다.
그것이 제가 또한 결국 한 일입니다.
public class RoundedCornerLayout extends FrameLayout {
private double mCornerRadius;
public RoundedCornerLayout(Context context) {
this(context, null, 0);
}
public RoundedCornerLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RoundedCornerLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs, defStyle);
}
private void init(Context context, AttributeSet attrs, int defStyle) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
public double getCornerRadius() {
return mCornerRadius;
}
public void setCornerRadius(double cornerRadius) {
mCornerRadius = cornerRadius;
}
@Override
public void draw(Canvas canvas) {
int count = canvas.save();
final Path path = new Path();
path.addRoundRect(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), (float) mCornerRadius, (float) mCornerRadius, Path.Direction.CW);
canvas.clipPath(path, Region.Op.REPLACE);
canvas.clipPath(path);
super.draw(canvas);
canvas.restoreToCount(count);
}
}
제공 한 튜토리얼 링크는 자식 요소의 layout_width 및 layout_height 속성을 match_parent로 설정해야한다고 제안하는 것 같습니다.
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent">
Jaap van Hengstum의 답변과 다른 점 :
- 마스크 비트 맵 대신 BitmapShader 를 사용하십시오 .
- 비트 맵을 한 번만 만듭니다.
public class RoundedFrameLayout extends FrameLayout {
private Bitmap mOffscreenBitmap;
private Canvas mOffscreenCanvas;
private BitmapShader mBitmapShader;
private Paint mPaint;
private RectF mRectF;
public RoundedFrameLayout(Context context) {
super(context);
init();
}
public RoundedFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public RoundedFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
setWillNotDraw(false);
}
@Override
public void draw(Canvas canvas) {
if (mOffscreenBitmap == null) {
mOffscreenBitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
mOffscreenCanvas = new Canvas(mOffscreenBitmap);
mBitmapShader = new BitmapShader(mOffscreenBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setShader(mBitmapShader);
mRectF = new RectF(0f, 0f, canvas.getWidth(), canvas.getHeight());
}
super.draw(mOffscreenCanvas);
canvas.drawRoundRect(mRectF, 8, 8, mPaint);
}
}
선형 레이아웃으로이 속성을 시도하면
tools : context = ". youractivity"에 도움이됩니다 .
public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, int pixels) {
Bitmap roundedBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap
.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(roundedBitmap);
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);
final float roundPx = pixels;
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 roundedBitmap;
}
직사각형과 함께 xml의 모양을 사용하고 원하는대로 아래쪽 또는 위쪽 반경의 속성을 설정 한 다음 해당 xml을 ur 뷰에 배경으로 적용합니다.
참고 URL : https://stackoverflow.com/questions/26074784/how-to-make-a-view-in-android-with-rounded-corners
'Program Tip' 카테고리의 다른 글
Ruby 스크립트에서 터미널에서 비밀번호 입력을 숨기는 방법 (0) | 2020.10.22 |
---|---|
Windows에서 모든 .svn 디렉토리를 재귀 적으로 제거하는 명령 (0) | 2020.10.22 |
.htaccess를 사용하여 HTTP를 HTTP로 리디렉션 (0) | 2020.10.22 |
MVC 면도기 @foreach (0) | 2020.10.22 |
Docker의 개인 1.0 레지스트리에서 이미지를 검색하는 방법은 무엇입니까? (0) | 2020.10.22 |