com.rks.musicx.misc.widgets.DiagonalLayout.java Source code

Java tutorial

Introduction

Here is the source code for com.rks.musicx.misc.widgets.DiagonalLayout.java

Source

package com.rks.musicx.misc.widgets;

import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Outline;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.os.Build;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.widget.FrameLayout;

/*
 * Created by Coolalien on 6/28/2016.
 */

/*
 * 2017 Rajneesh Singh
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *     http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

public class DiagonalLayout extends FrameLayout {

    private static final float EPSILON = 0.5f;

    com.rks.musicx.misc.widgets.DiagonalLayoutSettings settings;

    int height = 0;

    int width = 0;

    Path clipPath, outlinePath;

    Paint paint;

    Integer defaultMargin_forPosition;

    private PorterDuffXfermode pdMode;

    public DiagonalLayout(Context context) {
        super(context);
        init(context, null);
    }

    public DiagonalLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public void init(Context context, AttributeSet attrs) {
        settings = new com.rks.musicx.misc.widgets.DiagonalLayoutSettings(context, attrs);
        settings.setElevation(ViewCompat.getElevation(this));

        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.WHITE);

        pdMode = new PorterDuffXfermode(PorterDuff.Mode.CLEAR);
    }

    private void calculateLayout() {
        if (settings == null) {
            return;
        }
        height = getMeasuredHeight();
        width = getMeasuredWidth();
        if (width > 0 && height > 0) {

            final float perpendicularHeight = (float) (width * Math.tan(Math.toRadians(settings.getAngle())));

            clipPath = createClipPath(perpendicularHeight);
            outlinePath = createOutlinePath(perpendicularHeight);

            handleMargins(perpendicularHeight);

            ViewCompat.setElevation(this, settings.getElevation());

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                setOutlineProvider(getOutlineProvider());
            }
        }
    }

    private Path createClipPath(float perpendicularHeight) {
        Path path = new Path();
        if (settings.isBottom()) {
            if (settings.isGravityLeft()) {
                path.moveTo(width - getPaddingRight() + EPSILON,
                        height - perpendicularHeight - getPaddingBottom() + EPSILON);
                path.lineTo(width - getPaddingRight() + EPSILON, height - getPaddingBottom() + EPSILON);
                path.lineTo(getPaddingLeft() - EPSILON, height - getPaddingBottom() + EPSILON);
                path.close();
            } else {
                path.moveTo(width - getPaddingRight() + EPSILON, height - getPaddingBottom() + EPSILON);
                path.lineTo(getPaddingLeft() - EPSILON, height - getPaddingBottom() + EPSILON);
                path.lineTo(getPaddingLeft() - EPSILON,
                        height - perpendicularHeight - getPaddingBottom() + EPSILON);
                path.close();
            }
        } else {
            if (settings.isGravityLeft()) {
                path.moveTo(width - getPaddingRight() + EPSILON, getPaddingTop() + perpendicularHeight - EPSILON);
                path.lineTo(getPaddingLeft() - EPSILON, getPaddingTop() - EPSILON);
                path.lineTo(width - getPaddingRight() + EPSILON, getPaddingTop() - EPSILON);
                path.close();
            } else {
                path.moveTo(width - getPaddingRight() + EPSILON, getPaddingTop() - EPSILON);
                path.lineTo(getPaddingLeft() - EPSILON, getPaddingTop() + perpendicularHeight - EPSILON);
                path.lineTo(getPaddingLeft() - EPSILON, getPaddingTop() - EPSILON);
                path.close();
            }
        }
        return path;
    }

    private Path createOutlinePath(float perpendicularHeight) {
        Path path = new Path();
        if (settings.isBottom()) {
            if (settings.isGravityLeft()) {
                path.moveTo(getPaddingLeft(), getPaddingRight());
                path.lineTo(width - getPaddingRight(), getPaddingTop());
                path.lineTo(width - getPaddingRight(), height - perpendicularHeight - getPaddingBottom());
                path.lineTo(getPaddingLeft(), height - getPaddingBottom());
                path.close();
            } else {
                path.moveTo(width - getPaddingRight(), height - getPaddingBottom());
                path.lineTo(getPaddingLeft(), height - perpendicularHeight - getPaddingBottom());
                path.lineTo(getPaddingLeft(), getPaddingTop());
                path.lineTo(width - getPaddingRight(), getPaddingTop());
                path.close();
            }
        } else {
            if (settings.isGravityLeft()) {
                path.moveTo(width - getPaddingRight(), height - getPaddingBottom());
                path.lineTo(width - getPaddingRight(), getPaddingTop() + perpendicularHeight);
                path.lineTo(getPaddingLeft(), getPaddingTop());
                path.lineTo(getPaddingLeft(), height - getPaddingBottom());
                path.close();
            } else {
                path.moveTo(width - getPaddingRight(), height - getPaddingBottom());
                path.lineTo(width - getPaddingRight(), getPaddingTop());
                path.lineTo(getPaddingLeft(), getPaddingTop() + perpendicularHeight);
                path.lineTo(getPaddingLeft(), height - getPaddingBottom());
                path.close();
            }
        }
        return path;
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    @Override
    public ViewOutlineProvider getOutlineProvider() {
        return new ViewOutlineProvider() {
            @Override
            public void getOutline(View view, Outline outline) {
                outline.setConvexPath(outlinePath);
            }
        };
    }

    private void handleMargins(float perpendicularHeight) {
        if (settings.isHandleMargins()) {
            ViewGroup.LayoutParams layoutParams = getLayoutParams();
            if (layoutParams instanceof MarginLayoutParams) {
                MarginLayoutParams lp = (MarginLayoutParams) layoutParams;

                if (settings.isBottom()) {
                    if (defaultMargin_forPosition == null) {
                        defaultMargin_forPosition = lp.bottomMargin;
                    } else {
                        defaultMargin_forPosition = 0;
                    }
                    lp.bottomMargin = (int) (defaultMargin_forPosition - perpendicularHeight);
                } else {
                    if (defaultMargin_forPosition == null) {
                        defaultMargin_forPosition = lp.topMargin;
                    } else {
                        defaultMargin_forPosition = 0;
                    }
                    lp.topMargin = (int) (defaultMargin_forPosition - perpendicularHeight);
                }
                setLayoutParams(lp);
            }
        }
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        if (changed) {
            calculateLayout();
        }
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        int saveCount = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);

        super.dispatchDraw(canvas);

        paint.setXfermode(pdMode);
        canvas.drawPath(clipPath, paint);

        canvas.restoreToCount(saveCount);
        paint.setXfermode(null);
    }
}