1.代码重新设置控件宽高:
public static void setViewHeightAndWidth(View view) { final View mv = view; final ViewTreeObserver vto = mv.getViewTreeObserver(); final ViewTreeObserver.OnPreDrawListener preDrawListener = new ViewTreeObserver.OnPreDrawListener() { public boolean onPreDraw() { int width = mv.getMeasuredWidth(); int height = mv.getMeasuredHeight(); android.view.ViewGroup.LayoutParams lp = mv.getLayoutParams(); if (width >= height) { lp.width = height; } else { lp.height = width; } mv.setLayoutParams(lp); final ViewTreeObserver vto1 = mv.getViewTreeObserver(); vto1.removeOnPreDrawListener(this); return true; } }; vto.addOnPreDrawListener(preDrawListener); }
2.透明标题栏
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) private void setStatusBarUpperAPI21() { Window window = getWindow(); window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); window.setStatusBarColor(Color.TRANSPARENT); window.setNavigationBarColor(Color.TRANSPARENT); }
super.onCreate(savedInstanceState); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { setStatusBarUpperAPI21(); } setContentView(R.layout.activity_main);
3.切换语言:
public void updataLanguage(String s){ SharedPreferences sp =getSharedPreferences("语言",MODE_PRIVATE); String language; if(s.equals("")){ language=sp.getString("name","zhCN"); Log.e("language",language); }else{ language=s; } Resources resources =getResources(); Configuration config =resources.getConfiguration(); String localelanguage=config.locale.getLanguage(); String localeCountry=config.locale.getCountry(); Log.e("localelanguage",localelanguage); Log.e("localeCountry",localeCountry); if(!(localelanguage+localeCountry).equals(language)){ Intent intent = new Intent(this,MainActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK); startActivity(intent); } Log.e("设置语言:","设置语言"); DisplayMetrics dm=resources.getDisplayMetrics(); switch (language){ case "zhCN": config.locale= Locale.CHINA; showViewCN(); break; case "zhTW": config.locale= Locale.TAIWAN; showViewCN(); break; case "enUS": config.locale= Locale.US; showViewEN(); break; case "koKR": config.locale= Locale.KOREA; showViewCN(); break; case "deDE": config.locale= Locale.GERMANY; showViewEN(); break; case "jaJP": config.locale= Locale.JAPAN; showViewEN(); break; case "ruRU": config.locale= new Locale("ru", "RU"); showViewEN(); break; default: config.locale= Locale.CHINA; showViewCN(); break; } resources.updateConfiguration(config,dm); }
4.
public void showSnackbar(String str){ if(toast==null){ toast=Toast.makeText(getApplicationContext(),str,Toast.LENGTH_SHORT); }else{ toast.setText(str); } toast.show(); // Log.e("showSnackbar",str); // final Snackbar snackbar = Snackbar.make(videoView, str, Snackbar // .LENGTH_LONG); // snackbar.show(); // snackbar.setAction("确定", new View.OnClickListener() { // @Override // public void onClick(View view) { // snackbar.dismiss(); // } // }); }
5.自定义VIEW
package com.example.administrator.newtrainingclothes.view.mySnackbar; import android.support.v4.view.animation.FastOutLinearInInterpolator; import android.support.v4.view.animation.FastOutSlowInInterpolator; import android.support.v4.view.animation.LinearOutSlowInInterpolator; import android.view.animation.Animation; import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; import android.view.animation.LinearInterpolator; public class AnimationUtils { static final Interpolator LINEAR_INTERPOLATOR = new LinearInterpolator(); static final Interpolator FAST_OUT_SLOW_IN_INTERPOLATOR = new FastOutSlowInInterpolator(); static final Interpolator FAST_OUT_LINEAR_IN_INTERPOLATOR = new FastOutLinearInInterpolator(); static final Interpolator LINEAR_OUT_SLOW_IN_INTERPOLATOR = new LinearOutSlowInInterpolator(); static final Interpolator DECELERATE_INTERPOLATOR = new DecelerateInterpolator(); /** * Linear interpolation between {@code startValue} and {@code endValue} by {@code fraction}. */ static float lerp(float startValue, float endValue, float fraction) { return startValue + (fraction * (endValue - startValue)); } static int lerp(int startValue, int endValue, float fraction) { return startValue + Math.round(fraction * (endValue - startValue)); } static class AnimationListenerAdapter implements Animation.AnimationListener { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { } } }
package com.example.administrator.newtrainingclothes.view.mySnackbar; import com.example.administrator.newtrainingclothes.R; public enum Prompt { /** * 红色,错误 */ ERROR(R.drawable.common_bounced_icon_error, R.color.prompt_error), /** * 红色,警告 */ WARNING(R.drawable.common_bounced_icon_warning, R.color.prompt_warning), /** * 绿色,成功 */ SUCCESS(R.drawable.common_bounced_icon_successful, R.color.prompt_success); private int resIcon; private int backgroundColor; Prompt(int resIcon, int backgroundColor) { this.resIcon = resIcon; this.backgroundColor = backgroundColor; } public int getResIcon() { return resIcon; } public void setResIcon(int resIcon) { this.resIcon = resIcon; } public int getBackgroundColor() { return backgroundColor; } public void setBackgroundColor(int backgroundColor) { this.backgroundColor = backgroundColor; } }
package com.example.administrator.newtrainingclothes.view.mySnackbar; import android.app.Activity; import android.app.ActivityGroup; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Rect; import android.os.Build; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.util.TypedValue; import android.view.View; import android.view.ViewGroup; /** * 获得屏幕相关的辅助类 */ public class ScreenUtil { private ScreenUtil() { /* cannot be instantiated */ throw new UnsupportedOperationException("cannot be instantiated"); } private static int mStatusHeight = -1; /** * 获得状态栏的高度 * @param context * @return mStatusHeight */ public static int getStatusHeight(Context context) { if (mStatusHeight != -1) { return mStatusHeight; } try { int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); if (resourceId > 0) { mStatusHeight = context.getResources().getDimensionPixelSize(resourceId); } } catch (Exception e) { e.printStackTrace(); } return mStatusHeight; } /** * 获取当前屏幕截图,不包含状态栏 * @param activity * @return bp */ public static Bitmap snapShotWithoutStatusBar(Activity activity) { View view = activity.getWindow().getDecorView(); view.setDrawingCacheEnabled(true); view.buildDrawingCache(); Bitmap bmp = view.getDrawingCache(); if (bmp == null) { return null; } Rect frame = new Rect(); activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame); int statusBarHeight = frame.top; Bitmap bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, bmp.getWidth(), bmp.getHeight() - statusBarHeight); view.destroyDrawingCache(); view.setDrawingCacheEnabled(false); return bp; } /** * 获取actionbar的像素高度,默认使用android官方兼容包做actionbar兼容 * * @return */ public static int getActionBarHeight(Context context) { int actionBarHeight=0; if(context instanceof AppCompatActivity &&((AppCompatActivity) context).getSupportActionBar()!=null) { Log.d("isAppCompatActivity", "==AppCompatActivity"); actionBarHeight = ((AppCompatActivity) context).getSupportActionBar().getHeight(); }else if(context instanceof Activity && ((Activity) context).getActionBar()!=null) { Log.d("isActivity","==Activity"); actionBarHeight = ((Activity) context).getActionBar().getHeight(); }else if(context instanceof ActivityGroup){ Log.d("ActivityGroup","==ActivityGroup"); if (((ActivityGroup) context).getCurrentActivity() instanceof AppCompatActivity && ((AppCompatActivity) ((ActivityGroup) context).getCurrentActivity()).getSupportActionBar()!=null){ actionBarHeight = ((AppCompatActivity) ((ActivityGroup) context).getCurrentActivity()).getSupportActionBar().getHeight(); }else if (((ActivityGroup) context).getCurrentActivity() instanceof Activity && ((Activity) ((ActivityGroup) context).getCurrentActivity()).getActionBar()!=null){ actionBarHeight = ((Activity) ((ActivityGroup) context).getCurrentActivity()).getActionBar().getHeight(); } } if (actionBarHeight != 0) return actionBarHeight; final TypedValue tv = new TypedValue(); if(context.getTheme().resolveAttribute( android.support.v7.appcompat.R.attr.actionBarSize, tv, true)){ if (context.getTheme().resolveAttribute(android.support.v7.appcompat.R.attr.actionBarSize, tv, true)) actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data, context.getResources().getDisplayMetrics()); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { if (context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data, context.getResources().getDisplayMetrics()); }else { if (context.getTheme().resolveAttribute(android.support.v7.appcompat.R.attr.actionBarSize, tv, true)) actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data, context.getResources().getDisplayMetrics()); } Log.d("actionBarHeight","===="+actionBarHeight); return actionBarHeight; } /** * 设置view margin * @param v * @param l * @param t * @param r * @param b */ public static void setMargins (View v, int l, int t, int r, int b) { if (v.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) { ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) v.getLayoutParams(); p.setMargins(l, t, r, b); v.requestLayout(); } } }
package com.example.administrator.newtrainingclothes.view.mySnackbar; /* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import android.os.Handler; import android.os.Looper; import android.os.Message; import android.support.design.widget.Snackbar; import java.lang.ref.WeakReference; class SnackbarManager { private static final int MSG_TIMEOUT = 0; private static final int SHORT_DURATION_MS = 1500; private static final int LONG_DURATION_MS = 2750; private static SnackbarManager sSnackbarManager; static SnackbarManager getInstance() { if (sSnackbarManager == null) { sSnackbarManager = new SnackbarManager(); } return sSnackbarManager; } private final Object mLock; private final Handler mHandler; private SnackbarRecord mCurrentSnackbar; private SnackbarRecord mNextSnackbar; private SnackbarManager() { mLock = new Object(); mHandler = new Handler(Looper.getMainLooper(), new Handler.Callback() { @Override public boolean handleMessage(Message message) { switch (message.what) { case MSG_TIMEOUT: handleTimeout((SnackbarRecord) message.obj); return true; } return false; } }); } interface Callback { void show(); void dismiss(int event); } public void show(int duration, Callback callback) { synchronized (mLock) { if (isCurrentSnackbarLocked(callback)) { // Means that the callback is already in the queue. We'll just update the duration mCurrentSnackbar.duration = duration; // If this is the Snackbar currently being shown, call re-schedule it's // timeout mHandler.removeCallbacksAndMessages(mCurrentSnackbar); scheduleTimeoutLocked(mCurrentSnackbar); return; } else if (isNextSnackbarLocked(callback)) { // We'll just update the duration mNextSnackbar.duration = duration; } else { // Else, we need to create a new record and queue it mNextSnackbar = new SnackbarRecord(duration, callback); } if (mCurrentSnackbar != null && cancelSnackbarLocked(mCurrentSnackbar, Snackbar.Callback.DISMISS_EVENT_CONSECUTIVE)) { // If we currently have a Snackbar, try and cancel it and wait in line return; } else { // Clear out the current snackbar mCurrentSnackbar = null; // Otherwise, just show it now showNextSnackbarLocked(); } } } public void dismiss(Callback callback, int event) { synchronized (mLock) { if (isCurrentSnackbarLocked(callback)) { cancelSnackbarLocked(mCurrentSnackbar, event); } else if (isNextSnackbarLocked(callback)) { cancelSnackbarLocked(mNextSnackbar, event); } } } /** * Should be called when a Snackbar is no longer displayed. This is after any exit * animation has finished. */ public void onDismissed(Callback callback) { synchronized (mLock) { if (isCurrentSnackbarLocked(callback)) { // If the callback is from a Snackbar currently show, remove it and show a new one mCurrentSnackbar = null; if (mNextSnackbar != null) { showNextSnackbarLocked(); } } } } /** * Should be called when a Snackbar is being shown. This is after any entrance animation has * finished. */ public void onShown(Callback callback) { synchronized (mLock) { if (isCurrentSnackbarLocked(callback)) { scheduleTimeoutLocked(mCurrentSnackbar); } } } public void cancelTimeout(Callback callback) { synchronized (mLock) { if (isCurrentSnackbarLocked(callback)) { mHandler.removeCallbacksAndMessages(mCurrentSnackbar); } } } public void restoreTimeout(Callback callback) { synchronized (mLock) { if (isCurrentSnackbarLocked(callback)) { scheduleTimeoutLocked(mCurrentSnackbar); } } } public boolean isCurrent(Callback callback) { synchronized (mLock) { return isCurrentSnackbarLocked(callback); } } public boolean isCurrentOrNext(Callback callback) { synchronized (mLock) { return isCurrentSnackbarLocked(callback) || isNextSnackbarLocked(callback); } } private static class SnackbarRecord { private final WeakReference<Callback> callback; private int duration; SnackbarRecord(int duration, Callback callback) { this.callback = new WeakReference<>(callback); this.duration = duration; } boolean isSnackbar(Callback callback) { return callback != null && this.callback.get() == callback; } } private void showNextSnackbarLocked() { if (mNextSnackbar != null) { mCurrentSnackbar = mNextSnackbar; mNextSnackbar = null; final Callback callback = mCurrentSnackbar.callback.get(); if (callback != null) { callback.show(); } else { // The callback doesn't exist any more, clear out the Snackbar mCurrentSnackbar = null; } } } private boolean cancelSnackbarLocked(SnackbarRecord record, int event) { final Callback callback = record.callback.get(); if (callback != null) { // Make sure we remove any timeouts for the SnackbarRecord mHandler.removeCallbacksAndMessages(record); callback.dismiss(event); return true; } return false; } private boolean isCurrentSnackbarLocked(Callback callback) { return mCurrentSnackbar != null && mCurrentSnackbar.isSnackbar(callback); } private boolean isNextSnackbarLocked(Callback callback) { return mNextSnackbar != null && mNextSnackbar.isSnackbar(callback); } private void scheduleTimeoutLocked(SnackbarRecord r) { if (r.duration == Snackbar.LENGTH_INDEFINITE) { // If we're set to indefinite, we don't want to set a timeout return; } int durationMs = LONG_DURATION_MS; if (r.duration > 0) { durationMs = r.duration; } else if (r.duration == Snackbar.LENGTH_SHORT) { durationMs = SHORT_DURATION_MS; } mHandler.removeCallbacksAndMessages(r); mHandler.sendMessageDelayed(Message.obtain(mHandler, MSG_TIMEOUT, r), durationMs); } private void handleTimeout(SnackbarRecord record) { synchronized (mLock) { if (mCurrentSnackbar == record || mNextSnackbar == record) { cancelSnackbarLocked(record, Snackbar.Callback.DISMISS_EVENT_TIMEOUT); } } } }
package com.example.administrator.newtrainingclothes.view.mySnackbar; /* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import android.animation.Animator; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.content.Context; import android.content.res.ColorStateList; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.support.annotation.ColorInt; import android.support.annotation.IntDef; import android.support.annotation.NonNull; import android.support.annotation.StringRes; import android.support.design.widget.CoordinatorLayout; import android.support.design.widget.SwipeDismissBehavior; import android.support.v4.view.ViewCompat; import android.text.TextUtils; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; import android.view.accessibility.AccessibilityManager; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.view.animation.LinearInterpolator; import android.widget.Button; import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.TextView; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import static com.example.administrator.newtrainingclothes.view.mySnackbar.AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR; import com.example.administrator.newtrainingclothes.R; /** * TSnackbar provides lightweight feedback about an operation. They show a brief message at the * top of the screen on mobile. TSnackbar appear above all other * elements on screen and only one can be displayed at a time. * <p> * They automatically disappear after a timeout or after user interaction elsewhere on the screen, * particularly after interactions that summon a new surface or activity. Snackbars can be swiped * off screen. * <p> * Snackbars can contain an action which is set via * {@link #setAction(CharSequence, View.OnClickListener)}. * <p> * To be notified when a snackbar has been shown or dismissed, you can provide a {@link Callback} * via {@link #setCallback(Callback)}.</p> */ public final class TSnackbar { /** * Callback class for {@link TSnackbar} instances. * * @see TSnackbar#setCallback(Callback) */ public static abstract class Callback { /** * Indicates that the TSnackbar was dismissed via a swipe. */ public static final int DISMISS_EVENT_SWIPE = 0; /** * Indicates that the TSnackbar was dismissed via an action click. */ public static final int DISMISS_EVENT_ACTION = 1; /** * Indicates that the TSnackbar was dismissed via a timeout. */ public static final int DISMISS_EVENT_TIMEOUT = 2; /** * Indicates that the TSnackbar was dismissed via a call to {@link #dismiss()}. */ public static final int DISMISS_EVENT_MANUAL = 3; /** * Indicates that the TSnackbar was dismissed from a new Snackbar being shown. */ public static final int DISMISS_EVENT_CONSECUTIVE = 4; @IntDef({DISMISS_EVENT_SWIPE, DISMISS_EVENT_ACTION, DISMISS_EVENT_TIMEOUT, DISMISS_EVENT_MANUAL, DISMISS_EVENT_CONSECUTIVE}) @Retention(RetentionPolicy.SOURCE) public @interface DismissEvent { } /** * Called when the given {@link TSnackbar} has been dismissed, either through a time-out, * having been manually dismissed, or an action being clicked. * * @param TSnackbar The snackbar which has been dismissed. * @param event The event which caused the dismissal. One of either: * {@link #DISMISS_EVENT_SWIPE}, {@link #DISMISS_EVENT_ACTION}, * {@link #DISMISS_EVENT_TIMEOUT}, {@link #DISMISS_EVENT_MANUAL} or * {@link #DISMISS_EVENT_CONSECUTIVE}. * @see TSnackbar#dismiss() */ public void onDismissed(TSnackbar TSnackbar, @DismissEvent int event) { } /** * Called when the given {@link TSnackbar} is visible. * * @param TSnackbar The snackbar which is now visible. * @see TSnackbar#show() */ public void onShown(TSnackbar TSnackbar) { } } @IntDef({APPEAR_FROM_TOP_TO_DOWN, APPEAR_FROM_BOTTOM_TO_TOP}) @Retention(RetentionPolicy.SOURCE) public @interface OverSnackAppearDirection { } /** * Show the TSnackbar from top to down. */ public static final int APPEAR_FROM_TOP_TO_DOWN = 0; /** * Show the TSnackbar from top to down. */ public static final int APPEAR_FROM_BOTTOM_TO_TOP = 1; @IntDef({LENGTH_INDEFINITE, LENGTH_SHORT, LENGTH_LONG}) @Retention(RetentionPolicy.SOURCE) public @interface Duration { } /** * Show the TSnackbar indefinitely. This means that the TSnackbar will be displayed from the time * that is {@link #show() shown} until either it is dismissed, or another TSnackbar is shown. * * @see #setDuration */ public static final int LENGTH_INDEFINITE = -2; /** * Show the TSnackbar for a short period of time. * * @see #setDuration */ public static final int LENGTH_SHORT = -1; /** * Show the TSnackbar for a long period of time. * * @see #setDuration */ public static final int LENGTH_LONG = 0; private static final int ANIMATION_DURATION = 250; private static final int ANIMATION_FADE_DURATION = 180; private static final Handler sHandler; private static final int MSG_SHOW = 0; private static final int MSG_DISMISS = 1; private @OverSnackAppearDirection int appearDirection = APPEAR_FROM_TOP_TO_DOWN; static { sHandler = new Handler(Looper.getMainLooper(), new Handler.Callback() { @Override public boolean handleMessage(Message message) { switch (message.what) { case MSG_SHOW: ((TSnackbar) message.obj).showView(); return true; case MSG_DISMISS: ((TSnackbar) message.obj).hideView(message.arg1); return true; } return false; } }); } private final ViewGroup mParent; private final Context mContext; private final SnackbarLayout mView; private int mDuration; private Callback mCallback; private final AccessibilityManager mAccessibilityManager; private TSnackbar(ViewGroup parent) { appearDirection = APPEAR_FROM_TOP_TO_DOWN; mParent = parent; mContext = parent.getContext(); LayoutInflater inflater = LayoutInflater.from(mContext); if(appearDirection == APPEAR_FROM_BOTTOM_TO_TOP){ mView = (SnackbarLayout) inflater.inflate(R.layout.view_bsnackbar_layout, mParent, false); }else{ mView = (SnackbarLayout) inflater.inflate(R.layout.view_tsnackbar_layout, mParent, false); } mAccessibilityManager = (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE); } private TSnackbar(ViewGroup parent, @OverSnackAppearDirection int appearDirection) { this.appearDirection = appearDirection; mParent = parent; mContext = parent.getContext(); LayoutInflater inflater = LayoutInflater.from(mContext); if(appearDirection == APPEAR_FROM_BOTTOM_TO_TOP){ mView = (SnackbarLayout) inflater.inflate(R.layout.view_bsnackbar_layout, mParent, false); }else{ mView = (SnackbarLayout) inflater.inflate(R.layout.view_tsnackbar_layout, mParent, false); } mAccessibilityManager = (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE); if(appearDirection == APPEAR_FROM_TOP_TO_DOWN) { setMinHeight(0,0); } } /** * * @param stateBarHeight * @param actionBarHeight * @return */ public TSnackbar setMinHeight(int stateBarHeight,int actionBarHeight){ if(appearDirection == APPEAR_FROM_TOP_TO_DOWN) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if(stateBarHeight>0 || actionBarHeight>0){ mView.setPadding(0, stateBarHeight, 0, 0); mView.setMinimumHeight(stateBarHeight+actionBarHeight); }else{ mView.setPadding(0, ScreenUtil.getStatusHeight(mContext), 0, 0); mView.setMinimumHeight(ScreenUtil.getActionBarHeight(mContext)+ScreenUtil.getStatusHeight(mContext)); } }else{ if(stateBarHeight>0 || actionBarHeight>0){ mView.setMinimumHeight(actionBarHeight); ScreenUtil.setMargins(mView,0,stateBarHeight,0,0); }else{ mView.setMinimumHeight(ScreenUtil.getActionBarHeight(mContext)); ScreenUtil.setMargins(mView,0,ScreenUtil.getStatusHeight(mContext),0,0); } } } return this; } /** * Make a TSnackbar to display a message * <p/> * <p>TSnackbar will try and find a parent view to hold TSnackbar's view from the value given * to {@code view}. Snackbar will walk up the view tree trying to find a suitable parent, * which is defined as a {@link CoordinatorLayout} or the window decor's content view, * whichever comes first. * <p/> * <p>Having a {@link CoordinatorLayout} in your view hierarchy allows TSnackbar to enable * certain features, such as swipe-to-dismiss and automatically moving of widgets like * {@link }. * * @param view The view to find a parent from. * @param text The text to show. Can be formatted text. * @param duration How long to display the message. Either {@link #LENGTH_SHORT} or {@link * #LENGTH_LONG} */ @NonNull public static TSnackbar make(@NonNull View view, @NonNull CharSequence text, @Duration int duration) { TSnackbar tSnackbar = new TSnackbar(findSuitableParent(view), APPEAR_FROM_TOP_TO_DOWN); tSnackbar.setText(text); tSnackbar.setDuration(duration); return tSnackbar; } @NonNull public static TSnackbar make(@NonNull View view, @NonNull CharSequence text, @Duration int duration, @OverSnackAppearDirection int appearDirection) { TSnackbar tSnackbar = new TSnackbar(findSuitableParent(view), appearDirection); tSnackbar.setText(text); tSnackbar.setDuration(duration); return tSnackbar; } /** * Make a TSnackbar to display a message. * <p/> * <p>TSnackbar will try and find a parent view to hold TSnackbar's view from the value given * to {@code view}. TSnackbar will walk up the view tree trying to find a suitable parent, * which is defined as a {@link CoordinatorLayout} or the window decor's content view, * whichever comes first. * <p/> * <p>Having a {@link CoordinatorLayout} in your view hierarchy allows TSnackbar to enable * certain features, such as swipe-to-dismiss and automatically moving of widgets like * {@link }. * * @param view The view to find a parent from. * @param resId The resource id of the string resource to use. Can be formatted text. * @param duration How long to display the message. Either {@link #LENGTH_SHORT} or {@link * #LENGTH_LONG} */ @NonNull public static TSnackbar make(@NonNull View view, @StringRes int resId, @Duration int duration) { return make(view, view.getResources().getText(resId), duration); } private static ViewGroup findSuitableParent(View view) { ViewGroup fallback = null; do { if (view instanceof CoordinatorLayout) { // We've found a CoordinatorLayout, use it return (ViewGroup) view; } else if (view instanceof FrameLayout) { if (view.getId() == android.R.id.content) { // If we've hit the decor content view, then we didn't find a CoL in the // hierarchy, so use it. return (ViewGroup) view; } else { // It's not the content view but we'll use it as our fallback fallback = (ViewGroup) view; } } if (view != null) { // Else, we will loop and crawl up the view hierarchy and try to find a parent final ViewParent parent = view.getParent(); view = parent instanceof View ? (View) parent : null; } } while (view != null); // If we reach here then we didn't find a CoL or a suitable content view so we'll fallback return fallback; //return (ViewGroup) view; } /** * * @param resource_id * @return */ public TSnackbar addIcon(int resource_id) { final TextView tv = mView.getMessageView(); tv.setCompoundDrawablesWithIntrinsicBounds(mContext.getResources().getDrawable(resource_id), null, null, null); return this; } /** * * @param resource_id image id * @param width image width * @param height image height * @return */ public TSnackbar addIcon(int resource_id, int width, int height) { final TextView tv = mView.getMessageView(); if(width>0 || height>0){ tv.setCompoundDrawablesWithIntrinsicBounds(new BitmapDrawable(Bitmap.createScaledBitmap(((BitmapDrawable) (mContext.getResources().getDrawable(resource_id))).getBitmap(), width, height, true)), null, null, null); }else{ addIcon(resource_id); } return this; } /** * show loading progressBar * @param resource_id image id * @param left show textview left * @param right show textview right * @return TSnackbar */ public TSnackbar addIconProgressLoading(int resource_id,boolean left,boolean right) { Drawable drawable = mContext.getResources().getDrawable(R.drawable.rotate); if(resource_id>0 ){ drawable = mContext.getResources().getDrawable(resource_id); } addIconProgressLoading(drawable,left,right); return this; } /** * * @param drawable * @param left * @param right * @return */ public TSnackbar addIconProgressLoading(Drawable drawable, boolean left, boolean right) { final ObjectAnimator animator = ObjectAnimator.ofInt(drawable, "level", 0, 10000); animator.setDuration(1000); animator.setInterpolator(new LinearInterpolator()); animator.setRepeatCount(ValueAnimator.INFINITE); animator.setRepeatMode(ValueAnimator.INFINITE); mView.setBackgroundColor(mContext.getResources().getColor(Prompt.SUCCESS.getBackgroundColor())); if(left){ mView.getMessageView().setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null); } if(right){ mView.getMessageView().setCompoundDrawablesWithIntrinsicBounds(null, null, drawable, null); } animator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { if (mCallback != null) { mCallback.onShown(TSnackbar.this); } SnackbarManager.getInstance().onShown(mManagerCallback); } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }); animator.start(); return this; } /** * default style {ERROR , WARNING , SUCCESS} * @param prompt * @return */ public TSnackbar setPromptThemBackground(Prompt prompt) { if (prompt == Prompt.SUCCESS) { setBackgroundColor(mContext.getResources().getColor(Prompt.SUCCESS.getBackgroundColor())); addIcon(Prompt.SUCCESS.getResIcon(), 0, 0); } else if (prompt == Prompt.ERROR) { setBackgroundColor(mContext.getResources().getColor(Prompt.ERROR.getBackgroundColor())); addIcon(Prompt.ERROR.getResIcon(), 0, 0); } else if (prompt == Prompt.WARNING) { setBackgroundColor(mContext.getResources().getColor(Prompt.WARNING.getBackgroundColor())); addIcon(Prompt.WARNING.getResIcon(), 0, 0); } return this; } /** * * @param colorId * @return */ public TSnackbar setBackgroundColor(int colorId) { mView.setBackgroundColor(colorId); return this; } /** * Set the action to be displayed in this {@link TSnackbar}. * * @param resId String resource to display * @param listener callback to be invoked when the action is clicked */ @NonNull public TSnackbar setAction(@StringRes int resId, View.OnClickListener listener) { return setAction(mContext.getText(resId), listener); } /** * Set the action to be displayed in this {@link TSnackbar}. * * @param text Text to display * @param listener callback to be invoked when the action is clicked */ @NonNull public TSnackbar setAction(CharSequence text, final View.OnClickListener listener) { final TextView tv = mView.getActionView(); if (TextUtils.isEmpty(text) || listener == null) { tv.setVisibility(View.GONE); tv.setOnClickListener(null); } else { tv.setVisibility(View.VISIBLE); tv.setText(text); tv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { listener.onClick(view); dispatchDismiss(Callback.DISMISS_EVENT_ACTION); } }); } return this; } /** * Sets the text color of the action specified in * {@link #setAction(CharSequence, View.OnClickListener)}. */ @NonNull public TSnackbar setActionTextColor(ColorStateList colors) { final Button btn = mView.getActionView(); btn.setTextColor(colors); return this; } /** * Sets the text color of the action specified in * */ @NonNull public TSnackbar setActionTextSize(int size) { final Button btn = mView.getActionView(); btn.setTextSize(size); return this; } /** * Sets the text color of the action specified in * */ @NonNull public TSnackbar setMessageTextSize( int size) { final TextView tv = mView.getMessageView(); tv.setTextSize(size); return this; } /** * Sets the text color of the action specified in * */ @NonNull public TSnackbar setActionTextColor(@ColorInt int color) { final Button btn = mView.getActionView(); btn.setTextColor(color); return this; } /** * Sets the text color of the action specified in * */ @NonNull public TSnackbar setTextColor(@ColorInt int color) { setActionTextColor(color); setMessageTextColor(color); return this; } /** * Sets the text color of the action specified in * {@link #setAction(CharSequence, View.OnClickListener)}. */ @NonNull public TSnackbar setColor(ColorStateList colors) { setActionTextColor(colors); setMessageTextColor(colors); return this; } /** * Sets the text color of the action specified in * {@link #setAction(CharSequence, View.OnClickListener)}. */ @NonNull public TSnackbar setMessageTextColor(@ColorInt int color) { final TextView tv = mView.getMessageView(); tv.setTextColor(color); return this; } /** * Sets the text color of the action specified in * {@link #setAction(CharSequence, View.OnClickListener)}. */ @NonNull public TSnackbar setMessageTextColor(ColorStateList colors) { final TextView tv = mView.getMessageView(); tv.setTextColor(colors); return this; } /** * Update the text in this {@link TSnackbar}. * * @param message The new text for the Toast. */ @NonNull public TSnackbar setText(@NonNull CharSequence message) { final TextView tv = mView.getMessageView(); tv.setText(message); return this; } /** * Update the text in this {@link TSnackbar}. * * @param resId The new text for the Toast. */ @NonNull public TSnackbar setText(@StringRes int resId) { return setText(mContext.getText(resId)); } /** * Set how long to show the view for. * * @param duration either be one of the predefined lengths: * {@link #LENGTH_SHORT}, {@link #LENGTH_LONG}, or a custom duration * in milliseconds. */ @NonNull public TSnackbar setDuration(@Duration int duration) { mDuration = duration; return this; } /** * Return the duration. * * @see #setDuration */ @Duration public int getDuration() { return mDuration; } /** * Returns the {@link TSnackbar}'s view. */ @NonNull public View getView() { return mView; } /** * Show the {@link TSnackbar}. */ public void show() { SnackbarManager.getInstance().show(mDuration, mManagerCallback); } /** * Dismiss the {@link TSnackbar}. */ public void dismiss() { dispatchDismiss(Callback.DISMISS_EVENT_MANUAL); } private void dispatchDismiss(@Callback.DismissEvent int event) { SnackbarManager.getInstance().dismiss(mManagerCallback, event); } /** * Set a callback to be called when this the visibility of this {@link TSnackbar} changes. */ @NonNull public TSnackbar setCallback(Callback callback) { mCallback = callback; return this; } /** * Return whether this {@link TSnackbar} is currently being shown. */ public boolean isShown() { return SnackbarManager.getInstance().isCurrent(mManagerCallback); } /** * Returns whether this {@link TSnackbar} is currently being shown, or is queued to be * shown next. */ public boolean isShownOrQueued() { return SnackbarManager.getInstance().isCurrentOrNext(mManagerCallback); } private final SnackbarManager.Callback mManagerCallback = new SnackbarManager.Callback() { @Override public void show() { sHandler.sendMessage(sHandler.obtainMessage(MSG_SHOW, TSnackbar.this)); } @Override public void dismiss(int event) { sHandler.sendMessage(sHandler.obtainMessage(MSG_DISMISS, event, 0, TSnackbar.this)); } }; final void showView() { if (mView.getParent() == null) { final ViewGroup.LayoutParams lp = mView.getLayoutParams(); if (lp instanceof CoordinatorLayout.LayoutParams) { // If our LayoutParams are from a CoordinatorLayout, we'll setup our Behavior final Behavior behavior = new Behavior(); behavior.setStartAlphaSwipeDistance(0.1f); behavior.setEndAlphaSwipeDistance(0.6f); behavior.setSwipeDirection(SwipeDismissBehavior.SWIPE_DIRECTION_START_TO_END); behavior.setListener(new SwipeDismissBehavior.OnDismissListener() { @Override public void onDismiss(View view) { view.setVisibility(View.GONE); dispatchDismiss(Callback.DISMISS_EVENT_SWIPE); } @Override public void onDragStateChanged(int state) { switch (state) { case SwipeDismissBehavior.STATE_DRAGGING: case SwipeDismissBehavior.STATE_SETTLING: SnackbarManager.getInstance().cancelTimeout(mManagerCallback); break; case SwipeDismissBehavior.STATE_IDLE: SnackbarManager.getInstance().restoreTimeout(mManagerCallback); break; } } }); ((CoordinatorLayout.LayoutParams) lp).setBehavior(behavior); ((CoordinatorLayout.LayoutParams) lp).setMargins(0, -30, 0, 0); } mParent.addView(mView); } if (ViewCompat.isLaidOut(mView)) { animateViewIn(); } else { mView.setOnLayoutChangeListener(new SnackbarLayout.OnLayoutChangeListener() { @Override public void onLayoutChange(View view, int left, int top, int right, int bottom) { animateViewIn(); mView.setOnLayoutChangeListener(null); } }); } mView.setOnAttachStateChangeListener(new SnackbarLayout.OnAttachStateChangeListener() { @Override public void onViewAttachedToWindow(View v) {} @Override public void onViewDetachedFromWindow(View v) { if (isShownOrQueued()) { // If we haven't already been dismissed then this event is coming from a // non-user initiated action. Hence we need to make sure that we callback // and keep our state up to date. We need to post the call since removeView() // will call through to onDetachedFromWindow and thus overflow. sHandler.post(new Runnable() { @Override public void run() { onViewHidden(Callback.DISMISS_EVENT_MANUAL); } }); } } }); if (ViewCompat.isLaidOut(mView)) { if (shouldAnimate()) { // If animations are enabled, animate it in animateViewIn(); } else { // Else if anims are disabled just call back now onViewShown(); } } else { // Otherwise, add one of our layout change listeners and show it in when laid out mView.setOnLayoutChangeListener(new SnackbarLayout.OnLayoutChangeListener() { @Override public void onLayoutChange(View view, int left, int top, int right, int bottom) { mView.setOnLayoutChangeListener(null); if (shouldAnimate()) { // If animations are enabled, animate it in animateViewIn(); } else { // Else if anims are disabled just call back now onViewShown(); } } }); } } private void animateViewIn() { Animation anim; if (appearDirection == APPEAR_FROM_TOP_TO_DOWN) { anim = getAnimationInFromTopToDown(); } else { anim = getAnimationInFromBottomToTop(); } anim.setInterpolator(FAST_OUT_SLOW_IN_INTERPOLATOR); anim.setDuration(ANIMATION_DURATION); anim.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationEnd(Animation animation) { onViewShown(); } @Override public void onAnimationStart(Animation animation) {} @Override public void onAnimationRepeat(Animation animation) {} }); mView.startAnimation(anim); } private void animateViewOut(final int event) { Animation anim; if (appearDirection == APPEAR_FROM_TOP_TO_DOWN) { anim = getAnimationOutFromTopToDown(); } else { anim = getAnimationOutFromBottomToTop(); } anim.setInterpolator(FAST_OUT_SLOW_IN_INTERPOLATOR); anim.setDuration(ANIMATION_DURATION); anim.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationEnd(Animation animation) { onViewHidden(event); } @Override public void onAnimationStart(Animation animation) {} @Override public void onAnimationRepeat(Animation animation) {} }); mView.startAnimation(anim); } private Animation getAnimationInFromTopToDown() { return AnimationUtils.loadAnimation(mView.getContext(), R.anim.top_in); } private Animation getAnimationInFromBottomToTop() { return AnimationUtils.loadAnimation(mView.getContext(), R.anim.design_snackbar_in); } private Animation getAnimationOutFromTopToDown() { return AnimationUtils.loadAnimation(mView.getContext(), R.anim.top_out); } private Animation getAnimationOutFromBottomToTop() { return AnimationUtils.loadAnimation(mView.getContext(), R.anim.design_snackbar_out); } final void hideView(@Callback.DismissEvent final int event) { if (shouldAnimate() && mView.getVisibility() == View.VISIBLE) { animateViewOut(event); } else { // If anims are disabled or the view isn't visible, just call back now onViewHidden(event); } } private void onViewShown() { SnackbarManager.getInstance().onShown(mManagerCallback); if (mCallback != null) { mCallback.onShown(this); } } private void onViewHidden(int event) { // First tell the SnackbarManager that it has been dismissed SnackbarManager.getInstance().onDismissed(mManagerCallback); // Now call the dismiss listener (if available) if (mCallback != null) { mCallback.onDismissed(this, event); } // Lastly, remove the view from the parent (if attached) final ViewParent parent = mView.getParent(); if (parent instanceof ViewGroup) { ((ViewGroup) parent).removeView(mView); } } /** * Returns true if we should animate the Snackbar view in/out. */ private boolean shouldAnimate() { return !mAccessibilityManager.isEnabled(); } /** * @return if the view is being being dragged or settled by {@link SwipeDismissBehavior}. */ private boolean isBeingDragged() { final ViewGroup.LayoutParams lp = mView.getLayoutParams(); if (lp instanceof CoordinatorLayout.LayoutParams) { final CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) lp; final CoordinatorLayout.Behavior behavior = layoutParams.getBehavior(); if (behavior instanceof SwipeDismissBehavior) { return ((SwipeDismissBehavior) behavior).getDragState() != SwipeDismissBehavior.STATE_IDLE; } } return false; } public static class SnackbarLayout extends LinearLayout { private TextView mMessageView; private Button mActionView; private int mMaxWidth; private int mMaxInlineActionWidth; interface OnLayoutChangeListener { void onLayoutChange(View view, int left, int top, int right, int bottom); } interface OnAttachStateChangeListener { void onViewAttachedToWindow(View v); void onViewDetachedFromWindow(View v); } private OnLayoutChangeListener mOnLayoutChangeListener; private OnAttachStateChangeListener mOnAttachStateChangeListener; public SnackbarLayout(Context context) { this(context, null); } public SnackbarLayout(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SnackbarLayout); mMaxWidth = a.getDimensionPixelSize(R.styleable.SnackbarLayout_android_maxWidth, -1); mMaxInlineActionWidth = a.getDimensionPixelSize(R.styleable.SnackbarLayout_maxActionInlineWidth, -1); if (a.hasValue(R.styleable.SnackbarLayout_elevation)) { ViewCompat.setElevation(this, a.getDimensionPixelSize( R.styleable.SnackbarLayout_elevation, 0)); } a.recycle(); setClickable(true); // Now inflate our content. We need to do this manually rather than using an <include> // in the layout since older versions of the Android do not inflate includes with // the correct Context. LayoutInflater.from(context).inflate(R.layout.view_tsnackbar_layout_include, this); ViewCompat.setAccessibilityLiveRegion(this, ViewCompat.ACCESSIBILITY_LIVE_REGION_POLITE); ViewCompat.setImportantForAccessibility(this, ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES); } @Override protected void onFinishInflate() { super.onFinishInflate(); mMessageView = (TextView) findViewById(R.id.snackbar_text); mActionView = (Button) findViewById(R.id.snackbar_action); } TextView getMessageView() { return mMessageView; } Button getActionView() { return mActionView; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (mMaxWidth > 0 && getMeasuredWidth() > mMaxWidth) { widthMeasureSpec = MeasureSpec.makeMeasureSpec(mMaxWidth, MeasureSpec.EXACTLY); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } final int multiLineVPadding = getResources().getDimensionPixelSize( R.dimen.design_snackbar_padding_vertical_2lines); final int singleLineVPadding = getResources().getDimensionPixelSize( R.dimen.design_snackbar_padding_vertical); final boolean isMultiLine = mMessageView.getLayout().getLineCount() > 1; boolean remeasure = false; if (isMultiLine && mMaxInlineActionWidth > 0 && mActionView.getMeasuredWidth() > mMaxInlineActionWidth) { if (updateViewsWithinLayout(VERTICAL, multiLineVPadding, multiLineVPadding - singleLineVPadding)) { remeasure = true; } } else { final int messagePadding = isMultiLine ? multiLineVPadding : singleLineVPadding; if (updateViewsWithinLayout(HORIZONTAL, messagePadding, messagePadding)) { remeasure = true; } } if (remeasure) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } void animateChildrenIn(int delay, int duration) { ViewCompat.setAlpha(mMessageView, 0f); ViewCompat.animate(mMessageView).alpha(1f).setDuration(duration) .setStartDelay(delay).start(); if (mActionView.getVisibility() == VISIBLE) { ViewCompat.setAlpha(mActionView, 0f); ViewCompat.animate(mActionView).alpha(1f).setDuration(duration) .setStartDelay(delay).start(); } } void animateChildrenOut(int delay, int duration) { ViewCompat.setAlpha(mMessageView, 1f); ViewCompat.animate(mMessageView).alpha(0f).setDuration(duration) .setStartDelay(delay).start(); if (mActionView.getVisibility() == VISIBLE) { ViewCompat.setAlpha(mActionView, 1f); ViewCompat.animate(mActionView).alpha(0f).setDuration(duration) .setStartDelay(delay).start(); } } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); if (changed && mOnLayoutChangeListener != null) { mOnLayoutChangeListener.onLayoutChange(this, l, t, r, b); } } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); if (mOnAttachStateChangeListener != null) { mOnAttachStateChangeListener.onViewAttachedToWindow(this); } } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (mOnAttachStateChangeListener != null) { mOnAttachStateChangeListener.onViewDetachedFromWindow(this); } } void setOnLayoutChangeListener(OnLayoutChangeListener onLayoutChangeListener) { mOnLayoutChangeListener = onLayoutChangeListener; } void setOnAttachStateChangeListener(OnAttachStateChangeListener listener) { mOnAttachStateChangeListener = listener; } private boolean updateViewsWithinLayout(final int orientation, final int messagePadTop, final int messagePadBottom) { boolean changed = false; if (orientation != getOrientation()) { setOrientation(orientation); changed = true; } if (mMessageView.getPaddingTop() != messagePadTop || mMessageView.getPaddingBottom() != messagePadBottom) { updateTopBottomPadding(mMessageView, messagePadTop, messagePadBottom); changed = true; } return changed; } private static void updateTopBottomPadding(View view, int topPadding, int bottomPadding) { if (ViewCompat.isPaddingRelative(view)) { ViewCompat.setPaddingRelative(view, ViewCompat.getPaddingStart(view), topPadding, ViewCompat.getPaddingEnd(view), bottomPadding); } else { view.setPadding(view.getPaddingLeft(), topPadding, view.getPaddingRight(), bottomPadding); } } } final class Behavior extends SwipeDismissBehavior<SnackbarLayout> { @Override public boolean canSwipeDismissView(View child) { return child instanceof SnackbarLayout; } @Override public boolean onInterceptTouchEvent(CoordinatorLayout parent, SnackbarLayout child, MotionEvent event) { // We want to make sure that we disable any Snackbar timeouts if the user is // currently touching the Snackbar. We restore the timeout when complete if (parent.isPointInChildBounds(child, (int) event.getX(), (int) event.getY())) { switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: SnackbarManager.getInstance().cancelTimeout(mManagerCallback); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: SnackbarManager.getInstance().restoreTimeout(mManagerCallback); break; } } return super.onInterceptTouchEvent(parent, child, event); } } }
top_in.xml
<?xml version="1.0" encoding="utf-8"?> <!--从上到下--> <translate xmlns:android="http://schemas.android.com/apk/res/android" android:fromYDelta="-100%" android:toYDelta="0%" />top_out.xml
<?xml version="1.0" encoding="utf-8"?> <!--从下到上--> <translate xmlns:android="http://schemas.android.com/apk/res/android" android:fromYDelta="0%" android:toYDelta="-100%"/>
touch_raise.xml
<?xml version="1.0" encoding="utf-8"?> <!--从下到上--> <translate xmlns:android="http://schemas.android.com/apk/res/android" android:fromYDelta="0%" android:toYDelta="-100%"/>view_bsnackbar_layout.xml
<view xmlns:android="http://schemas.android.com/apk/res/android" class="com.example.administrator.newtrainingclothes.view.mySnackbar.TSnackbar$SnackbarLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="@dimen/top" android:layout_gravity="bottom" android:theme="@style/ThemeOverlay.AppCompat.Dark" style="@style/Widget.Design.Snackbar" />
view_tsnackbar_layout.xml
<view xmlns:android="http://schemas.android.com/apk/res/android" class="com.example.administrator.newtrainingclothes.view.mySnackbar.TSnackbar$SnackbarLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top" android:theme="@style/ThemeOverlay.AppCompat.Dark" style="@style/mySnackbar" />view_tsnackbar_layout_include.xml
<merge xmlns:android="http://schemas.android.com/apk/res/android"> <TextView android:id="@+id/snackbar_text" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:layout_marginLeft="@dimen/dp82" android:textAppearance="@style/TextAppearance.Design.Snackbar.Message" android:maxLines="@integer/design_snackbar_text_max_lines" android:drawablePadding="10dp" android:gravity="center" android:padding="@dimen/top" android:layout_gravity="center_vertical|left|start" android:textColor="@android:color/white" android:textSize="@dimen/dp10" android:ellipsize="end"/> <Button android:id="@+id/snackbar_action" android:layout_width="@dimen/dp82" android:layout_height="match_parent" android:layout_marginLeft="@dimen/dp16" android:layout_marginStart="@dimen/design_snackbar_extra_spacing_horizontal" android:layout_gravity="center_vertical|right|end" android:padding="@dimen/top" android:visibility="gone" android:textSize="@dimen/dp10" android:textColor="@android:color/holo_red_light" android:textAppearance="@style/TextAppearance.Design.Snackbar.Message" style="?attr/borderlessButtonStyle"/> <!--android:textColor="?attr/colorPrimaryDark"--> </merge>attrs.xml
<declare-styleable name="LoopView"> <attr name="loopTextSize" format="integer" /> </declare-styleable>
<color name="prompt_success">#31c27c</color> <color name="prompt_error">#ff0000</color> <color name="prompt_warning">#f0633d</color>
<style name="mySnackbar" parent="android:Widget"> <item name="android:minWidth">-1px</item> <item name="android:maxWidth">-1px</item> <item name="android:background">@drawable/design_snackbar_background</item> <item name="android:paddingLeft">@dimen/dp12</item> <item name="android:paddingRight">@dimen/dp12</item> <item name="elevation">@dimen/dp5</item> <item name="maxActionInlineWidth">-1px</item> </style>
<com.example.administrator.newtrainingclothes.view.loopview.LoopView android:id="@+id/fen" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_centerInParent="true"/>
fenLoop.setViewPadding(50, 0, 50, 0); //设置原始数据 fenLoop.setItems(listFen); //设置字体大小 fenLoop.setTextSize(35); fenLoop.setInitPosition(19);
6.圆形进度条
package com.example.administrator.newtrainingclothes.view; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.graphics.Typeface; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; import android.view.View; import android.view.WindowManager; import com.example.administrator.newtrainingclothes.R; /** * 仿iphone带进度的进度条,线程安全的View,可直接在线程中更新进度 * * @author xiaanming */ public class RoundProgressBar extends View { /** * 宽高,直径 */ private int resWidth; private int resHeight; private int resDiameter; /** * 画笔对象的引用 */ private Paint paint; /** * 圆环的颜色 */ private int roundColor; /** * 圆环进度的颜色 */ private int roundProgressColor; /** * 中间进度百分比的字符串的字体 */ private int textColor; /** * 中间进度百分比的字符串的字体 */ private float textSize; /** * 圆环的宽度 */ private float roundWidth; /** * 最大进度 */ private int max; /** * 当前进度 */ private int progress; /** * 是否显示中间的进度 */ private boolean textIsDisplayable; /** * 进度的风格,实心或者空心 */ private int style; public static final int STROKE = 0; public static final int FILL = 1; @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { resWidth = 0; resHeight = 0; int specSize = MeasureSpec.getSize(widthMeasureSpec); resWidth = specSize; specSize = MeasureSpec.getSize(heightMeasureSpec); resHeight = specSize; resDiameter = Math.min(resWidth, resHeight); setMeasuredDimension(resWidth, resHeight); } public RoundProgressBar(Context context) { this(context, null); } public RoundProgressBar(Context context, AttributeSet attrs) { this(context, attrs, 0); } public RoundProgressBar(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); paint = new Paint(); TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.RoundProgressBar); roundColor = mTypedArray.getColor(R.styleable.RoundProgressBar_roundColor, Color.RED); roundProgressColor = mTypedArray.getColor(R.styleable.RoundProgressBar_roundProgressColor, Color.GREEN); textColor = mTypedArray.getColor(R.styleable.RoundProgressBar_textColor, Color.GREEN); textSize = mTypedArray.getDimension(R.styleable.RoundProgressBar_textSize, 15); roundWidth = mTypedArray.getDimension(R.styleable.RoundProgressBar_roundWidth, 5); max = mTypedArray.getInteger(R.styleable.RoundProgressBar_max, 100); textIsDisplayable = mTypedArray.getBoolean(R.styleable.RoundProgressBar_textIsDisplayable, true); style = mTypedArray.getInt(R.styleable.RoundProgressBar_style, 0); progress = mTypedArray.getInteger(R.styleable.RoundProgressBar_progress, 0); mTypedArray.recycle(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); /** * 画最外层的大圆环 */ int centre = resDiameter / 2; //��ȡԲ�ĵ�x���� int radius = (int) (centre - roundWidth / 2); //Բ���İ뾶 paint.setColor(roundColor); //����Բ������ɫ paint.setStyle(Paint.Style.STROKE); //���ÿ��� paint.setStrokeWidth(roundWidth); //����Բ���Ŀ�� paint.setAntiAlias(true); //������� canvas.drawCircle(resWidth / 2, resHeight / 2, radius, paint); //����Բ�� Log.e("log", centre + ""); /** * 画进度百分比 */ paint.setStrokeWidth(0); paint.setColor(textColor); paint.setTextSize(textSize); paint.setTypeface(Typeface.DEFAULT_BOLD); //�������� int percent = (int) (((float) progress / (float) max) * 100); //�м�Ľ��Ȱٷֱȣ���ת����float�ڽ��г������㣬��Ȼ��Ϊ0 float textWidth = paint.measureText(percent + "%"); //���������ȣ�������Ҫ��������Ŀ��������Բ���м� if (textIsDisplayable && percent != 0 && style == STROKE) { canvas.drawText(percent + "%", centre - textWidth / 2, centre + textSize / 2, paint); //�������Ȱٷֱ� } /** * 画圆弧 ,画圆环的进度 */ //设置进度是实心还是空心 �� paint.setStrokeWidth(roundWidth);//设置圆环的宽度 � paint.setColor(roundProgressColor); //设置进度的颜色 RectF oval = new RectF(resWidth/2 - radius, resHeight/2 - radius, resWidth/2 + radius, resHeight/2 + radius); //用于定义的圆弧的形状和大小的界限 switch (style) { case STROKE: { paint.setStyle(Paint.Style.STROKE); canvas.drawArc(oval, 0, 360 * progress / max, false, paint); //���ݽ��Ȼ�Բ�� break; } case FILL: { paint.setStyle(Paint.Style.FILL_AND_STROKE); if (progress != 0) canvas.drawArc(oval, 0, 360 * progress / max, true, paint); //���ݽ��Ȼ�Բ�� break; } } } public synchronized int getMax() { return max; } /** * 设置进度的最大值 * * @param max */ public synchronized void setMax(int max) { if (max < 0) { throw new IllegalArgumentException("max not less than 0"); } this.max = max; } /** * 获取进度.需要同步 * * @return */ public synchronized int getProgress() { return progress; } /** * 设置进度,此为线程安全控件,由于考虑多线的问题,需要同步 * 刷新界面调用postInvalidate()能在非UI线程刷新 * * @param progress */ public synchronized void setProgress(int progress) { if (progress < 0) { throw new IllegalArgumentException("progress not less than 0"); } if (progress > max) { progress = max; } if (progress <= max) { this.progress = progress; postInvalidate(); } } private int getDefaultWidth() { WindowManager wm = (WindowManager) getContext().getSystemService( Context.WINDOW_SERVICE); DisplayMetrics outMetrics = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(outMetrics); return Math.min(outMetrics.widthPixels, outMetrics.heightPixels); } public int getCricleColor() { return roundColor; } public void setCricleColor(int cricleColor) { this.roundColor = cricleColor; } public int getCricleProgressColor() { return roundProgressColor; } public void setCricleProgressColor(int cricleProgressColor) { this.roundProgressColor = cricleProgressColor; } public int getTextColor() { return textColor; } public void setTextColor(int textColor) { this.textColor = textColor; } public float getTextSize() { return textSize; } public void setTextSize(float textSize) { this.textSize = textSize; } public float getRoundWidth() { return roundWidth; } public void setRoundWidth(float roundWidth) { this.roundWidth = roundWidth; } }artt
<declare-styleable name="RoundProgressBar"> <attr name="roundColor" format="color"/> <attr name="roundProgressColor" format="color"/> <attr name="roundWidth" format="dimension"></attr> <attr name="textColor" format="color" /> <attr name="textSize" format="dimension" /> <attr name="max" format="integer"></attr> <attr name="progress" format="integer"></attr> <attr name="textIsDisplayable" format="boolean"></attr> <attr name="style"> <enum name="STROKE" value="0"></enum> <enum name="FILL" value="1"></enum> </attr> </declare-styleable>
<com.example.administrator.newtrainingclothes.view.RoundProgressBar android:id="@+id/time_pro" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_centerInParent="true" android:layout_margin="@dimen/dp15" app:max="100" app:progress="26" app:roundColor="#78819f" app:roundProgressColor="#02fcfe" app:roundWidth="8dp" app:style="STROKE" app:textIsDisplayable="false" />