둥근 보기 만들기

어쩌면 이것이 가장 쉽다고 생각합니다.

둥근



머티리얼 디자인에서는 별로 사용하지 않지만, 미리보기 이미지를 둥글게하고 싶다거나 드물게 자주 있을까 생각합니다.
실장 방법도 여러가지 있습니다만, 이번은 나누기와 범용성 높은 것 같은 실장 방법을 소개합니다.

FrameLayout이야말로 최고


ViewGroup 의 구현은 몹시 괴롭습니다만, 우선 FrameLayout 를 확장하면 어떻게 됩니다.LinearLayout 와 같이 옆에 늘어놓고 싶었다고 해도, 우선 FrameLayout 의 아이에 LinearLayout 두면 좋을 뿐이므로, LinearLayout 를 확장한다고는 하지 않습니다. 어떻게 생각해도 편하지 않다.

샘플 코드



이번은 View 에 있는 dispatchDraw(Canvas) 메소드를 이용합니다.
요컨대 아이 뷰의 draw에 대해 둥근으로 clip하면 됩니다.

CornerClipFrameLayout.java
public class RoundClipFrameLayout extends FrameLayout {

    private final Path mPath = new Path();

    private final RectF mRect = new RectF();

    private int mCornerRadius;

    public RoundClipFrameLayout(Context context) {
        this(context, null);
    }

    public RoundClipFrameLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RoundClipFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.RoundClipFrameLayout, defStyleAttr, 0);
        mCornerRadius = ta.getDimensionPixelSize(R.styleable.RoundClipFrameLayout_cornerRadius, 0);

        ta.recycle();
    }

    public void setCornerRadius(int radiusPx) {
        if (mCornerRadius != radiusPx) {
            mCornerRadius = radiusPx;
            rebuildPath();
            invalidate();
        }
    }

    private void rebuildPath() {
        mPath.reset();
        mPath.addRoundRect(mRect, mCornerRadius, mCornerRadius, Path.Direction.CW);
        mPath.close();
    }

    @Override
    protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
        super.onSizeChanged(width, height, oldWidth, oldHeight);

        mRect.set(0, 0, width, height);
        rebuildPath();
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        int save = canvas.save();
        canvas.clipPath(mPath);
        super.dispatchDraw(canvas);
        canvas.restoreToCount(save);
    }
}

attrs.xml
<resources>
    <declare-styleable name="RoundClipFrameLayout">
        <attr name="cornerRadius" format="dimension"/>
    </declare-styleable>
</resources>

잡다



대상을 둘러싸면 됩니다.

activity_main.xml
<com.example.widget.RoundClipFrameLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:cornerRadius="4dp">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@drawable/sample"/>

</com.example.widget.RoundClipFrameLayout>



샘플



자신도 둥글고 싶다.



위의 구현에서는, 아이 View 밖에 모퉁이가 됩니다.
해당 Viewbackground 도 둥글고 싶어! 라고 하는 경우는 draw() 메소드에 같은 구현을 하면 OK입니다.
@Override
public void draw(Canvas canvas) {
    int save = canvas.save();
    canvas.clipPath(mPath);
    super.draw(canvas);
    canvas.restoreToCount(save);
}

더 즐거운 방법이있었습니다.



API Level 21에서 추가된 ViewOutlineProvider를 사용하면 View 외부에서도 clipping 처리를 중단할 수 있습니다.

CircleOutlineProvider
public static class CircleOutlineProvider extends ViewOutlineProvider {

    @Override
    public void getOutline(View view, Outline outline) {
        outline.setRoundRect(
                0,
                0,
                view.getWidth(),
                view.getHeight(),
                radius);
        view.setClipToOutline(true);
    }
}
view.setViewOutlineProvider(new CircleOutlineProvider());

참고했습니다.



Custom Layout that rounds the corners of its content - Stack Overflow

googlesamples/android-ClippingBasic

ViewOutlineProvider 사용하기 | Y.A.M 잡기장

좋은 웹페이지 즐겨찾기