[android] 둥근 모서리로 레이아웃을 만드는 방법 ..?
모서리가 둥근 레이아웃을 만들려면 어떻게해야합니까? 내 둥근 모서리를 적용하고 싶습니다 LinearLayout
.
답변
1 : 드로어 블에 layout_bg.xml 을 정의하십시오 .
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFFFFF"/>
<stroke android:width="3dp" android:color="#B1BCBE" />
<corners android:radius="10dp"/>
<padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" />
</shape>
2 : layout_bg.xml
레이아웃에 배경으로 추가
android:background="@drawable/layout_bg"
답변
API 21+의 경우 클립 뷰 사용
반올림 개요 클리핑이 View
API 21 의 클래스에 추가되었습니다 . 자세한 내용은이 교육 문서 또는이 참조 를 참조하십시오.
이 내장 기능은 둥근 모서리를 구현하기가 매우 쉽습니다. 모든보기 또는 레이아웃에서 작동하며 적절한 클리핑을 지원합니다.
해야 할 일 :
- 둥근 모양 드로어 블을 만들고 뷰의 배경으로 설정하십시오.
android:background="@drawable/round_outline"
- 설명서에 따르면 다음과 같이하면됩니다.
android:clipToOutline="true"
불행히도 버그 가있는 것으로 보이며 현재이 XML 속성이 인식되지 않습니다. 운 좋게도 Java에서 클리핑을 설정할 수 있습니다.
- 활동 또는 단편에서 :
View.setClipToOutline(true)
보이는 모습 :
ImageView에 대한 특별 참고 사항
setClipToOutline()
뷰의 배경이 도형 드로어 블로 설정된 경우에만 작동합니다. 이 배경 모양이 있으면 View는 배경의 윤곽선을 클리핑 및 그림자 목적의 테두리로 취급합니다.
즉, ImageView에서 모서리를 둥글게하려면 배경이 둥근 모양에 사용되므로 대신 setClipToOutline()
이미지를 가져와야 합니다 . src 대신 background를 사용하여 이미지를 설정 해야하는 경우이 중첩 뷰 해결 방법을 사용할 수 있습니다.android:src
android:background
- 배경을 모양 드로어 블로 설정하여 외부 레이아웃 만들기
- 패딩없이 ImageView 주위에 레이아웃을 감싸십시오.
- ImageView (레이아웃의 다른 것을 포함)가 이제 외부 레이아웃의 둥근 모양으로 잘립니다.
답변
다음은 흰색 배경, 검은 색 테두리 및 모서리가 둥근 드로어 블을 만드는 XML 파일의 복사본입니다.
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#ffffffff"/>
<stroke android:width="3dp"
android:color="#ff000000"
/>
<padding android:left="1dp"
android:top="1dp"
android:right="1dp"
android:bottom="1dp"
/>
<corners android:bottomRightRadius="7dp" android:bottomLeftRadius="7dp"
android:topLeftRadius="7dp" android:topRightRadius="7dp"/>
</shape>
드로어 블 디렉토리에 xml 파일로 저장하고 리소스 이름 (R.drawable.your_xml_name)을 사용하여 드로어 블 배경 (아이콘 또는 리소스 파일)을 사용하는 것처럼 사용하십시오.
답변
안드로이드 v7 지원 라이브러리에서 CardView를 사용하십시오. 약간 무겁지만 모든 문제를 해결하고 충분히 쉽습니다. 설정된 드로어 블 백그라운드 방법과 달리 하위 뷰를 성공적으로 클리핑 할 수 있습니다.
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardBackgroundColor="@android:color/transparent"
card_view:cardCornerRadius="5dp"
card_view:cardElevation="0dp"
card_view:contentPadding="0dp">
<YOUR_LINEARLAYOUT_HERE>
</android.support.v7.widget.CardView>
답변
나는 이렇게했다 :
스크린 샷 확인 :
만들기 당김 으로 지정된 파일 custom_rectangle.xml
에 그릴 수 폴더를 :
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="@android:color/white" />
<corners android:radius="10dip" />
<stroke
android:width="1dp"
android:color="@android:color/white" />
</shape>
이제 뷰에 사각형 배경 을 적용하십시오 .
mView.setBackground(R.drawlable.custom_rectangle);
끝난
답변
더 좋은 방법은 두 가지를 병합하는 것입니다.
이것은 코너가있는 컨텐츠를 갖는 것과 같이 다른 솔루션이 해결하지 못한 경우를 처리합니다.
2 대신 단일 레이어를 보여주기 때문에 GPU 친화적 인 것으로 생각됩니다.
유일한 더 좋은 방법은 완전히 사용자 정의 된 뷰를 만드는 것입니다. 그러나 그것은 많은 코드이며 많은 시간이 걸릴 수 있습니다. 여기에서 내가 제안한 것이 두 세계의 최고라고 생각합니다.
다음은 수행 방법에 대한 스 니펫입니다.
RoundedCornersDrawable.java
/**
* shows a bitmap as if it had rounded corners. based on :
* http://rahulswackyworld.blogspot.co.il/2013/04/android-drawables-with-rounded_7.html
* easy alternative from support library: RoundedBitmapDrawableFactory.create( ...) ;
*/
public class RoundedCornersDrawable extends BitmapDrawable {
private final BitmapShader bitmapShader;
private final Paint p;
private final RectF rect;
private final float borderRadius;
public RoundedCornersDrawable(final Resources resources, final Bitmap bitmap, final float borderRadius) {
super(resources, bitmap);
bitmapShader = new BitmapShader(getBitmap(), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
final Bitmap b = getBitmap();
p = getPaint();
p.setAntiAlias(true);
p.setShader(bitmapShader);
final int w = b.getWidth(), h = b.getHeight();
rect = new RectF(0, 0, w, h);
this.borderRadius = borderRadius < 0 ? 0.15f * Math.min(w, h) : borderRadius;
}
@Override
public void draw(final Canvas canvas) {
canvas.drawRoundRect(rect, borderRadius, borderRadius, p);
}
}
CustomView.java
public class CustomView extends ImageView {
private View mMainContainer;
private boolean mIsDirty=false;
// TODO for each change of views/content, set mIsDirty to true and call invalidate
@Override
protected void onDraw(final Canvas canvas) {
if (mIsDirty) {
mIsDirty = false;
drawContent();
return;
}
super.onDraw(canvas);
}
/**
* draws the view's content to a bitmap. code based on :
* http://nadavfima.com/android-snippet-inflate-a-layout-draw-to-a-bitmap/
*/
public static Bitmap drawToBitmap(final View viewToDrawFrom, final int width, final int height) {
// Create a new bitmap and a new canvas using that bitmap
final Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(bmp);
viewToDrawFrom.setDrawingCacheEnabled(true);
// Supply measurements
viewToDrawFrom.measure(MeasureSpec.makeMeasureSpec(canvas.getWidth(), MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(canvas.getHeight(), MeasureSpec.EXACTLY));
// Apply the measures so the layout would resize before drawing.
viewToDrawFrom.layout(0, 0, viewToDrawFrom.getMeasuredWidth(), viewToDrawFrom.getMeasuredHeight());
// and now the bmp object will actually contain the requested layout
canvas.drawBitmap(viewToDrawFrom.getDrawingCache(), 0, 0, new Paint());
return bmp;
}
private void drawContent() {
if (getMeasuredWidth() <= 0 || getMeasuredHeight() <= 0)
return;
final Bitmap bitmap = drawToBitmap(mMainContainer, getMeasuredWidth(), getMeasuredHeight());
final RoundedCornersDrawable drawable = new RoundedCornersDrawable(getResources(), bitmap, 15);
setImageDrawable(drawable);
}
}
편집 : “RoundKornersLayouts”라이브러리를 기반으로 좋은 대안을 찾았습니다 . 확장하려는 모든 레이아웃 클래스에 사용할 클래스를 반올림하십시오.
//based on https://github.com/JcMinarro/RoundKornerLayouts
class CanvasRounder(cornerRadius: Float, cornerStrokeColor: Int = 0, cornerStrokeWidth: Float = 0F) {
private val path = android.graphics.Path()
private lateinit var rectF: RectF
private var strokePaint: Paint?
var cornerRadius: Float = cornerRadius
set(value) {
field = value
resetPath()
}
init {
if (cornerStrokeWidth <= 0)
strokePaint = null
else {
strokePaint = Paint()
strokePaint!!.style = Paint.Style.STROKE
strokePaint!!.isAntiAlias = true
strokePaint!!.color = cornerStrokeColor
strokePaint!!.strokeWidth = cornerStrokeWidth
}
}
fun round(canvas: Canvas, drawFunction: (Canvas) -> Unit) {
val save = canvas.save()
canvas.clipPath(path)
drawFunction(canvas)
if (strokePaint != null)
canvas.drawRoundRect(rectF, cornerRadius, cornerRadius, strokePaint)
canvas.restoreToCount(save)
}
fun updateSize(currentWidth: Int, currentHeight: Int) {
rectF = android.graphics.RectF(0f, 0f, currentWidth.toFloat(), currentHeight.toFloat())
resetPath()
}
private fun resetPath() {
path.reset()
path.addRoundRect(rectF, cornerRadius, cornerRadius, Path.Direction.CW)
path.close()
}
}
그런 다음 각 사용자 정의 된 레이아웃 클래스에서 다음과 유사한 코드를 추가하십시오.
class RoundedConstraintLayout : ConstraintLayout {
private lateinit var canvasRounder: CanvasRounder
constructor(context: Context) : super(context) {
init(context, null, 0)
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
init(context, attrs, 0)
}
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
init(context, attrs, defStyle)
}
private fun init(context: Context, attrs: AttributeSet?, defStyle: Int) {
val array = context.obtainStyledAttributes(attrs, R.styleable.RoundedCornersView, 0, 0)
val cornerRadius = array.getDimension(R.styleable.RoundedCornersView_corner_radius, 0f)
val cornerStrokeColor = array.getColor(R.styleable.RoundedCornersView_corner_stroke_color, 0)
val cornerStrokeWidth = array.getDimension(R.styleable.RoundedCornersView_corner_stroke_width, 0f)
array.recycle()
canvasRounder = CanvasRounder(cornerRadius,cornerStrokeColor,cornerStrokeWidth)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
setLayerType(FrameLayout.LAYER_TYPE_SOFTWARE, null)
}
}
override fun onSizeChanged(currentWidth: Int, currentHeight: Int, oldWidth: Int, oldheight: Int) {
super.onSizeChanged(currentWidth, currentHeight, oldWidth, oldheight)
canvasRounder.updateSize(currentWidth, currentHeight)
}
override fun draw(canvas: Canvas) = canvasRounder.round(canvas) { super.draw(canvas) }
override fun dispatchDraw(canvas: Canvas) = canvasRounder.round(canvas) { super.dispatchDraw(canvas) }
}
속성을 지원하려면 라이브러리에 작성된대로 사용하십시오.
<resources>
<declare-styleable name="RoundedCornersView">
<attr name="corner_radius" format="dimension"/>
<attr name="corner_stroke_width" format="dimension"/>
<attr name="corner_stroke_color" format="color"/>
</declare-styleable>
</resources>
대부분의 용도에 더 쉬운 또 다른 대안 : use MaterialCardView. 둥근 모서리, 획 색상 및 너비 및 높이를 사용자 정의 할 수 있습니다.
예:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:clipChildren="false" android:clipToPadding="false"
tools:context=".MainActivity">
<com.google.android.material.card.MaterialCardView
android:layout_width="100dp" android:layout_height="100dp" android:layout_gravity="center"
app:cardCornerRadius="8dp" app:cardElevation="8dp" app:strokeColor="#f00" app:strokeWidth="2dp">
<ImageView
android:layout_width="match_parent" android:layout_height="match_parent" android:background="#0f0"/>
</com.google.android.material.card.MaterialCardView>
</FrameLayout>
그리고 결과 :
사용하는 경우 획 가장자리에 약간의 아티팩트 문제가 있습니다 (내용의 일부 픽셀이 남음). 확대하면 알 수 있습니다. 여기서이 문제에 대해보고 했습니다 .
답변
이 시도…
1. 드로어 블 XML 생성 (custom_layout.xml) :
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="#FFFFFF" />
<stroke
android:width="2dp"
android:color="#FF785C" />
<corners android:radius="10dp" />
</shape>
2.보기 배경을 추가
android:background="@drawable/custom_layout"