1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.fmradio.views; 18 19 import android.content.Context; 20 import android.graphics.PixelFormat; 21 import android.os.Handler; 22 import android.util.Log; 23 import android.view.Gravity; 24 import android.view.View; 25 import android.view.WindowManager; 26 import android.widget.Button; 27 import android.widget.RelativeLayout; 28 import android.widget.TextView; 29 30 import com.android.fmradio.R; 31 32 /** 33 * The view used to display the customized toast 34 * 35 * Usage: 36 * 37 * FmSnackBar snackBar = FmSnackBar.make(context, title, action, 38 * listener,FmSnackBar.DEFAULT_DURATION); 39 * snackBar.show(); 40 * snackBar.dismiss(); 41 */ 42 public final class FmSnackBar extends View { 43 44 private static final String TAG = "FmSnackBar"; 45 private static final Object LOCK = new Object(); 46 public static final int DEFAULT_DURATION = 3000; 47 public static final int MIN_DURATION = 1000; 48 private Context mContext = null; 49 private WindowManager.LayoutParams mWindowParams = null; 50 private RelativeLayout mLayout = null; 51 private boolean mIsDisplayed = false; 52 private Button mButton = null; 53 private TextView mTextView = null; 54 private OnActionTriggerListener mActionListener = null; 55 private Handler mHandler = null; 56 private int mDuration = DEFAULT_DURATION; 57 58 private final Runnable mDismissionRunnable = new Runnable() { 59 @Override 60 public void run() { 61 FmSnackBar.this.dismiss(); 62 } 63 }; 64 65 /** 66 * The callback listener, it will called while the action button 67 * was set and the action button was clicked 68 */ 69 public interface OnActionTriggerListener { 70 /** 71 * Action button callback 72 */ onActionTriggered()73 void onActionTriggered(); 74 } 75 76 /** 77 * To make a FmSnackBar instance 78 * 79 * @param context The context instance 80 * @param title The notification text 81 * @param actionName The action name displayed to end user 82 * @param listener The callback listener 83 * @param duration The displaying duration 84 * @return The FmSnackBar instance 85 */ make(Context context, String title, String actionName, OnActionTriggerListener listener, int duration)86 public static synchronized FmSnackBar make(Context context, String title, String actionName, 87 OnActionTriggerListener listener, int duration) { 88 FmSnackBar instance = new FmSnackBar(context); 89 if (title == null) { 90 instance.mTextView.setText(""); 91 } else { 92 instance.mTextView.setText(title); 93 } 94 if (actionName != null & listener != null) { 95 instance.mButton.setText(actionName); 96 instance.mActionListener = listener; 97 instance.mButton.setVisibility(View.VISIBLE); 98 } else { 99 instance.mButton.setVisibility(View.GONE); 100 } 101 if (duration < MIN_DURATION) { 102 instance.mDuration = MIN_DURATION; 103 } else { 104 instance.mDuration = duration; 105 } 106 return instance; 107 } 108 FmSnackBar(Context context)109 private FmSnackBar(Context context) { 110 super(context); 111 init(context); 112 } 113 init(Context context)114 private void init(Context context) { 115 mContext = context; 116 mHandler = new Handler(); 117 mLayout = (RelativeLayout) RelativeLayout.inflate(context, R.layout.snackbar, null); 118 mWindowParams = new WindowManager.LayoutParams(); 119 mWindowParams.type = WindowManager.LayoutParams.TYPE_APPLICATION; 120 mWindowParams.format = PixelFormat.RGBA_8888; 121 mWindowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 122 mWindowParams.gravity = Gravity.LEFT | Gravity.BOTTOM; 123 mWindowParams.x = 0; 124 mWindowParams.y = 0; 125 mWindowParams.width = WindowManager.LayoutParams.MATCH_PARENT; 126 mWindowParams.height = WindowManager.LayoutParams.WRAP_CONTENT; 127 128 mButton = (Button) mLayout.findViewById(R.id.snackbar_action); 129 mButton.setOnClickListener(new OnClickListener() { 130 @Override 131 public void onClick(View arg0) { 132 if (mActionListener != null) { 133 mActionListener.onActionTriggered(); 134 } 135 } 136 }); 137 mButton.setVisibility(View.GONE); 138 139 mTextView = (TextView) mLayout.findViewById(R.id.snackbar_text); 140 } 141 142 /** 143 * To display the view of FmSnackBar 144 */ show()145 public void show() { 146 synchronized (LOCK) { 147 WindowManager manager = (WindowManager) mContext 148 .getSystemService(Context.WINDOW_SERVICE); 149 if (mIsDisplayed) { 150 manager.removeViewImmediate(mLayout); 151 } 152 manager.addView(mLayout, mWindowParams); 153 mIsDisplayed = true; 154 mHandler.postDelayed(mDismissionRunnable, mDuration); 155 } 156 } 157 158 /** 159 * To dismiss the view of Snackbar 160 */ dismiss()161 public void dismiss() { 162 synchronized (LOCK) { 163 WindowManager manager = (WindowManager) mContext 164 .getSystemService(Context.WINDOW_SERVICE); 165 if (mIsDisplayed) { 166 try { 167 manager.removeViewImmediate(mLayout); 168 } catch (IllegalArgumentException e) { 169 Log.d(TAG, "dismiss, " + e.toString()); 170 } 171 } 172 mIsDisplayed = false; 173 } 174 } 175 } 176