編輯:關於Android編程
安卓中為了給用戶的友好提示,一般的表現形式為Dialog、PopWindow、Toast,自從Snackbar的出現絕對是秒殺Toast了,Snackbar不僅能夠簡單實現toast的效果而且還能setAction,但是還是有很多的應用是使用了Toast的,並且安卓死丟丟也有toast的插件,可見toast還是有他存在的價值。
csdn傳圖片不能太大,馬蛋來2張好了:
Toast窗口其實和前面分析的Activity、Dialog、PopWindow都是不同的,因為它和輸入法、牆紙類似,都是系統窗口。
我們先看下Toast的靜態makeText方法吧,如下:
public static Toast makeText(Context context, CharSequence text, @Duration int duration) {
//new一個Toast對象
Toast result = new Toast(context);
//獲取前面有篇文章分析的LayoutInflater
LayoutInflater inflate = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//加載解析Toast的布局,實質transient_notification.xml是一個LinearLayout中套了一個@android:id/message的TextView而已
View v = inflate.inflate(com.android.internal.R.layout.transient_notification, null);
//取出布局中的TextView
TextView tv = (TextView)v.findViewById(com.android.internal.R.id.message);
//把我們的文字設置到TextView上
tv.setText(text);
//設置一些屬性
result.mNextView = v;
result.mDuration = duration;
//返回新建的Toast
return result;
}
可以看見,這個方法構造了一個Toast,然後把要顯示的文本放到這個View的TextView中,然後初始化相關屬性後返回這個新的Toast對象。
當我們有了這個Toast對象之後,可以通過show方法來顯示出來,如下看下show方法源碼:
public void show() {
......
//通過AIDL(Binder)通信拿到NotificationManagerService的服務訪問接口,當前Toast類相當於上面例子的客戶端!!!相當重要!!!
INotificationManager service = getService();
String pkg = mContext.getOpPackageName();
TN tn = mTN;
tn.mNextView = mNextView;
try {
//把TN對象和一些參數傳遞到遠程NotificationManagerService中去
service.enqueueToast(pkg, tn, mDuration);
} catch (RemoteException e) {
// Empty
}
}
繼續來看Toast中的show方法的service.enqueueToast(pkg, tn, mDuration);語句,service實質是遠程的NotificationManagerService,所以enqueueToast方法就是 NotificationManagerService類的,如下:
private final IBinder mService = new INotificationManager.Stub() {
@Override
public void enqueueToast(String pkg, ITransientNotification callback, int duration)
{
......
synchronized (mToastQueue) {
int callingPid = Binder.getCallingPid();
long callingId = Binder.clearCallingIdentity();
try {
ToastRecord record;
//查看該Toast是否已經在隊列當中
int index = indexOfToastLocked(pkg, callback);
// If it's already in the queue, we update it in place, we don't
// move it to the end of the queue.
//注釋說了,已經存在則直接取出update
if (index >= 0) {
record = mToastQueue.get(index);
record.update(duration);
} else {
// Limit the number of toasts that any given package except the android
// package can enqueue. Prevents DOS attacks and deals with leaks.
......
//將Toast封裝成ToastRecord對象,放入mToastQueue中
record = new ToastRecord(callingPid, pkg, callback, duration);
//把他添加到ToastQueue隊列中
mToastQueue.add(record);
index = mToastQueue.size() - 1;
//將當前Toast所在的進程設置為前台進程
keepProcessAliveLocked(callingPid);
}
//如果index為0,說明當前入隊的Toast在隊頭,需要調用showNextToastLocked方法直接顯示
if (index == 0) {
showNextToastLocked();
}
} finally {
Binder.restoreCallingIdentity(callingId);
}
}
}
}
不多看了,我們知道Toast都是加入到一個enqueueToast,然後通過handle來處理,因為是系統的窗口,所以我們換個界面然後toast還沒有完你也不要感到奇怪。
package com.losileeya.toastmaster.view;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Handler;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.TranslateAnimation;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
import android.widget.Toast;
import com.losileeya.toastmaster.R;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Date;
/**
* 超級自定義的Toast,單例模式獲取本類
*/
public class SuperCustomToast {
/**
* 獲取當前Android系統版本
*/
static int currentapiVersion = Build.VERSION.SDK_INT;
/**
* 入場動畫持續時間
*/
private static final int TIME_START_ANIM = 500;
/**
* 離場動畫持續時間
*/
private static final int TIME_END_ANIM = 500;
/**
* 每條Toast顯示持續時間
*/
private static final int TIME_DURATION = 2500;
/**
* UI線程句柄
*/
Handler mHandler;
/**
* 內容對象
*/
Context mContext;
/**
* 頂層布局
*/
LinearLayout mTopView, mTopView2;
/**
* 內容布局
*/
public LinearLayout mView;
/**
* 布局屬性
*/
LayoutParams lp_WW, lp_MM;
/**
* 屏幕寬度
*/
int screenWidth;
/**
* 屏幕高度
*/
int screenHeight;
/**
* 默認背景的resid
*/
Integer defaultBackgroundResid;
/**
* 默認背景的顏色
*/
Drawable defaultBackgroundColor;
/**
* 默認文字顏色
*/
int defaultTextColor;
private View layout;
/**
* 反射過程中是否出現異常的標志
*/
boolean hasReflectException = false;
/**
* 單例
*/
private static SuperCustomToast instance;
/**
* 獲得單例
*
* @param context
* @return
*/
public static SuperCustomToast getInstance(Context context) {
if (instance == null) {
instance = new SuperCustomToast(context);
}
return instance;
}
private SuperCustomToast(Context context) {
if (context == null || context.getApplicationContext() == null) {
throw new NullPointerException("context can't be null");
}
mContext = context.getApplicationContext();
initView();
initTN();
// 防反射獲取實例
if (instance != null)
throw new NullPointerException("error");
}
/**
* 初始化視圖控件
*/
public void initView() {
mHandler = new Handler(mContext.getMainLooper());
lp_WW = new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
lp_MM = new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
//獲取屏幕密度
DisplayMetrics mDisplayMetrics = mContext.getResources()
.getDisplayMetrics();
//獲取屏幕寬高
screenWidth = mDisplayMetrics.widthPixels;
screenHeight = mDisplayMetrics.heightPixels;
mTopView = new LinearLayout(mContext);
mTopView.setLayoutParams(lp_MM);
mTopView.setOrientation(LinearLayout.VERTICAL);
mTopView.setGravity(Gravity.CENTER);
mTopView2 = new LinearLayout(mContext);
LayoutParams params = new LayoutParams(screenWidth, screenHeight);
mTopView2.setLayoutParams(params);
mTopView2.setOrientation(LinearLayout.VERTICAL);
mTopView2.setGravity(Gravity.BOTTOM);
mView = new LinearLayout(mContext);
mView.setLayoutParams(lp_MM);
mView.setOrientation(LinearLayout.VERTICAL);
mView.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
View gapView = new View(mContext);
gapView.setLayoutParams(new LayoutParams(screenWidth, screenHeight / 4));
mView.addView(gapView);
mTopView.addView(mTopView2);
mTopView2.addView(mView);
resetDefaultBackgroundAndTextColor();
}
/**
* 顯示一條Toast
* layoutId 自定義布局
* @param msg
* 消息內容
*/
public void show(String msg, int layoutId, int rootId, Activity activity) {
LayoutInflater inflater = activity.getLayoutInflater();
layout = inflater.inflate(layoutId,
(ViewGroup) activity.findViewById(rootId));
layout.setLayoutParams(lp_WW);
TextView title = (TextView) layout.findViewById(R.id.title);
title.setText(msg);
title.setTextColor(defaultTextColor);
show(layout, null, null, null);
}
/**
* 顯示一條Toast
*
* @param msg
* 消息內容
*/
public void show(String msg) {
show(getTextView(msg), null, null, null);
}
/**
* 顯示一條Toast
*
* @param v
* 消息內容
*/
public void show(View v) {
show(v, null, null, null);
}
/**
* 顯示一條Toast
*
* @param msg
* 消息內容
* @param duration
* 持續時間,單位為毫秒
*/
public void show(String msg, long duration) {
show(getTextView(msg), duration, null, null);
}
/**
* 一個toast已經顯示,在下一個msg相同的情況下, 一定時間不顯示新的toast. 如果同樣的消息,在兩次顯示時間差
* 大於duration的情況下,才出現新的toast
*
* @param msg
* 消息內容
* @param duration
* 持續時間,單位為毫秒
*/
Long totalTime;
public void setTime(Long time) {
this.totalTime = time;
}
private boolean firstCalled = true;
String lastMsg;
long startTime;
public void showSameMsg(String msg, long duration) {
if (firstCalled) {
lastMsg = msg;
show(getTextView(msg), duration, null, null);
firstCalled = false;
// 第一次調用的時間
startTime = (new Date()).getTime();
} else if (msg.equals(lastMsg)) {
long endTime = (new Date()).getTime();
long totalTime = endTime - startTime;
Log.e("time", "開始時間:" + startTime + " 結束時間: " + endTime + " 總時間"
+ totalTime);
// 第二次相同
if (totalTime > duration) {
show(getTextView(msg), duration, null, null);
startTime = endTime;
}
}
}
/**
* 顯示一條Toast
*
* @param v
* 消息內容
* @param duration
* 持續時間,單位為毫秒
*/
public void show(View v, long duration) {
show(v, duration, null, null);
}
/**
* 顯示一條Toast
*
* @param msg
* 消息內容
* @param duration
* 持續時間,單位為毫秒
* @param startAnim
* 入場動畫
* @param endAnim
* 離場動畫
*/
public void show(String msg, Long duration, Animation startAnim,
Animation endAnim) {
show(getTextView(msg), duration, startAnim, endAnim);
}
/**
* 顯示一條圖文並存Toast
*
* @param resid
* 圖片資源
* @param msg
* 消息內容
* @param duration
* 持續時間,單位為毫秒
* @param startAnim
* 入場動畫
* @param endAnim
* 離場動畫
*/
public void show(int resid, String msg, Long duration, Animation startAnim,
Animation endAnim) {
show(getView(resid, msg), duration, null, null);
}
/**
* 顯示一條Toast
*
* @param v
* 顯示的內容
* @param duration
* 持續時間,單位為毫秒
* @param startAnim
* 入場動畫
* @param endAnim
* 離場動畫
*/
public final void show(final View v, Long duration, Animation startAnim,
final Animation endAnim) {
// 反射過程異常時則使用源生Toast
if (hasReflectException) {
Toast t = new Toast(mContext);
t.setView(v);
t.setDuration(Toast.LENGTH_SHORT);
t.show();
// 重新獲取反射對象
initTN();
return;
}
// 顯示頂層容器控件
if (mView.getChildCount() == 1)
showToast();
// 獲得入場動畫
if (startAnim == null) {
startAnim = getStartAnimation();
}
v.clearAnimation();
v.startAnimation(startAnim);
// 把傳入的toast顯示出來
mView.addView(v, 0);
// 延遲後隱藏傳入toast
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
hide(v, endAnim);
}
}, duration == null ? TIME_DURATION : duration);
}
/**
* 設置默認背景顏色
*
* @param color
* 顏色值
* @param alpha
* 透明度
*/
public void setDefaultBackgroundColor(int color, Integer alpha) {
defaultBackgroundColor = new ColorDrawable(color);
if (alpha != null)
defaultBackgroundColor.setAlpha(alpha);
defaultBackgroundResid = null;
}
/**
* 設置默認背景資源
*
* @param resid
* 圖片資源文件
*/
public void setDefaultBackgroundResource(int resid) {
defaultBackgroundResid = resid;
}
/**
* 設置默認文字顏色
*
* @param color
*/
public void setDefaultTextColor(int color) {
defaultTextColor = color;
}
/**
* 重置背景和文字顏色
*/
public void resetDefaultBackgroundAndTextColor() {
defaultTextColor = Color.WHITE;
defaultBackgroundColor = new ColorDrawable(Color.BLACK);
defaultBackgroundColor.setAlpha(200);
defaultBackgroundResid = null;
}
/**
* 隱藏指定控件
*
* @param v
* 需要隱藏的控件
* @param endAnim
* 結束動畫
*/
public final void hide(final View v, Animation endAnim) {
if (v == null || mView.indexOfChild(v) < 0)
return;
// 獲得出場動畫
if (endAnim == null)
endAnim = getEndAnimation();
v.clearAnimation();
// 開始出場動畫
v.startAnimation(endAnim);
// 動畫結束後移除控件
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (v == null || mView.indexOfChild(v) < 0)
return;
// 移除指定控件
mView.removeView(v);
// 隱藏頂層容器控件
if (mView.getChildCount() == 1)
hideToast();
}
}, TIME_END_ANIM);
}
/**
* 獲得一個設置好屬性的TextView
*
* @param msg
* @return
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public TextView getTextView(String msg) {
TextView tv = new TextView(mContext);
tv.setLayoutParams(lp_WW);
tv.setText(msg);
tv.setTextColor(defaultTextColor);
Drawable background = null;
if (defaultBackgroundResid != null) {
background = mContext.getResources().getDrawable(
defaultBackgroundResid);
} else {
background = defaultBackgroundColor;
}
if (currentapiVersion > 10)
tv.setBackground(background);
else
tv.setBackgroundDrawable(background);
tv.setPadding(5, 5, 5, 5);
tv.setGravity(Gravity.CENTER);
return tv;
}
/**
* 獲得一圖片或圖文並存的toast
*
* @param msg
* @return
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public LinearLayout getView(int resId, String msg) {
LinearLayout layout = new LinearLayout(mContext);
layout.setLayoutParams(new LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
layout.setOrientation(LinearLayout.VERTICAL);
layout.setGravity(Gravity.CENTER);
layout.setPadding(10, 10, 10, 10);
ImageView imageView = new ImageView(mContext);
imageView.setLayoutParams(lp_WW);
imageView.setImageResource(resId);
layout.addView(imageView);
if(!TextUtils.isEmpty(msg)){
TextView tv = new TextView(mContext);
tv.setLayoutParams(lp_WW);
tv.setText(msg);
tv.setTextColor(defaultTextColor);
tv.setPadding(5, 5, 5, 5);
tv.setGravity(Gravity.CENTER);
layout.addView(tv);
}
Drawable background = null;
if (defaultBackgroundResid != null) {
background = mContext.getResources().getDrawable(
defaultBackgroundResid);
} else {
background = defaultBackgroundColor;
}
if (currentapiVersion > 10)
layout.setBackground(background);
else
layout.setBackgroundDrawable(background);
return layout;
}
/**
* 獲得入場動畫
*
* @return
*/
protected Animation getStartAnimation() {
AlphaAnimation animAlpha = new AlphaAnimation(0, 1);
animAlpha.setDuration(TIME_START_ANIM);
animAlpha.setFillAfter(true);
TranslateAnimation animTrans = new TranslateAnimation(
Animation.RELATIVE_TO_PARENT, 1.5f,
Animation.RELATIVE_TO_PARENT, 0f, Animation.RELATIVE_TO_PARENT,
0f, Animation.RELATIVE_TO_PARENT, 0f);
animTrans.setDuration(TIME_START_ANIM);
animTrans.setFillAfter(true);
animTrans.setInterpolator(new DecelerateInterpolator());
AnimationSet sets = new AnimationSet(true);
sets.addAnimation(animAlpha);
sets.addAnimation(animTrans);
return sets;
}
/**
* 獲得離場動畫
*
* @return
*/
protected Animation getEndAnimation() {
AlphaAnimation animAlpha = new AlphaAnimation(1, 0);
animAlpha.setDuration(TIME_END_ANIM);
animAlpha.setFillAfter(true);
TranslateAnimation animTrans = new TranslateAnimation(
Animation.RELATIVE_TO_PARENT, 0f, Animation.RELATIVE_TO_PARENT,
-1.5f, Animation.RELATIVE_TO_PARENT, 0f,
Animation.RELATIVE_TO_PARENT, 0f);
animTrans.setDuration(TIME_END_ANIM);
animTrans.setFillAfter(true);
animTrans.setInterpolator(new AccelerateInterpolator());
AnimationSet sets = new AnimationSet(true);
sets.addAnimation(animAlpha);
sets.addAnimation(animTrans);
return sets;
}
/* 以下為反射相關內容 */
Toast mToast;
Field mTN;
Object mObj;
Method showMethod, hideMethod;
/**
* 通過反射獲得mTN下的show和hide方法
*/
private void initTN() {
mToast = new Toast(mContext);
mToast.setView(mTopView);
Class clazz = Toast.class;
try {
mTN = clazz.getDeclaredField("mTN");
mTN.setAccessible(true);
mObj = mTN.get(mToast);
showMethod = mObj.getClass().getDeclaredMethod("show",
new Class[0]);
hideMethod = mObj.getClass().getDeclaredMethod("hide",
new Class[0]);
hasReflectException = false;
} catch (NoSuchFieldException e) {
hasReflectException = true;
System.out.println(e.getMessage());
} catch (IllegalAccessException e) {
hasReflectException = true;
System.out.println(e.getMessage());
} catch (IllegalArgumentException e) {
hasReflectException = true;
System.out.println(e.getMessage());
} catch (NoSuchMethodException e) {
hasReflectException = true;
System.out.println(e.getMessage());
}
}
/**
* 通過反射獲得的show方法顯示指定View
*/
private void showToast() {
try {
// 高版本需要再次手動設置mNextView屬性
if (currentapiVersion > 10) {
Field mNextView = mObj.getClass().getDeclaredField("mNextView");
mNextView.setAccessible(true);
mNextView.set(mObj, mTopView);
}
showMethod.invoke(mObj, new Object[0]);
hasReflectException = false;
} catch (Exception e) {
hasReflectException = true;
System.out.println(e.getMessage());
}
}
/**
* 通過反射獲得的hide方法隱藏指定View
*/
public void hideToast() {
try {
hideMethod.invoke(mObj, new Object[0]);
hasReflectException = false;
} catch (Exception e) {
hasReflectException = true;
System.out.println(e.getMessage());
}
}
public void removeView() {
}
}
從上面的代碼可以看出:裡面反射來創建Toast,通過反射來獲得mTN下的show和hide方法來控制toast的show和hide,然後獲得handle來處理ui的刷新,代碼通過一些參數來設置toast,比如顯示的文字,背景顏色,背景圖片,顯示的圖片和時長。
然後就是activity_main.xml
為了效果好看點使用CardView,也有點陰影和動畫效果。
接下來就是代碼的示例使用了:
package com.losileeya.toastmaster;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.RotateAnimation;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
import android.widget.TextView;
import com.losileeya.toastmaster.view.SuperCustomToast;
import java.lang.ref.WeakReference;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class MainActivity extends AppCompatActivity {
SuperCustomToast toast;//自定義Toast
int i = 0;
final StringBuffer sb = new StringBuffer("默認Toast");
final String info = "默認Toast-";
final String sameString = "相同信息Toast";
Handler mHandler;
@BindView(R.id.showToast1)
TextView showToast1;
@BindView(R.id.showToast2)
TextView showToast2;
@BindView(R.id.showToast3)
TextView showToast3;
@BindView(R.id.showToast4)
TextView showToast4;
@BindView(R.id.showToast5)
TextView showToast5;
@BindView(R.id.showToast6)
TextView showToast6;
@BindView(R.id.showToast7)
TextView showToast7;
@BindView(R.id.showToast8)
TextView showToast8;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//綁定視圖
ButterKnife.bind(MainActivity.this);
//初始化handle
mHandler = new MyHandler(this);
//獲取自定義toast的實例
toast = SuperCustomToast.getInstance(getApplicationContext());
}
/**
* 入場動畫
*/
private void showAnimate() {
// 旋轉
RotateAnimation rAnim = new RotateAnimation(0, 720,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
rAnim.setDuration(500);
rAnim.setFillAfter(true);
// 縮放
ScaleAnimation sAnim = new ScaleAnimation(0, 1, 0, 1,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
sAnim.setDuration(500);
sAnim.setFillAfter(true);
// 透明度
AlphaAnimation aAnim1 = new AlphaAnimation(0, 1);
aAnim1.setDuration(500);
aAnim1.setFillAfter(true);
AnimationSet startAnim = new AnimationSet(false);
startAnim.addAnimation(rAnim);
startAnim.addAnimation(aAnim1);
startAnim.addAnimation(sAnim);
// 移動
TranslateAnimation animTrans = new TranslateAnimation(
Animation.RELATIVE_TO_PARENT, 0f,
Animation.RELATIVE_TO_PARENT, 0f,
Animation.RELATIVE_TO_SELF, 0f,
Animation.RELATIVE_TO_SELF, 1f);
animTrans.setDuration(500);
animTrans.setFillAfter(true);
// 透明度
AlphaAnimation aAnim2 = new AlphaAnimation(1, 0);
aAnim2.setDuration(500);
aAnim2.setFillAfter(true);
AnimationSet endAnim = new AnimationSet(false);
endAnim.addAnimation(animTrans);
endAnim.addAnimation(aAnim2);
toast.show("自定義動畫的Toast-" + i++, null, startAnim, endAnim);
}
private static class MyHandler extends Handler {
private WeakReference activityWeakReference;
public MyHandler(MainActivity activity) {
activityWeakReference = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
MainActivity activity = activityWeakReference.get();
if (activity != null) {
}
}
}
@Override
protected void onPause() {
super.onPause();
toast.hideToast();
toast.mView.removeAllViews();
toast.initView();
}
@OnClick({R.id.showToast1, R.id.showToast2, R.id.showToast3, R.id.showToast4, R.id.showToast5, R.id.showToast6, R.id.showToast7,R.id.showToast8})
public void onClick(View view) {
switch (view.getId()) {
case R.id.showToast1:
mHandler.post(new Runnable() {
@Override
public void run() {
//默認toast
toast.show(info + i++);
}
});
break;
case R.id.showToast2:
// 持續5秒的toast
toast.showSameMsg(sameString, 5000);
break;
case R.id.showToast3:
//帶背景色Toast
toast.setDefaultBackgroundColor(Color.RED, 200);//Toast背景
toast.setDefaultTextColor(Color.BLUE);//文字顏色
toast.show("帶有背景色Toast");
break;
case R.id.showToast4:
//給Toast添加背景圖片
toast.setDefaultBackgroundResource(R.drawable.bg);
toast.setDefaultTextColor(Color.BLACK);
toast.show("背景圖片的Toast");
break;
case R.id.showToast5:
//給Toast加動畫
showAnimate();
break;
case R.id.showToast6:
//帶圖片的Toast
toast.setDefaultBackgroundResource(R.drawable.frame_bg_theme_light);
toast.show(R.drawable.tips_smile, "", null, null, null);
break;
case R.id.showToast7:
//圖文混合的toast
toast.setDefaultTextColor(Color.RED);
toast.setDefaultBackgroundResource(R.drawable.frame_bg_theme_light);
toast.show(R.drawable.tips_smile, "我笑了", null, null, null);
break;
case R.id.showToast8:
//自定義布局Toast
toast.setDefaultTextColor(Color.RED);
toast.show(info + i++, R.layout.super_toast_theme_light,
R.id.content_toast, MainActivity.this);
break;
}
}
}
上面的代碼呢就是對8種toast的效果的展示,基本上也能適合開發的所有場景了,實在不行的話那麼你就使用snackbar咯,效果或許不好,但是也還是能學到一些東西的。
由於使用的butterknife5.0.1我手賤更新到了8.0.1,差點被坑了
我是這樣做的:
compile ‘com.jakewharton:butterknife:8.0.1’
然後代碼也能使用:@BindView,@OnClick特麼怎麼出鬼了,提示unused(木有使用) ,木有辦法只能去github上了,然後改成這樣
apply plugin: 'com.neenbedankt.android-apt'
dependencies {
compile 'com.jakewharton:butterknife:8.0.1'
apt 'com.jakewharton:butterknife-compiler:8.0.1'
}
然後工程的也要改:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.0.0'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
}
對toast的源碼翻出來一部分,然後跟我們一般的toast的封裝還是有些不同,當然封裝一下toast對開發的效率還是能夠提高的 ,代碼中用到了動畫有溫習了一下,學習就是這樣從難到易。
好了,所有的講解就到這裡了,能力有限見丑了,就到這裡。感覺不錯麻煩幫頂一下,贊一個,哪裡有問題指出來。
根據人眼視覺殘留現象,連續播放一些列的圖像,形成動畫效果。Android中的動畫:游戲:利用自定義View的繪制方法,開啟線程頻繁的刷新界面,形成動畫; Android
上一篇文章總結的布局優化的問題,如果對布局優化不是很熟悉的,可以看一下Android Studido下的應用性能優化總結–布局優化 , 這周一直籌劃總結一下內
本文實例講述了Android使用criteria選擇合適的地理位置服務實現方法。分享給大家供大家參考,具體如下:/* LocationActivity.java * @a
Android基礎入門教程——2.4.7 構建一個可復用的自定義BaseAdapter標簽(空格分隔): Android基礎入門教程本節引言: 如