SnackbarUtils:一行代码搞定Snackbar
此文章是我在简书的文章
http://www.jianshu.com/p/f4ba05d7bbda
Snackbar在Android中的使用日益广泛,很大程度上替代了传统的Toast,相比Toast拥有更好的使用体验.
但在我们的APP中,很多时候用到Snackbar,都需要对Snackbar的样式及显示效果进行一些定制以满足不同的使用场景,比如设置文字颜色,背景颜色,自定义显示时间,设置Snackbar显示的具体位置,设置文字的对齐方式,甚至是向Snackbar布局中添加View等,为了实现这些需求,将一些方法整理出来,应该可以节约开发者部分的时间.
标题中的说的'一行代码'在某些使用场景下有些夸大其词,实际意思是指SnackbarUtils中的方法支持链式调用,可以快捷的为Snackbar设置多种效果!
源码及所在DEMO已上传至GITHUB:SnackbarUtils
https://github.com/HuanHaiLiuXin/SnackbarUtils
欢迎大家提Bug,或者有关于Snackbar新的使用场景也可以交流,我会继续把这个工具类继续完善!
**废话不多说,直接上效果图:**

**已经实现的功能点:**
1:设置Snackbar显示时间长短
2:设置Snackbar背景颜色
3:设置TextView(@+id/snackbar_text)的文字颜色
4:设置Button(@+id/snackbar_action)的文字颜色
5:设置Snackbar背景的透明度
6:设置Snackbar显示的位置
7:设置Button(@+id/snackbar_action)文字内容 及 点击监听
8:设置Snackbar展示完成 及 隐藏完成 的监听
9:设置TextView(@+id/snackbar_text)左右两侧的图片
10:设置TextView(@+id/snackbar_text)中文字的对齐方式
11:向Snackbar布局中添加View(Google不建议,复杂的布局应该使用DialogFragment进行展示)
12:设置Snackbar布局的外边距
13:设置Snackbar布局的圆角半径值
14:设置Snackbar布局的圆角半径值及边框颜色及边框宽度
15:设置Snackbar显示在指定View的上方
16:设置Snackbar显示在指定View的下方
**SnackbarUtils代码:**
public class SnackbarUtils {
//设置Snackbar背景颜色
private static final int color_info = 0XFF2094F3;
private static final int color_confirm = 0XFF4CB04E;
private static final int color_warning = 0XFFFEC005;
private static final int color_danger = 0XFFF44336;
//工具类当前持有的Snackbar实例
private static WeakReference<Snackbar> snackbarWeakReference;
private SnackbarUtils(){
throw new RuntimeException("禁止无参创建实例");
}
public SnackbarUtils(@Nullable WeakReference<Snackbar> snackbarWeakReference){
this.snackbarWeakReference = snackbarWeakReference;
}
/**
* 获取 mSnackbar
* @return
*/
public Snackbar getSnackbar() {
if(this.snackbarWeakReference != null && this.snackbarWeakReference.get()!=null){
return this.snackbarWeakReference.get();
}else {
return null;
}
}
/**
* 初始化Snackbar实例
* 展示时间:Snackbar.LENGTH_SHORT
* @param view
* @param message
* @return
*/
public static SnackbarUtils Short(View view, String message){
return new SnackbarUtils(new WeakReference<Snackbar>(Snackbar.make(view,message,Snackbar.LENGTH_SHORT))).backColor(0XFF323232);
}
/**
* 初始化Snackbar实例
* 展示时间:Snackbar.LENGTH_LONG
* @param view
* @param message
* @return
*/
public static SnackbarUtils Long(View view, String message){
return new SnackbarUtils(new WeakReference<Snackbar>(Snackbar.make(view,message,Snackbar.LENGTH_LONG))).backColor(0XFF323232);
}
/**
* 初始化Snackbar实例
* 展示时间:Snackbar.LENGTH_INDEFINITE
* @param view
* @param message
* @return
*/
public static SnackbarUtils Indefinite(View view, String message){
return new SnackbarUtils(new WeakReference<Snackbar>(Snackbar.make(view,message,Snackbar.LENGTH_INDEFINITE))).backColor(0XFF323232);
}
/**
* 初始化Snackbar实例
* 展示时间:duration 毫秒
* @param view
* @param message
* @param duration 展示时长(毫秒)
* @return
*/
public static SnackbarUtils Custom(View view, String message, int duration){
return new SnackbarUtils(new WeakReference<Snackbar>(Snackbar.make(view,message,Snackbar.LENGTH_SHORT).setDuration(duration))).backColor(0XFF323232);
}
/**
* 设置mSnackbar背景色为 color_info
*/
public SnackbarUtils info(){
Snackbar snackbar = getSnackbar();
if(snackbar!=null){
snackbar.getView().setBackgroundColor(color_info);
}
return new SnackbarUtils(snackbarWeakReference);
}
/**
* 设置mSnackbar背景色为 color_confirm
*/
public SnackbarUtils confirm(){
Snackbar snackbar = getSnackbar();
if(snackbar!=null){
snackbar.getView().setBackgroundColor(color_confirm);
}
return new SnackbarUtils(snackbarWeakReference);
}
/**
* 设置Snackbar背景色为 color_warning
*/
public SnackbarUtils warning(){
Snackbar snackbar = getSnackbar();
if(snackbar!=null){
snackbar.getView().setBackgroundColor(color_warning);
}
return new SnackbarUtils(snackbarWeakReference);
}
/**
* 设置Snackbar背景色为 color_warning
*/
public SnackbarUtils danger(){
Snackbar snackbar = getSnackbar();
if(snackbar!=null){
snackbar.getView().setBackgroundColor(color_danger);
}
return new SnackbarUtils(snackbarWeakReference);
}
/**
* 设置Snackbar背景色
* @param backgroundColor
*/
public SnackbarUtils backColor(@ColorInt int backgroundColor){
Snackbar snackbar = getSnackbar();
if(snackbar!=null){
snackbar.getView().setBackgroundColor(backgroundColor);
}
return new SnackbarUtils(snackbarWeakReference);
}
/**
* 设置TextView(@+id/snackbar_text)的文字颜色
* @param messageColor
*/
public SnackbarUtils messageColor(@ColorInt int messageColor){
Snackbar snackbar = getSnackbar();
if(snackbar!=null){
((TextView)snackbar.getView().findViewById(R.id.snackbar_text)).setTextColor(messageColor);
}
return new SnackbarUtils(snackbarWeakReference);
}
/**
* 设置Button(@+id/snackbar_action)的文字颜色
* @param actionTextColor
*/
public SnackbarUtils actionColor(@ColorInt int actionTextColor){
Snackbar snackbar = getSnackbar();
if(snackbar!=null){
((Button)snackbar.getView().findViewById(R.id.snackbar_action)).setTextColor(actionTextColor);
}
return new SnackbarUtils(snackbarWeakReference);
}
/**
* 设置 Snackbar背景色 + TextView(@+id/snackbar_text)的文字颜色 + Button(@+id/snackbar_action)的文字颜色
* @param backgroundColor
* @param messageColor
* @param actionTextColor
*/
public SnackbarUtils colors(@ColorInt int backgroundColor, @ColorInt int messageColor, @ColorInt int actionTextColor){
Snackbar snackbar = getSnackbar();
if(snackbar!=null){
snackbar.getView().setBackgroundColor(backgroundColor);
((TextView)snackbar.getView().findViewById(R.id.snackbar_text)).setTextColor(messageColor);
((Button)snackbar.getView().findViewById(R.id.snackbar_action)).setTextColor(actionTextColor);
}
return new SnackbarUtils(snackbarWeakReference);
}
/**
* 设置Snackbar 背景透明度
* @param alpha
* @return
*/
public SnackbarUtils alpha(float alpha){
Snackbar snackbar = getSnackbar();
if(snackbar!=null){
alpha = alpha>=1.0f?1.0f:(alpha<=0.0f?0.0f:alpha);
snackbar.getView().setAlpha(alpha);
}
return new SnackbarUtils(snackbarWeakReference);
}
/**
* 设置Snackbar显示的位置
* @param gravity
*/
public SnackbarUtils gravityFrameLayout(int gravity){
Snackbar snackbar = getSnackbar();
if(snackbar!=null){
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(snackbarWeakReference.get().getView().getLayoutParams().width,snackbarWeakReference.get().getView().getLayoutParams().height);
params.gravity = gravity;
snackbar.getView().setLayoutParams(params);
}
return new SnackbarUtils(snackbarWeakReference);
}
/**
* 设置Snackbar显示的位置,当Snackbar和CoordinatorLayout组合使用的时候
* @param gravity
*/
public SnackbarUtils gravityCoordinatorLayout(int gravity){
Snackbar snackbar = getSnackbar();
if(snackbar!=null){
CoordinatorLayout.LayoutParams params = new CoordinatorLayout.LayoutParams(snackbarWeakReference.get().getView().getLayoutParams().width,snackbarWeakReference.get().getView().getLayoutParams().height);
params.gravity = gravity;
snackbar.getView().setLayoutParams(params);
}
return new SnackbarUtils(snackbarWeakReference);
}
/**
* 设置按钮文字内容 及 点击监听
* {@link Snackbar#setAction(CharSequence, View.OnClickListener)}
* @param resId
* @param listener
* @return
*/
public SnackbarUtils setAction(@StringRes int resId, View.OnClickListener listener){
Snackbar snackbar = getSnackbar();
if(snackbar!=null){
return setAction(snackbar.getView().getResources().getText(resId), listener);
}else {
return new SnackbarUtils(snackbarWeakReference);
}
}
/**
* 设置按钮文字内容 及 点击监听
* {@link Snackbar#setAction(CharSequence, View.OnClickListener)}
* @param text
* @param listener
* @return
*/
public SnackbarUtils setAction(CharSequence text, View.OnClickListener listener){
Snackbar snackbar = getSnackbar();
if(snackbar!=null){
snackbar.setAction(text,listener);
}
return new SnackbarUtils(snackbarWeakReference);
}
/**
* 设置 mSnackbar 展示完成 及 隐藏完成 的监听
* @param setCallback
* @return
*/
public SnackbarUtils setCallback(Snackbar.Callback setCallback){
Snackbar snackbar = getSnackbar();
if(snackbar!=null){
snackbar.setCallback(setCallback);
}
return new SnackbarUtils(snackbarWeakReference);
}
/**
* 设置TextView(@+id/snackbar_text)左右两侧的图片
* @param leftDrawable
* @param rightDrawable
* @return
*/
public SnackbarUtils leftAndRightDrawable(@Nullable @DrawableRes Integer leftDrawable, @Nullable @DrawableRes Integer rightDrawable){
Snackbar snackbar = getSnackbar();
if(snackbar!=null){
Drawable drawableLeft = null;
Drawable drawableRight = null;
if(leftDrawable!=null){
try {
drawableLeft = snackbar.getView().getResources().getDrawable(leftDrawable.intValue());
}catch (Exception e){
}
}
if(rightDrawable!=null){
try {
drawableRight = snackbar.getView().getResources().getDrawable(rightDrawable.intValue());
}catch (Exception e){
}
}
return leftAndRightDrawable(drawableLeft,drawableRight);
}else {
return new SnackbarUtils(snackbarWeakReference);
}
}
/**
* 设置TextView(@+id/snackbar_text)左右两侧的图片
* @param leftDrawable
* @param rightDrawable
* @return
*/
public SnackbarUtils leftAndRightDrawable(@Nullable Drawable leftDrawable, @Nullable Drawable rightDrawable){
Snackbar snackbar = getSnackbar();
if(snackbar!=null){
TextView message = (TextView) snackbar.getView().findViewById(R.id.snackbar_text);
LinearLayout.LayoutParams paramsMessage = (LinearLayout.LayoutParams) message.getLayoutParams();
paramsMessage = new LinearLayout.LayoutParams(paramsMessage.width, paramsMessage.height,0.0f);
message.setLayoutParams(paramsMessage);
message.setCompoundDrawablePadding(message.getPaddingLeft());
int textSize = (int) message.getTextSize();
Log.e("Jet","textSize:"+textSize);
if(leftDrawable!=null){
leftDrawable.setBounds(0,0,textSize,textSize);
}
if(rightDrawable!=null){
rightDrawable.setBounds(0,0,textSize,textSize);
}
message.setCompoundDrawables(leftDrawable,null,rightDrawable,null);
LinearLayout.LayoutParams paramsSpace = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT,1.0f);
((Snackbar.SnackbarLayout)snackbar.getView()).addView(new Space(snackbar.getView().getContext()),1,paramsSpace);
}
return new SnackbarUtils(snackbarWeakReference);
}
/**
* 设置TextView(@+id/snackbar_text)中文字的对齐方式 居中
* @return
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public SnackbarUtils messageCenter(){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1){
Snackbar snackbar = getSnackbar();
if(snackbar!=null){
TextView message = (TextView) snackbar.getView().findViewById(R.id.snackbar_text);
//View.setTextAlignment需要SDK>=17
message.setTextAlignment(View.TEXT_ALIGNMENT_GRAVITY);
message.setGravity(Gravity.CENTER);
}
}
return new SnackbarUtils(snackbarWeakReference);
}
/**
* 设置TextView(@+id/snackbar_text)中文字的对齐方式 居右
* @return
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public SnackbarUtils messageRight(){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1){
Snackbar snackbar = getSnackbar();
if(snackbar!=null){
TextView message = (TextView) snackbar.getView().findViewById(R.id.snackbar_text);
//View.setTextAlignment需要SDK>=17
message.setTextAlignment(View.TEXT_ALIGNMENT_GRAVITY);
message.setGravity(Gravity.CENTER_VERTICAL|Gravity.RIGHT);
}
}
return new SnackbarUtils(snackbarWeakReference);
}
/**
* 向Snackbar布局中添加View(Google不建议,复杂的布局应该使用DialogFragment进行展示)
* @param layoutId 要添加的View的布局文件ID
* @param index
* @return
*/
public SnackbarUtils addView(int layoutId, int index) {
Snackbar snackbar = getSnackbar();
if(snackbar!=null){
//加载布局文件新建View
View addView = LayoutInflater.from(snackbar.getView().getContext()).inflate(layoutId,null);
return addView(addView,index);
}else {
return new SnackbarUtils(snackbarWeakReference);
}
}
/**
* 向Snackbar布局中添加View(Google不建议,复杂的布局应该使用DialogFragment进行展示)
* @param addView
* @param index
* @return
*/
public SnackbarUtils addView(View addView, int index) {
Snackbar snackbar = getSnackbar();
if(snackbar!=null){
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);//设置新建布局参数
//设置新建View在Snackbar内垂直居中显示
params.gravity= Gravity.CENTER_VERTICAL;
addView.setLayoutParams(params);
((Snackbar.SnackbarLayout)snackbar.getView()).addView(addView,index);
}
return new SnackbarUtils(snackbarWeakReference);
}
/**
* 设置Snackbar布局的外边距
* 注:经试验发现,调用margins后再调用 gravityFrameLayout,则margins无效.
* 为保证margins有效,应该先调用 gravityFrameLayout,在 show() 之前调用 margins
* @param margin
* @return
*/
public SnackbarUtils margins(int margin){
Snackbar snackbar = getSnackbar();
if(snackbar!=null){
return margins(margin,margin,margin,margin);
}else {
return new SnackbarUtils(snackbarWeakReference);
}
}
/**
* 设置Snackbar布局的外边距
* 注:经试验发现,调用margins后再调用 gravityFrameLayout,则margins无效.
* 为保证margins有效,应该先调用 gravityFrameLayout,在 show() 之前调用 margins
* @param left
* @param top
* @param right
* @param bottom
* @return
*/
public SnackbarUtils margins(int left, int top, int right, int bottom){
Snackbar snackbar = getSnackbar();
if(snackbar!=null){
ViewGroup.LayoutParams params = snackbar.getView().getLayoutParams();
((ViewGroup.MarginLayoutParams) params).setMargins(left,top,right,bottom);
snackbar.getView().setLayoutParams(params);
}
return new SnackbarUtils(snackbarWeakReference);
}
/**
* 经试验发现:
* 执行过{@link SnackbarUtils#backColor(int)}后:background instanceof ColorDrawable
* 未执行过{@link SnackbarUtils#backColor(int)}:background instanceof GradientDrawable
* @return
*/
/*
public SnackbarUtils radius(){
Drawable background = snackbarWeakReference.get().getView().getBackground();
if(background instanceof GradientDrawable){
Log.e("Jet","radius():GradientDrawable");
}
if(background instanceof ColorDrawable){
Log.e("Jet","radius():ColorDrawable");
}
if(background instanceof StateListDrawable){
Log.e("Jet","radius():StateListDrawable");
}
Log.e("Jet","radius()background:"+background.getClass().getSimpleName());
return new SnackbarUtils(mSnackbar);
}
*/
/**
* 通过SnackBar现在的背景,获取其设置圆角值时候所需的GradientDrawable实例
* @param backgroundOri
* @return
*/
private GradientDrawable getRadiusDrawable(Drawable backgroundOri){
GradientDrawable background = null;
if(backgroundOri instanceof GradientDrawable){
background = (GradientDrawable) backgroundOri;
}else if(backgroundOri instanceof ColorDrawable){
int backgroundColor = ((ColorDrawable)backgroundOri).getColor();
background = new GradientDrawable();
background.setColor(backgroundColor);
}else {
}
return background;
}
/**
* 设置Snackbar布局的圆角半径值
* @param radius 圆角半径
* @return
*/
public SnackbarUtils radius(float radius){
Snackbar snackbar = getSnackbar();
if(snackbar!=null){
//将要设置给mSnackbar的背景
GradientDrawable background = getRadiusDrawable(snackbar.getView().getBackground());
if(background != null){
radius = radius<=0?12:radius;
background.setCornerRadius(radius);
snackbar.getView().setBackgroundDrawable(background);
}
}
return new SnackbarUtils(snackbarWeakReference);
}
/**
* 设置Snackbar布局的圆角半径值及边框颜色及边框宽度
* @param radius
* @param strokeWidth
* @param strokeColor
* @return
*/
public SnackbarUtils radius(int radius, int strokeWidth, @ColorInt int strokeColor){
Snackbar snackbar = getSnackbar();
if(snackbar!=null){
//将要设置给mSnackbar的背景
GradientDrawable background = getRadiusDrawable(snackbar.getView().getBackground());
if(background != null){
radius = radius<=0?12:radius;
strokeWidth = strokeWidth<=0?1:(strokeWidth>=snackbar.getView().findViewById(R.id.snackbar_text).getPaddingTop()?2:strokeWidth);
background.setCornerRadius(radius);
background.setStroke(strokeWidth,strokeColor);
snackbar.getView().setBackgroundDrawable(background);
}
}
return new SnackbarUtils(snackbarWeakReference);
}
/**
* 计算单行的Snackbar的高度值(单位 pix)
* @return
*/
private int calculateSnackBarHeight(){
int SnackbarHeight = ScreenUtil.dp2px(snackbarWeakReference.get().getView().getContext(),28) + ScreenUtil.sp2px(snackbarWeakReference.get().getView().getContext(),14);
Log.e("Jet","直接获取MessageView高度:"+snackbarWeakReference.get().getView().findViewById(R.id.snackbar_text).getHeight());
return SnackbarHeight;
}
/**
* 设置Snackbar显示在指定View的上方
* 注:暂时仅支持单行的Snackbar,因为{@link SnackbarUtils#calculateSnackBarHeight()}暂时仅支持单行Snackbar的高度计算
* @param targetView 指定View
* @param contentViewTop Activity中的View布局区域 距离屏幕顶端的距离
* @param marginLeft 左边距
* @param marginRight 右边距
* @return
*/
public SnackbarUtils above(View targetView, int contentViewTop, int marginLeft, int marginRight){
Snackbar snackbar = getSnackbar();
if(snackbar!=null){
marginLeft = marginLeft<=0?0:marginLeft;
marginRight = marginRight<=0?0:marginRight;
int[] locations = new int[2];
targetView.getLocationOnScreen(locations);
Log.e("Jet","距离屏幕左侧:"+locations[0]+"==距离屏幕顶部:"+locations[1]);
int snackbarHeight = calculateSnackBarHeight();
Log.e("Jet","Snackbar高度:"+snackbarHeight);
//必须保证指定View的顶部可见 且 单行Snackbar可以完整的展示
if(locations[1] >= contentViewTop+snackbarHeight){
gravityFrameLayout(Gravity.BOTTOM);
ViewGroup.LayoutParams params = snackbar.getView().getLayoutParams();
((ViewGroup.MarginLayoutParams) params).setMargins(marginLeft,0,marginRight,snackbar.getView().getResources().getDisplayMetrics().heightPixels-locations[1]);
snackbar.getView().setLayoutParams(params);
}
}
return new SnackbarUtils(snackbarWeakReference);
}
/**
* 设置Snackbar显示在指定View的下方
* 注:暂时仅支持单行的Snackbar,因为{@link SnackbarUtils#calculateSnackBarHeight()}暂时仅支持单行Snackbar的高度计算
* @param targetView 指定View
* @param contentViewTop Activity中的View布局区域 距离屏幕顶端的距离
* @param marginLeft 左边距
* @param marginRight 右边距
* @return
*/
public SnackbarUtils bellow(View targetView, int contentViewTop, int marginLeft, int marginRight){
Snackbar snackbar = getSnackbar();
if(snackbar!=null){
marginLeft = marginLeft<=0?0:marginLeft;
marginRight = marginRight<=0?0:marginRight;
int[] locations = new int[2];
targetView.getLocationOnScreen(locations);
int snackbarHeight = calculateSnackBarHeight();
int screenHeight = ScreenUtil.getScreenHeight(snackbar.getView().getContext());
//必须保证指定View的底部可见 且 单行Snackbar可以完整的展示
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
//为什么要'+2'? 因为在Android L(Build.VERSION_CODES.LOLLIPOP)以上,例如Button会有一定的'阴影(shadow)',阴影的大小由'高度(elevation)'决定.
//为了在Android L以上的系统中展示的Snackbar不要覆盖targetView的阴影部分太大比例,所以人为减小2px的layout_marginBottom属性.
if(locations[1]+targetView.getHeight()>=contentViewTop&&locations[1]+targetView.getHeight()+snackbarHeight+2<=screenHeight){
gravityFrameLayout(Gravity.BOTTOM);
ViewGroup.LayoutParams params = snackbar.getView().getLayoutParams();
((ViewGroup.MarginLayoutParams) params).setMargins(marginLeft,0,marginRight,screenHeight - (locations[1]+targetView.getHeight()+snackbarHeight+2));
snackbar.getView().setLayoutParams(params);
}
}else {
if(locations[1]+targetView.getHeight()>=contentViewTop&&locations[1]+targetView.getHeight()+snackbarHeight<=screenHeight){
gravityFrameLayout(Gravity.BOTTOM);
ViewGroup.LayoutParams params = snackbar.getView().getLayoutParams();
((ViewGroup.MarginLayoutParams) params).setMargins(marginLeft,0,marginRight,screenHeight - (locations[1]+targetView.getHeight()+snackbarHeight));
snackbar.getView().setLayoutParams(params);
}
}
}
return new SnackbarUtils(snackbarWeakReference);
}
/**
* 显示 mSnackbar
*/
public void show(){
if(getSnackbar()!=null){
snackbarWeakReference.get().show();
}else {
}
}
}
DEMO中还包括另一个工具类ScreenUtil,及测试Activity文件,详情可查看GITHUB:SnackbarUtils
https://github.com/HuanHaiLiuXin/SnackbarUtils
欢迎大家提Bug,谨慎轻拍哈!
That's all !
SnackbarUtils:一行代码搞定Snackbar的更多相关文章
- 一行代码搞定Adapter
15年Google I/O大会发不了三个重要支持库 >Material design (Android Support Design) >百分比布局:Percent support lib ...
- Asp.Net Core 轻松学-一行代码搞定文件上传 JSONHelper
Asp.Net Core 轻松学-一行代码搞定文件上传 前言 在 Web 应用程序开发过程中,总是无法避免涉及到文件上传,这次我们来聊一聊怎么去实现一个简单方便可复用文件上传功能:通过创建 ...
- 一行代码搞定 FTP 服务
环境搭建: python windows/linux pip install pyftpdlib (安装失败请到这里下载:https://pypi.python.org/pypi/pyftpdlib/ ...
- 一行代码搞定所有屏幕适配AbViewUtil
适配原理:抛弃google提供的dip理论与多套图片与布局方案,采用与UI设计师通用的px作为标准单位,原理是将UI设计师的设计图与当前查看的手机或其他设备的屏幕像素尺寸进行换算,得到缩放比例,在Ac ...
- 开源作品ThinkJDBC—一行代码搞定数据库操作
1 简介 ThinkJD,又名ThinkJDBC,一个简洁而强大的开源JDBC操作库.你可以使用Java像ThinkPHP框架的M方法一样,一行代码搞定数据库操作.ThinkJD会自动管理数据库连接, ...
- 【springboot+easypoi】一行代码搞定excel导入导出
原文:https://www.jianshu.com/p/5d67fb720ece 开发中经常会遇到excel的处理,导入导出解析等等,java中比较流行的用poi,但是每次都要写大段工具类来搞定这事 ...
- easypoi 一行代码搞定excel导入导出
开发中经常会遇到excel的处理,导入导出解析等等,java中比较流行的用poi,但是每次都要写大段工具类来搞定这事儿,此处推荐一个别人造好的轮子[easypoi],下面介绍下“轮子”的使用. pom ...
- 一行代码搞定WordPress面包屑导航breadcrumb
有好几位网友在问WordPress面包屑导航breadcrumb怎么操作,网上有些教程是去function文件中定义,其实不用那么复杂,很简单一行代码就能搞定.下面随ytkah一起来看看.如果是单页, ...
- 初识sa-token,一行代码搞定登录授权!
前言 在java的世界里,有很多优秀的权限认证框架,如Apache Shiro.Spring Security 等等.这些框架背景强大,历史悠久,其生态也比较齐全. 但同时这些框架也并非十分完美,在前 ...
随机推荐
- WCF小实例以及三种宿主
WCF小实例以及三种宿主 最近一直在学习WCF相关知识,下面将通过一个小实例对所学的知识进行简单的回顾:本实例是一个简单三层操作数据库,并且也简单实现的三种宿主(控制台宿主,IIS宿主以及Window ...
- 权限系统设计实现MVC4 + WebAPI + EasyUI + Knouckout
权限系统设计实现MVC4 + WebAPI + EasyUI + Knouckout (一) 一.前言 之前的博客一直都还没写到框架的实现及权限系统,今天开始写我的权限系统,我以前做过的项目基本上都有 ...
- 一步一步深入spring(2)-三种方式来实例化bean
在一步一步深入spring(1)--搭建和测试spring的开发环境中提到了一种实例化bean的方式,也是最基本的使用构造器实例化bean 1.使用构造器实例化bean:这是最简单的方式,Spring ...
- python schedule processor
run some tasks which could look like CRON within linux/UNIX in python. Here's a demo which run on ub ...
- Bottle GET method. Request
python bottle framework #!/usr/bin/python # -*- coding utf-8 -*- from bottle import route, run, debu ...
- CF 192 DIV.2
总结一下这场比赛,就是我太SB了.说多了都是泪. A,大水题. B,根据题意,可以肯定有一个城市是可以与所有城市相连的,直接找到该点然后输出该点与其他所有点相连即可. int x[111111] , ...
- 下载编译Chrome详细步骤
文章来源:http://blog.csdn.net/allendale/article/details/9262833 参考:http://dev.chromium.org/developers/ho ...
- Dom4j下载及使用Dom4j读写XML简介
sitinspring(如坐春风)原创,转载请注明作者及出处. 要使用dom4j读写XML文档,需要先下载dom4j包,dom4j官方网站在 http://www.dom4j.org/目前最新dom4 ...
- 使用MFC CImage类绘制PNG图片时遇到的问题
为了测试CImage绘制PNG图片的效果,我们用截图软件截得一张360的界面,然后使用PhotoShop等工具在图片的周边加上了透明的区域,然后保存成PNG图片文件.CImage首先从文件中加载,即 ...
- 深刻理解HDFS工作机制
深入理解一个技术的工作机制是灵活运用和快速解决问题的根本方法,也是唯一途径.对于HDFS来说除了要明白它的应用场景和用法以及通用分布式架构之外更重要的是理解关键步骤的原理和实现细节.在看这篇博文之前需 ...