Android Open Source - Material Snack Bar






From Project

Back to project page Material.

License

The source code is released under:

Apache License

If you think the Android project Material listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.rey.material.view;
//from   w  w w  . ja  v  a 2 s.c o m
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.TextUtils.TruncateAt;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;

import com.rey.material.R;
import com.rey.material.drawable.RippleDrawable;
import com.rey.material.util.ThemeUtil;

public class SnackBar extends FrameLayout {

  private TextView mText;
  private Button mAction;
  
  public static final int MATCH_PARENT = ViewGroup.LayoutParams.MATCH_PARENT;
  public static final int WRAP_CONTENT = ViewGroup.LayoutParams.WRAP_CONTENT;
  
  private BackgroundDrawable mBackground;
  private int mMarginLeft;
  private int mMarginBottom;
  private int mWidth;
  private int mHeight;
  private int mInAnimationId;
  private int mOutAnimationId;
  private long mDuration = -1;
  private int mActionId;
  
  private Runnable mDismissRunnable = new Runnable() {
        @Override
        public void run() {
            dismiss();
        }
    };
  
  private int mState = STATE_DISMISSED;
    
  public static final int STATE_DISMISSED = 0;
  public static final int STATE_SHOWED = 1;
  public static final int STATE_SHOWING = 2;
  public static final int STATE_DISMISSING = 3;
  
  public interface OnActionClickListener{
    
    public void onActionClick(SnackBar sb, int actionId);
  }
  
  private OnActionClickListener mActionClickListener;
  
  public interface OnStateChangeListener{
    
    public void onStateChange(SnackBar sb, int oldState, int newState);
  }
  
  private OnStateChangeListener mStateChangeListener;
    
  public static SnackBar make(Context context){
    return new SnackBar(context);
  }
  
  @SuppressWarnings("deprecation")
  @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
  private SnackBar(Context context){
    super(context);
    
    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();
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
      setBackground(mBackground);
    else
      setBackgroundDrawable(mBackground);
    
    setClickable(true);
  }
    
  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    int width = 0;
    int height = 0;
    
    if(mAction.getVisibility() == View.VISIBLE){
      mAction.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), heightMeasureSpec);
      mText.measure(MeasureSpec.makeMeasureSpec(widthSize - (mAction.getMeasuredWidth() - mText.getPaddingRight()), widthMode), heightMeasureSpec);
      width = mText.getMeasuredWidth() + mAction.getMeasuredWidth() - mText.getPaddingRight();
    }
    else{
      mText.measure(MeasureSpec.makeMeasureSpec(widthSize, widthMode), heightMeasureSpec);
      width = mText.getMeasuredWidth();
    }
        
    height = Math.max(mText.getMeasuredHeight(), mAction.getMeasuredHeight());
    
    switch (widthMode) {
      case MeasureSpec.AT_MOST:
        width = Math.min(widthSize, width);
        break;
      case MeasureSpec.EXACTLY:
        width = widthSize;
        break;
    }
    
    switch (heightMode) {
      case MeasureSpec.AT_MOST:
        height = Math.min(heightSize, height);
        break;
      case MeasureSpec.EXACTLY:
        height = heightSize;
        break;
    }
        
    setMeasuredDimension(width, height);
  }
  
  @Override
  protected void onLayout(boolean changed, int l, int t, int r, int b) {
    int childLeft = getPaddingLeft();
    int childRight = r - l - getPaddingRight();
    int childTop = getPaddingTop();
    int childBottom = b - t - getPaddingBottom();
        
    if(mAction.getVisibility() == View.VISIBLE){
      mAction.layout(childRight - mAction.getMeasuredWidth(), childTop, childRight, childBottom);
      mText.layout(childLeft, childTop, childRight - mAction.getMeasuredWidth() + mText.getPaddingRight(), childBottom);
    }
    else      
      mText.layout(childLeft, childTop, childRight, childBottom);
  }    
  
  @SuppressWarnings("deprecation")
  @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
  public SnackBar applyStyle(int resId){
    Context context = getContext();
    TypedArray a = context.obtainStyledAttributes(null, R.styleable.SnackBar, 0, resId);
    
    int backgroundColor = a.getColor(R.styleable.SnackBar_sb_backgroundColor, 0xFF323232);
    int backgroundRadius = a.getDimensionPixelSize(R.styleable.SnackBar_sb_backgroundCornerRadius, 0);      
    int horizontalPadding = a.getDimensionPixelSize(R.styleable.SnackBar_sb_horizontalPadding, ThemeUtil.dpToPx(context, 24));
    int verticalPadding = a.getDimensionPixelSize(R.styleable.SnackBar_sb_verticalPadding, 0);
    TypedValue value = a.peekValue(R.styleable.SnackBar_sb_width);
    if(value.type == TypedValue.TYPE_INT_DEC)
      mWidth = a.getInteger(R.styleable.SnackBar_sb_width, MATCH_PARENT);
    else
      mWidth = a.getDimensionPixelSize(R.styleable.SnackBar_sb_width, MATCH_PARENT);    
    int minWidth = a.getDimensionPixelSize(R.styleable.SnackBar_sb_minWidth, 0);
    int maxWidth = a.getDimensionPixelSize(R.styleable.SnackBar_sb_maxWidth, 0);
    value = a.peekValue(R.styleable.SnackBar_sb_height);
    if(value.type == TypedValue.TYPE_INT_DEC)
      mHeight = a.getInteger(R.styleable.SnackBar_sb_height, WRAP_CONTENT);
    else
      mHeight = a.getDimensionPixelSize(R.styleable.SnackBar_sb_height, WRAP_CONTENT);  
    mMarginLeft = a.getDimensionPixelSize(R.styleable.SnackBar_sb_marginLeft, 0);
    mMarginBottom = a.getDimensionPixelSize(R.styleable.SnackBar_sb_marginBottom, 0);
    int textSize = a.getDimensionPixelSize(R.styleable.SnackBar_sb_textSize, 0);
    boolean hasTextColor = a.hasValue(R.styleable.SnackBar_sb_textColor);    
    int textColor = hasTextColor ? a.getColor(R.styleable.SnackBar_sb_textColor, 0xFFFFFFFF) : 0;
    int textAppearance = a.getResourceId(R.styleable.SnackBar_sb_textAppearance, 0);
    boolean singleLine = a.getBoolean(R.styleable.SnackBar_sb_singleLine, true);
    int maxLines = a.getInteger(R.styleable.SnackBar_sb_maxLines, 0);
    int lines = a.getInteger(R.styleable.SnackBar_sb_lines, 0);
    int ellipsize = a.getInteger(R.styleable.SnackBar_sb_ellipsize, 0);
    int actionTextSize = a.getDimensionPixelSize(R.styleable.SnackBar_sb_actionTextSize, 0);
    ColorStateList actionTextColor;
    value = a.peekValue(R.styleable.SnackBar_sb_actionTextColor);
    if(value.type >= TypedValue.TYPE_FIRST_COLOR_INT && value.type <= TypedValue.TYPE_LAST_COLOR_INT)
      actionTextColor = ColorStateList.valueOf(a.getColor(R.styleable.SnackBar_sb_actionTextColor, 0xFF000000));
    else
      actionTextColor = a.getColorStateList(R.styleable.SnackBar_sb_actionTextColor);
    int actionTextAppearance = a.getResourceId(R.styleable.SnackBar_sb_actionTextAppearance, 0);
    int actionRipple = a.getResourceId(R.styleable.SnackBar_sb_actionRipple, 0);
    mInAnimationId = a.getResourceId(R.styleable.SnackBar_sb_inAnimation, 0);
    mOutAnimationId = a.getResourceId(R.styleable.SnackBar_sb_outAnimation, 0);
    
    a.recycle();
        
    backgroundColor(backgroundColor)
        .backgroundRadius(backgroundRadius);
    
    padding(horizontalPadding, verticalPadding);
    
    textAppearance(textAppearance);
    if(textSize > 0)
      textSize(textSize);
    if(hasTextColor)
      textColor(textColor);  
    singleLine(singleLine);
    if(maxLines > 0)
      maxLines(maxLines);
    if(lines > 0)
      lines(lines);
    if(minWidth > 0)
      minWidth(minWidth);
    if(maxWidth > 0)
      maxWidth(maxWidth);
    switch (ellipsize) {
      case 1:
        ellipsize(TruncateAt.START);
        break;
      case 2:
        ellipsize(TruncateAt.MIDDLE);
        break;
      case 3:
        ellipsize(TruncateAt.END);
        break;
      case 4:
        ellipsize(TruncateAt.MARQUEE);
        break;
      default:
        ellipsize(TruncateAt.END);
        break;          
    }
    
    if(textAppearance != 0)
      actionTextAppearance(actionTextAppearance);
    actionTextSize(actionTextSize);
    actionTextColor(actionTextColor != null ? actionTextColor : ColorStateList.valueOf(ThemeUtil.colorAccent(context, 0xFF000000)));    
    actionRipple(actionRipple);      
    return this;
  }
  
  public SnackBar text(CharSequence text){
    mText.setText(text);
    return this;
  }
  
  public SnackBar text(int id){
    return text(getContext().getResources().getString(id));
  }
  
  public SnackBar textColor(int color){
    mText.setTextColor(color);
    return this;
  }
  
  public SnackBar textSize(int size){
    mText.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);
    return this;
  }
  
  public SnackBar textAppearance(int resId){
    if(resId != 0)
      mText.setTextAppearance(getContext(), resId);
    return this;
  }
  
  public SnackBar ellipsize(TruncateAt at){
    mText.setEllipsize(at);
    return this;
  }
  
  public SnackBar singleLine(boolean b){
    mText.setSingleLine(b);
    return this;
  }
  
  public SnackBar maxLines(int lines){
    mText.setMaxLines(lines);
    return this;
  }
  
  public SnackBar lines(int lines){
    mText.setLines(lines);
    return this;
  }
  
  public SnackBar actionId(int id){
    mActionId = id;    
    return this;
  }
  
  public SnackBar actionText(CharSequence text){
    if(text == null)
      mAction.setVisibility(View.INVISIBLE);
    else{
      mAction.setVisibility(View.VISIBLE);    
      mAction.setText(text);
    }
    return this;
  }
  
  public SnackBar actionText(int id){
    if(id == 0)
      return actionText(null);
    
    return actionText(getContext().getResources().getString(id));
  }
  
  public SnackBar actionTextColor(int color){
    mAction.setTextColor(color);
    return this;
  }
  
  public SnackBar actionTextColor(ColorStateList colors){
    mAction.setTextColor(colors);
    return this;
  }
  
  public SnackBar actionTextAppearance(int resId){
    if(resId != 0)
      mAction.setTextAppearance(getContext(), resId);
    return this;
  }
  
  public SnackBar actionTextSize(int size){
    mAction.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);
    return this;
  }
  
  @SuppressWarnings("deprecation")
  @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
  public SnackBar actionRipple(int resId){
    if(resId != 0){
      if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
        mAction.setBackground(new RippleDrawable.Builder(getContext(), null, resId).build());
      else
        mAction.setBackgroundDrawable(new RippleDrawable.Builder(getContext(), null, resId).build());
    }  
    return this;
  }
  
  public SnackBar duration(long duration){
    mDuration = duration;
    return this;
  }
  
  public SnackBar backgroundColor(int color){
    mBackground.setColor(color);
    return this;
  }
  
  public SnackBar backgroundRadius(int radius){
    mBackground.setRadius(radius);
    return this;
  }
  
  public SnackBar horizontalPadding(int padding){
    mText.setPadding(padding, mText.getPaddingTop(), padding, mText.getPaddingBottom());  
    mAction.setPadding(padding, mAction.getPaddingTop(), padding, mAction.getPaddingBottom());
    return this;
  }
  
  public SnackBar verticalPadding(int padding){
    mText.setPadding(mText.getPaddingLeft(), padding, mText.getPaddingRight(), padding);  
    mAction.setPadding(mAction.getPaddingLeft(), padding, mAction.getPaddingRight(), padding);
    return this;
  }
  
  public SnackBar padding(int horizontalPadding, int verticalPadding){
    mText.setPadding(horizontalPadding, verticalPadding, horizontalPadding, verticalPadding);    
    mAction.setPadding(horizontalPadding, verticalPadding, horizontalPadding, verticalPadding);    
    return this;
  }
  
  public SnackBar width(int width){
    mWidth = width;
    return this;
  }
  
  public SnackBar minWidth(int width){
    mText.setMinWidth(width);
    return this;
  }
  
  public SnackBar maxWidth(int width){
    mText.setMaxWidth(width);
    return this;
  }
  
  public SnackBar height(int height){
    mHeight = height;
    return this;
  }
  
  public SnackBar marginLeft(int size){
    mMarginLeft = size;
    return this;
  }
  
  public SnackBar marginBottom(int size){
    mMarginBottom = size;
    return this;
  }
  
  public SnackBar actionClickListener(OnActionClickListener listener){
    mActionClickListener = listener;
    return this;
  }
  
  public SnackBar stateChangeListener(OnStateChangeListener listener){
    mStateChangeListener = listener;
    return this;
  }
  
  public void show(Activity activity){
    if(mState != STATE_DISMISSED)
      return;
    
    if(getParent() != null && getParent() instanceof ViewGroup)
      ((ViewGroup)getParent()).removeView(this);
        
    LayoutParams params = new LayoutParams(mWidth, mHeight);
        params.gravity = Gravity.BOTTOM;
        params.leftMargin = mMarginLeft;
        params.bottomMargin = mMarginBottom;
        
    activity.getWindow().addContentView(this, params);
    
    if(mInAnimationId != 0){
      Animation anim = AnimationUtils.loadAnimation(getContext(), mInAnimationId);
      anim.setAnimationListener(new Animation.AnimationListener() {
        
        @Override
        public void onAnimationStart(Animation animation) {
          setState(STATE_SHOWING);
        }
        
        @Override
        public void onAnimationRepeat(Animation animation) {}
        
        @Override
        public void onAnimationEnd(Animation animation) {          
          setState(STATE_SHOWED);
          startTimer();
        }
      });
      startAnimation(anim);
    }
    else{
      setState(STATE_SHOWED);
      startTimer();
    }
  }
  
  private void startTimer(){
    removeCallbacks(mDismissRunnable);
    if(mDuration > 0)
      postDelayed(mDismissRunnable, mDuration);
  }
  
  public void dismiss(){
    if(mState != STATE_SHOWED)
      return;
    
    removeCallbacks(mDismissRunnable);
    
    if(mOutAnimationId != 0){
      Animation anim = AnimationUtils.loadAnimation(getContext(), mOutAnimationId);
      anim.setAnimationListener(new Animation.AnimationListener() {
        
        @Override
        public void onAnimationStart(Animation animation) {
          setState(STATE_DISMISSING);
        }
        
        @Override
        public void onAnimationRepeat(Animation animation) {}
        
        @Override
        public void onAnimationEnd(Animation animation) {
          if(getParent() != null && getParent() instanceof ViewGroup)
            ((ViewGroup)getParent()).removeView(SnackBar.this);
          
          setState(STATE_DISMISSED);
        }
      });
      startAnimation(anim);
    }
    else{
      if(getParent() != null && getParent() instanceof ViewGroup)
        ((ViewGroup)getParent()).removeView(this);
      
      setState(STATE_DISMISSED);
    }    
    
  }
  
  public int getState(){
    return mState;
  }
  
  private void setState(int state){
    if(mState != state){
      int oldState = mState;
      mState = state;
      if(mStateChangeListener != null)
        mStateChangeListener.onStateChange(this, oldState, mState);
    }
  }
  
  private class BackgroundDrawable extends Drawable{

    private int mBackgroundColor;
    private int mBackgroundRadius;
    
    private Paint mPaint;
    private RectF mRect;
    
    public BackgroundDrawable(){
      mPaint = new Paint();
      mPaint.setAntiAlias(true);
      mPaint.setStyle(Paint.Style.FILL);
      
      mRect = new RectF();
    }    
    
    public void setColor(int color){
      if(mBackgroundColor != color){
        mBackgroundColor = color;
        mPaint.setColor(mBackgroundColor);
        invalidateSelf();
      }
    }
    
    public void setRadius(int radius){
      if(mBackgroundRadius != radius){
        mBackgroundRadius = radius;
        invalidateSelf();
      }
    }
    
    @Override
    protected void onBoundsChange(Rect bounds) {
      mRect.set(bounds);
    }

    @Override
    public void draw(Canvas canvas) {
      canvas.drawRoundRect(mRect, mBackgroundRadius, mBackgroundRadius, mPaint);
    }

    @Override
    public void setAlpha(int alpha) {
      mPaint.setAlpha(alpha);
    }

    @Override
    public void setColorFilter(ColorFilter cf) {
      mPaint.setColorFilter(cf);
    }

    @Override
    public int getOpacity() {
      return PixelFormat.TRANSLUCENT;
    }
    
  }
}




Java Source Code List

com.rey.material.ApplicationTest.java
com.rey.material.demo.ButtonFragment.java
com.rey.material.demo.MainActivity.java
com.rey.material.demo.ProgressFragment.java
com.rey.material.demo.SnackbarFragment.java
com.rey.material.demo.SwitchesFragment.java
com.rey.material.demo.TextfieldFragment.java
com.rey.material.drawable.ArrowDrawable.java
com.rey.material.drawable.BlankDrawable.java
com.rey.material.drawable.CheckBoxDrawable.java
com.rey.material.drawable.CircularProgressDrawable.java
com.rey.material.drawable.DividerDrawable.java
com.rey.material.drawable.LineMorphingDrawable.java
com.rey.material.drawable.LinearProgressDrawable.java
com.rey.material.drawable.NavigationDrawerDrawable.java
com.rey.material.drawable.RadioButtonDrawable.java
com.rey.material.drawable.RevealDrawable.java
com.rey.material.drawable.RippleDrawable.java
com.rey.material.drawable.ToolbarRippleDrawable.java
com.rey.material.util.ColorUtil.java
com.rey.material.util.ThemeUtil.java
com.rey.material.util.ViewUtil.java
com.rey.material.view.Button.java
com.rey.material.view.CheckBox.java
com.rey.material.view.CheckedTextView.java
com.rey.material.view.CompoundButton.java
com.rey.material.view.EditText.java
com.rey.material.view.FloatingActionButton.java
com.rey.material.view.ListPopupWindow.java
com.rey.material.view.ListView.java
com.rey.material.view.PopupWindow.java
com.rey.material.view.ProgressView.java
com.rey.material.view.RadioButton.java
com.rey.material.view.RippleManager.java
com.rey.material.view.SnackBar.java
com.rey.material.view.Spinner.java
com.rey.material.view.Switch.java
com.rey.material.view.TabPageIndicator.java
com.rey.material.view.TextView.java