需要多个类的帮助,有需要的直接下载代码

记住需要先导入依赖包:compile ‘com.android.support:design:23.0.0’


主要代码的帮助类

  • 帮助类1

import java.lang.ref.WeakReference;/*** Snackbar的管理者*/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() {@Overridepublic 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)) {// 味着回调已经在队列中mCurrentSnackbar.duration = duration;// If this is the Snackbar currently being shown, call re-schedule it's// timeoutmHandler.removeCallbacksAndMessages(mCurrentSnackbar);scheduleTimeoutLocked(mCurrentSnackbar);return;} else if (isNextSnackbarLocked(callback)) {// We'll just update the durationmNextSnackbar.duration = duration;} else {// Else, we need to create a new record and queue itmNextSnackbar = 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 linereturn;} else {// Clear out the current snackbarmCurrentSnackbar = null;// Otherwise, just show it nowshowNextSnackbarLocked();}}}public void dismiss(Callback callback, int event) {synchronized (mLock) {if (isCurrentSnackbarLocked(callback)) {cancelSnackbarLocked(mCurrentSnackbar, event);} else if (isNextSnackbarLocked(callback)) {cancelSnackbarLocked(mNextSnackbar, event);}}}/*** Snackbar不再显示,退出动画完成。*/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 onemCurrentSnackbar = null;if (mNextSnackbar != null) {showNextSnackbarLocked();}}}}/*** Snackbar被显示。这是在任何入口动画完成。*/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 SnackbarmCurrentSnackbar = 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 SnackbarRecordmHandler.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) {// 如果我们不确定,我们不希望设置一个超时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);}}}
}
  • 帮助类2
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.view.View;
import android.view.ViewGroup;/*** 获得屏幕相关的辅助类*/
public class ScreenUtil {private ScreenUtil() {/* 不能被实例化 */throw new UnsupportedOperationException("cannot be instantiated");}private static int mStatusHeight = -1;/*** 获得状态栏的高度*/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;}/*** 获取当前屏幕截图,不包含状态栏*/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兼容*/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*/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();}}
}
  • 帮助类3
package snackbarutil;import com.example.administrator.snackbars.R;/*** 弹出Snackbar时,图标已经背景色的改变*/
public enum Prompt {//枚举定义的常量/*** 红色,错误*/ERROR(R.mipmap.icon_error, R.color.error),/*** 红色,警告*/WARNING(R.mipmap.icon_warning, R.color.warning),/*** 绿色,成功*/SUCCESS(R.mipmap.icon_successful, R.color.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;}
}
  • 帮助类4

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();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 {@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationEnd(Animation animation) {}@Overridepublic void onAnimationRepeat(Animation animation) {}}
}
  • 帮助类5

自定义的Snackbar


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 com.example.administrator.snackbars.R;import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;/*** TSnackbar提供轻量级的反馈对一个操作。他们显示一个简短的信息* 包含一组动作是通过{ setAction(CharSequence进行View.OnClickListener)}。* 通知Snackbar已被证明或者被辞退的,您可以提供一个{ setCallback(回调)} }*/
public final class TSnackbar {/*** 回调类的实例。setCallback(Callback)*/public static abstract class Callback {/*** 表明TSnackbar通过猛击而消失。*/public static final int DISMISS_EVENT_SWIPE = 0;/*** 表明TSnackbar通过操作点击而消失。*/public static final int DISMISS_EVENT_ACTION = 1;/*** 表明TSnackbar通过超时而消失。*/public static final int DISMISS_EVENT_TIMEOUT = 2;/*** 表明TSnackbar通过调用{ dismiss()}而消失*/public static final int DISMISS_EVENT_MANUAL = 3;/*** 表明TSnackbar被另一个Tsnackbar出现而消失*/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 {}/*** snackbar的事件导致消失。之一:* {   DISMISS_EVENT_SWIPE },{  DISMISS_EVENT_ACTION },* {  DISMISS_EVENT_TIMEOUT },{  DISMISS_EVENT_MANUAL }* {  DISMISS_EVENT_CONSECUTIVE }。*/public void onDismissed(TSnackbar TSnackbar, @DismissEvent int event) {}/*** TSnackbar是可见的.*/public void onShown(TSnackbar TSnackbar) {}}@IntDef({APPEAR_FROM_TOP_TO_DOWN, APPEAR_FROM_BOTTOM_TO_TOP})@Retention(RetentionPolicy.SOURCE)public @interface OverSnackAppearDirection {}/*** 显示TSnackbar从上到下*/public static final int APPEAR_FROM_TOP_TO_DOWN = 0;/*** 显示TSnackbar从下到上*/public static final int APPEAR_FROM_BOTTOM_TO_TOP = 1;@IntDef({LENGTH_INDEFINITE, LENGTH_SHORT, LENGTH_LONG})@Retention(RetentionPolicy.SOURCE)public @interface Duration {}/*** 显示TSnackbar消失。这意味着TSnackbar将显示的时间* 这是{ show() },直到它被解职,或另一个TSnackbar显示。** @see #setDuration*/public static final int LENGTH_INDEFINITE = -2; //无限长/*** 显示TSnackbar很短的一段时间。** @see #setDuration*/public static final int LENGTH_SHORT = -1;  //短时间/*** 显示TSnackbar很长一段时间。** @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@OverSnackAppearDirectionint appearDirection;static {sHandler = new Handler(Looper.getMainLooper(), new Handler.Callback() {@Overridepublic 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);//显示Snackbar的布局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(parent);this.appearDirection = appearDirection;if (appearDirection == APPEAR_FROM_TOP_TO_DOWN) {setMinHeight(0, 0);}}/*** 设置TSnackbar最小的高度*/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;}/*** TSnackbar显示一条消息* 这是定义为一个{ @link CoordinatorLayout }或窗口装饰的内容来看,以先到期者作准。* 有一个{ CoordinatorLayout }在视图层次结构允许TSnackbar启用某些特性,* 如swipe-to-dismiss和自动移动的小部件{ @link FloatingActionButton }。** @param视图的父控件。* @param文本显示的文本。可以格式化文本。* @param持续时间多久来显示信息。{ LENGTH_SHORT }或{ LENGTH_LONG }*/@NonNullpublic 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;}@NonNullpublic 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;}@NonNullpublic 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) {return (ViewGroup) view;} else if (view instanceof FrameLayout) {if (view.getId() == android.R.id.content) {return (ViewGroup) view;} else {fallback = (ViewGroup) view;}}if (view != null) {final ViewParent parent = view.getParent();view = parent instanceof View ? (View) parent : null;}} while (view != null);return fallback;}/*** 给TSnackbar上添加图标** @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;}/*** 显示加载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 true 表示在左边* @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() {@Overridepublic void onAnimationStart(Animator animation) {}@Overridepublic void onAnimationEnd(Animator animation) {if (mCallback != null) {mCallback.onShown(TSnackbar.this);}SnackbarManager.getInstance().onShown(mManagerCallback);}@Overridepublic void onAnimationCancel(Animator animation) {}@Overridepublic void onAnimationRepeat(Animator animation) {}});animator.start();return this;}/*** 默认风格{错误、警告成功} {ERROR , WARNING , SUCCESS}*/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;}/*** 设置TSnackbar的背景色*/public TSnackbar setBackgroundColor(int colorId) {mView.setBackgroundColor(colorId);return this;}/*** 设置TSnackbar上的动作*/@NonNullpublic TSnackbar setAction(@StringRes int resId, View.OnClickListener listener) {return setAction(mContext.getText(resId), listener);}@NonNullpublic 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() {@Overridepublic void onClick(View view) {listener.onClick(view);dispatchDismiss(Callback.DISMISS_EVENT_ACTION);}});}return this;}/*** 设置这个动作上文字的颜色*/@NonNullpublic TSnackbar setActionTextColor(ColorStateList colors) {final TextView tv = mView.getActionView();tv.setTextColor(colors);return this;}@NonNullpublic TSnackbar setActionTextColor(@ColorInt int color) {final TextView tv = mView.getActionView();tv.setTextColor(color);return this;}/*** 更改TSnackbar的文本*/@NonNullpublic TSnackbar setText(@NonNull CharSequence message) {final TextView tv = mView.getMessageView();tv.setText(message);return this;}@NonNullpublic TSnackbar setText(@StringRes int resId) {return setText(mContext.getText(resId));}/*** 设置多长时间显示的视图。*/@NonNullpublic TSnackbar setDuration(@Duration int duration) {mDuration = duration;return this;}/*** 得到时间*/@Durationpublic int getDuration() {return mDuration;}/*** 得到view*/@NonNullpublic View getView() {return mView;}/*** 显示TSnackbar*/public void show() {SnackbarManager.getInstance().show(mDuration, mManagerCallback);}/*** TSnackbar消失*/public void dismiss() {dispatchDismiss(Callback.DISMISS_EVENT_MANUAL);}private void dispatchDismiss(@Callback.DismissEvent int event) {SnackbarManager.getInstance().dismiss(mManagerCallback, event);}/*** 设置回调时TSnackbar的可见性变化。*/@NonNullpublic TSnackbar setCallback(Callback callback) {mCallback = callback;return this;}/*** 返回TSnackbar 是否目前显示。*/public boolean isShown() {return SnackbarManager.getInstance().isCurrent(mManagerCallback);}/*** 返回TSnackbar 是否 目前显示,还是排队显示*/public boolean isShownOrQueued() {return SnackbarManager.getInstance().isCurrentOrNext(mManagerCallback);}private final SnackbarManager.Callback mManagerCallback = new SnackbarManager.Callback() {@Overridepublic void show() {sHandler.sendMessage(sHandler.obtainMessage(MSG_SHOW, TSnackbar.this));}@Overridepublic 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 Behaviorfinal 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() {@Overridepublic void onDismiss(View view) {view.setVisibility(View.GONE);dispatchDismiss(Callback.DISMISS_EVENT_SWIPE);}@Overridepublic 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() {@Overridepublic void onLayoutChange(View view, int left, int top, int right, int bottom) {animateViewIn();mView.setOnLayoutChangeListener(null);}});}mView.setOnAttachStateChangeListener(new SnackbarLayout.OnAttachStateChangeListener() {@Overridepublic void onViewAttachedToWindow(View v) {}@Overridepublic 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() {@Overridepublic void run() {onViewHidden(Callback.DISMISS_EVENT_MANUAL);}});}}});if (ViewCompat.isLaidOut(mView)) {if (shouldAnimate()) {// If animations are enabled, animate it inanimateViewIn();} else {// Else if anims are disabled just call back nowonViewShown();}} else {// Otherwise, add one of our layout change listeners and show it in when laid outmView.setOnLayoutChangeListener(new SnackbarLayout.OnLayoutChangeListener() {@Overridepublic void onLayoutChange(View view, int left, int top, int right, int bottom) {mView.setOnLayoutChangeListener(null);if (shouldAnimate()) {// If animations are enabled, animate it inanimateViewIn();} else {// Else if anims are disabled just call back nowonViewShown();}}});}}/*** 动画就入*/private void animateViewIn() {Animation anim;if (appearDirection == APPEAR_FROM_TOP_TO_DOWN) {anim = getAnimationInFromTopToDown();} else {anim = getAnimationInFromBottomToTop();}anim.setInterpolator(snackbarutil.AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR);//快速插入anim.setDuration(ANIMATION_DURATION);anim.setAnimationListener(new Animation.AnimationListener() {@Overridepublic void onAnimationEnd(Animation animation) {onViewShown();}@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic 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(snackbarutil.AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR);anim.setDuration(ANIMATION_DURATION);anim.setAnimationListener(new Animation.AnimationListener() {@Overridepublic void onAnimationEnd(Animation animation) {onViewHidden(event);}@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic 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 nowonViewHidden(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 dismissedSnackbarManager.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);}}/*** 返回true,动画。*/private boolean shouldAnimate() {return !mAccessibilityManager.isEnabled();}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./*** 弹出snackbar,显示文本*/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);}@Overrideprotected 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;}@Overrideprotected 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();}}@Overrideprotected 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);}}@Overrideprotected void onAttachedToWindow() {super.onAttachedToWindow();if (mOnAttachStateChangeListener != null) {mOnAttachStateChangeListener.onViewAttachedToWindow(this);}}@Overrideprotected 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> {public boolean canSwipeDismissView(View child) {return child instanceof SnackbarLayout;}@Overridepublic 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 completeif (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);}}
}

所需要的xml文件

  • 所需要的辅助 动画,在res文件夹下新建一个 anim 的文件夹,用于存放动画文件夹
<?xml version="1.0" encoding="utf-8"?><!--从上到下-->
<translate xmlns:android="http://schemas.android.com/apk/res/android"android:fromYDelta="-100%"android:toYDelta="0%" />
<?xml version="1.0" encoding="utf-8"?><!--从下到上-->
<translate xmlns:android="http://schemas.android.com/apk/res/android"android:fromYDelta="0%"android:toYDelta="-100%"/>
  • 所需要的辅助 drawable文件
<?xml version="1.0" encoding="utf-8"?><!--旋转的加载进度条-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"><item><rotate
            android:drawable="@mipmap/kprogresshud_spinner"android:fromDegrees="0"android:pivotX="50%"android:pivotY="50%"android:toDegrees="360"/></item>
</layer-list>
  • 所需要的辅助 布局文件
view_tsnackbar_layout.xml<?xml version="1.0" encoding="utf-8"?><!--出现的顶部的Snackbar-->
<view xmlns:android="http://schemas.android.com/apk/res/android"style="@style/Widget.Design.Snackbar"class="snackbarutil.TSnackbar$SnackbarLayout"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="top"/>
view_tsnackbar_layout_include.xml<?xml version="1.0" encoding="utf-8"?>
<!--弹出的snackbar上显示的内容-->
<merge xmlns:android="http://schemas.android.com/apk/res/android"><TextView
        android:id="@+id/snackbar_text"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_vertical|left|start"android:layout_weight="1"android:drawablePadding="10dp"android:ellipsize="end"android:gravity="center_vertical"android:maxLines="@integer/design_snackbar_text_max_lines"android:paddingBottom="@dimen/design_snackbar_padding_vertical"android:paddingLeft="@dimen/design_snackbar_padding_horizontal"android:paddingRight="@dimen/design_snackbar_padding_horizontal"android:paddingTop="@dimen/design_snackbar_padding_vertical"android:text="fdfdfd"android:textAppearance="@style/TextAppearance.Design.Snackbar.Message"/><Button
        android:id="@+id/snackbar_action"style="?attr/borderlessButtonStyle"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_vertical|right|end"android:layout_marginLeft="@dimen/design_snackbar_extra_spacing_horizontal"android:layout_marginStart="@dimen/design_snackbar_extra_spacing_horizontal"android:paddingBottom="@dimen/design_snackbar_padding_vertical"android:paddingLeft="@dimen/design_snackbar_padding_horizontal"android:paddingRight="@dimen/design_snackbar_padding_horizontal"android:paddingTop="@dimen/design_snackbar_padding_vertical"android:textAppearance="@style/TextAppearance.Design.Snackbar.Message"android:visibility="gone"/>
</merge>

做完了准备工作,接下来的代码就更简单了

  • 主要的布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/rr"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/colorPrimaryDark"android:fitsSystemWindows="true"><LinearLayout        android:layout_width="match_parent"android:layout_height="match_parent"android:background="@android:color/white"android:orientation="vertical"><Button            android:id="@+id/one"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="20dp"android:text="one"android:textAllCaps="false"/><Button
            android:id="@+id/two"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="20dp"android:text="two"android:textAllCaps="false"/><Button
            android:id="@+id/three"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="20dp"android:text="three"android:textAllCaps="false"/><Button
            android:id="@+id/fore"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="20dp"android:text="fore"android:textAllCaps="false"/><Button
            android:id="@+id/five"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="20dp"android:text="five"android:textAllCaps="false"/></LinearLayout>
</RelativeLayout>
  • 主要的代码逻辑实现
package com.example.administrator.snackbars;import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.RelativeLayout;import butterknife.ButterKnife;
import butterknife.InjectView;
import butterknife.OnClick;
import snackbarutil.Prompt;
import snackbarutil.TSnackbar;/*** 自定义Snackbar的使用方式---出现在顶部*/
public class MainActivity extends Activity {@InjectView(R.id.one)Button one;@InjectView(R.id.two)Button two;@InjectView(R.id.three)Button three;@InjectView(R.id.fore)Button fore;@InjectView(R.id.five)Button five;@InjectView(R.id.rr)RelativeLayout mRr;private TSnackbar suSnackbar;//定时private Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);switch (msg.what) {case 0:if (suSnackbar != null) {suSnackbar.setPromptThemBackground(Prompt.SUCCESS).setText("登录成功").setDuration(TSnackbar.LENGTH_LONG).show();}break;case 1:if (suSnackbar != null) {suSnackbar.setPromptThemBackground(Prompt.ERROR).setText("登录失败").setDuration(TSnackbar.LENGTH_LONG).show();}break;default:break;}}};;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ButterKnife.inject(this);}@OnClick({R.id.one, R.id.two, R.id.three, R.id.fore, R.id.five})public void onClick(View view) {switch (view.getId()) {case R.id.one:suSnackbar = TSnackbar.make(mRr, "第一种展示的形式", TSnackbar.LENGTH_LONG);suSnackbar.addIcon(R.mipmap.ic_launcher);//suSnackbar上添加图标suSnackbar.setBackgroundColor(Color.RED);//设置suSnackbar背景色suSnackbar.addIconProgressLoading(0, false, true);//suSnackbar上添加图标以及图标的位置suSnackbar.show();break;case R.id.two:suSnackbar = TSnackbar.make(mRr, "第二种展示的形式", TSnackbar.LENGTH_SHORT, TSnackbar.APPEAR_FROM_TOP_TO_DOWN);suSnackbar.setAction("取消", new View.OnClickListener() {@Overridepublic void onClick(View v) {}});suSnackbar.setActionTextColor(Color.BLACK);//设置Action上文字的颜色suSnackbar.setPromptThemBackground(Prompt.SUCCESS);//设置样式suSnackbar.show();break;case R.id.three:suSnackbar = TSnackbar.make(mRr, "正在登录,请稍后...", TSnackbar.LENGTH_INDEFINITE, TSnackbar.APPEAR_FROM_TOP_TO_DOWN);suSnackbar.setAction("取消", new View.OnClickListener() {@Overridepublic void onClick(View v) {}});suSnackbar.setPromptThemBackground(Prompt.SUCCESS);suSnackbar.addIconProgressLoading(0, true, false);suSnackbar.show();mHandler.postDelayed(gotoLoginActSuccess, 5000);//5秒后执行任务break;case R.id.fore:suSnackbar = TSnackbar.make(mRr, "第四种展示的形式", TSnackbar.LENGTH_SHORT, TSnackbar.APPEAR_FROM_TOP_TO_DOWN);suSnackbar.setAction("取消", new View.OnClickListener() {@Overridepublic void onClick(View v) {}});suSnackbar.setPromptThemBackground(Prompt.SUCCESS);suSnackbar.show();break;case R.id.five:suSnackbar = TSnackbar.make(mRr, "第五种展示的形式...", TSnackbar.LENGTH_LONG, TSnackbar.APPEAR_FROM_TOP_TO_DOWN);suSnackbar.addIcon(R.mipmap.ic_launcher, 100, 100);//设置图标,以及图标的宽高suSnackbar.setAction("取消", new View.OnClickListener() {@Overridepublic void onClick(View v) {}});suSnackbar.setPromptThemBackground(Prompt.WARNING);suSnackbar.show();break;}}Runnable gotoLoginActSuccess = new Runnable() {@Overridepublic void run() {Message msg = new Message();msg.what = 1;mHandler.sendMessage(msg);}};
}

已经完成,谢谢阅读

Snackbars从顶部滑出的实现相关推荐

  1. 高仿途牛App下拉顶部滑出更多

    现在旅游的App可谓已经很多了,携程,去哪,途牛.个人三个都用过,感觉途牛的体验还是比较不错的,个人体验,仅供参考. 好了,上面的一段扯淡衬托了我今天要和大家分享的一个功能效果,在途牛App的行程玩法 ...

  2. vue封装一个 从顶部滑出的浮层小组件, 原生和react都可以仿照做出来

    先看下效果哈,相信这种效果业务中还是比较常见的, 因为吧pdf最大只能上传5M的大小,所以稍微动下就要超过了,所以录制的时候我点的很快.将就着看吧.毕竟代码才是关键 哈哈.效果就凑合着看 大部分情况下 ...

  3. css鼠标滑过图标显示_CSS和jQuery教程:苹果风格的花式图标滑出导航

    css鼠标滑过图标显示 View demo 查看演示Download Source 下载源 Today I want to show you, how to create an Apple-style ...

  4. word修订显示修订人_美丽的滑出导航修订

    word修订显示修订人 View demo 查看演示 Download Source 下载源 After I got a lot of feedback for the Beautiful Slide ...

  5. android底部滑出view,Android CoordinatorLayout与NestedScrollView基于Behavior几行代码实现底部View滑入滑出...

    Android CoordinatorLayout与NestedScrollView基于Behavior几行代码实现底部View滑入滑出 在CoordinatorLayout的Behavior出现之前 ...

  6. 如何用 Swift 编写滑出式导航面板

    原文:How to Create Your Own Slide-Out Navigation Panel in Swift 作者:Nicholas Sakaimbo 译者:kmyhy 更新说明:本教程 ...

  7. 【Android】Activity和PopupWindow都实现从底部弹出或滑出选择菜单或窗口

    使用Activity和PopupWindow都实现从底部弹出或滑出选择菜单或窗口 [Android]测试与popwindow PopupWindow转载自:Android PopupWindow实现从 ...

  8. 纯css实现网页侧边栏弹窗滑进滑出

    目录 效果图 代码 这种效果在大多数网站中都是常见的,屏幕右边有一列列表,鼠标放上去之后,列表弹窗就从右边滑出,因为常用自己写一下方便以后直接使用. 效果图 代码 <div class=&quo ...

  9. Android开发之高仿百度地图底部滑出菜单

    老套路上图: 底部菜单滑出效果如上图: 首先依赖三方库 implementation 'androidx.appcompat:appcompat:1.2.0'implementation 'com.g ...

最新文章

  1. 浅谈自然语言处理技术在自动化的应用
  2. 开启AngularJS学习之旅
  3. 全国计算机等级考试二级教程第七章,2012年全国计算机等级考试二级VB入门教程第七章(1)...
  4. 一键去除网页BOM属性【解决乱码,头部空白,#65279问题】
  5. Qt UDP的初步使用
  6. 迄今为止最快的 JSON 序列化工具 Jil
  7. c++ python混合编程 restful_简单上手nodejs调用c++(c++和js的混合编程)
  8. java逻辑判断_阿里JAVA开发强制要求的10条条件控制及逻辑判断的规范,切记
  9. Struts2标签库(三)之表单标签
  10. Ubuntu更改hosts档
  11. 21次课(安装软件包的三种方法、rpm包介绍、rpm工具用法、yum工具用法、 yum搭建本地仓库)...
  12. java学习视频 java常用23种设计模式
  13. Git可视化工具——SourceTree教程
  14. NEXTCHIP图像品牌ISP和AHD都是有哪些功能?型号有多少型号?
  15. SLT学习(一)——STL组成介绍
  16. QLabel文字过长显示不全处理方法
  17. 计算机控制作业来看,带PID控制器的最小拍系统设计
  18. HDU 1859 最小长方形
  19. C语言设计A与B的区别,C语言辅导 - abc与a=b=c的区别 and something else
  20. 帝国搜索模板不支持php,解决帝国CMS搜索模板不支持灵动标签的方法

热门文章

  1. Java反射机制实现与原理
  2. Java爬虫 爬取某招聘网站招聘信息
  3. apache、php安装
  4. 如何快速算出一个数有多少个因子(c++)
  5. 站长还应该发布外链吗?
  6. 5.cuBLAS开发指南中文版--cuBLAS中的Create()和Destroy()
  7. 三门外语 精通oracle_《精通Oracle SQL(第2版)》PDF 下载
  8. 搜图出处的软件_【识图】怎样查找图片的来源出处,又快又好
  9. js取得当前url,javascript获取当前页面url值,js获取域名
  10. .Net 常用的ORM框架