@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
  private void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    mText = new TextView(context);
    mText.setGravity(Gravity.START | Gravity.CENTER_VERTICAL);
    addView(mText, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

    mAction = new Button(context);
    mAction.setBackgroundResource(0);
    mAction.setGravity(Gravity.CENTER);
    mAction.setOnClickListener(
        new OnClickListener() {

          @Override
          public void onClick(View v) {
            if (mActionClickListener != null)
              mActionClickListener.onActionClick(SnackBar.this, mActionId);

            dismiss();
          }
        });
    addView(mAction, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

    mBackground = new BackgroundDrawable();
    ViewUtil.setBackground(this, mBackground);
    setClickable(true);

    applyStyle(context, attrs, defStyleAttr, defStyleRes);
  }
Beispiel #2
0
 public void applyStyle(int resId) {
   ViewUtil.applyStyle(this, resId);
   applyStyle(getContext(), null, 0, resId);
 }
Beispiel #3
0
  private void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    setWillNotDraw(false);

    mRippleManager.onCreate(this, context, attrs, defStyleAttr, defStyleRes);

    TypedArray a =
        context.obtainStyledAttributes(attrs, R.styleable.ContactView, defStyleAttr, defStyleRes);

    mAvatarSize =
        a.getDimensionPixelSize(
            R.styleable.ContactView_cv_avatarSize, ThemeUtil.dpToPx(context, 40));
    mSpacing =
        a.getDimensionPixelOffset(R.styleable.ContactView_cv_spacing, ThemeUtil.dpToPx(context, 8));
    mMinHeight = a.getDimensionPixelOffset(R.styleable.ContactView_android_minHeight, 0);
    int avatarSrc = a.getResourceId(R.styleable.ContactView_cv_avatarSrc, 0);

    mNameView = new TextView(context);
    mNameView.setGravity(GravityCompat.START);
    mNameView.setSingleLine(true);
    mNameView.setEllipsize(TextUtils.TruncateAt.END);
    int nameTextSize = a.getDimensionPixelSize(R.styleable.ContactView_cv_nameTextSize, 0);
    ColorStateList nameTextColor = a.getColorStateList(R.styleable.ContactView_cv_nameTextColor);
    int nameTextAppearance = a.getResourceId(R.styleable.ContactView_cv_nameTextAppearance, 0);
    if (nameTextAppearance > 0) mNameView.setTextAppearance(context, nameTextAppearance);
    if (nameTextSize > 0) mNameView.setTextSize(TypedValue.COMPLEX_UNIT_PX, nameTextSize);
    if (nameTextColor != null) mNameView.setTextColor(nameTextColor);
    setNameText(a.getString(R.styleable.ContactView_cv_name));

    mAddressView = new TextView(context);
    mAddressView.setGravity(GravityCompat.START);
    mAddressView.setSingleLine(true);
    mAddressView.setEllipsize(TextUtils.TruncateAt.END);
    int addressTextSize = a.getDimensionPixelSize(R.styleable.ContactView_cv_addressTextSize, 0);
    ColorStateList addressTextColor =
        a.getColorStateList(R.styleable.ContactView_cv_addressTextColor);
    int addressTextAppearance =
        a.getResourceId(R.styleable.ContactView_cv_addressTextAppearance, 0);
    if (addressTextAppearance > 0) mAddressView.setTextAppearance(context, addressTextAppearance);
    if (addressTextSize > 0) mAddressView.setTextSize(TypedValue.COMPLEX_UNIT_PX, addressTextSize);
    if (addressTextColor != null) mAddressView.setTextColor(addressTextColor);
    setAddressText(a.getString(R.styleable.ContactView_cv_address));

    mButtonSize = a.getDimensionPixelOffset(R.styleable.ContactView_cv_buttonSize, 0);

    if (mButtonSize > 0) {
      mButton = new ImageButton(context);
      int resId = a.getResourceId(R.styleable.ContactView_cv_buttonSrc, 0);
      if (resId != 0) mButton.setImageResource(resId);
      ViewUtil.setBackground(mButton, BlankDrawable.getInstance());
      mButton.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
      mButton.setFocusableInTouchMode(false);
      mButton.setFocusable(false);
      mButton.setClickable(false);
    }

    a.recycle();

    addView(mNameView);
    addView(mAddressView);
    if (mButton != null) addView(mButton);

    mAvatarDrawable = new AvatarDrawable();
    if (avatarSrc != 0) setAvatarResource(avatarSrc);
  }
 /**
  * Set the style of RippleEffect of the ActionButton.
  *
  * @param resId The resourceId of RippleEffect.
  * @return This SnackBar for chaining methods.
  */
 public SnackBar actionRipple(int resId) {
   if (resId != 0)
     ViewUtil.setBackground(mAction, new RippleDrawable.Builder(getContext(), resId).build());
   return this;
 }
Beispiel #5
0
/** Created by Rey on 12/10/2014. */
public class Dialog extends android.app.Dialog {

  private ContainerFrameLayout mContainer;
  private int mLayoutWidth;
  private int mLayoutHeight;

  protected TextView mTitle;
  protected Button mPositiveAction;
  protected Button mNegativeAction;
  protected Button mNeutralAction;
  private View mContent;
  private DialogCardView mCardView;

  protected int mContentPadding;
  protected int mActionHeight;
  protected int mActionOuterHeight;
  protected int mActionOuterPadding;
  protected int mActionMinWidth;
  protected int mActionPadding;
  protected int mDialogHorizontalPadding;
  protected int mDialogVerticalPadding;

  protected int mInAnimationId;
  protected int mOutAnimationId;

  private final Handler mHandler = new Handler();
  private final Runnable mDismissAction =
      new Runnable() {
        public void run() {
          // dirty fix for java.lang.IllegalArgumentException: View not attached to window manager
          try {
            Dialog.super.dismiss();
          } catch (IllegalArgumentException ex) {
          }
        }
      };

  private boolean mLayoutActionVertical = false;

  private boolean mCancelable = true;
  private boolean mCanceledOnTouchOutside = true;

  public static final int ACTION_POSITIVE = ViewUtil.generateViewId();
  public static final int ACTION_NEGATIVE = ViewUtil.generateViewId();
  public static final int ACTION_NEUTRAL = ViewUtil.generateViewId();

  public Dialog(Context context) {
    this(context, R.style.Material_App_Dialog_Light);
  }

  public Dialog(Context context, int style) {
    super(context, style);

    // Override style to ensure not show window's title or background.
    // TODO: find a way to ensure windowIsFloating attribute is false.
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setBackgroundDrawable(BlankDrawable.getInstance());
    getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);

    init(context, style);
  }

  private void init(Context context, int style) {
    mContentPadding = ThemeUtil.dpToPx(context, 24);
    mActionMinWidth = ThemeUtil.dpToPx(context, 64);
    mActionHeight = ThemeUtil.dpToPx(context, 36);
    mActionOuterHeight = ThemeUtil.dpToPx(context, 48);
    mActionPadding = ThemeUtil.dpToPx(context, 8);
    mActionOuterPadding = ThemeUtil.dpToPx(context, 16);
    mDialogHorizontalPadding = ThemeUtil.dpToPx(context, 40);
    mDialogVerticalPadding = ThemeUtil.dpToPx(context, 24);

    mCardView = new DialogCardView(context);
    mContainer = new ContainerFrameLayout(context);
    mTitle = new TextView(context);
    mPositiveAction = new Button(context);
    mNegativeAction = new Button(context);
    mNeutralAction = new Button(context);

    mCardView.setPreventCornerOverlap(false);
    mCardView.setUseCompatPadding(true);

    mTitle.setPadding(
        mContentPadding, mContentPadding, mContentPadding, mContentPadding - mActionPadding);
    mPositiveAction.setId(ACTION_POSITIVE);
    mPositiveAction.setPadding(mActionPadding, 0, mActionPadding, 0);
    mPositiveAction.setBackgroundResource(0);
    mNegativeAction.setId(ACTION_NEGATIVE);
    mNegativeAction.setPadding(mActionPadding, 0, mActionPadding, 0);
    mNegativeAction.setBackgroundResource(0);
    mNeutralAction.setId(ACTION_NEUTRAL);
    mNeutralAction.setPadding(mActionPadding, 0, mActionPadding, 0);
    mNeutralAction.setBackgroundResource(0);

    mContainer.addView(mCardView);
    mCardView.addView(mTitle);
    mCardView.addView(mPositiveAction);
    mCardView.addView(mNegativeAction);
    mCardView.addView(mNeutralAction);

    cancelable(true);
    canceledOnTouchOutside(true);
    clearContent();
    onCreate();
    applyStyle(style);

    super.setContentView(mContainer);
  }

  protected void onCreate() {}

  public Dialog applyStyle(int resId) {
    Context context = getContext();
    TypedArray a = context.obtainStyledAttributes(resId, R.styleable.Dialog);

    int layout_width;
    int layout_height;

    if (ThemeUtil.getType(a, R.styleable.Dialog_android_layout_width) == TypedValue.TYPE_DIMENSION)
      layout_width = a.getDimensionPixelSize(R.styleable.Dialog_android_layout_width, 0);
    else
      layout_width =
          a.getInteger(
              R.styleable.Dialog_android_layout_width, ViewGroup.LayoutParams.WRAP_CONTENT);

    if (ThemeUtil.getType(a, R.styleable.Dialog_android_layout_height) == TypedValue.TYPE_DIMENSION)
      layout_height = a.getDimensionPixelSize(R.styleable.Dialog_android_layout_height, 0);
    else
      layout_height =
          a.getInteger(
              R.styleable.Dialog_android_layout_height, ViewGroup.LayoutParams.WRAP_CONTENT);

    layoutParams(layout_width, layout_height);

    dimAmount(a.getFloat(R.styleable.Dialog_di_dimAmount, 0.5f));
    backgroundColor(
        a.getColor(
            R.styleable.Dialog_di_backgroundColor,
            ThemeUtil.windowBackground(context, 0xFFFFFFFF)));
    maxElevation(a.getDimensionPixelOffset(R.styleable.Dialog_di_maxElevation, 0));
    elevation(
        a.getDimensionPixelOffset(R.styleable.Dialog_di_elevation, ThemeUtil.dpToPx(context, 4)));
    cornerRadius(
        a.getDimensionPixelOffset(
            R.styleable.Dialog_di_cornerRadius, ThemeUtil.dpToPx(context, 2)));

    titleTextAppearance(
        a.getResourceId(
            R.styleable.Dialog_di_titleTextAppearance, R.style.TextAppearance_AppCompat_Title));
    if (ThemeUtil.getType(a, R.styleable.Dialog_di_titleTextColor) != TypedValue.TYPE_NULL)
      titleColor(a.getColor(R.styleable.Dialog_di_titleTextColor, 0));

    if (ThemeUtil.getType(a, R.styleable.Dialog_di_actionBackground) != TypedValue.TYPE_NULL)
      actionBackground(a.getResourceId(R.styleable.Dialog_di_actionBackground, 0));

    if (ThemeUtil.getType(a, R.styleable.Dialog_di_actionRipple) != TypedValue.TYPE_NULL)
      actionRipple(a.getResourceId(R.styleable.Dialog_di_actionRipple, 0));

    actionTextAppearance(
        a.getResourceId(
            R.styleable.Dialog_di_actionTextAppearance, R.style.TextAppearance_AppCompat_Button));

    if (ThemeUtil.getType(a, R.styleable.Dialog_di_actionTextColor) != TypedValue.TYPE_NULL)
      actionTextColor(a.getColorStateList(R.styleable.Dialog_di_actionTextColor));

    if (ThemeUtil.getType(a, R.styleable.Dialog_di_positiveActionBackground)
        != TypedValue.TYPE_NULL)
      positiveActionBackground(a.getResourceId(R.styleable.Dialog_di_positiveActionBackground, 0));

    if (ThemeUtil.getType(a, R.styleable.Dialog_di_positiveActionRipple) != TypedValue.TYPE_NULL)
      positiveActionRipple(a.getResourceId(R.styleable.Dialog_di_positiveActionRipple, 0));

    if (ThemeUtil.getType(a, R.styleable.Dialog_di_positiveActionTextAppearance)
        != TypedValue.TYPE_NULL)
      positiveActionTextAppearance(
          a.getResourceId(R.styleable.Dialog_di_positiveActionTextAppearance, 0));

    if (ThemeUtil.getType(a, R.styleable.Dialog_di_positiveActionTextColor) != TypedValue.TYPE_NULL)
      positiveActionTextColor(a.getColorStateList(R.styleable.Dialog_di_positiveActionTextColor));

    if (ThemeUtil.getType(a, R.styleable.Dialog_di_negativeActionBackground)
        != TypedValue.TYPE_NULL)
      negativeActionBackground(a.getResourceId(R.styleable.Dialog_di_negativeActionBackground, 0));

    if (ThemeUtil.getType(a, R.styleable.Dialog_di_negativeActionRipple) != TypedValue.TYPE_NULL)
      negativeActionRipple(a.getResourceId(R.styleable.Dialog_di_negativeActionRipple, 0));

    if (ThemeUtil.getType(a, R.styleable.Dialog_di_negativeActionTextAppearance)
        != TypedValue.TYPE_NULL)
      negativeActionTextAppearance(
          a.getResourceId(R.styleable.Dialog_di_negativeActionTextAppearance, 0));

    if (ThemeUtil.getType(a, R.styleable.Dialog_di_negativeActionTextColor) != TypedValue.TYPE_NULL)
      negativeActionTextColor(a.getColorStateList(R.styleable.Dialog_di_negativeActionTextColor));

    if (ThemeUtil.getType(a, R.styleable.Dialog_di_neutralActionBackground) != TypedValue.TYPE_NULL)
      neutralActionBackground(a.getResourceId(R.styleable.Dialog_di_neutralActionBackground, 0));

    if (ThemeUtil.getType(a, R.styleable.Dialog_di_neutralActionRipple) != TypedValue.TYPE_NULL)
      neutralActionRipple(a.getResourceId(R.styleable.Dialog_di_neutralActionRipple, 0));

    if (ThemeUtil.getType(a, R.styleable.Dialog_di_neutralActionTextAppearance)
        != TypedValue.TYPE_NULL)
      neutralActionTextAppearance(
          a.getResourceId(R.styleable.Dialog_di_neutralActionTextAppearance, 0));

    if (ThemeUtil.getType(a, R.styleable.Dialog_di_neutralActionTextColor) != TypedValue.TYPE_NULL)
      neutralActionTextColor(a.getColorStateList(R.styleable.Dialog_di_neutralActionTextColor));

    inAnimation(a.getResourceId(R.styleable.Dialog_di_inAnimation, 0));
    outAnimation(a.getResourceId(R.styleable.Dialog_di_outAnimation, 0));
    dividerColor(a.getColor(R.styleable.Dialog_di_dividerColor, 0x1E000000));
    dividerHeight(
        a.getDimensionPixelOffset(
            R.styleable.Dialog_di_dividerHeight, ThemeUtil.dpToPx(context, 1)));
    setCancelable(a.getBoolean(R.styleable.Dialog_di_cancelable, true));
    setCanceledOnTouchOutside(a.getBoolean(R.styleable.Dialog_di_canceledOnTouchOutside, true));

    a.recycle();
    return this;
  }

  public Dialog clearContent() {
    title(0);
    positiveAction(0);
    positiveActionClickListener(null);
    negativeAction(0);
    negativeActionClickListener(null);
    neutralAction(0);
    neutralActionClickListener(null);
    contentView(null);
    return this;
  }

  public Dialog layoutParams(int width, int height) {
    mLayoutWidth = width;
    mLayoutHeight = height;
    return this;
  }

  public Dialog dimAmount(float amount) {
    Window window = getWindow();
    if (amount > 0f) {
      window.addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
      WindowManager.LayoutParams lp = window.getAttributes();
      lp.dimAmount = amount;
      window.setAttributes(lp);
    } else window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
    return this;
  }

  public Dialog backgroundColor(int color) {
    mCardView.setCardBackgroundColor(color);
    return this;
  }

  public Dialog elevation(float radius) {
    if (mCardView.getMaxCardElevation() < radius) mCardView.setMaxCardElevation(radius);

    mCardView.setCardElevation(radius);
    return this;
  }

  public Dialog maxElevation(float radius) {
    mCardView.setMaxCardElevation(radius);
    return this;
  }

  public Dialog cornerRadius(float radius) {
    mCardView.setRadius(radius);
    return this;
  }

  public Dialog dividerColor(int color) {
    mCardView.setDividerColor(color);
    return this;
  }

  public Dialog dividerHeight(int height) {
    mCardView.setDividerHeight(height);
    return this;
  }

  public Dialog title(CharSequence title) {
    mTitle.setText(title);
    mTitle.setVisibility(TextUtils.isEmpty(title) ? View.GONE : View.VISIBLE);
    return this;
  }

  public Dialog title(int id) {
    return title(id == 0 ? null : getContext().getResources().getString(id));
  }

  @Override
  public void setTitle(CharSequence title) {
    title(title);
  }

  @Override
  public void setTitle(int titleId) {
    title(titleId);
  }

  public Dialog titleColor(int color) {
    mTitle.setTextColor(color);
    return this;
  }

  public Dialog titleTextAppearance(int resId) {
    mTitle.setTextAppearance(getContext(), resId);
    return this;
  }

  public Dialog actionBackground(int id) {
    positiveActionBackground(id);
    negativeActionBackground(id);
    neutralActionBackground(id);
    return this;
  }

  public Dialog actionBackground(Drawable drawable) {
    positiveActionBackground(drawable);
    negativeActionBackground(drawable);
    neutralActionBackground(drawable);
    return this;
  }

  public Dialog actionRipple(int resId) {
    positiveActionRipple(resId);
    negativeActionRipple(resId);
    neutralActionRipple(resId);
    return this;
  }

  public Dialog actionTextAppearance(int resId) {
    positiveActionTextAppearance(resId);
    negativeActionTextAppearance(resId);
    neutralActionTextAppearance(resId);
    return this;
  }

  public Dialog actionTextColor(ColorStateList color) {
    positiveActionTextColor(color);
    negativeActionTextColor(color);
    neutralActionTextColor(color);
    return this;
  }

  public Dialog actionTextColor(int color) {
    positiveActionTextColor(color);
    negativeActionTextColor(color);
    neutralActionTextColor(color);
    return this;
  }

  public Dialog positiveAction(CharSequence action) {
    mPositiveAction.setText(action);
    mPositiveAction.setVisibility(TextUtils.isEmpty(action) ? View.GONE : View.VISIBLE);
    return this;
  }

  public Dialog positiveAction(int id) {
    return positiveAction(id == 0 ? null : getContext().getResources().getString(id));
  }

  @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
  @SuppressWarnings("deprecation")
  public Dialog positiveActionBackground(Drawable drawable) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
      mPositiveAction.setBackground(drawable);
    else mPositiveAction.setBackgroundDrawable(drawable);
    return this;
  }

  public Dialog positiveActionBackground(int id) {
    return positiveActionBackground(id == 0 ? null : getContext().getResources().getDrawable(id));
  }

  public Dialog positiveActionRipple(int resId) {
    RippleDrawable drawable = new RippleDrawable.Builder(getContext(), resId).build();
    return positiveActionBackground(drawable);
  }

  public Dialog positiveActionTextAppearance(int resId) {
    mPositiveAction.setTextAppearance(getContext(), resId);
    return this;
  }

  public Dialog positiveActionTextColor(ColorStateList color) {
    mPositiveAction.setTextColor(color);
    return this;
  }

  public Dialog positiveActionTextColor(int color) {
    mPositiveAction.setTextColor(color);
    return this;
  }

  public Dialog positiveActionClickListener(View.OnClickListener listener) {
    mPositiveAction.setOnClickListener(listener);
    return this;
  }

  public Dialog negativeAction(CharSequence action) {
    mNegativeAction.setText(action);
    mNegativeAction.setVisibility(TextUtils.isEmpty(action) ? View.GONE : View.VISIBLE);
    return this;
  }

  public Dialog negativeAction(int id) {
    return negativeAction(id == 0 ? null : getContext().getResources().getString(id));
  }

  @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
  @SuppressWarnings("deprecation")
  public Dialog negativeActionBackground(Drawable drawable) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
      mNegativeAction.setBackground(drawable);
    else mNegativeAction.setBackgroundDrawable(drawable);
    return this;
  }

  public Dialog negativeActionBackground(int id) {
    return negativeActionBackground(id == 0 ? null : getContext().getResources().getDrawable(id));
  }

  public Dialog negativeActionRipple(int resId) {
    RippleDrawable drawable = new RippleDrawable.Builder(getContext(), resId).build();
    return negativeActionBackground(drawable);
  }

  public Dialog negativeActionTextAppearance(int resId) {
    mNegativeAction.setTextAppearance(getContext(), resId);
    return this;
  }

  public Dialog negativeActionTextColor(ColorStateList color) {
    mNegativeAction.setTextColor(color);
    return this;
  }

  public Dialog negativeActionTextColor(int color) {
    mNegativeAction.setTextColor(color);
    return this;
  }

  public Dialog negativeActionClickListener(View.OnClickListener listener) {
    mNegativeAction.setOnClickListener(listener);
    return this;
  }

  public Dialog neutralAction(CharSequence action) {
    mNeutralAction.setText(action);
    mNeutralAction.setVisibility(TextUtils.isEmpty(action) ? View.GONE : View.VISIBLE);
    return this;
  }

  public Dialog neutralAction(int id) {
    return neutralAction(id == 0 ? null : getContext().getResources().getString(id));
  }

  @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
  @SuppressWarnings("deprecation")
  public Dialog neutralActionBackground(Drawable drawable) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
      mNeutralAction.setBackground(drawable);
    else mNeutralAction.setBackgroundDrawable(drawable);
    return this;
  }

  public Dialog neutralActionBackground(int id) {
    return neutralActionBackground(id == 0 ? null : getContext().getResources().getDrawable(id));
  }

  public Dialog neutralActionRipple(int resId) {
    RippleDrawable drawable = new RippleDrawable.Builder(getContext(), resId).build();
    return neutralActionBackground(drawable);
  }

  public Dialog neutralActionTextAppearance(int resId) {
    mNeutralAction.setTextAppearance(getContext(), resId);
    return this;
  }

  public Dialog neutralActionTextColor(ColorStateList color) {
    mNeutralAction.setTextColor(color);
    return this;
  }

  public Dialog neutralActionTextColor(int color) {
    mNeutralAction.setTextColor(color);
    return this;
  }

  public Dialog neutralActionClickListener(View.OnClickListener listener) {
    mNeutralAction.setOnClickListener(listener);
    return this;
  }

  public Dialog inAnimation(int resId) {
    mInAnimationId = resId;
    return this;
  }

  public Dialog outAnimation(int resId) {
    mOutAnimationId = resId;
    return this;
  }

  public Dialog showDivider(boolean show) {
    mCardView.setShowDivider(show);
    return this;
  }

  public Dialog contentView(View v) {
    if (mContent != v) {
      if (mContent != null) mCardView.removeView(mContent);

      mContent = v;
    }

    if (mContent != null) mCardView.addView(mContent);

    return this;
  }

  public Dialog contentView(int layoutId) {
    if (layoutId == 0) return this;

    View v = LayoutInflater.from(getContext()).inflate(layoutId, null);
    return contentView(v);
  }

  public Dialog cancelable(boolean cancelable) {
    super.setCancelable(cancelable);
    mCancelable = cancelable;
    return this;
  }

  public Dialog canceledOnTouchOutside(boolean cancel) {
    super.setCanceledOnTouchOutside(cancel);
    mCanceledOnTouchOutside = cancel;
    return this;
  }

  public Dialog contentMargin(int margin) {
    mCardView.setContentMargin(margin);
    return this;
  }

  public Dialog contentMargin(int left, int top, int right, int bottom) {
    mCardView.setContentMargin(left, top, right, bottom);
    return this;
  }

  @Override
  public void setCancelable(boolean flag) {
    cancelable(flag);
  }

  @Override
  public void setCanceledOnTouchOutside(boolean cancel) {
    canceledOnTouchOutside(cancel);
  }

  @Override
  public void setContentView(View v) {
    contentView(v);
  }

  @Override
  public void setContentView(int layoutId) {
    contentView(layoutId);
  }

  @Override
  public void setContentView(View v, ViewGroup.LayoutParams params) {
    contentView(v);
  }

  @Override
  public void addContentView(View view, ViewGroup.LayoutParams params) {
    contentView(view);
  }

  @Override
  public void show() {
    if (mInAnimationId != 0)
      mCardView
          .getViewTreeObserver()
          .addOnPreDrawListener(
              new ViewTreeObserver.OnPreDrawListener() {
                @Override
                public boolean onPreDraw() {
                  mCardView.getViewTreeObserver().removeOnPreDrawListener(this);
                  Animation anim =
                      AnimationUtils.loadAnimation(mCardView.getContext(), mInAnimationId);
                  mCardView.startAnimation(anim);
                  return false;
                }
              });
    super.show();
  }

  @Override
  public void dismiss() {
    if (mOutAnimationId != 0) {
      Animation anim = AnimationUtils.loadAnimation(mContainer.getContext(), mOutAnimationId);
      anim.setAnimationListener(
          new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {}

            @Override
            public void onAnimationRepeat(Animation animation) {}

            @Override
            public void onAnimationEnd(Animation animation) {
              mHandler.post(mDismissAction);
            }
          });
      mCardView.startAnimation(anim);
    } else mHandler.post(mDismissAction);
  }

  private class ContainerFrameLayout extends FrameLayout {

    private boolean mClickOutside = false;

    public ContainerFrameLayout(Context context) {
      super(context);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
      int widthSize = MeasureSpec.getSize(widthMeasureSpec);
      int heightSize = MeasureSpec.getSize(heightMeasureSpec);

      mCardView.measure(widthMeasureSpec, heightMeasureSpec);
      setMeasuredDimension(widthSize, heightSize);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
      int childLeft = (right - left - mCardView.getMeasuredWidth()) / 2;
      int childTop = (bottom - top - mCardView.getMeasuredHeight()) / 2;
      int childRight = childLeft + mCardView.getMeasuredWidth();
      int childBottom = childTop + mCardView.getMeasuredHeight();

      mCardView.layout(childLeft, childTop, childRight, childBottom);
    }

    private boolean isOutsideDialog(float x, float y) {
      return x < mCardView.getLeft() + mCardView.getPaddingLeft()
          || x > mCardView.getRight() - mCardView.getPaddingRight()
          || y < mCardView.getTop() + mCardView.getPaddingTop()
          || y > mCardView.getBottom() - mCardView.getPaddingBottom();
    }

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

      if (handled) return true;

      switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
          if (isOutsideDialog(event.getX(), event.getY())) {
            mClickOutside = true;
            return true;
          }
          return false;
        case MotionEvent.ACTION_MOVE:
          return mClickOutside;
        case MotionEvent.ACTION_CANCEL:
          mClickOutside = false;
          return false;
        case MotionEvent.ACTION_UP:
          if (mClickOutside && isOutsideDialog(event.getX(), event.getY())) {
            mClickOutside = false;
            if (mCancelable && mCanceledOnTouchOutside) dismiss();
            return true;
          }
          return false;
      }

      return false;
    }
  }

  private class DialogCardView extends CardView {

    private Paint mDividerPaint;
    private float mDividerPos = -1f;
    private boolean mShowDivider = false;

    private int mContentMarginLeft;
    private int mContentMarginTop;
    private int mContentMarginRight;
    private int mContentMarginBottom;

    public DialogCardView(Context context) {
      super(context);

      mDividerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
      mDividerPaint.setStyle(Paint.Style.STROKE);
      setWillNotDraw(false);
    }

    public void setContentMargin(int margin) {
      setContentMargin(margin, margin, margin, margin);
    }

    public void setContentMargin(int left, int top, int right, int bottom) {
      mContentMarginLeft = left;
      mContentMarginTop = top;
      mContentMarginRight = right;
      mContentMarginBottom = bottom;
    }

    public void setDividerColor(int color) {
      mDividerPaint.setColor(color);
      invalidate();
    }

    public void setDividerHeight(int height) {
      mDividerPaint.setStrokeWidth(height);
      invalidate();
    }

    public void setShowDivider(boolean show) {
      if (mShowDivider != show) {
        mShowDivider = show;
        invalidate();
      }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
      int widthSize = MeasureSpec.getSize(widthMeasureSpec);
      int heightSize = MeasureSpec.getSize(heightMeasureSpec);

      int paddingLeft = Math.max(mDialogHorizontalPadding, mCardView.getPaddingLeft());
      int paddingRight = Math.max(mDialogHorizontalPadding, mCardView.getPaddingRight());
      int paddingTop = Math.max(mDialogVerticalPadding, mCardView.getPaddingTop());
      int paddingBottom = Math.max(mDialogVerticalPadding, mCardView.getPaddingBottom());

      int maxWidth = widthSize - paddingLeft - paddingRight;
      int maxHeight = heightSize - paddingTop - paddingBottom;

      int width = mLayoutWidth == ViewGroup.LayoutParams.MATCH_PARENT ? maxWidth : mLayoutWidth;
      int height = mLayoutHeight == ViewGroup.LayoutParams.MATCH_PARENT ? maxHeight : mLayoutHeight;

      int widthMs;
      int heightMs;

      int titleWidth = 0;
      int titleHeight = 0;

      if (mTitle.getVisibility() == View.VISIBLE) {
        widthMs =
            MeasureSpec.makeMeasureSpec(
                width == ViewGroup.LayoutParams.WRAP_CONTENT ? maxWidth : width,
                MeasureSpec.AT_MOST);
        heightMs = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST);
        mTitle.measure(widthMs, heightMs);
        titleWidth = mTitle.getMeasuredWidth();
        titleHeight = mTitle.getMeasuredHeight();
      }

      int contentWidth = 0;
      int contentHeight = 0;

      if (mContent != null) {
        widthMs =
            MeasureSpec.makeMeasureSpec(
                (width == ViewGroup.LayoutParams.WRAP_CONTENT ? maxWidth : width)
                    - mContentMarginLeft
                    - mContentMarginRight,
                MeasureSpec.AT_MOST);
        heightMs =
            MeasureSpec.makeMeasureSpec(
                maxHeight - mContentMarginTop - mContentMarginBottom, MeasureSpec.AT_MOST);
        mContent.measure(widthMs, heightMs);
        contentWidth = mContent.getMeasuredWidth();
        contentHeight = mContent.getMeasuredHeight();
      }

      int visibleActions = 0;
      int positiveActionWidth = 0;

      if (mPositiveAction.getVisibility() == View.VISIBLE) {
        widthMs = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
        heightMs = MeasureSpec.makeMeasureSpec(mActionHeight, MeasureSpec.EXACTLY);
        mPositiveAction.measure(widthMs, heightMs);

        positiveActionWidth = mPositiveAction.getMeasuredWidth();

        if (positiveActionWidth < mActionMinWidth) {
          mPositiveAction.measure(
              MeasureSpec.makeMeasureSpec(mActionMinWidth, MeasureSpec.EXACTLY), heightMs);
          positiveActionWidth = mActionMinWidth;
        }

        visibleActions++;
      }

      int negativeActionWidth = 0;

      if (mNegativeAction.getVisibility() == View.VISIBLE) {
        widthMs = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
        heightMs = MeasureSpec.makeMeasureSpec(mActionHeight, MeasureSpec.EXACTLY);
        mNegativeAction.measure(widthMs, heightMs);

        negativeActionWidth = mNegativeAction.getMeasuredWidth();

        if (negativeActionWidth < mActionMinWidth) {
          mNegativeAction.measure(
              MeasureSpec.makeMeasureSpec(mActionMinWidth, MeasureSpec.EXACTLY), heightMs);
          negativeActionWidth = mActionMinWidth;
        }

        visibleActions++;
      }

      int neutralActionWidth = 0;

      if (mNeutralAction.getVisibility() == View.VISIBLE) {
        widthMs = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
        heightMs = MeasureSpec.makeMeasureSpec(mActionHeight, MeasureSpec.EXACTLY);
        mNeutralAction.measure(widthMs, heightMs);

        neutralActionWidth = mNeutralAction.getMeasuredWidth();

        if (neutralActionWidth < mActionMinWidth) {
          mNeutralAction.measure(
              MeasureSpec.makeMeasureSpec(mActionMinWidth, MeasureSpec.EXACTLY), heightMs);
          neutralActionWidth = mActionMinWidth;
        }

        visibleActions++;
      }

      int actionBarWidth =
          positiveActionWidth
              + negativeActionWidth
              + neutralActionWidth
              + mActionOuterPadding * 2
              + mActionPadding * Math.max(0, visibleActions - 1);

      if (width == ViewGroup.LayoutParams.WRAP_CONTENT)
        width =
            Math.min(
                maxWidth,
                Math.max(
                    titleWidth,
                    Math.max(
                        contentWidth + mContentMarginLeft + mContentMarginRight, actionBarWidth)));

      mLayoutActionVertical = actionBarWidth > width;

      int nonContentHeight =
          titleHeight + mActionPadding + mContentMarginTop + mContentMarginBottom;
      if (mLayoutActionVertical) nonContentHeight += mActionOuterHeight * visibleActions;
      else nonContentHeight += (visibleActions > 0) ? mActionOuterHeight : 0;

      if (height == ViewGroup.LayoutParams.WRAP_CONTENT)
        height = Math.min(maxHeight, contentHeight + nonContentHeight);

      if (mContent != null)
        mContent.measure(
            MeasureSpec.makeMeasureSpec(
                width - mContentMarginLeft - mContentMarginRight, MeasureSpec.EXACTLY),
            MeasureSpec.makeMeasureSpec(height - nonContentHeight, MeasureSpec.EXACTLY));

      setMeasuredDimension(
          width + getPaddingLeft() + getPaddingRight(),
          height + getPaddingTop() + getPaddingBottom());
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
      int childLeft = 0;
      int childTop = 0;
      int childRight = right - left;
      int childBottom = bottom - top;

      childLeft += getPaddingLeft();
      childTop += getPaddingTop();
      childRight -= getPaddingRight();
      childBottom -= getPaddingBottom();

      if (mTitle.getVisibility() == View.VISIBLE) {
        mTitle.layout(childLeft, childTop, childRight, childTop + mTitle.getMeasuredHeight());
        childTop += mTitle.getMeasuredHeight();
      }

      childBottom -= mActionPadding;

      int temp = (mActionOuterHeight - mActionHeight) / 2;

      if (mLayoutActionVertical) {
        if (mNeutralAction.getVisibility() == View.VISIBLE) {
          mNeutralAction.layout(
              childRight - mActionOuterPadding - mNeutralAction.getMeasuredWidth(),
              childBottom - mActionOuterHeight + temp,
              childRight - mActionOuterPadding,
              childBottom - temp);
          childBottom -= mActionOuterHeight;
        }

        if (mNegativeAction.getVisibility() == View.VISIBLE) {
          mNegativeAction.layout(
              childRight - mActionOuterPadding - mNegativeAction.getMeasuredWidth(),
              childBottom - mActionOuterHeight + temp,
              childRight - mActionOuterPadding,
              childBottom - temp);
          childBottom -= mActionOuterHeight;
        }

        if (mPositiveAction.getVisibility() == View.VISIBLE) {
          mPositiveAction.layout(
              childRight - mActionOuterPadding - mPositiveAction.getMeasuredWidth(),
              childBottom - mActionOuterHeight + temp,
              childRight - mActionOuterPadding,
              childBottom - temp);
          childBottom -= mActionOuterHeight;
        }
      } else {
        int actionRight = childRight - mActionOuterPadding;
        int actionTop = childBottom - mActionOuterHeight + temp;
        int actionBottom = childBottom - temp;
        boolean hasAction = false;

        if (mPositiveAction.getVisibility() == View.VISIBLE) {
          mPositiveAction.layout(
              actionRight - mPositiveAction.getMeasuredWidth(),
              actionTop,
              actionRight,
              actionBottom);
          actionRight -= mPositiveAction.getMeasuredWidth() + mActionPadding;
          hasAction = true;
        }

        if (mNegativeAction.getVisibility() == View.VISIBLE) {
          mNegativeAction.layout(
              actionRight - mNegativeAction.getMeasuredWidth(),
              actionTop,
              actionRight,
              actionBottom);
          hasAction = true;
        }

        if (mNeutralAction.getVisibility() == View.VISIBLE) {
          mNeutralAction.layout(
              childLeft + mActionOuterPadding,
              actionTop,
              childLeft + mActionOuterPadding + mNeutralAction.getMeasuredWidth(),
              actionBottom);
          hasAction = true;
        }

        if (hasAction) childBottom -= mActionOuterHeight;
      }

      mDividerPos = childBottom - mDividerPaint.getStrokeWidth() / 2f;

      if (mContent != null)
        mContent.layout(
            childLeft + mContentMarginLeft,
            childTop + mContentMarginTop,
            childRight - mContentMarginRight,
            childBottom - mContentMarginBottom);
    }

    @Override
    public void draw(Canvas canvas) {
      super.draw(canvas);

      if (mShowDivider
          && (mPositiveAction.getVisibility() == View.VISIBLE
              || mNegativeAction.getVisibility() == View.VISIBLE
              || mNeutralAction.getVisibility() == View.VISIBLE))
        canvas.drawLine(
            getPaddingLeft(),
            mDividerPos,
            getWidth() - getPaddingRight(),
            mDividerPos,
            mDividerPaint);
    }
  }

  public static class Builder implements DialogFragment.Builder, Parcelable {

    protected int mStyleId;
    protected int mContentViewId;
    protected CharSequence mTitle;
    protected CharSequence mPositive;
    protected CharSequence mNegative;
    protected CharSequence mNeutral;

    protected Dialog mDialog;

    public Builder() {
      this(R.style.Material_App_Dialog_Light);
    }

    public Builder(int styleId) {
      mStyleId = styleId;
    }

    public Builder style(int styleId) {
      mStyleId = styleId;
      return this;
    }

    public Builder contentView(int layoutId) {
      mContentViewId = layoutId;
      return this;
    }

    public Builder title(CharSequence title) {
      mTitle = title;
      return this;
    }

    public Builder positiveAction(CharSequence action) {
      mPositive = action;
      return this;
    }

    public Builder negativeAction(CharSequence action) {
      mNegative = action;
      return this;
    }

    public Builder neutralAction(CharSequence action) {
      mNeutral = action;
      return this;
    }

    @Override
    public void onPositiveActionClicked(DialogFragment fragment) {
      fragment.dismiss();
    }

    @Override
    public void onNegativeActionClicked(DialogFragment fragment) {
      fragment.dismiss();
    }

    @Override
    public void onNeutralActionClicked(DialogFragment fragment) {
      fragment.dismiss();
    }

    @Override
    public Dialog build(Context context) {
      mDialog = onBuild(context, mStyleId);

      mDialog
          .title(mTitle)
          .positiveAction(mPositive)
          .negativeAction(mNegative)
          .neutralAction(mNeutral);

      if (mContentViewId != 0) mDialog.contentView(mContentViewId);

      return mDialog;
    }

    protected Dialog onBuild(Context context, int styleId) {
      return new Dialog(context, styleId);
    }

    protected Builder(Parcel in) {
      mStyleId = in.readInt();
      mContentViewId = in.readInt();
      mTitle = (CharSequence) in.readParcelable(null);
      mPositive = (CharSequence) in.readParcelable(null);
      mNegative = (CharSequence) in.readParcelable(null);
      mNeutral = (CharSequence) in.readParcelable(null);

      onReadFromParcel(in);
    }

    protected void onReadFromParcel(Parcel in) {}

    protected void onWriteToParcel(Parcel dest, int flags) {}

    @Override
    public void writeToParcel(Parcel dest, int flags) {
      dest.writeInt(mStyleId);
      dest.writeInt(mContentViewId);
      dest.writeValue(mTitle);
      dest.writeValue(mPositive);
      dest.writeValue(mNegative);
      dest.writeValue(mNeutral);
      onWriteToParcel(dest, flags);
    }

    @Override
    public int describeContents() {
      return 0;
    }

    public static final Parcelable.Creator<Builder> CREATOR =
        new Parcelable.Creator<Builder>() {
          public Builder createFromParcel(Parcel in) {
            return new Builder(in);
          }

          public Builder[] newArray(int size) {
            return new Builder[size];
          }
        };
  }
}
  @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
  @Override
  protected void onCreate() {
    View v = LayoutInflater.from(getContext()).inflate(R.layout.dialog_recurring, null);
    setContentView(v);

    FrameLayout fl_mode = (FrameLayout) v.findViewById(R.id.rd_fl_mode);
    final ScrollView sv_repeat = (ScrollView) v.findViewById(R.id.rd_sv_repeat);
    final LinearLayout ll_repeat = (LinearLayout) v.findViewById(R.id.rd_ll_repeat);
    mModeSpinner = (Spinner) fl_mode.findViewById(R.id.rd_spn_mode);
    mEndSpinner = (Spinner) v.findViewById(R.id.rd_spn_end);
    mPeriodEditText = (EditText) v.findViewById(R.id.rd_et_period);
    mPeriodUnitTextView = (TextView) v.findViewById(R.id.rd_tv_period_unit);
    mSameDayRadioButton = (RadioButton) v.findViewById(R.id.rd_month_rb_same);
    mSameWeekdayRadioButton = (RadioButton) v.findViewById(R.id.rd_month_rb_week);
    mEndNumEditText = (EditText) v.findViewById(R.id.rd_et_end_num);
    mEndNumUnitTextView = (TextView) v.findViewById(R.id.rd_tv_end_num_unit);
    mEndDateButton = (Button) v.findViewById(R.id.rd_bt_end_date);
    mWeekView = (WeekView) v.findViewById(R.id.rd_wv_week);

    sv_repeat
        .getViewTreeObserver()
        .addOnGlobalLayoutListener(
            new ViewTreeObserver.OnGlobalLayoutListener() {
              @Override
              public void onGlobalLayout() {
                showDivider(ll_repeat.getMeasuredHeight() > sv_repeat.getMeasuredHeight());
              }
            });

    mHeaderBackground = new HeaderDrawable(getContext());

    ViewCompat.setPaddingRelative(fl_mode, mContentPadding, 0, mContentPadding, 0);
    ViewUtil.setBackground(fl_mode, mHeaderBackground);
    ViewCompat.setPaddingRelative(
        ll_repeat, mContentPadding, mActionOuterPadding, mContentPadding, mActionPadding);

    mModeAdapter = new ModeAdapter();
    mModeSpinner.setAdapter(mModeAdapter);
    mModeSpinner.setOnItemSelectedListener(
        new Spinner.OnItemSelectedListener() {
          @Override
          public void onItemSelected(Spinner parent, View view, int position, long id) {
            onModeSelected(position);
          }
        });

    mEndAdapter = new EndAdapter();
    mEndSpinner.setAdapter(mEndAdapter);
    mEndSpinner.setOnItemSelectedListener(
        new Spinner.OnItemSelectedListener() {
          @Override
          public void onItemSelected(Spinner parent, View view, int position, long id) {
            onEndSelected(position);
          }
        });

    mPeriodEditText.addTextChangedListener(
        new TextWatcher() {
          @Override
          public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

          @Override
          public void onTextChanged(CharSequence s, int start, int before, int count) {}

          @Override
          public void afterTextChanged(Editable s) {
            onPeriodChanged();
          }
        });

    mPeriodEditText.setOnKeyListener(
        new View.OnKeyListener() {
          @Override
          public boolean onKey(View v, int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_UP) {
              String text = mPeriodEditText.getText().toString();
              if (TextUtils.isEmpty(text))
                mPeriodEditText.setText(String.valueOf(mRecurring.getPeriod()));
            }
            return false;
          }
        });

    CompoundButton.OnCheckedChangeListener mCheckChangeListener =
        new android.widget.CompoundButton.OnCheckedChangeListener() {
          @Override
          public void onCheckedChanged(
              android.widget.CompoundButton buttonView, boolean isChecked) {
            if (isChecked) {
              if (buttonView == mSameDayRadioButton) mSameWeekdayRadioButton.setChecked(false);
              else mSameDayRadioButton.setChecked(false);
              onMonthSettingChanged();
            }
          }
        };

    mSameDayRadioButton.setOnCheckedChangeListener(mCheckChangeListener);
    mSameWeekdayRadioButton.setOnCheckedChangeListener(mCheckChangeListener);

    mEndNumEditText.addTextChangedListener(
        new TextWatcher() {
          @Override
          public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

          @Override
          public void onTextChanged(CharSequence s, int start, int before, int count) {}

          @Override
          public void afterTextChanged(Editable s) {
            onEventNumberChanged();
          }
        });

    mEndNumEditText.setOnKeyListener(
        new View.OnKeyListener() {
          @Override
          public boolean onKey(View v, int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_UP) {
              String text = mEndNumEditText.getText().toString();
              if (TextUtils.isEmpty(text))
                mEndNumEditText.setText(String.valueOf(mRecurring.getEventNumber()));
            }
            return false;
          }
        });

    View.OnClickListener mDateClickListener =
        new View.OnClickListener() {
          @Override
          public void onClick(View v) {
            final DatePickerDialog dialog =
                new DatePickerDialog(getContext(), mDatePickerDialogStyleId);
            long minTime = System.currentTimeMillis();
            Calendar cal = dialog.getCalendar();
            cal.setTimeInMillis(minTime);
            cal.add(Calendar.YEAR, 100);
            long maxTime = cal.getTimeInMillis();

            dialog
                .dateRange(minTime, maxTime)
                .date((long) mEndDateButton.getTag())
                .positiveAction(mPositiveAction.getText())
                .positiveActionClickListener(
                    new View.OnClickListener() {
                      @Override
                      public void onClick(View v) {
                        onEndDateChanged(dialog.getDate());
                        dialog.dismiss();
                      }
                    })
                .negativeAction(mNegativeAction.getText())
                .negativeActionClickListener(
                    new View.OnClickListener() {
                      @Override
                      public void onClick(View v) {
                        dialog.dismiss();
                      }
                    })
                .show();
          }
        };

    mEndDateButton.setOnClickListener(mDateClickListener);

    mWeekView.setOnDaySelectionChangedListener(this);
  }