public interface ImaterialBinder {
    int getLayout();

    View init(View view);
} public interface MaterialSectionChangeListener {
    public void onBeforeChangeSection(MaterialSection newSection);

    public void onAfterChangeSection(MaterialSection newSection);
} public interface MaterialSectionImpleLayout {


    void select();

    void unSelect();

    View getView();

    void setIcon(Drawable drawbleicon);

    void setIcon(Bitmap drawbleicon);

    void checkrefresh();

} public interface MaterialSectionOnClickListener {

    void onClick(MaterialSection section, View v);
} public class MaterialPlain extends FrameLayout {
    private Drawable normal, press;
    private View childView;

    public MaterialPlain(Context context) {
        this(context, null, 0);
    }

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

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    public MaterialPlain(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setWillNotDraw(false);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MaterialPlain);
        normal = a.getDrawable(R.styleable.MaterialPlain_mrlsxm_touch_normal);
        press = a.getDrawable(R.styleable.MaterialPlain_mrlsxm_touch_press);
        a.recycle();
        try {
            if (normal == null) normal = getResources().getDrawable(R.drawable.normal);
            if (press == null) press = getResources().getDrawable(R.drawable.pressfill);
            setBackground(normal);
            requestLayout();
        } catch (Resources.NotFoundException e) {

        }
    }

    @SuppressWarnings("unchecked")
    public <T extends View> T getChildView() {
        return (T) childView;
    }

    @Override
    public void setOnClickListener(OnClickListener onClickListener) {
        if (childView == null) {
            throw new IllegalStateException("MaterialRippleLayout must have a child view to handle clicks");
        }
        childView.setOnClickListener(onClickListener);
    }

    @Override
    public final void addView(View child, int index, ViewGroup.LayoutParams params) {
        if (getChildCount() > 0) {
            throw new IllegalStateException("MaterialRippleLayout can host only one child");
        }
        //noinspection unchecked
        childView = child;
        super.addView(child, index, params);
    }

    private boolean findClickableViewInChild(View view, int x, int y) {
        if (view instanceof ViewGroup) {
            ViewGroup viewGroup = (ViewGroup) view;
            for (int i = 0; i < viewGroup.getChildCount(); i++) {
                View child = viewGroup.getChildAt(i);
                final Rect rect = new Rect();
                child.getHitRect(rect);

                final boolean contains = rect.contains(x, y);
                if (contains) {
                    return findClickableViewInChild(child, x - rect.left, y - rect.top);
                }
            }
        } else if (view != childView) {
            return (view.isEnabled() && (view.isClickable() || view.isLongClickable() || view.isFocusableInTouchMode()));
        }

        return view.isFocusableInTouchMode();
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return !findClickableViewInChild(childView, (int) event.getX(), (int) event.getY());
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean superOnTouchEvent = super.onTouchEvent(event);
        if (!isEnabled() || !childView.isEnabled()) return superOnTouchEvent;

        int action = event.getActionMasked();
        switch (action) {
            case MotionEvent.ACTION_UP:
                setBackground(normal);
                break;
            case MotionEvent.ACTION_DOWN:
                setBackground(press);
                break;
        }
        return true;
    }
} public class MaterialRippleLayout extends FrameLayout {

    private static final int     DEFAULT_DURATION        = 350;
    private static final int     DEFAULT_FADE_DURATION   = 75;
    private static final float   DEFAULT_DIAMETER_DP     = 35;
    private static final float   DEFAULT_ALPHA           = 0.2f;
    private static final int     DEFAULT_COLOR           = Color.BLACK;
    private static final int     DEFAULT_BACKGROUND      = Color.TRANSPARENT;
    private static final boolean DEFAULT_HOVER           = true;
    private static final boolean DEFAULT_DELAY_CLICK     = true;
    private static final boolean DEFAULT_PERSISTENT      = false;
    private static final boolean DEFAULT_SEARCH_ADAPTER  = false;
    private static final boolean DEFAULT_RIPPLE_OVERLAY  = false;
    private static final int     DEFAULT_ROUNDED_CORNERS = 0;

    private static final int  FADE_EXTRA_DELAY = 50;
    private static final long HOVER_DURATION   = 2500;

    private final Paint paint  = new Paint(Paint.ANTI_ALIAS_FLAG);
    private final Rect  bounds = new Rect();

    private int      rippleColor;
    private boolean  rippleOverlay;
    private boolean  rippleHover;
    private int      rippleDiameter;
    private int      rippleDuration;
    private int      rippleAlpha;
    private boolean  rippleDelayClick;
    private int      rippleFadeDuration;
    private boolean  ripplePersistent;
    private Drawable rippleBackground;
    private boolean  rippleInAdapter;
    private float    rippleRoundedCorners;

    private float radius;

    private AdapterView parentAdapter;
    private View        childView;

    private AnimatorSet    rippleAnimator;
    private ObjectAnimator hoverAnimator;

    private Point currentCoords  = new Point();
    private Point previousCoords = new Point();

    private int layerType;

    private boolean eventCancelled;
    private boolean prepressed;
    private int     positionInAdapter;

    private GestureDetector   gestureDetector;
    private PerformClickEvent pendingClickEvent;
    private PressedEvent      pendingPressEvent;

    public static RippleBuilder on(View view) {
        return new RippleBuilder(view);
    }

    public MaterialRippleLayout(Context context) {
        this(context, null, 0);
    }

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

    public MaterialRippleLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        setWillNotDraw(false);
        gestureDetector = new GestureDetector(context, longClickListener);

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MaterialRippleLayout);
        rippleColor = a.getColor(R.styleable.MaterialRippleLayout_mrlsxm_rippleColor, DEFAULT_COLOR);
        rippleDiameter = a.getDimensionPixelSize(
                R.styleable.MaterialRippleLayout_mrlsxm_rippleDimension,
                (int) dpToPx(getResources(), DEFAULT_DIAMETER_DP)
        );
        rippleOverlay = a.getBoolean(R.styleable.MaterialRippleLayout_mrlsxm_rippleOverlay, DEFAULT_RIPPLE_OVERLAY);
        rippleHover = a.getBoolean(R.styleable.MaterialRippleLayout_mrlsxm_rippleHover, DEFAULT_HOVER);
        rippleDuration = a.getInt(R.styleable.MaterialRippleLayout_mrlsxm_rippleDuration, DEFAULT_DURATION);
        rippleAlpha = (int) (255 * a.getFloat(R.styleable.MaterialRippleLayout_mrlsxm_rippleAlpha, DEFAULT_ALPHA));
        rippleDelayClick = a.getBoolean(R.styleable.MaterialRippleLayout_mrlsxm_rippleDelayClick, DEFAULT_DELAY_CLICK);
        rippleFadeDuration = a.getInteger(R.styleable.MaterialRippleLayout_mrlsxm_rippleFadeDuration, DEFAULT_FADE_DURATION);
        rippleBackground = new ColorDrawable(a.getColor(R.styleable.MaterialRippleLayout_mrlsxm_rippleBackground, DEFAULT_BACKGROUND));
        ripplePersistent = a.getBoolean(R.styleable.MaterialRippleLayout_mrlsxm_ripplePersistent, DEFAULT_PERSISTENT);
        rippleInAdapter = a.getBoolean(R.styleable.MaterialRippleLayout_mrlsxm_rippleInAdapter, DEFAULT_SEARCH_ADAPTER);
        rippleRoundedCorners = a.getDimensionPixelSize(R.styleable.MaterialRippleLayout_mrlsxm_rippleRoundedCorners, DEFAULT_ROUNDED_CORNERS);

        a.recycle();

        paint.setColor(rippleColor);
        paint.setAlpha(rippleAlpha);

        enableClipPathSupportIfNecessary();
    }


    @SuppressWarnings("unchecked")
    public <T extends View> T getChildView() {
        return (T) childView;
    }

    @Override
    public final void addView(View child, int index, ViewGroup.LayoutParams params) {
        if (getChildCount() > 0) {
            throw new IllegalStateException("MaterialRippleLayout can host only one child");
        }
        //noinspection unchecked
        childView = child;
        super.addView(child, index, params);
    }

    @Override
    public void setOnClickListener(OnClickListener onClickListener) {
        if (childView == null) {
            throw new IllegalStateException("MaterialRippleLayout must have a child view to handle clicks");
        }
        childView.setOnClickListener(onClickListener);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return !findClickableViewInChild(childView, (int) event.getX(), (int) event.getY());
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean superOnTouchEvent = super.onTouchEvent(event);

        if (!isEnabled() || !childView.isEnabled()) return superOnTouchEvent;

        boolean isEventInBounds = bounds.contains((int) event.getX(), (int) event.getY());

        if (isEventInBounds) {
            previousCoords.set(currentCoords.x, currentCoords.y);
            currentCoords.set((int) event.getX(), (int) event.getY());
        }

        boolean gestureResult = gestureDetector.onTouchEvent(event);
        if (gestureResult || mHasPerformedLongPress) {
            return true;
        } else {
            int action = event.getActionMasked();
            switch (action) {
                case MotionEvent.ACTION_UP:
                    pendingClickEvent = new PerformClickEvent();

                    if (prepressed) {
                        childView.setPressed(true);
                        postDelayed(
                                new Runnable() {
                                    @Override public void run() {
                                        childView.setPressed(false);
                                    }
                                }, ViewConfiguration.getPressedStateDuration());
                    }

                    if (isEventInBounds) {
                        startRipple(pendingClickEvent);
                    } else if (!rippleHover) {
                        setRadius(0);
                    }
                    if (!rippleDelayClick && isEventInBounds) {
                        pendingClickEvent.run();
                    }
                    cancelPressedEvent();
                    break;
                case MotionEvent.ACTION_DOWN:
                    setPositionInAdapter();
                    eventCancelled = false;
                    pendingPressEvent = new PressedEvent(event);
                    if (isInScrollingContainer()) {
                        cancelPressedEvent();
                        prepressed = true;
                        postDelayed(pendingPressEvent, ViewConfiguration.getTapTimeout());
                    } else {
                        pendingPressEvent.run();
                    }
                    break;
                case MotionEvent.ACTION_CANCEL:
                    if (rippleInAdapter) {
                        // dont use current coords in adapter since they tend to jump drastically on scroll
                        currentCoords.set(previousCoords.x, previousCoords.y);
                        previousCoords = new Point();
                    }
                    childView.onTouchEvent(event);
                    if (rippleHover) {
                        if (!prepressed) {
                            startRipple(null);
                        }
                    } else {
                        childView.setPressed(false);
                    }
                    cancelPressedEvent();
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (rippleHover) {
                        if (isEventInBounds && !eventCancelled) {
                            invalidate();
                        } else if (!isEventInBounds) {
                            startRipple(null);
                        }
                    }

                    if (!isEventInBounds) {
                        cancelPressedEvent();
                        if (hoverAnimator != null) {
                            hoverAnimator.cancel();
                        }
                        childView.onTouchEvent(event);
                        eventCancelled = true;
                    }
                    break;
            }
            return true;
        }
    }

    private void cancelPressedEvent() {
        if (pendingPressEvent != null) {
            removeCallbacks(pendingPressEvent);
            prepressed = false;
        }
    }

    private boolean mHasPerformedLongPress;
    private SimpleOnGestureListener longClickListener = new SimpleOnGestureListener() {
        public void onLongPress(MotionEvent e) {
            mHasPerformedLongPress = childView.performLongClick();
            if (mHasPerformedLongPress) {
                if (rippleHover) {
                    startRipple(null);
                }
                cancelPressedEvent();
            }
        }

        @Override
        public boolean onDown(MotionEvent e) {
            mHasPerformedLongPress = false;
            return super.onDown(e);
        }
    };

    @TargetApi(14)
    private void startHover() {
        if (eventCancelled) return;

        if (hoverAnimator != null) {
            hoverAnimator.cancel();
        }
        final float radius = (float) (Math.sqrt(Math.pow(getWidth(), 2) + Math.pow(getHeight(), 2)) * 1.2f);
        hoverAnimator = ObjectAnimator.ofFloat(this, radiusProperty(), rippleDiameter, radius)
                .setDuration(HOVER_DURATION);
        hoverAnimator.setInterpolator(new LinearInterpolator());
        hoverAnimator.start();
    }

    @TargetApi(14)
    private void startRipple(final Runnable animationEndRunnable) {
        if (eventCancelled) return;

        float endRadius = getEndRadius();

        cancelAnimations();

        rippleAnimator = new AnimatorSet();
        rippleAnimator.addListener(new AnimatorListenerAdapter() {
            @Override public void onAnimationEnd(Animator animation) {
                if (!ripplePersistent) {
                    setRadius(0);
                    setRippleAlpha(rippleAlpha);
                }
                if (animationEndRunnable != null && rippleDelayClick) {
                    animationEndRunnable.run();
                }
                childView.setPressed(false);
            }
        });

        ObjectAnimator ripple = ObjectAnimator.ofFloat(this, radiusProperty(), radius, endRadius);
        ripple.setDuration(rippleDuration);
        ripple.setInterpolator(new DecelerateInterpolator());
        ObjectAnimator fade = ObjectAnimator.ofInt(this, circleAlphaProperty(), rippleAlpha, 0);
        fade.setDuration(rippleFadeDuration);
        fade.setInterpolator(new AccelerateInterpolator());
        fade.setStartDelay(rippleDuration - rippleFadeDuration - FADE_EXTRA_DELAY);

        if (ripplePersistent) {
            rippleAnimator.play(ripple);
        } else if (getRadius() > endRadius) {
            fade.setStartDelay(0);
            rippleAnimator.play(fade);
        } else {
            rippleAnimator.playTogether(ripple, fade);
        }
        rippleAnimator.start();
    }

    private void cancelAnimations() {
        if (rippleAnimator != null) {
            rippleAnimator.cancel();
            rippleAnimator.removeAllListeners();
        }

        if (hoverAnimator != null) {
            hoverAnimator.cancel();
        }
    }

    private float getEndRadius() {
        final int width = getWidth();
        final int height = getHeight();

        final int halfWidth = width / 2;
        final int halfHeight = height / 2;

        final float radiusX = halfWidth > currentCoords.x ? width - currentCoords.x : currentCoords.x;
        final float radiusY = halfHeight > currentCoords.y ? height - currentCoords.y : currentCoords.y;

        return (float) Math.sqrt(Math.pow(radiusX, 2) + Math.pow(radiusY, 2)) * 1.2f;
    }

    @TargetApi(14)
    private boolean isInScrollingContainer() {
        ViewParent p = getParent();
        while (p != null && p instanceof ViewGroup) {
            if (((ViewGroup) p).shouldDelayChildPressedState()) {
                return true;
            }
            p = p.getParent();
        }
        return false;
    }

    private AdapterView findParentAdapterView() {
        if (parentAdapter != null) {
            return parentAdapter;
        }
        ViewParent current = getParent();
        while (true) {
            if (current instanceof AdapterView) {
                parentAdapter = (AdapterView) current;
                return parentAdapter;
            } else {
                try {
                    current = current.getParent();
                } catch (NullPointerException npe) {
                    throw new RuntimeException("Could not find a parent AdapterView");
                }
            }
        }
    }

    private void setPositionInAdapter() {
        if (rippleInAdapter) {
            positionInAdapter = findParentAdapterView().getPositionForView(MaterialRippleLayout.this);
        }
    }

    private boolean adapterPositionChanged() {
        if (rippleInAdapter) {
            int newPosition = findParentAdapterView().getPositionForView(MaterialRippleLayout.this);
            final boolean changed = newPosition != positionInAdapter;
            positionInAdapter = newPosition;
            if (changed) {
                cancelPressedEvent();
                cancelAnimations();
                childView.setPressed(false);
                setRadius(0);
            }
            return changed;
        }
        return false;
    }

    private boolean findClickableViewInChild(View view, int x, int y) {
        if (view instanceof ViewGroup) {
            ViewGroup viewGroup = (ViewGroup) view;
            for (int i = 0; i < viewGroup.getChildCount(); i++) {
                View child = viewGroup.getChildAt(i);
                final Rect rect = new Rect();
                child.getHitRect(rect);

                final boolean contains = rect.contains(x, y);
                if (contains) {
                    return findClickableViewInChild(child, x - rect.left, y - rect.top);
                }
            }
        } else if (view != childView) {
            return (view.isEnabled() && (view.isClickable() || view.isLongClickable() || view.isFocusableInTouchMode()));
        }

        return view.isFocusableInTouchMode();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        bounds.set(0, 0, w, h);
        rippleBackground.setBounds(bounds);
    }

    @Override
    public boolean isInEditMode() {
        return true;
    }

    /*
     * Drawing
     */
    @Override
    public void draw(Canvas canvas) {
        final boolean positionChanged = adapterPositionChanged();
        if (rippleOverlay) {
            if (!positionChanged) {
                rippleBackground.draw(canvas);
            }
            super.draw(canvas);
            if (!positionChanged) {
                if (rippleRoundedCorners != 0) {
                    Path clipPath = new Path();
                    RectF rect = new RectF(0, 0, canvas.getWidth(), canvas.getHeight());
                    clipPath.addRoundRect(rect, rippleRoundedCorners, rippleRoundedCorners, Path.Direction.CW);
                    canvas.clipPath(clipPath);
                }
                canvas.drawCircle(currentCoords.x, currentCoords.y, radius, paint);
            }
        } else {
            if (!positionChanged) {
                rippleBackground.draw(canvas);
                canvas.drawCircle(currentCoords.x, currentCoords.y, radius, paint);
            }
            super.draw(canvas);
        }
    }

    /*
     * Animations
     */
    @TargetApi(14)
    private Property<MaterialRippleLayout, Float> radiusProperty() {
        Property<MaterialRippleLayout, Float> radiusProperty
                = new Property<MaterialRippleLayout, Float>(Float.class, "radius") {
            @Override
            public Float get(MaterialRippleLayout object) {
                return object.getRadius();
            }

            @Override
            public void set(MaterialRippleLayout object, Float value) {
                object.setRadius(value);
            }
        };
        return radiusProperty;
    }

    private float getRadius() {
        return radius;
    }


    public void setRadius(float radius) {
        this.radius = radius;
        invalidate();
    }


    @TargetApi(14)
    private Property<MaterialRippleLayout, Integer> circleAlphaProperty() {
        Property<MaterialRippleLayout, Integer> circleAlphaProperty
                = new Property<MaterialRippleLayout, Integer>(Integer.class, "rippleAlpha") {
            @Override
            public Integer get(MaterialRippleLayout object) {
                return object.getRippleAlpha();
            }

            @Override
            public void set(MaterialRippleLayout object, Integer value) {
                object.setRippleAlpha(value);
            }
        };
        return circleAlphaProperty;
    }

    public int getRippleAlpha() {
        return paint.getAlpha();
    }

    public void setRippleAlpha(Integer rippleAlpha) {
        paint.setAlpha(rippleAlpha);
        invalidate();
    }

    /*
    * Accessor
     */
    public void setRippleColor(int rippleColor) {
        this.rippleColor = rippleColor;
        paint.setColor(rippleColor);
        paint.setAlpha(rippleAlpha);
        invalidate();
    }

    public void setRippleOverlay(boolean rippleOverlay) {
        this.rippleOverlay = rippleOverlay;
    }

    public void setRippleDiameter(int rippleDiameter) {
        this.rippleDiameter = rippleDiameter;
    }

    public void setRippleDuration(int rippleDuration) {
        this.rippleDuration = rippleDuration;
    }

    public void setRippleBackground(int color) {
        rippleBackground = new ColorDrawable(color);
        rippleBackground.setBounds(bounds);
        invalidate();
    }

    public void setRippleHover(boolean rippleHover) {
        this.rippleHover = rippleHover;
    }

    public void setRippleDelayClick(boolean rippleDelayClick) {
        this.rippleDelayClick = rippleDelayClick;
    }

    public void setRippleFadeDuration(int rippleFadeDuration) {
        this.rippleFadeDuration = rippleFadeDuration;
    }

    public void setRipplePersistent(boolean ripplePersistent) {
        this.ripplePersistent = ripplePersistent;
    }

    public void setRippleInAdapter(boolean rippleInAdapter) {
        this.rippleInAdapter = rippleInAdapter;
    }

    public void setRippleRoundedCorners(int rippleRoundedCorner) {
        this.rippleRoundedCorners = rippleRoundedCorner;
        enableClipPathSupportIfNecessary();
    }

    public void setDefaultRippleAlpha(int alpha) {
        this.rippleAlpha = alpha;
        paint.setAlpha(alpha);
        invalidate();
    }

    public void performRipple() {
        currentCoords = new Point(getWidth() / 2, getHeight() / 2);
        startRipple(null);
    }

    public void performRipple(Point anchor) {
        currentCoords = new Point(anchor.x, anchor.y);
        startRipple(null);
    }

    /**
     * {@link Canvas#clipPath(Path)} is not supported in hardware accelerated layers
     * before API 18. Use software layer instead
     * <p/>
     * https://developer.android.com/guide/topics/graphics/hardware-accel.html#unsupported
     */
    private void enableClipPathSupportIfNecessary() {
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            if (rippleRoundedCorners != 0) {
                layerType = getLayerType();
                setLayerType(LAYER_TYPE_SOFTWARE, null);
            } else {
                setLayerType(layerType, null);
            }
        }
    }

    /*
     * Helper
     */
    private class PerformClickEvent implements Runnable {

        @Override public void run() {
            if (mHasPerformedLongPress) return;

            // if parent is an AdapterView, try to call its ItemClickListener
            if (getParent() instanceof AdapterView) {
                clickAdapterView((AdapterView) getParent());
            } else if (rippleInAdapter) {
                // find adapter view
                clickAdapterView(findParentAdapterView());
            } else {
                // otherwise, just perform click on child
                childView.performClick();
            }
        }

        private void clickAdapterView(AdapterView parent) {
            final int position = parent.getPositionForView(MaterialRippleLayout.this);
            final long itemId = parent.getAdapter() != null
                    ? parent.getAdapter().getItemId(position)
                    : 0;
            if (position != AdapterView.INVALID_POSITION) {
                parent.performItemClick(MaterialRippleLayout.this, position, itemId);
            }
        }
    }

    private final class PressedEvent implements Runnable {

        private final MotionEvent event;

        public PressedEvent(MotionEvent event) {
            this.event = event;
        }

        @Override
        public void run() {
            prepressed = false;
            childView.setLongClickable(false);//prevent the child's long click,let's the ripple layout call it's performLongClick
            childView.onTouchEvent(event);
            childView.setPressed(true);
            if (rippleHover) {
                startHover();
            }
        }
    }

    static float dpToPx(Resources resources, float dp) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, resources.getDisplayMetrics());
    }

    /*
     * Builder
     */

    public static class RippleBuilder {

        private final Context context;
        private final View    child;

        private int     rippleColor         = DEFAULT_COLOR;
        private boolean rippleOverlay       = DEFAULT_RIPPLE_OVERLAY;
        private boolean rippleHover         = DEFAULT_HOVER;
        private float   rippleDiameter      = DEFAULT_DIAMETER_DP;
        private int     rippleDuration      = DEFAULT_DURATION;
        private float   rippleAlpha         = DEFAULT_ALPHA;
        private boolean rippleDelayClick    = DEFAULT_DELAY_CLICK;
        private int     rippleFadeDuration  = DEFAULT_FADE_DURATION;
        private boolean ripplePersistent    = DEFAULT_PERSISTENT;
        private int     rippleBackground    = DEFAULT_BACKGROUND;
        private boolean rippleSearchAdapter = DEFAULT_SEARCH_ADAPTER;
        private float   rippleRoundedCorner = DEFAULT_ROUNDED_CORNERS;

        public RippleBuilder(View child) {
            this.child = child;
            this.context = child.getContext();
        }

        public RippleBuilder rippleColor(int color) {
            this.rippleColor = color;
            return this;
        }

        public RippleBuilder rippleOverlay(boolean overlay) {
            this.rippleOverlay = overlay;
            return this;
        }

        public RippleBuilder rippleHover(boolean hover) {
            this.rippleHover = hover;
            return this;
        }

        public RippleBuilder rippleDiameterDp(int diameterDp) {
            this.rippleDiameter = diameterDp;
            return this;
        }

        public RippleBuilder rippleDuration(int duration) {
            this.rippleDuration = duration;
            return this;
        }

        public RippleBuilder rippleAlpha(float alpha) {
            this.rippleAlpha = 255 * alpha;
            return this;
        }

        public RippleBuilder rippleDelayClick(boolean delayClick) {
            this.rippleDelayClick = delayClick;
            return this;
        }

        public RippleBuilder rippleFadeDuration(int fadeDuration) {
            this.rippleFadeDuration = fadeDuration;
            return this;
        }

        public RippleBuilder ripplePersistent(boolean persistent) {
            this.ripplePersistent = persistent;
            return this;
        }

        public RippleBuilder rippleBackground(int color) {
            this.rippleBackground = color;
            return this;
        }

        public RippleBuilder rippleInAdapter(boolean inAdapter) {
            this.rippleSearchAdapter = inAdapter;
            return this;
        }

        public RippleBuilder rippleRoundedCorners(int radiusDp) {
            this.rippleRoundedCorner = radiusDp;
            return this;
        }

        public MaterialRippleLayout create() {
            MaterialRippleLayout layout = new MaterialRippleLayout(context);
            layout.setRippleColor(rippleColor);
            layout.setDefaultRippleAlpha((int) rippleAlpha);
            layout.setRippleDelayClick(rippleDelayClick);
            layout.setRippleDiameter((int) dpToPx(context.getResources(), rippleDiameter));
            layout.setRippleDuration(rippleDuration);
            layout.setRippleFadeDuration(rippleFadeDuration);
            layout.setRippleHover(rippleHover);
            layout.setRipplePersistent(ripplePersistent);
            layout.setRippleOverlay(rippleOverlay);
            layout.setRippleBackground(rippleBackground);
            layout.setRippleInAdapter(rippleSearchAdapter);
            layout.setRippleRoundedCorners((int) dpToPx(context.getResources(), rippleRoundedCorner));

            ViewGroup.LayoutParams params = child.getLayoutParams();
            ViewGroup parent = (ViewGroup) child.getParent();
            int index = 0;

            if (parent != null && parent instanceof MaterialRippleLayout) {
                throw new IllegalStateException("MaterialRippleLayout could not be created: parent of the view already is a MaterialRippleLayout");
            }

            if (parent != null) {
                index = parent.indexOfChild(child);
                parent.removeView(child);
            }

            layout.addView(child, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));

            if (parent != null) {
                parent.addView(layout, index, params);
            }

            return layout;
        }
    }
} public class MaterialRippleLayoutNineOld extends FrameLayout {

    private static final int DEFAULT_DURATION = 350;
    private static final int DEFAULT_FADE_DURATION = 75;
    private static final float DEFAULT_DIAMETER_DP = 35;
    private static final float DEFAULT_ALPHA = 0.2f;
    private static final int DEFAULT_COLOR = Color.BLACK;
    private static final int DEFAULT_BACKGROUND = Color.TRANSPARENT;
    private static final boolean DEFAULT_HOVER = true;
    private static final boolean DEFAULT_DELAY_CLICK = true;
    private static final boolean DEFAULT_PERSISTENT = false;
    private static final boolean DEFAULT_SEARCH_ADAPTER = false;
    private static final boolean DEFAULT_RIPPLE_OVERLAY = false;
    private static final int DEFAULT_ROUNDED_CORNERS = 0;

    private static final int FADE_EXTRA_DELAY = 50;
    private static final long HOVER_DURATION = 2500;

    private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private final Rect bounds = new Rect();

    private int rippleColor;
    private boolean rippleOverlay;
    private boolean rippleHover;
    private int rippleDiameter;
    private int rippleDuration;
    private int rippleAlpha;
    private boolean rippleDelayClick;
    private int rippleFadeDuration;
    private boolean ripplePersistent;
    private Drawable rippleBackground;
    private boolean rippleInAdapter;
    private float rippleRoundedCorners;

    private float radius;

    private AdapterView parentAdapter;
    private View childView;

    private AnimatorSet rippleAnimator;
    private ObjectAnimator hoverAnimator;

    private Point currentCoords = new Point();
    private Point previousCoords = new Point();

    private int layerType;

    private boolean eventCancelled;
    private boolean prepressed;
    private int positionInAdapter;

    private GestureDetector gestureDetector;
    private PerformClickEvent pendingClickEvent;
    private PressedEvent pendingPressEvent;

    public static RippleBuilder on(View view) {
        return new RippleBuilder(view);
    }

    public MaterialRippleLayoutNineOld(Context context) {
        this(context, null, 0);
    }

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

    public MaterialRippleLayoutNineOld(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        setWillNotDraw(false);
        gestureDetector = new GestureDetector(context, longClickListener);

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MaterialRippleLayout);
        rippleColor = a.getColor(R.styleable.MaterialRippleLayout_mrlsxm_rippleColor, DEFAULT_COLOR);
        rippleDiameter = a.getDimensionPixelSize(
                R.styleable.MaterialRippleLayout_mrlsxm_rippleDimension,
                (int) dpToPx(getResources(), DEFAULT_DIAMETER_DP)
        );
        rippleOverlay = a.getBoolean(R.styleable.MaterialRippleLayout_mrlsxm_rippleOverlay, DEFAULT_RIPPLE_OVERLAY);
        rippleHover = a.getBoolean(R.styleable.MaterialRippleLayout_mrlsxm_rippleHover, DEFAULT_HOVER);
        rippleDuration = a.getInt(R.styleable.MaterialRippleLayout_mrlsxm_rippleDuration, DEFAULT_DURATION);
        rippleAlpha = (int) (255 * a.getFloat(R.styleable.MaterialRippleLayout_mrlsxm_rippleAlpha, DEFAULT_ALPHA));
        rippleDelayClick = a.getBoolean(R.styleable.MaterialRippleLayout_mrlsxm_rippleDelayClick, DEFAULT_DELAY_CLICK);
        rippleFadeDuration = a.getInteger(R.styleable.MaterialRippleLayout_mrlsxm_rippleFadeDuration, DEFAULT_FADE_DURATION);
        rippleBackground = new ColorDrawable(a.getColor(R.styleable.MaterialRippleLayout_mrlsxm_rippleBackground, DEFAULT_BACKGROUND));
        ripplePersistent = a.getBoolean(R.styleable.MaterialRippleLayout_mrlsxm_ripplePersistent, DEFAULT_PERSISTENT);
        rippleInAdapter = a.getBoolean(R.styleable.MaterialRippleLayout_mrlsxm_rippleInAdapter, DEFAULT_SEARCH_ADAPTER);
        rippleRoundedCorners = a.getDimensionPixelSize(R.styleable.MaterialRippleLayout_mrlsxm_rippleRoundedCorners, DEFAULT_ROUNDED_CORNERS);

        a.recycle();

        paint.setColor(rippleColor);
        paint.setAlpha(rippleAlpha);

        enableClipPathSupportIfNecessary();
    }


    @SuppressWarnings("unchecked")
    public <T extends View> T getChildView() {
        return (T) childView;
    }

    @Override
    public final void addView(View child, int index, ViewGroup.LayoutParams params) {
        if (getChildCount() > 0) {
            throw new IllegalStateException("MaterialRippleLayout can host only one child");
        }
        //noinspection unchecked
        childView = child;
        super.addView(child, index, params);
    }

    @Override
    public void setOnClickListener(OnClickListener onClickListener) {
        if (childView == null) {
            throw new IllegalStateException("MaterialRippleLayout must have a child view to handle clicks");
        }
        childView.setOnClickListener(onClickListener);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return !findClickableViewInChild(childView, (int) event.getX(), (int) event.getY());
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean superOnTouchEvent = super.onTouchEvent(event);

        if (!isEnabled() || !childView.isEnabled()) return superOnTouchEvent;

        boolean isEventInBounds = bounds.contains((int) event.getX(), (int) event.getY());

        if (isEventInBounds) {
            previousCoords.set(currentCoords.x, currentCoords.y);
            currentCoords.set((int) event.getX(), (int) event.getY());
        }

        boolean gestureResult = gestureDetector.onTouchEvent(event);
        if (gestureResult || mHasPerformedLongPress) {
            return true;
        } else {
            int action = event.getActionMasked();
            switch (action) {
                case MotionEvent.ACTION_UP:
                    pendingClickEvent = new PerformClickEvent();

                    if (prepressed) {
                        childView.setPressed(true);
                        postDelayed(
                                new Runnable() {
                                    @Override
                                    public void run() {
                                        childView.setPressed(false);
                                    }
                                }, ViewConfiguration.getPressedStateDuration());
                    }

                    if (isEventInBounds) {
                        startRipple(pendingClickEvent);
                    } else if (!rippleHover) {
                        setRadius(0);
                    }
                    if (!rippleDelayClick && isEventInBounds) {
                        pendingClickEvent.run();
                    }
                    cancelPressedEvent();
                    break;
                case MotionEvent.ACTION_DOWN:
                    setPositionInAdapter();
                    eventCancelled = false;
                    pendingPressEvent = new PressedEvent(event);
                    if (isInScrollingContainer()) {
                        cancelPressedEvent();
                        prepressed = true;
                        postDelayed(pendingPressEvent, ViewConfiguration.getTapTimeout());
                    } else {
                        pendingPressEvent.run();
                    }
                    break;
                case MotionEvent.ACTION_CANCEL:
                    if (rippleInAdapter) {
                        // dont use current coords in adapter since they tend to jump drastically on scroll
                        currentCoords.set(previousCoords.x, previousCoords.y);
                        previousCoords = new Point();
                    }
                    childView.onTouchEvent(event);
                    if (rippleHover) {
                        if (!prepressed) {
                            startRipple(null);
                        }
                    } else {
                        childView.setPressed(false);
                    }
                    cancelPressedEvent();
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (rippleHover) {
                        if (isEventInBounds && !eventCancelled) {
                            invalidate();
                        } else if (!isEventInBounds) {
                            startRipple(null);
                        }
                    }

                    if (!isEventInBounds) {
                        cancelPressedEvent();
                        if (hoverAnimator != null) {
                            hoverAnimator.cancel();
                        }
                        childView.onTouchEvent(event);
                        eventCancelled = true;
                    }
                    break;
            }
            return true;
        }
    }

    private void cancelPressedEvent() {
        if (pendingPressEvent != null) {
            removeCallbacks(pendingPressEvent);
            prepressed = false;
        }
    }

    private boolean mHasPerformedLongPress;
    private SimpleOnGestureListener longClickListener = new SimpleOnGestureListener() {
        public void onLongPress(MotionEvent e) {
            mHasPerformedLongPress = childView.performLongClick();
            if (mHasPerformedLongPress) {
                if (rippleHover) {
                    startRipple(null);
                }
                cancelPressedEvent();
            }
        }

        @Override
        public boolean onDown(MotionEvent e) {
            mHasPerformedLongPress = false;
            return super.onDown(e);
        }
    };

    private void startHover() {
        if (eventCancelled) return;

        if (hoverAnimator != null) {
            hoverAnimator.cancel();
        }
        final float radius = (float) (Math.sqrt(Math.pow(getWidth(), 2) + Math.pow(getHeight(), 2)) * 1.2f);
        hoverAnimator = ObjectAnimator.ofFloat(this, radiusProperty, rippleDiameter, radius)
                .setDuration(HOVER_DURATION);
        hoverAnimator.setInterpolator(new LinearInterpolator());
        hoverAnimator.start();
    }

    private void startRipple(final Runnable animationEndRunnable) {
        if (eventCancelled) return;

        float endRadius = getEndRadius();


        cancelAnimations();

        rippleAnimator = new AnimatorSet();
        rippleAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                if (!ripplePersistent) {
                    setRadius(0);
                    setRippleAlpha(rippleAlpha);
                }
                if (animationEndRunnable != null && rippleDelayClick) {
                    animationEndRunnable.run();
                }
                childView.setPressed(false);
            }
        });

        ObjectAnimator ripple = ObjectAnimator.ofFloat(this, radiusProperty, radius, endRadius);
        ripple.setDuration(rippleDuration);
        ripple.setInterpolator(new DecelerateInterpolator());
        ObjectAnimator fade = ObjectAnimator.ofInt(this, circleAlphaProperty, rippleAlpha, 0);
        fade.setDuration(rippleFadeDuration);
        fade.setInterpolator(new AccelerateInterpolator());
        fade.setStartDelay(rippleDuration - rippleFadeDuration - FADE_EXTRA_DELAY);

        if (ripplePersistent) {
            rippleAnimator.play(ripple);
        } else if (getRadius() > endRadius) {
            fade.setStartDelay(0);
            rippleAnimator.play(fade);
        } else {
            rippleAnimator.playTogether(ripple, fade);
        }
        rippleAnimator.start();
    }

    private void cancelAnimations() {
        if (rippleAnimator != null) {
            rippleAnimator.cancel();
            rippleAnimator.removeAllListeners();
        }

        if (hoverAnimator != null) {
            hoverAnimator.cancel();
        }
    }

    private float getEndRadius() {
        final int width = getWidth();
        final int height = getHeight();

        final int halfWidth = width / 2;
        final int halfHeight = height / 2;

        final float radiusX = halfWidth > currentCoords.x ? width - currentCoords.x : currentCoords.x;
        final float radiusY = halfHeight > currentCoords.y ? height - currentCoords.y : currentCoords.y;

        return (float) Math.sqrt(Math.pow(radiusX, 2) + Math.pow(radiusY, 2)) * 1.2f;
    }

    private boolean isInScrollingContainer() {
        ViewParent p = getParent();
        /*while (p != null && p instanceof ViewGroup) {
            if (((ViewGroup) p).shouldDelayChildPressedState()) {
                return true;
            }
            p = p.getParent();
        }*/
        return false;
    }

    private AdapterView findParentAdapterView() {
        if (parentAdapter != null) {
            return parentAdapter;
        }
        ViewParent current = getParent();
        while (true) {
            if (current instanceof AdapterView) {
                parentAdapter = (AdapterView) current;
                return parentAdapter;
            } else {
                try {
                    current = current.getParent();
                } catch (NullPointerException npe) {
                    throw new RuntimeException("Could not find a parent AdapterView");
                }
            }
        }
    }

    private void setPositionInAdapter() {
        if (rippleInAdapter) {
            positionInAdapter = findParentAdapterView().getPositionForView(MaterialRippleLayoutNineOld.this);
        }
    }

    private boolean adapterPositionChanged() {
        if (rippleInAdapter) {
            int newPosition = findParentAdapterView().getPositionForView(MaterialRippleLayoutNineOld.this);
            final boolean changed = newPosition != positionInAdapter;
            positionInAdapter = newPosition;
            if (changed) {
                cancelPressedEvent();
                cancelAnimations();
                childView.setPressed(false);
                setRadius(0);
            }
            return changed;
        }
        return false;
    }

    private boolean findClickableViewInChild(View view, int x, int y) {
        if (view instanceof ViewGroup) {
            ViewGroup viewGroup = (ViewGroup) view;
            for (int i = 0; i < viewGroup.getChildCount(); i++) {
                View child = viewGroup.getChildAt(i);
                final Rect rect = new Rect();
                child.getHitRect(rect);

                final boolean contains = rect.contains(x, y);
                if (contains) {
                    return findClickableViewInChild(child, x - rect.left, y - rect.top);
                }
            }
        } else if (view != childView) {
            return (view.isEnabled() && (view.isClickable() || view.isLongClickable() || view.isFocusableInTouchMode()));
        }

        return view.isFocusableInTouchMode();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        bounds.set(0, 0, w, h);
        rippleBackground.setBounds(bounds);
    }

    @Override
    public boolean isInEditMode() {
        return true;
    }

    /*
     * Drawing
     */
    @Override
    public void draw(Canvas canvas) {
        final boolean positionChanged = adapterPositionChanged();
        if (rippleOverlay) {
            if (!positionChanged) {
                rippleBackground.draw(canvas);
            }
            super.draw(canvas);
            if (!positionChanged) {
                if (rippleRoundedCorners != 0) {
                    Path clipPath = new Path();
                    RectF rect = new RectF(0, 0, canvas.getWidth(), canvas.getHeight());
                    clipPath.addRoundRect(rect, rippleRoundedCorners, rippleRoundedCorners, Path.Direction.CW);
                    canvas.clipPath(clipPath);
                }
                canvas.drawCircle(currentCoords.x, currentCoords.y, radius, paint);
            }
        } else {
            if (!positionChanged) {
                rippleBackground.draw(canvas);
                canvas.drawCircle(currentCoords.x, currentCoords.y, radius, paint);
            }
            super.draw(canvas);
        }
    }

    /*
     * Animations
     */
    private Property<MaterialRippleLayoutNineOld, Float> radiusProperty
            = new Property<MaterialRippleLayoutNineOld, Float>(Float.class, "radius") {
        @Override
        public Float get(MaterialRippleLayoutNineOld object) {
            return object.getRadius();
        }

        @Override
        public void set(MaterialRippleLayoutNineOld object, Float value) {
            object.setRadius(value);
        }
    };

    private float getRadius() {
        return radius;
    }


    public void setRadius(float radius) {
        this.radius = radius;
        invalidate();
    }

    private Property<MaterialRippleLayoutNineOld, Integer> circleAlphaProperty
            = new Property<MaterialRippleLayoutNineOld, Integer>(Integer.class, "rippleAlpha") {
        @Override
        public Integer get(MaterialRippleLayoutNineOld object) {
            return object.getRippleAlpha();
        }

        @Override
        public void set(MaterialRippleLayoutNineOld object, Integer value) {
            object.setRippleAlpha(value);
        }
    };

    public int getRippleAlpha() {
        return paint.getAlpha();
    }

    public void setRippleAlpha(Integer rippleAlpha) {
        paint.setAlpha(rippleAlpha);
        invalidate();
    }

    /*
    * Accessor
     */
    public void setRippleColor(int rippleColor) {
        this.rippleColor = rippleColor;
        paint.setColor(rippleColor);
        paint.setAlpha(rippleAlpha);
        invalidate();
    }

    public void setRippleOverlay(boolean rippleOverlay) {
        this.rippleOverlay = rippleOverlay;
    }

    public void setRippleDiameter(int rippleDiameter) {
        this.rippleDiameter = rippleDiameter;
    }

    public void setRippleDuration(int rippleDuration) {
        this.rippleDuration = rippleDuration;
    }

    public void setRippleBackground(int color) {
        rippleBackground = new ColorDrawable(color);
        rippleBackground.setBounds(bounds);
        invalidate();
    }

    public void setRippleHover(boolean rippleHover) {
        this.rippleHover = rippleHover;
    }

    public void setRippleDelayClick(boolean rippleDelayClick) {
        this.rippleDelayClick = rippleDelayClick;
    }

    public void setRippleFadeDuration(int rippleFadeDuration) {
        this.rippleFadeDuration = rippleFadeDuration;
    }

    public void setRipplePersistent(boolean ripplePersistent) {
        this.ripplePersistent = ripplePersistent;
    }

    public void setRippleInAdapter(boolean rippleInAdapter) {
        this.rippleInAdapter = rippleInAdapter;
    }

    public void setRippleRoundedCorners(int rippleRoundedCorner) {
        this.rippleRoundedCorners = rippleRoundedCorner;
        enableClipPathSupportIfNecessary();
    }

    public void setDefaultRippleAlpha(int alpha) {
        this.rippleAlpha = alpha;
        paint.setAlpha(alpha);
        invalidate();
    }

    public void performRipple() {
        currentCoords = new Point(getWidth() / 2, getHeight() / 2);
        startRipple(null);
    }

    public void performRipple(Point anchor) {
        currentCoords = new Point(anchor.x, anchor.y);
        startRipple(null);
    }

    /**
     * {@link Canvas#clipPath(Path)} is not supported in hardware accelerated layers
     * before API 18. Use software layer instead
     * <p/>
     * https://developer.android.com/guide/topics/graphics/hardware-accel.html#unsupported
     */
    @TargetApi(11)
    private void enableClipPathSupportIfNecessary() {
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR1 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            if (rippleRoundedCorners != 0) {
                layerType = getLayerType();
                setLayerType(LAYER_TYPE_SOFTWARE, null);
            } else {
                setLayerType(layerType, null);
            }
        }
    }

    /*
     * Helper
     */
    private class PerformClickEvent implements Runnable {

        @Override
        public void run() {
            if (mHasPerformedLongPress) return;

            // if parent is an AdapterView, try to call its ItemClickListener
            if (getParent() instanceof AdapterView) {
                clickAdapterView((AdapterView) getParent());
            } else if (rippleInAdapter) {
                // find adapter view
                clickAdapterView(findParentAdapterView());
            } else {
                // otherwise, just perform click on child
                childView.performClick();
            }
        }

        private void clickAdapterView(AdapterView parent) {
            final int position = parent.getPositionForView(MaterialRippleLayoutNineOld.this);
            final long itemId = parent.getAdapter() != null
                    ? parent.getAdapter().getItemId(position)
                    : 0;
            if (position != AdapterView.INVALID_POSITION) {
                parent.performItemClick(MaterialRippleLayoutNineOld.this, position, itemId);
            }
        }
    }

    private final class PressedEvent implements Runnable {

        private final MotionEvent event;

        public PressedEvent(MotionEvent event) {
            this.event = event;
        }

        @Override
        public void run() {
            prepressed = false;
            childView.setLongClickable(false);//prevent the child's long click,let's the ripple layout call it's performLongClick
            childView.onTouchEvent(event);
            childView.setPressed(true);
            if (rippleHover) {
                startHover();
            }
        }
    }

    static float dpToPx(Resources resources, float dp) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, resources.getDisplayMetrics());
    }

    /*
     * Builder
     */

    public static class RippleBuilder {

        private final Context context;
        private final View child;

        private int rippleColor = DEFAULT_COLOR;
        private boolean rippleOverlay = DEFAULT_RIPPLE_OVERLAY;
        private boolean rippleHover = DEFAULT_HOVER;
        private float rippleDiameter = DEFAULT_DIAMETER_DP;
        private int rippleDuration = DEFAULT_DURATION;
        private float rippleAlpha = DEFAULT_ALPHA;
        private boolean rippleDelayClick = DEFAULT_DELAY_CLICK;
        private int rippleFadeDuration = DEFAULT_FADE_DURATION;
        private boolean ripplePersistent = DEFAULT_PERSISTENT;
        private int rippleBackground = DEFAULT_BACKGROUND;
        private boolean rippleSearchAdapter = DEFAULT_SEARCH_ADAPTER;
        private float rippleRoundedCorner = DEFAULT_ROUNDED_CORNERS;

        public RippleBuilder(View child) {
            this.child = child;
            this.context = child.getContext();
        }

        public RippleBuilder rippleColor(int color) {
            this.rippleColor = color;
            return this;
        }

        public RippleBuilder rippleOverlay(boolean overlay) {
            this.rippleOverlay = overlay;
            return this;
        }

        public RippleBuilder rippleHover(boolean hover) {
            this.rippleHover = hover;
            return this;
        }

        public RippleBuilder rippleDiameterDp(int diameterDp) {
            this.rippleDiameter = diameterDp;
            return this;
        }

        public RippleBuilder rippleDuration(int duration) {
            this.rippleDuration = duration;
            return this;
        }

        public RippleBuilder rippleAlpha(float alpha) {
            this.rippleAlpha = 255 * alpha;
            return this;
        }

        public RippleBuilder rippleDelayClick(boolean delayClick) {
            this.rippleDelayClick = delayClick;
            return this;
        }

        public RippleBuilder rippleFadeDuration(int fadeDuration) {
            this.rippleFadeDuration = fadeDuration;
            return this;
        }

        public RippleBuilder ripplePersistent(boolean persistent) {
            this.ripplePersistent = persistent;
            return this;
        }

        public RippleBuilder rippleBackground(int color) {
            this.rippleBackground = color;
            return this;
        }

        public RippleBuilder rippleInAdapter(boolean inAdapter) {
            this.rippleSearchAdapter = inAdapter;
            return this;
        }

        public RippleBuilder rippleRoundedCorners(int radiusDp) {
            this.rippleRoundedCorner = radiusDp;
            return this;
        }

        public MaterialRippleLayoutNineOld create() {
            MaterialRippleLayoutNineOld layout = new MaterialRippleLayoutNineOld(context);
            layout.setRippleColor(rippleColor);
            layout.setDefaultRippleAlpha((int) rippleAlpha);
            layout.setRippleDelayClick(rippleDelayClick);
            layout.setRippleDiameter((int) dpToPx(context.getResources(), rippleDiameter));
            layout.setRippleDuration(rippleDuration);
            layout.setRippleFadeDuration(rippleFadeDuration);
            layout.setRippleHover(rippleHover);
            layout.setRipplePersistent(ripplePersistent);
            layout.setRippleOverlay(rippleOverlay);
            layout.setRippleBackground(rippleBackground);
            layout.setRippleInAdapter(rippleSearchAdapter);
            layout.setRippleRoundedCorners((int) dpToPx(context.getResources(), rippleRoundedCorner));

            ViewGroup.LayoutParams params = child.getLayoutParams();
            ViewGroup parent = (ViewGroup) child.getParent();
            int index = 0;

            if (parent != null && parent instanceof MaterialRippleLayoutNineOld) {
                throw new IllegalStateException("MaterialRippleLayout could not be created: parent of the view already is a MaterialRippleLayout");
            }

            if (parent != null) {
                index = parent.indexOfChild(child);
                parent.removeView(child);
            }

            layout.addView(child, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));

            if (parent != null) {
                parent.addView(layout, index, params);
            }

            return layout;
        }
    }
} public class MaterialListSection<TD, CustomTextView extends TextView, RenderBinder extends MaterialListSection.RenderViewBindAdapter> implements ImaterialBinder {
    public CustomTextView text, notificationtext;
    public ImageView indicator, icon;
    public UltimateRecyclerView listview;
    public static String TAG = "txtNavigation";
    private RenderBinder renderer;
    private boolean mstatusShown, animate_indicator;
    private View mContainer;
    private int mContainerOriginalHeight, itemcounts, bottomNavigationHeight;
    private LockableScrollView scrollcontainer;
    private int DURATION = 900;
    private ValueAnimator anim;


    public MaterialListSection() {
        mstatusShown = false;
    }

    @Override
    public int getLayout() {
        return R.layout.section_list_header;
    }

    private int submenu_item_height = 0, containerTHeight = 0;


    @SuppressLint("WrongViewCast")
    @Override
    public View init(View view) {
        indicator = (ImageView) view.findViewById(R.id.indicatorIcon);
        text = (CustomTextView) view.findViewById(R.id.section_text);
        notificationtext = (CustomTextView) view.findViewById(R.id.section_notification);
        listview = (UltimateRecyclerView) view.findViewById(R.id.ultimate_recycler_view);
        // listview.disableLoadmore();
        listview.setSaveEnabled(false);
        CustomLinearLayoutManager mlayout = new CustomLinearLayoutManager(view.getContext(), LinearLayoutManager.VERTICAL, false);
        listview.setLayoutManager(mlayout);
        listview.setHasFixedSize(false);
        listview.setAdapter(renderer);
        mContainer = view;

        submenu_item_height = view.getContext().getResources().getDimensionPixelSize(R.dimen.sectionNormalHeight);

        animate_indicator = true;

        final Resources resources = view.getContext().getResources();
        int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
        if (resourceId > 0) {
            bottomNavigationHeight = resources.getDimensionPixelSize(resourceId);
        }
        return view;
    }


    private float mdensity;

    public void setDensity(final float density) {
        this.mdensity = density;
    }

    public void setAnimateIndicator(final boolean b) {
        this.animate_indicator = b;
    }

    public void setNormalHeight(int mContainerOriginalHeight) {
        this.mContainerOriginalHeight = mContainerOriginalHeight;
    }

    public void setScrollContainer(LockableScrollView scroll) {
        this.scrollcontainer = scroll;
        this.containerTHeight = scroll.getChildAt(0).getHeight();
    }

    public MaterialListSection andRenderWith(RenderBinder rbinder) {
        this.renderer = rbinder;
        return this;
    }

    public MaterialListSection toggleListShown() {
        mstatusShown = !mstatusShown;
        showList(mstatusShown);
        return this;
    }

    private MaterialListSection showList(boolean t) {
        itemcounts = listview.getAdapter().getItemCount();
        this.containerTHeight = this.scrollcontainer.getChildAt(0).getHeight();
        if (itemcounts > 0) {
            postAnimationListHeight(listview, t);
        }
        return this;
    }


    private void animateIndicator(final boolean open) {
        if (animate_indicator) {
            //indicator.clearAnimation();
            final Animation r = new RotateAnimation(indicator.getRotation(),
                    !open ? 0 : 90f, open ? Animation.RELATIVE_TO_SELF : Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
            r.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {

                }

                @Override
                public void onAnimationEnd(Animation animation) {
                    ViewCompat.setRotation(indicator, !open ? 0f : 90f);
                }

                @Override
                public void onAnimationRepeat(Animation animation) {

                }
            });
            r.setDuration(500);
            indicator.startAnimation(r);
        }
    }

    private void postAnimationListHeight(final UltimateRecyclerView listrv, final boolean expand) {
        final int listviewOriginalHeight = itemcounts * submenu_item_height;
        final int heightListView = Math.min(containerTHeight - mContainerOriginalHeight, listviewOriginalHeight);
        if (expand) {
            anim = ValueAnimator.ofInt(mContainerOriginalHeight, heightListView);
        } else {
            anim = ValueAnimator.ofInt(heightListView, mContainerOriginalHeight);
        }
        animateIndicator(expand);
        anim.setInterpolator(new AccelerateDecelerateInterpolator());
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                int val = (Integer) valueAnimator.getAnimatedValue();
                ViewGroup.MarginLayoutParams layoutParams1 = (ViewGroup.MarginLayoutParams) ((View) listrv).getLayoutParams();
                ViewGroup.MarginLayoutParams layoutParams2 = (ViewGroup.MarginLayoutParams) ((View) mContainer).getLayoutParams();
                //  ViewGroup.LayoutParams layoutParams = listrv.getLayoutParams();
                layoutParams2.height = val;
                layoutParams1.height = val - mContainerOriginalHeight;
                //listrv.setLayoutParams(layoutParams);
                listrv.requestLayout();
                mContainer.requestLayout();
                scrollcontainer.setScrollY(-val + mContainerOriginalHeight);
            }
        });
        anim.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                scrollcontainer.setScrollingEnabled(!expand);
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        anim.setDuration(DURATION);
        anim.start();
    }

    public static class RenderViewBindAdapter<TD> extends easyRegularAdapter<TD, RowBinder> {

        public static RenderViewBindAdapter newInstance(List<?> list) {
            return new RenderViewBindAdapter(list);
        }

        /**
         * dynamic object to start
         *
         * @param list the list source
         */
        public RenderViewBindAdapter(List list) {
            super(list);
        }

        @Override
        protected void withBindHolder(final RowBinder holder, final TD data, final int pos) {
            if (data instanceof String) {
                holder.text.setText((String) data);
            }
            holder.setOnSelectItem(pos);
        }

        /**
         * the layout id for the normal data
         *
         * @return the ID
         */
        @Override
        protected int getNormalLayoutResId() {
            return R.layout.section_sub_list_row;
        }

        @Override
        protected RowBinder newViewHolder(View view) {
            return new RowBinder(view);
        }

    }

} public class MaterialSectionBind<CustomTextView extends TextView> implements ImaterialBinder {
    public CustomTextView text;
    public ImageView iconHolder;
    private final boolean hasIcon;
    private int iconRes;

    public MaterialSectionBind() {
        hasIcon = false;
    }

    public MaterialSectionBind(@DrawableRes int icon) {
        hasIcon = true;
        iconRes = icon;
    }

    public boolean withIcon() {
        return hasIcon;
    }

    @Override
    public int getLayout() {
        return hasIcon ? R.layout.section_icon : R.layout.section_material;
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    @SuppressLint("WrongViewCast")
    public View init(View view) {
        text = (CustomTextView) view.findViewById(R.id.section_text);
        if (hasIcon) {
            iconHolder = (ImageView) view.findViewById(R.id.section_icon);
            Drawable icon = ContextCompat.getDrawable(view.getContext(), iconRes);
            iconHolder.setImageDrawable(icon);
        }
        return view;
    }

    public void tintColor(int iconColor) {
        if (withIcon())
            this.iconHolder.setColorFilter(iconColor);
    }

    private void checkVisibleAndVisible() {
        if (withIcon()) {
            if (iconHolder.getVisibility() == View.INVISIBLE || iconHolder.getVisibility() == View.GONE) {
                iconHolder.setVisibility(View.VISIBLE);
            }
        }
    }

    public void reConfigIcon(final Drawable image) {
        if (withIcon()) {
            iconHolder.setImageDrawable(image);
            checkVisibleAndVisible();
        }
    }

    public void reConfigIcon(final Drawable image, final int colorTint) {
        if (withIcon()) {
            iconHolder.setImageDrawable(image);
            iconHolder.setColorFilter(colorTint);
            checkVisibleAndVisible();
        }
    }


    public void reConfigIcon(final Bitmap image) {
        if (withIcon()) {
            iconHolder.setImageBitmap(image);
            checkVisibleAndVisible();
        }
    }

    public void reConfigIcon(final Bitmap image, final int colorTint) {
        if (withIcon()) {
            iconHolder.setImageBitmap(image);
            iconHolder.setColorFilter(colorTint);
            checkVisibleAndVisible();
        }
    }
} public class MaterialSectionNotificationBind<CustomTextView extends TextView> extends MaterialSectionBind {
    public CustomTextView notificationText;

    public MaterialSectionNotificationBind() {
        super();
    }

    public MaterialSectionNotificationBind(@DrawableRes int icon) {
        super(icon);
    }

    @SuppressLint("WrongViewCast")
    public View init(View view) {
        super.init(view);
        notificationText = (CustomTextView) view.findViewById(R.id.section_notification);
        return view;
    }

    @Override
    public int getLayout() {
        return withIcon() ? R.layout.section_icon : R.layout.section_material;
    }

    public void setNotificationStyle() {

    }

    public void setNumber(int notifications) {
        String textNotification;
        textNotification = String.valueOf(notifications);
        if (notifications < 1) {
            textNotification = "";
        }
        if (notifications > 99) {
            textNotification = "99+";
        }
        notificationText.setText(textNotification);
    }
}
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.LayoutRes;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import mxh.kickassmenu.R;
import mxh.kickassmenu.menucontent.ImaterialBinder;
import mxh.kickassmenu.menucontent.MaterialSectionChangeListener;
import mxh.kickassmenu.menucontent.MaterialSectionImpleLayout;
import mxh.kickassmenu.menucontent.MaterialSectionOnClickListener;
import mxh.kickassmenu.menucontent.containers.MaterialPlain;
import mxh.kickassmenu.menucontent.containers.MaterialRippleLayout;
import mxh.kickassmenu.menucontent.containers.MaterialRippleLayoutNineOld;
import mxh.kickassmenu.menucontent.sectionPlate.touchItems.MaterialListSection;
import mxh.kickassmenu.menucontent.sectionPlate.touchItems.MaterialSectionBind;
import mxh.kickassmenu.menucontent.sectionPlate.touchItems.MaterialSectionNotificationBind;
package mxh.kickassmenu.menucontent.sectionPlate;




public class MaterialSection<Fragment, SectionModel extends ImaterialBinder> implements View.OnTouchListener, View.OnClickListener, MaterialSectionImpleLayout {
    public static final String TAG = "materialsectionnow";
    public static final int TARGET_FRAGMENT = 0;
    public static final int TARGET_ACTIVITY = 1;
    public static final int TARGET_CLICK = 2;
    public static final int TARGET_LISTVIEW = 3;
    public static final int TARGET_EMBEDED_CHILDFRAGMENT = 4;

    private View view;
    private ImageView icon;
    private MaterialSectionOnClickListener listener;
    private MaterialSectionChangeListener changeListener;

    private boolean isSelected;
    private int targetType;
    private int sectionColor;
    private boolean fillIconColor;

    private boolean sticky;
    private boolean sectiondivided;
    private boolean hasSectionColor;
    private boolean hasColorDark;
    //private int colorPressed;
    private int colorUnpressed;
    private int colorSelected;
    private int colorOnPressHighlight;
    private int iconColor;
    private int colorDark;
    private int textColor;
    private int notificationColor;
    private int layout_item_section = -1;

    private int numberNotifications;

    private String title;
    private String fragmentTitle;
    private final SectionModel mSectionmodel;
    private Fragment targetFragment;
    private Intent targetIntent;

    private boolean hasIcon = false;

    private Context ctx;

    public MaterialSection(final int target, final boolean sticky, final
    MaterialSectionChangeListener changeListener, final SectionModel mSectionmodel) {
        this.targetType = target;
        this.sticky = sticky;
        this.changeListener = changeListener;
        this.mSectionmodel = mSectionmodel;
        isSelected = false;
        hasSectionColor = false;
        hasColorDark = false;
        numberNotifications = 0;
        fillIconColor = true;
    }

    private int getItemLayout(final TypedArray values, final @LayoutRes int defaultResId) {
        int resId = values.getResourceId(R.styleable.MaterialSection_section_item_layout, -1);
        if (resId == -1 || layout_item_section > -1) {
            return defaultResId;
        } else {
            return resId;
        }
    }

    private View getView(final Context c, final TypedArray arr, final @LayoutRes int rDefault) {
        if (mSectionmodel instanceof MaterialListSection) {
            return LayoutInflater.from(c).inflate(rDefault, null);
        } else {
            return LayoutInflater.from(c).inflate(getItemLayout(arr, rDefault), null);
        }
    }

    /**
     * for custom user layout swapping
     *
     * @param layout_custom the resource id from the layout
     */
    public void swapLayout(final @LayoutRes int layout_custom) {
        layout_item_section = layout_custom;
    }

    private void RippleCustomization(final TypedArray values, final View view) {

        if (view.findViewById(R.id.section_ripple) != null) {
            int rippleColor = values.getColor(R.styleable.MaterialSection_sectionRippleColor, 0x16000000);
            if (view.findViewById(R.id.section_ripple) instanceof MaterialRippleLayout) {
                MaterialRippleLayout ilayout = (MaterialRippleLayout) view.findViewById(R.id.section_ripple);
                ilayout.setRippleColor(rippleColor);
                ilayout.setOnClickListener(this);
                ilayout.setOnTouchListener(this);
            } else if (view.findViewById(R.id.section_ripple) instanceof MaterialRippleLayoutNineOld) {