├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── values
│ │ │ │ ├── strings.xml
│ │ │ │ ├── colors.xml
│ │ │ │ └── styles.xml
│ │ │ ├── mipmap-hdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── ic_launcher_round.png
│ │ │ │ ├── qmui_icon_notify_done.png
│ │ │ │ ├── qmui_icon_notify_error.png
│ │ │ │ └── qmui_icon_notify_info.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── ic_launcher_round.png
│ │ │ │ ├── qmui_icon_notify_done.png
│ │ │ │ ├── qmui_icon_notify_error.png
│ │ │ │ └── qmui_icon_notify_info.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── custom_tip.png
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── binding_tips.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── drawable
│ │ │ │ ├── progress_color.xml
│ │ │ │ ├── dialog_bg.xml
│ │ │ │ ├── custom_dialog_bg_color.xml
│ │ │ │ └── custom_dialog_bg_corner.xml
│ │ │ └── layout
│ │ │ │ ├── tip_view_layout.xml
│ │ │ │ ├── activity_home.xml
│ │ │ │ ├── tip_view_vertical.xml
│ │ │ │ ├── load_view_horizental.xml
│ │ │ │ ├── activity_toast_tip.xml
│ │ │ │ ├── load_view_vertical.xml
│ │ │ │ └── activity_main.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── xiaokun
│ │ │ │ └── loadview
│ │ │ │ ├── App.java
│ │ │ │ ├── HomeActivity.java
│ │ │ │ ├── MainActivity.java
│ │ │ │ ├── ToastTipActivity.java
│ │ │ │ ├── toast_tip
│ │ │ │ ├── ToastLoadUtil.java
│ │ │ │ └── ToastTipUtil.java
│ │ │ │ └── DialogTipActivity.java
│ │ └── AndroidManifest.xml
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── xiaokun
│ │ │ └── loadview
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── xiaokun
│ │ └── loadview
│ │ └── ExampleInstrumentedTest.java
├── proguard-rules.pro
└── build.gradle
├── dialogtiplib
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── values
│ │ │ │ ├── strings.xml
│ │ │ │ └── styles.xml
│ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── qmui_icon_notify_done.png
│ │ │ │ ├── qmui_icon_notify_info.png
│ │ │ │ └── qmui_icon_notify_error.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── qmui_icon_notify_done.png
│ │ │ │ ├── qmui_icon_notify_error.png
│ │ │ │ └── qmui_icon_notify_info.png
│ │ │ ├── drawable
│ │ │ │ └── dialog_bg.xml
│ │ │ └── layout
│ │ │ │ └── tip_dialog_view.xml
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ │ └── com
│ │ │ └── xiaokun
│ │ │ └── dialogtiplib
│ │ │ ├── util
│ │ │ ├── DimenUtils.java
│ │ │ └── AppUtils.java
│ │ │ └── dialog_tip
│ │ │ ├── FadeInTextView.java
│ │ │ ├── GraduallyTextView.java
│ │ │ └── TipLoadDialog.java
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── xiaokun
│ │ │ └── dialogtiplib
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── xiaokun
│ │ └── dialogtiplib
│ │ └── ExampleInstrumentedTest.java
├── build.gradle
└── proguard-rules.pro
├── settings.gradle
├── screenshots
├── 1.png
├── tip.gif
├── corner.gif
├── icon.gif
├── load.gif
├── load2.gif
├── shadow.gif
├── set_time.gif
├── load_time.gif
├── loadingview.gif
├── msg_color.gif
├── dis_listener.gif
├── load_tv_color.gif
└── new_bg_color.gif
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .gitignore
├── gradle.properties
├── gradlew.bat
├── README.md
└── gradlew
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/dialogtiplib/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':dialogtiplib'
2 |
--------------------------------------------------------------------------------
/screenshots/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Xiaocai9527/LoadingView/HEAD/screenshots/1.png
--------------------------------------------------------------------------------
/screenshots/tip.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Xiaocai9527/LoadingView/HEAD/screenshots/tip.gif
--------------------------------------------------------------------------------
/screenshots/corner.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Xiaocai9527/LoadingView/HEAD/screenshots/corner.gif
--------------------------------------------------------------------------------
/screenshots/icon.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Xiaocai9527/LoadingView/HEAD/screenshots/icon.gif
--------------------------------------------------------------------------------
/screenshots/load.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Xiaocai9527/LoadingView/HEAD/screenshots/load.gif
--------------------------------------------------------------------------------
/screenshots/load2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Xiaocai9527/LoadingView/HEAD/screenshots/load2.gif
--------------------------------------------------------------------------------
/screenshots/shadow.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Xiaocai9527/LoadingView/HEAD/screenshots/shadow.gif
--------------------------------------------------------------------------------
/screenshots/set_time.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Xiaocai9527/LoadingView/HEAD/screenshots/set_time.gif
--------------------------------------------------------------------------------
/screenshots/load_time.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Xiaocai9527/LoadingView/HEAD/screenshots/load_time.gif
--------------------------------------------------------------------------------
/screenshots/loadingview.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Xiaocai9527/LoadingView/HEAD/screenshots/loadingview.gif
--------------------------------------------------------------------------------
/screenshots/msg_color.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Xiaocai9527/LoadingView/HEAD/screenshots/msg_color.gif
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
9 | * 作者 : 肖坤 10 | * 时间 : 2018/01/18 11 | * 描述 : 12 | * 版本 : 1.0 13 | *14 | */ 15 | 16 | public class HomeActivity extends AppCompatActivity 17 | { 18 | @Override 19 | protected void onCreate(@Nullable Bundle savedInstanceState) 20 | { 21 | super.onCreate(savedInstanceState); 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_home.xml: -------------------------------------------------------------------------------- 1 | 2 |
15 | * 作者 : 肖坤 16 | * 时间 : 2017/12/28 17 | * 描述 : 18 | * 版本 : 1.0 19 | *20 | */ 21 | 22 | public class ToastTipActivity extends AppCompatActivity implements View.OnClickListener 23 | { 24 | 25 | private static final String LOADING = "加载中..."; 26 | public static final String SEND_SUCCESS = "发送成功"; 27 | 28 | private Button mBtn1; 29 | private Button mBtn2; 30 | private Button mBtn3; 31 | private Button mBtn4; 32 | 33 | @Override 34 | protected void onCreate(@Nullable Bundle savedInstanceState) 35 | { 36 | super.onCreate(savedInstanceState); 37 | setContentView(R.layout.activity_toast_tip); 38 | initView(); 39 | initListener(); 40 | } 41 | 42 | private void initView() 43 | { 44 | mBtn1 = (Button) findViewById(R.id.btn1); 45 | mBtn2 = (Button) findViewById(R.id.btn2); 46 | mBtn3 = (Button) findViewById(R.id.btn3); 47 | mBtn4 = (Button) findViewById(R.id.btn4); 48 | } 49 | 50 | private void initListener() 51 | { 52 | mBtn1.setOnClickListener(this); 53 | mBtn2.setOnClickListener(this); 54 | mBtn3.setOnClickListener(this); 55 | mBtn4.setOnClickListener(this); 56 | } 57 | 58 | @Override 59 | public void onClick(View view) 60 | { 61 | switch (view.getId()) 62 | { 63 | case R.id.btn1: 64 | ToastLoadUtil.showLoadTip(LOADING, ToastLoadUtil.HORIZENTAL); 65 | break; 66 | case R.id.btn2: 67 | ToastLoadUtil.showLoadTip(LOADING, ToastLoadUtil.VERTICAL); 68 | break; 69 | case R.id.btn3: 70 | ToastTipUtil.showTip(SEND_SUCCESS, 1500, ToastTipUtil.ICON_TYPE_SUCCESS); 71 | break; 72 | case R.id.btn4: 73 | mBtn4.setText("click"); 74 | break; 75 | default: 76 | 77 | break; 78 | } 79 | } 80 | 81 | @Override 82 | public boolean onKeyDown(int keyCode, KeyEvent event) 83 | { 84 | if (keyCode == KeyEvent.KEYCODE_BACK) 85 | { 86 | if (ToastLoadUtil.isShowing()) 87 | { 88 | ToastLoadUtil.dismissLoad(); 89 | return true; 90 | } else 91 | { 92 | return super.onKeyDown(keyCode, event); 93 | } 94 | } 95 | return super.onKeyDown(keyCode, event); 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /dialogtiplib/src/main/java/com/xiaokun/dialogtiplib/util/DimenUtils.java: -------------------------------------------------------------------------------- 1 | package com.xiaokun.dialogtiplib.util; 2 | 3 | import android.content.Context; 4 | import android.util.DisplayMetrics; 5 | 6 | /** 7 | * @author yuyh. 8 | * @date 16/4/10. 9 | */ 10 | public class DimenUtils 11 | { 12 | 13 | public enum EScreenDensity 14 | { 15 | XXHDPI, //超高分辨率 1080×1920 16 | XHDPI, //超高分辨率 720×1280 17 | HDPI, //高分辨率 480×800 18 | MDPI, //中分辨率 320×480 19 | } 20 | 21 | public static EScreenDensity getDisply(Context context) 22 | { 23 | EScreenDensity eScreenDensity; 24 | //初始化屏幕密度 25 | DisplayMetrics dm = context.getApplicationContext().getResources().getDisplayMetrics(); 26 | int densityDpi = dm.densityDpi; 27 | 28 | if (densityDpi <= 160) 29 | { 30 | eScreenDensity = EScreenDensity.MDPI; 31 | } else if (densityDpi <= 240) 32 | { 33 | eScreenDensity = EScreenDensity.HDPI; 34 | } else if (densityDpi < 400) 35 | { 36 | eScreenDensity = EScreenDensity.XHDPI; 37 | } else 38 | { 39 | eScreenDensity = EScreenDensity.XXHDPI; 40 | } 41 | return eScreenDensity; 42 | } 43 | 44 | /** 45 | * 获取屏幕宽度 46 | * 47 | * @return 48 | */ 49 | public static int getScreenWidth() 50 | { 51 | return AppUtils.getAppContext().getResources().getDisplayMetrics().widthPixels; 52 | } 53 | 54 | /** 55 | * 获取屏幕高度 56 | * 57 | * @return 58 | */ 59 | public static int getScreenHeight() 60 | { 61 | return AppUtils.getAppContext().getResources().getDisplayMetrics().heightPixels; 62 | } 63 | 64 | /** 65 | * 将dp转换成px 66 | * 67 | * @param dp 68 | * @return 69 | */ 70 | public static float dpToPx(float dp) 71 | { 72 | return dp * AppUtils.getAppContext().getResources().getDisplayMetrics().density; 73 | } 74 | 75 | public static int dpToPxInt(float dp) 76 | { 77 | return (int) (dpToPx(dp) + 0.5f); 78 | } 79 | 80 | /** 81 | * 将px转换成dp 82 | * 83 | * @param px 84 | * @return 85 | */ 86 | public static float pxToDp(float px) 87 | { 88 | return px / AppUtils.getAppContext().getResources().getDisplayMetrics().density; 89 | } 90 | 91 | public static int pxToDpInt(float px) 92 | { 93 | return (int) (pxToDp(px) + 0.5f); 94 | } 95 | 96 | /** 97 | * 将px值转换为sp值 98 | * 99 | * @param pxValue 100 | * @return 101 | */ 102 | public static float pxToSp(float pxValue) 103 | { 104 | return pxValue / AppUtils.getAppContext().getResources().getDisplayMetrics().scaledDensity; 105 | } 106 | 107 | /** 108 | * 将sp值转换为px值 109 | * 110 | * @param spValue 111 | * @return 112 | */ 113 | public static float spToPx(float spValue) 114 | { 115 | return spValue * AppUtils.getAppContext().getResources().getDisplayMetrics().scaledDensity; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /dialogtiplib/src/main/java/com/xiaokun/dialogtiplib/util/AppUtils.java: -------------------------------------------------------------------------------- 1 | /** 2 | * created by yuyh, 16/04/09 3 | * Copyright (c) 2016, smuyyh@gmail.com All Rights Reserved. 4 | * # # 5 | * # _oo0oo_ # 6 | * # o8888888o # 7 | * # 88" . "88 # 8 | * # (| -_- |) # 9 | * # 0\ = /0 # 10 | * # ___/`---'\___ # 11 | * # .' \\| |# '. # 12 | * # / \\||| : |||# \ # 13 | * # / _||||| -:- |||||- \ # 14 | * # | | \\\ - #/ | | # 15 | * # | \_| ''\---/'' |_/ | # 16 | * # \ .-\__ '-' ___/-. / # 17 | * # ___'. .' /--.--\ `. .'___ # 18 | * # ."" '< `.___\_<|>_/___.' >' "". # 19 | * # | | : `- \`.;`\ _ /`;.`/ - ` : | | # 20 | * # \ \ `_. \_ __\ /__ _/ .-` / / # 21 | * # =====`-.____`.___ \_____/___.-`___.-'===== # 22 | * # `=---=' # 23 | * # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # 24 | * # # 25 | * # 佛祖保佑 永无BUG # 26 | * # # 27 | */ 28 | 29 | 30 | package com.xiaokun.dialogtiplib.util; 31 | 32 | import android.content.Context; 33 | import android.content.res.AssetManager; 34 | import android.content.res.Resources; 35 | import android.os.Handler; 36 | import android.os.Looper; 37 | 38 | public class AppUtils 39 | { 40 | 41 | private static Context mContext; 42 | private static Thread mUiThread; 43 | 44 | private static Handler sHandler = new Handler(Looper.getMainLooper()); 45 | 46 | public static void init(Context context) 47 | { //在Application中初始化 48 | mContext = context; 49 | mUiThread = Thread.currentThread(); 50 | } 51 | 52 | public static Context getAppContext() 53 | { 54 | return mContext; 55 | } 56 | 57 | public static Handler getHandler() 58 | { 59 | return sHandler; 60 | } 61 | 62 | public static AssetManager getAssets() 63 | { 64 | return mContext.getAssets(); 65 | } 66 | 67 | public static Resources getResource() 68 | { 69 | return mContext.getResources(); 70 | } 71 | 72 | public static boolean isUIThread() 73 | { 74 | return Thread.currentThread() == mUiThread; 75 | } 76 | 77 | public static void runOnUI(Runnable r) 78 | { 79 | sHandler.post(r); 80 | } 81 | 82 | public static void runOnUIDelayed(Runnable r, long delayMills) 83 | { 84 | sHandler.postDelayed(r, delayMills); 85 | } 86 | 87 | public static void removeRunnable(Runnable r) 88 | { 89 | if (r == null) 90 | { 91 | sHandler.removeCallbacksAndMessages(null); 92 | } else 93 | { 94 | sHandler.removeCallbacks(r); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /app/src/main/java/com/xiaokun/loadview/toast_tip/ToastLoadUtil.java: -------------------------------------------------------------------------------- 1 | package com.xiaokun.loadview.toast_tip; 2 | 3 | import android.content.Context; 4 | import android.os.CountDownTimer; 5 | import android.view.Gravity; 6 | import android.view.View; 7 | import android.widget.TextView; 8 | import android.widget.Toast; 9 | 10 | import com.xiaokun.dialogtiplib.util.AppUtils; 11 | import com.xiaokun.loadview.R; 12 | 13 | import static java.lang.Integer.MAX_VALUE; 14 | 15 | /** 16 | * @author xiaokun 17 | * @date 2017/12/22 18 | */ 19 | 20 | public class ToastLoadUtil 21 | { 22 | /** 23 | * 横向 24 | */ 25 | public static final int HORIZENTAL = 0; 26 | /** 27 | * 纵向 28 | */ 29 | public static final int VERTICAL = 1; 30 | /** 31 | * 1s,取1s小于Toast.LENGTH_LONG=3.5s. 32 | * 这样就不会有闪烁现象 33 | */ 34 | public static final long ONE_SECOND = 1000; 35 | /** 36 | * toast状态 37 | */ 38 | private static boolean isShowing = false; 39 | 40 | private static CountDownTimer timer; 41 | private static Toast toast; 42 | 43 | /** 44 | * 无限弹窗 45 | * 46 | * @param msg 需要弹出的消息 47 | */ 48 | public static void showLoadTip(String msg, int direction) 49 | { 50 | if (isShowing()) 51 | { 52 | return; 53 | } 54 | Context appContext = AppUtils.getAppContext(); 55 | toast = getToast(appContext); 56 | View contentView = null; 57 | if (direction == HORIZENTAL) 58 | { 59 | contentView = View.inflate(appContext, R.layout.load_view_horizental, null); 60 | } else 61 | { 62 | contentView = View.inflate(appContext, R.layout.load_view_vertical, null); 63 | } 64 | TextView infoTv = (TextView) contentView.findViewById(R.id.info); 65 | infoTv.setText(msg); 66 | toast.setView(contentView); 67 | toast.setGravity(Gravity.CENTER, 0, 0); 68 | timer = getTimer(); 69 | timer.start(); 70 | isShowing = true; 71 | } 72 | 73 | private static Toast getToast(Context context) 74 | { 75 | if (toast == null) 76 | { 77 | toast = new Toast(context); 78 | toast.setDuration(Toast.LENGTH_LONG); 79 | } 80 | return toast; 81 | } 82 | 83 | private static CountDownTimer getTimer() 84 | { 85 | if (timer == null) 86 | { 87 | timer = new CountDownTimer(MAX_VALUE * ONE_SECOND, ONE_SECOND) 88 | { 89 | @Override 90 | public void onTick(long l) 91 | { 92 | toast.show(); 93 | } 94 | 95 | @Override 96 | public void onFinish() 97 | { 98 | toast.cancel(); 99 | } 100 | }; 101 | } 102 | return timer; 103 | } 104 | 105 | public static boolean isShowing() 106 | { 107 | return isShowing; 108 | } 109 | 110 | /** 111 | * 取消toast 112 | */ 113 | public static void dismissLoad() 114 | { 115 | if (timer != null && toast != null) 116 | { 117 | timer.onFinish(); 118 | timer.cancel(); 119 | //不置空,会有闪烁问题 120 | //但是置空会每次弹窗都创建toast实例,造成资源浪费 121 | toast = null; 122 | isShowing = false; 123 | } 124 | } 125 | 126 | } 127 | -------------------------------------------------------------------------------- /app/src/main/java/com/xiaokun/loadview/toast_tip/ToastTipUtil.java: -------------------------------------------------------------------------------- 1 | package com.xiaokun.loadview.toast_tip; 2 | 3 | import android.content.Context; 4 | import android.os.CountDownTimer; 5 | import android.view.Gravity; 6 | import android.view.View; 7 | import android.widget.ImageView; 8 | import android.widget.TextView; 9 | import android.widget.Toast; 10 | 11 | import com.xiaokun.dialogtiplib.util.AppUtils; 12 | import com.xiaokun.loadview.R; 13 | 14 | import static java.lang.Integer.MAX_VALUE; 15 | 16 | /** 17 | * @author xiaokun 18 | * @date 2017/12/22 19 | */ 20 | 21 | public class ToastTipUtil 22 | { 23 | /** 24 | * 不显示任何icon 25 | */ 26 | public static final int ICON_TYPE_NOTHING = 0; 27 | /** 28 | * 显示成功图标 29 | */ 30 | public static final int ICON_TYPE_SUCCESS = 2; 31 | /** 32 | * 显示失败图标 33 | */ 34 | public static final int ICON_TYPE_FAIL = 3; 35 | /** 36 | * 显示信息图标 37 | */ 38 | public static final int ICON_TYPE_INFO = 4; 39 | /** 40 | * 1s,取1s小于Toast.LENGTH_LONG=3.5s. 41 | * 这样就不会有闪烁现象 42 | */ 43 | public static final long ONE_SECOND = 1000; 44 | /** 45 | * toast状态 46 | */ 47 | private static boolean isShowing = false; 48 | 49 | private static CountDownTimer timer; 50 | private static Toast toast; 51 | 52 | /** 53 | * 显示tip,不带button 54 | * 55 | * @param msg 提示msg 56 | * @param duration toast时间 单位毫秒 57 | * @param type toast类型 58 | */ 59 | public static void showTip(String msg, int duration, int type) 60 | { 61 | if (isShowing()) 62 | { 63 | return; 64 | } 65 | Context appContext = AppUtils.getAppContext(); 66 | toast = getToast(appContext); 67 | View contentView = View.inflate(appContext, R.layout.tip_view_vertical, null); 68 | TextView infoTv = (TextView) contentView.findViewById(R.id.info); 69 | ImageView img = (ImageView) contentView.findViewById(R.id.img); 70 | infoTv.setText(msg); 71 | if (type == ICON_TYPE_SUCCESS) 72 | { 73 | img.setVisibility(View.VISIBLE); 74 | img.setImageResource(R.mipmap.qmui_icon_notify_done); 75 | } else if (type == ICON_TYPE_FAIL) 76 | { 77 | img.setVisibility(View.VISIBLE); 78 | img.setImageResource(R.mipmap.qmui_icon_notify_error); 79 | } else if (type == ICON_TYPE_INFO) 80 | { 81 | img.setVisibility(View.VISIBLE); 82 | img.setImageResource(R.mipmap.qmui_icon_notify_info); 83 | } else 84 | { 85 | img.setVisibility(View.GONE); 86 | } 87 | toast.setView(contentView); 88 | toast.setGravity(Gravity.CENTER, 0, 0); 89 | timer = getTimer(duration); 90 | timer.start(); 91 | isShowing = true; 92 | } 93 | 94 | private static Toast getToast(Context context) 95 | { 96 | if (toast == null) 97 | { 98 | toast = new Toast(context); 99 | toast.setDuration(Toast.LENGTH_LONG); 100 | } 101 | return toast; 102 | } 103 | 104 | private static CountDownTimer getTimer(int duration) 105 | { 106 | long totalTime; 107 | if (duration > 0) 108 | { 109 | totalTime = duration; 110 | } else 111 | { 112 | totalTime = MAX_VALUE; 113 | } 114 | if (timer == null) 115 | { 116 | timer = new CountDownTimer(totalTime, totalTime / 2) 117 | { 118 | @Override 119 | public void onTick(long l) 120 | { 121 | toast.show(); 122 | } 123 | 124 | @Override 125 | public void onFinish() 126 | { 127 | toast.cancel(); 128 | toast = null; 129 | isShowing = false; 130 | } 131 | }; 132 | } 133 | return timer; 134 | } 135 | 136 | public static boolean isShowing() 137 | { 138 | return isShowing; 139 | } 140 | 141 | 142 | /** 143 | * 取消toast 144 | */ 145 | public static void dismissLoad() 146 | { 147 | if (timer != null && toast != null) 148 | { 149 | timer.onFinish(); 150 | timer.cancel(); 151 | //不置空,会有闪烁问题 152 | //但是置空会每次弹窗都创建toast实例,造成资源浪费 153 | toast = null; 154 | isShowing = false; 155 | } 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LoadingView 2 | 耗时加载框和提示框。 3 | 4 | ### **图片展示:** 5 | 6 |  7 | 8 | 9 | 10 | ### **展示1:耗时加载框** 11 | 12 | 13 | 14 |  15 | 16 | **代码:** 17 | 18 | ``` 19 | tipLoadDialog = new TipLoadDialog(this); 20 | //默认是无阴影主题 21 | tipLoadDialog.setMsgAndType(LOADING_玩命, TipLoadDialog.ICON_TYPE_LOADING).show(); 22 | ``` 23 | 24 | 25 | 26 | ### 展示2:耗时加载框,样式2 27 | 28 |  29 | 30 | 31 | 32 | **代码:** 33 | 34 | ``` 35 | //设置另一种loading文字动画,注意不要加后缀... 36 | tipLoadDialog.setNoShadowTheme() 37 | .setMsgAndType("加载中", TipLoadDialog.ICON_TYPE_LOADING2) 38 | .show(); 39 | ``` 40 | 41 | 42 | 43 | ### **展示3:tip提示框 1s后自动消失** 44 | 45 |  46 | 47 | 48 | 49 | **代码:** 50 | 51 | ``` 52 | //设置无阴影主题 53 | tipLoadDialog.setNoShadowTheme().setMsgAndType(sucTip, TipLoadDialog.ICON_TYPE_SUCCESS).show(); 54 | ``` 55 | 56 | 57 | 58 | ### 展示4:阴影主题 59 | 60 |  61 | 62 | 63 | 64 | **代码:** 65 | 66 | ``` 67 | //设置提示框阴影主题 68 | tipLoadDialog.setShadowTheme().setMsgAndType(sucTip, TipLoadDialog.ICON_TYPE_SUCCESS).show(); 69 | ``` 70 | 71 | 72 | 73 | ### 展示5:设置圆角 74 | 75 |  76 | 77 | 78 | 79 | **代码:** 80 | 81 | ``` 82 | //设置圆角 83 | tipLoadDialog.setBackground(R.drawable.custom_dialog_bg_corner) 84 | .setNoShadowTheme() 85 | .setMsgAndType(LOADING_玩命, TipLoadDialog.ICON_TYPE_LOADING) 86 | .show(); 87 | ``` 88 | 89 | 90 | 91 | ### 展示6:设置icon 92 | 93 |  94 | 95 | **代码:** 96 | 97 | ``` 98 | //设置除了Loading之外的tip图标 99 | tipLoadDialog.setSuccessIcon(R.mipmap.custom_tip) 100 | .setMsgAndType(sucTip, TipLoadDialog.ICON_TYPE_SUCCESS) 101 | .show(); 102 | ``` 103 | 104 | 105 | 106 | ### 展示7:设置背景颜色 107 | 108 |  109 | 110 | **代码:** 111 | 112 | ``` 113 | //设置背景颜色 114 | tipLoadDialog.setBackground(R.drawable.custom_dialog_bg_color) 115 | .setNoShadowTheme() 116 | .setMsgAndType(sucTip, TipLoadDialog.ICON_TYPE_SUCCESS) 117 | .show(); 118 | ``` 119 | 120 | 121 | 122 | ### 展示8:设置提示文字颜色和大小 123 | 124 |  125 | 126 | 127 | 128 | **代码:** 129 | 130 | ``` 131 | //设置提示信息的text的颜色和大小 132 | tipLoadDialog.setNoShadowTheme() 133 | .setMsgColor(Color.BLUE) 134 | .setMsgSize(20) 135 | .setMsgAndType(failTip, TipLoadDialog.ICON_TYPE_FAIL) 136 | .show(); 137 | ``` 138 | 139 | 140 | 141 | ### 展示9:设置加载框文字颜色和大小,以及progressbar颜色 142 | 143 |  144 | 145 | 146 | 147 | **代码:** 148 | 149 | ``` 150 | //设置加载框文字的颜色和大小 以及progressbar的颜色 151 | tipLoadDialog.setNoShadowTheme() 152 | .setProgressbarColor(Color.RED) 153 | .setLoadingTextColor(Color.RED) 154 | .setLoadingTextSize(20) 155 | .setMsgAndType(LOADING_玩命, TipLoadDialog.ICON_TYPE_LOADING) 156 | .show(); 157 | ``` 158 | 159 | 160 | 161 | ### 展示10:设置加载一次文字动画时间 162 | 163 |  164 | 165 | 166 | 167 | **代码:** 168 | 169 | ``` 170 | //设置loadingText一次动画的时间 171 | tipLoadDialog.setNoShadowTheme() 172 | .setProgressbarColor(Color.WHITE) 173 | .setLoadingTextColor(Color.WHITE) 174 | .setLoadingTextSize(15) 175 | .setLoadingTime(10000) 176 | .setMsgAndType(LOADING_玩命, TipLoadDialog.ICON_TYPE_LOADING) 177 | .show(); 178 | ``` 179 | 180 | 181 | 182 | ### 展示11:弹窗消失事件监听 183 | 184 |  185 | 186 | 187 | 188 | **代码:**(比如用在登陆成功跳转页面时候调用) 189 | 190 | ``` 191 | //弹窗消失事件监听 192 | tipLoadDialog.setNoShadowTheme() 193 | .setMsgAndType("登录成功", TipLoadDialog.ICON_TYPE_SUCCESS) 194 | .setDismissListener(new TipLoadDialog.DismissListener() 195 | { 196 | @Override 197 | public void onDimissListener() 198 | { 199 | startActivity(new Intent(DialogTipActivity.this, HomeActivity.class)); 200 | //然后可以finish掉当前登录页 201 | } 202 | }) 203 | .show(); 204 | ``` 205 | 206 | 207 | 208 | ### 展示12:设置tip弹窗时间 209 | 210 |  211 | 212 | 213 | 214 | **代码:** 215 | 216 | ``` 217 | //设置tip提示弹框时间 218 | tipLoadDialog.setNoShadowTheme() 219 | .setMsgAndType("停留2秒消失", TipLoadDialog.ICON_TYPE_SUCCESS) 220 | .setTipTime(2000) 221 | .show(); 222 | ``` 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | ### 两种实现模式: 231 | 232 | 一、采用Dialog模式实现: 233 | 234 | 缺点:必须得依赖Activity页面,所以很难用单例模式来生成,因为会造成内存泄漏。 235 | 236 | 优点:dialog本来就是为这个而生的,比较简单。 237 | 238 | 239 | 240 | 二、采用Toast模式实现: 241 | 242 | 缺点:无法像dialog一样能获取焦点,屏蔽其他控件事件。(比如正在加载网络请求时,页面其他控件是不能点击 243 | 244 | 的,但是toast无法屏蔽事件) 245 | 246 | 优点:不依赖Activity,只需要Application即可。 247 | 248 | 249 | 250 | duration时间问题。因为toast时间系统设置为固定的2秒和3.5秒。 251 | 252 | 使用toast需要解决两个问题: 253 | 254 | ①当duration不是2或者3.5秒时,怎么解决; 255 | 256 | ②当duration不确定时,怎么解决,比如正在进行网络请求; 257 | 258 | **解决方案:主要是利用了CountDownTimer类。Android自带的倒计时控件。** 259 | 260 | 261 | 262 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /dialogtiplib/src/main/java/com/xiaokun/dialogtiplib/dialog_tip/FadeInTextView.java: -------------------------------------------------------------------------------- 1 | package com.xiaokun.dialogtiplib.dialog_tip; 2 | 3 | import android.animation.ValueAnimator; 4 | import android.content.Context; 5 | import android.graphics.Paint; 6 | import android.graphics.Rect; 7 | import android.support.annotation.Nullable; 8 | import android.util.AttributeSet; 9 | import android.view.animation.LinearInterpolator; 10 | 11 | /** 12 | *
13 | * 作者 : 肖坤
14 | * 时间 : 2018/01/04
15 | * 描述 : Created by allen on 2017/6/5
16 | * 字符串逐字显示的view
17 | * fadeInTextView
18 | * .setTextString("自己的字符串")
19 | * .startFadeInAnimation()
20 | * .setTextAnimationListener(new FadeInTextView.TextAnimationListener()
21 | * {
22 | * @Override
23 | * public void animationFinish() {
24 | *
25 | * }
26 | * });
27 | * 版本 : 1.0
28 | *
29 | */
30 |
31 | public class FadeInTextView extends android.support.v7.widget.AppCompatTextView
32 | {
33 | private Rect textRect = new Rect();
34 |
35 | private StringBuffer stringBuffer = new StringBuffer();
36 |
37 | private String[] arr;
38 |
39 | private int textCount;
40 |
41 | private int currentIndex = -1;
42 |
43 | /**
44 | * 每个字出现的时间
45 | */
46 | private long duration = 700;
47 | private ValueAnimator textAnimation;
48 | private String contentStr;
49 |
50 | private TextAnimationListener textAnimationListener;
51 |
52 |
53 | public FadeInTextView setTextAnimationListener(TextAnimationListener textAnimationListener)
54 | {
55 | this.textAnimationListener = textAnimationListener;
56 | return this;
57 | }
58 |
59 | public FadeInTextView(Context context)
60 | {
61 | this(context, null);
62 | }
63 |
64 | public FadeInTextView(Context context, @Nullable AttributeSet attrs)
65 | {
66 | super(context, attrs);
67 | init();
68 | }
69 |
70 | private Paint mPaint;
71 |
72 | private void init()
73 | {
74 | mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
75 | mPaint.setStyle(Paint.Style.FILL);
76 | }
77 |
78 | @Override
79 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
80 | {
81 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
82 | float width = mPaint.measureText(contentStr + "...");
83 | setWidth((int) width);
84 | }
85 |
86 | /**
87 | * 文字逐个显示动画 通过插值的方式改变数据源
88 | */
89 | private void initAnimation()
90 | {
91 | if (textAnimation != null)
92 | {
93 | return;
94 | }
95 | //从0到textCount - 1 是设置从第一个字到最后一个字的变化因子
96 | textAnimation = ValueAnimator.ofInt(0, textCount);
97 | //执行总时间就是每个字的时间乘以字数
98 | textAnimation.setDuration((textCount - 1) * duration);
99 | //匀速显示文字
100 | textAnimation.setInterpolator(new LinearInterpolator());
101 | textAnimation.setRepeatCount(ValueAnimator.INFINITE);
102 | textAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
103 | {
104 | @Override
105 | public void onAnimationUpdate(ValueAnimator valueAnimator)
106 | {
107 | int index = (int) valueAnimator.getAnimatedValue();
108 | //过滤去重,保证每个字只重绘一次
109 | if (currentIndex != index)
110 | {
111 | stringBuffer.append(arr[index]);
112 | //重复动画使用append会造成内存泄漏
113 | // append(arr[index]);
114 |
115 | currentIndex = index;
116 | //所有文字都显示完成之后进度回调结束动画
117 | if (currentIndex == (textCount - 1))
118 | {
119 | stringBuffer.setLength(0);
120 | if (textAnimationListener != null)
121 | {
122 | textAnimationListener.animationFinish();
123 | }
124 | }
125 | setText(contentStr + stringBuffer.toString());
126 | }
127 | }
128 | });
129 | }
130 |
131 |
132 | /**
133 | * 设置逐渐显示的字符串
134 | *
135 | * @param textString 主体文字
136 | * @param flickerStr 动画的字体,一般设置为...
137 | * @return
138 | */
139 | public FadeInTextView setTextString(String textString, String flickerStr)
140 | {
141 | if (textString != null && flickerStr != null)
142 | {
143 | mPaint.setTextSize(getTextSize());
144 | contentStr = textString;
145 | setText(contentStr);
146 | //总字数
147 | textCount = flickerStr.length();
148 | //存放单个字的数组
149 | arr = new String[textCount];
150 | for (int i = 0; i < textCount; i++)
151 | {
152 | arr[i] = flickerStr.substring(i, i + 1);
153 | }
154 | initAnimation();
155 | }
156 |
157 | return this;
158 | }
159 |
160 | public FadeInTextView setDuration(long duration)
161 | {
162 | this.duration = duration;
163 | return this;
164 | }
165 |
166 | private boolean isLoading = false;
167 |
168 | /**
169 | * 开启动画
170 | *
171 | * @return
172 | */
173 | public FadeInTextView startFadeInAnimation()
174 | {
175 | if (textAnimation != null)
176 | {
177 | isLoading = true;
178 | stringBuffer.setLength(0);
179 | currentIndex = -1;
180 | textAnimation.start();
181 | }
182 | return this;
183 | }
184 |
185 | public boolean isLoading()
186 | {
187 | return isLoading;
188 | }
189 |
190 | /**
191 | * 停止动画
192 | *
193 | * @return
194 | */
195 | public FadeInTextView stopFadeInAnimation()
196 | {
197 | if (textAnimation != null)
198 | {
199 | isLoading = false;
200 | stringBuffer.setLength(0);
201 | textAnimation.cancel();
202 | }
203 | return this;
204 | }
205 |
206 | /**
207 | * 回调接口
208 | */
209 | public interface TextAnimationListener
210 | {
211 | void animationFinish();
212 | }
213 |
214 | }
215 |
--------------------------------------------------------------------------------
/dialogtiplib/src/main/java/com/xiaokun/dialogtiplib/dialog_tip/GraduallyTextView.java:
--------------------------------------------------------------------------------
1 | package com.xiaokun.dialogtiplib.dialog_tip;
2 |
3 | import android.animation.ValueAnimator;
4 | import android.content.Context;
5 | import android.graphics.Canvas;
6 | import android.graphics.Paint;
7 | import android.os.Build;
8 | import android.support.v7.widget.AppCompatEditText;
9 | import android.text.TextUtils;
10 | import android.util.AttributeSet;
11 | import android.util.Log;
12 | import android.view.View;
13 | import android.view.animation.AccelerateDecelerateInterpolator;
14 | import android.view.animation.Animation;
15 |
16 | import com.xiaokun.dialogtiplib.util.DimenUtils;
17 |
18 |
19 | /**
20 | * 借鉴http://www.jianshu.com/p/f8a9cfb729f9
21 | * 并加以扩展
22 | *
23 | * @author xiaokun
24 | * @date 2017/12/5
25 | */
26 |
27 | public class GraduallyTextView extends AppCompatEditText
28 | {
29 | private CharSequence text;//自定义的文本
30 | private int startY = 0;
31 | private float progress;//读取进度条
32 | private boolean isLoading;//判断是否正在读取
33 | private Paint mPaint;
34 | private int textLength;//设置文本长度
35 | private boolean isStop = true;
36 | /**
37 | * 总时长
38 | */
39 | private int duration = 2000;
40 | /**
41 | * 单字时长
42 | */
43 | private float sigleDuration;
44 |
45 | private ValueAnimator valueAnimator;//设置属性平移、缩放动画
46 |
47 | public GraduallyTextView(Context context)
48 | {
49 | super(context);
50 | init();
51 | }
52 |
53 | public GraduallyTextView(Context context, AttributeSet attrs)
54 | {
55 | super(context, attrs);
56 | init();
57 | }
58 |
59 | public GraduallyTextView(Context context, AttributeSet attrs, int defStyleAttr)
60 | {
61 | super(context, attrs, defStyleAttr);
62 | init();
63 | }
64 |
65 | public void init()
66 | {
67 | mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
68 | mPaint.setStyle(Paint.Style.FILL);
69 | setBackground(null);
70 | setCursorVisible(false);
71 | setFocusable(false);
72 | setEnabled(false);
73 | setFocusableInTouchMode(false);
74 | //设置平移动画
75 | valueAnimator = ValueAnimator.ofFloat(0, 100).setDuration(duration);
76 | valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
77 | valueAnimator.setRepeatCount(Animation.INFINITE);
78 | valueAnimator.setRepeatMode(ValueAnimator.RESTART);
79 | valueAnimator.addUpdateListener(
80 | new ValueAnimator.AnimatorUpdateListener()
81 | {
82 | @Override
83 | public void onAnimationUpdate(ValueAnimator animation)
84 | {
85 | //设置监听,当动画更新的时候触发重绘
86 | progress = (Float) animation.getAnimatedValue();
87 | GraduallyTextView.this.invalidate();
88 | }
89 | });
90 | }
91 |
92 | @Override
93 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
94 | {
95 | // super.onMeasure(widthMeasureSpec, heightMeasureSpec);
96 | mPaint.setTextSize(getTextSize());
97 | float width = mPaint.measureText(text.toString());
98 | float fontSpacing = mPaint.getFontSpacing();
99 | Log.e("GraduallyTextView", "onMeasure(GraduallyTextView.java:99)" + fontSpacing);
100 | setMeasuredDimension((int) width, (int) fontSpacing);
101 | }
102 |
103 | //设置开始读取的方法
104 | public void startLoading()
105 | {
106 | init();
107 | if (!isStop)
108 | {
109 | return;
110 | }
111 | textLength = getText().length();
112 | if (TextUtils.isEmpty(getText().toString()))
113 | {
114 | return;
115 | }
116 | isLoading = true;
117 | isStop = false;
118 | text = getText();
119 |
120 | mPaint.setTextSize(getTextSize());
121 | mPaint.setColor(getCurrentTextColor());
122 | int height = (int) mPaint.getFontSpacing();
123 | //计算startY的值,应该是dialog中心点需要下移的值
124 | //计算方法startY = (progressbarHeight +marginTop+loadviewHeight)/2
125 | startY = (int) (height + DimenUtils.dpToPx(60)) / 2;
126 | Log.e("GraduallyTextView", "run(GraduallyTextView.java:132)" + startY);
127 | setMinWidth(getWidth());
128 | setText("");//清空
129 | setHint("");//清空
130 | valueAnimator.start();
131 | //计算单个字的progress
132 | sigleDuration = 100f / textLength;
133 | }
134 |
135 | public boolean isLoading()
136 | {
137 | return isLoading;
138 | }
139 |
140 | //停止loading的方法
141 | public void stopLoading()
142 | {
143 | isLoading = false;
144 | isStop = true;
145 | if (valueAnimator != null)
146 | {
147 | valueAnimator.end();
148 | valueAnimator.cancel();
149 | setText(text);
150 | }
151 | }
152 |
153 | //设置时长
154 | public void setDuration(int duration)
155 | {
156 | this.duration = duration;
157 | }
158 |
159 | @Override
160 | protected void onVisibilityChanged(View changedView, int visibility)
161 | {
162 | super.onVisibilityChanged(changedView, visibility);
163 | if (!isLoading)
164 | {
165 | return;
166 | }
167 | if (visibility == View.VISIBLE)
168 | {
169 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
170 | {
171 | valueAnimator.resume();
172 | } else
173 | {
174 | startLoading();
175 | }
176 | } else
177 | {
178 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
179 | {
180 | valueAnimator.pause();
181 | } else
182 | {
183 | stopLoading();
184 | }
185 | }
186 | }
187 |
188 | //重写ondraw方法,如果还在loading,而且进度还小于1,则让它和透明度联动
189 | @Override
190 | protected void onDraw(Canvas canvas)
191 | {
192 | super.onDraw(canvas);
193 | if (!isStop)
194 | {
195 | mPaint.setAlpha(255);
196 | //当progress进度大于一个字的进度时
197 | if (progress / sigleDuration >= 1)
198 | {
199 | canvas.drawText(String.valueOf(text), 0, (int) (progress / sigleDuration), 0, startY, mPaint);
200 | }
201 | //设置即将出现那个字的透明度
202 | mPaint.setAlpha((int) (255 * ((progress % sigleDuration) / sigleDuration)));
203 | //下一个显示出来的字的position
204 | int nextOne = (int) (progress / sigleDuration);
205 | //如果position小于textLength
206 | if (nextOne < textLength)
207 | {
208 | //即将显示那一个字的透明度
209 | //measureText测量出text的宽度
210 | canvas.drawText(String.valueOf(text.charAt(nextOne)), 0, 1,
211 | getPaint().measureText(text.subSequence(0, nextOne).toString()), startY, mPaint);
212 | }
213 | }
214 | }
215 | }
216 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 | 17 | * 作者 : 肖坤 18 | * 时间 : 2017/12/28 19 | * 描述 : 20 | * 版本 : 1.0 21 | *22 | */ 23 | 24 | public class DialogTipActivity extends AppCompatActivity implements View.OnClickListener 25 | { 26 | public static final String LOADING_玩命 = "玩命加载中..."; 27 | private final String sucTip = "发送成功"; 28 | private final String failTip = "发送失败"; 29 | private final String infoTip = "字数太多就分段显示,保证textview的宽度"; 30 | 31 | private Context mContext; 32 | public TipLoadDialog tipLoadDialog; 33 | private Button mLoading; 34 | private Button mSuccessTip; 35 | private Button mFailTip; 36 | private Button mInfoTip; 37 | private Button mToastTip; 38 | private Button mThemeTip; 39 | private Button mCornerTip; 40 | private Button mIconTip; 41 | private Button mBgTip; 42 | private Button mMsgColorTip; 43 | private Button mLvColorTip; 44 | private Button mLvTimeTip; 45 | private Button mDisListenerTip; 46 | private Button mTipTimeTip; 47 | private Button mLoading2; 48 | private Button mLogin1; 49 | private Button mLogin2; 50 | 51 | 52 | @Override 53 | protected void onCreate(@Nullable Bundle savedInstanceState) 54 | { 55 | super.onCreate(savedInstanceState); 56 | setContentView(R.layout.activity_main); 57 | mContext = this; 58 | tipLoadDialog = new TipLoadDialog(this); 59 | initView(); 60 | initListener(); 61 | } 62 | 63 | private void initView() 64 | { 65 | mLoading = (Button) findViewById(R.id.loading); 66 | mSuccessTip = (Button) findViewById(R.id.success_tip); 67 | mFailTip = (Button) findViewById(R.id.fail_tip); 68 | mInfoTip = (Button) findViewById(R.id.info_tip); 69 | mToastTip = (Button) findViewById(R.id.toast_tip); 70 | mThemeTip = (Button) findViewById(R.id.theme_tip); 71 | mCornerTip = (Button) findViewById(R.id.corner_tip); 72 | mIconTip = (Button) findViewById(R.id.icon_tip); 73 | mBgTip = (Button) findViewById(R.id.bg_tip); 74 | mMsgColorTip = (Button) findViewById(R.id.msg_color_tip); 75 | mLvColorTip = (Button) findViewById(R.id.lv_color_tip); 76 | mLvTimeTip = (Button) findViewById(R.id.lv_time_tip); 77 | mDisListenerTip = (Button) findViewById(R.id.dis_listener_tip); 78 | mTipTimeTip = (Button) findViewById(R.id.tip_time_tip); 79 | mLoading2 = (Button) findViewById(R.id.loading2); 80 | mLogin1 = (Button) findViewById(R.id.login1); 81 | mLogin2 = (Button) findViewById(R.id.login2); 82 | } 83 | 84 | private void initListener() 85 | { 86 | mLoading.setOnClickListener(this); 87 | mSuccessTip.setOnClickListener(this); 88 | mFailTip.setOnClickListener(this); 89 | mInfoTip.setOnClickListener(this); 90 | mToastTip.setOnClickListener(this); 91 | mThemeTip.setOnClickListener(this); 92 | mCornerTip.setOnClickListener(this); 93 | mIconTip.setOnClickListener(this); 94 | mBgTip.setOnClickListener(this); 95 | mMsgColorTip.setOnClickListener(this); 96 | mLvColorTip.setOnClickListener(this); 97 | mLvTimeTip.setOnClickListener(this); 98 | mDisListenerTip.setOnClickListener(this); 99 | mTipTimeTip.setOnClickListener(this); 100 | mLoading2.setOnClickListener(this); 101 | mLogin1.setOnClickListener(this); 102 | mLogin2.setOnClickListener(this); 103 | } 104 | 105 | @Override 106 | public void onClick(View view) 107 | { 108 | switch (view.getId()) 109 | { 110 | case R.id.loading: 111 | //默认是无阴影主题 112 | tipLoadDialog.setMsgAndType(LOADING_玩命, TipLoadDialog.ICON_TYPE_LOADING).show(); 113 | break; 114 | case R.id.success_tip: 115 | //设置无阴影主题 116 | tipLoadDialog.setNoShadowTheme().setMsgAndType(sucTip, TipLoadDialog.ICON_TYPE_SUCCESS).show(); 117 | break; 118 | case R.id.fail_tip: 119 | //设置无阴影主题 120 | tipLoadDialog.setNoShadowTheme().setMsgAndType(failTip, TipLoadDialog.ICON_TYPE_FAIL).show(); 121 | break; 122 | case R.id.info_tip: 123 | //设置无阴影主题 124 | tipLoadDialog.setNoShadowTheme().setMsgAndType(infoTip, TipLoadDialog.ICON_TYPE_INFO).show(); 125 | break; 126 | case R.id.toast_tip: 127 | //设置提示框阴影主题 128 | tipLoadDialog.setShadowTheme().setMsgAndType(sucTip, TipLoadDialog.ICON_TYPE_SUCCESS).show(); 129 | break; 130 | case R.id.theme_tip: 131 | //设置加载框阴影主题 132 | tipLoadDialog.setShadowTheme().setMsgAndType(LOADING_玩命, TipLoadDialog.ICON_TYPE_LOADING).show(); 133 | break; 134 | case R.id.corner_tip: 135 | //设置圆角 136 | tipLoadDialog.setBackground(R.drawable.custom_dialog_bg_corner) 137 | .setNoShadowTheme() 138 | .setMsgAndType(LOADING_玩命, TipLoadDialog.ICON_TYPE_LOADING) 139 | .show(); 140 | break; 141 | case R.id.icon_tip: 142 | //设置除了Loading之外的tip图标 143 | tipLoadDialog.setSuccessIcon(R.mipmap.custom_tip) 144 | .setMsgAndType(sucTip, TipLoadDialog.ICON_TYPE_SUCCESS) 145 | .show(); 146 | break; 147 | case R.id.bg_tip: 148 | //设置背景颜色 149 | tipLoadDialog.setBackground(R.drawable.custom_dialog_bg_color) 150 | .setNoShadowTheme() 151 | .setMsgAndType(sucTip, TipLoadDialog.ICON_TYPE_SUCCESS) 152 | .show(); 153 | break; 154 | case R.id.msg_color_tip: 155 | //设置提示信息的text的颜色和大小 156 | tipLoadDialog.setNoShadowTheme() 157 | .setMsgColor(Color.BLUE) 158 | .setMsgSize(20) 159 | .setMsgAndType(failTip, TipLoadDialog.ICON_TYPE_FAIL) 160 | .show(); 161 | break; 162 | case R.id.lv_color_tip: 163 | //设置加载框文字的颜色和大小 以及progressbar的颜色 164 | tipLoadDialog.setNoShadowTheme() 165 | .setProgressbarColor(Color.RED) 166 | .setLoadingTextColor(Color.RED) 167 | .setLoadingTextSize(20) 168 | .setMsgAndType(LOADING_玩命, TipLoadDialog.ICON_TYPE_LOADING) 169 | .show(); 170 | break; 171 | case R.id.lv_time_tip: 172 | //设置loadingText一次动画的时间 173 | tipLoadDialog.setNoShadowTheme() 174 | .setProgressbarColor(Color.WHITE) 175 | .setLoadingTextColor(Color.WHITE) 176 | .setLoadingTextSize(15) 177 | .setLoadingTime(10000) 178 | .setMsgAndType(LOADING_玩命, TipLoadDialog.ICON_TYPE_LOADING) 179 | .show(); 180 | break; 181 | case R.id.dis_listener_tip: 182 | //弹窗消失事件监听 183 | tipLoadDialog.setNoShadowTheme() 184 | .setMsgAndType("登录成功", TipLoadDialog.ICON_TYPE_SUCCESS) 185 | .setDismissListener(new TipLoadDialog.DismissListener() 186 | { 187 | @Override 188 | public void onDimissListener() 189 | { 190 | startActivity(new Intent(DialogTipActivity.this, HomeActivity.class)); 191 | //然后可以finish掉当前登录页 192 | } 193 | }) 194 | .show(); 195 | break; 196 | case R.id.tip_time_tip: 197 | //设置tip提示弹框时间 198 | tipLoadDialog.setNoShadowTheme() 199 | .setMsgAndType("停留2秒消失", TipLoadDialog.ICON_TYPE_SUCCESS) 200 | .setTipTime(2000) 201 | .show(); 202 | break; 203 | case R.id.loading2: 204 | //设置另一种loading文字动画,注意不要加后缀... 205 | tipLoadDialog.setNoShadowTheme() 206 | .setMsgAndType("加载中", TipLoadDialog.ICON_TYPE_LOADING2) 207 | .show(); 208 | break; 209 | case R.id.login1: 210 | tipLoadDialog.setMsgAndType("登录中...", TipLoadDialog.ICON_TYPE_LOADING).show(); 211 | startThread(); 212 | break; 213 | case R.id.login2: 214 | tipLoadDialog.setNoShadowTheme().setMsgAndType("登录中", TipLoadDialog.ICON_TYPE_LOADING2).show(); 215 | startThread(); 216 | break; 217 | default: 218 | 219 | break; 220 | } 221 | } 222 | 223 | private void startThread() 224 | { 225 | new Thread(new Runnable() 226 | { 227 | @Override 228 | public void run() 229 | { 230 | try 231 | { 232 | Thread.sleep(2000); 233 | } catch (InterruptedException e) 234 | { 235 | e.printStackTrace(); 236 | } 237 | runOnUiThread(new Runnable() 238 | { 239 | @Override 240 | public void run() 241 | { 242 | tipLoadDialog.setMsgAndType("登录成功", TipLoadDialog.ICON_TYPE_SUCCESS) 243 | .setDismissListener(new TipLoadDialog.DismissListener() 244 | { 245 | @Override 246 | public void onDimissListener() 247 | { 248 | startActivity(new Intent(DialogTipActivity.this, HomeActivity.class)); 249 | //然后可以finish掉当前登录页 250 | } 251 | }).show(); 252 | } 253 | }); 254 | } 255 | }).start(); 256 | } 257 | 258 | /** 259 | * 配置,操作dialog 260 | * 261 | * @param type 262 | * @param msg 263 | */ 264 | public void showDialog(Context context, String msg, int type) 265 | { 266 | if (tipLoadDialog == null) 267 | { 268 | tipLoadDialog = new TipLoadDialog(context, msg, type); 269 | } 270 | if (tipLoadDialog.isShowing()) 271 | { 272 | tipLoadDialog.dismiss(); 273 | } 274 | tipLoadDialog.setMsgAndType(msg, type).show(); 275 | } 276 | } 277 | -------------------------------------------------------------------------------- /dialogtiplib/src/main/java/com/xiaokun/dialogtiplib/dialog_tip/TipLoadDialog.java: -------------------------------------------------------------------------------- 1 | package com.xiaokun.dialogtiplib.dialog_tip; 2 | 3 | import android.app.Dialog; 4 | import android.content.Context; 5 | import android.content.res.ColorStateList; 6 | import android.graphics.PorterDuff; 7 | import android.os.Build; 8 | import android.os.Handler; 9 | import android.os.Looper; 10 | import android.support.annotation.NonNull; 11 | import android.support.annotation.StyleRes; 12 | import android.support.v4.content.ContextCompat; 13 | import android.util.TypedValue; 14 | import android.view.KeyEvent; 15 | import android.view.LayoutInflater; 16 | import android.view.View; 17 | import android.widget.FrameLayout; 18 | import android.widget.ImageView; 19 | import android.widget.LinearLayout; 20 | import android.widget.ProgressBar; 21 | import android.widget.TextView; 22 | 23 | import com.xiaokun.dialogtiplib.R; 24 | import com.xiaokun.dialogtiplib.util.DimenUtils; 25 | 26 | /** 27 | * @author xiaokun 28 | * @date 2017/12/14 29 | */ 30 | 31 | public class TipLoadDialog 32 | { 33 | /** 34 | * 不显示任何icon 35 | */ 36 | public static final int ICON_TYPE_NOTHING = 0; 37 | /** 38 | * Loading状态 39 | */ 40 | public static final int ICON_TYPE_LOADING = 1; 41 | 42 | /** 43 | * loading状态2 44 | */ 45 | public static final int ICON_TYPE_LOADING2 = 5; 46 | 47 | /** 48 | * 显示成功状态 49 | */ 50 | public static final int ICON_TYPE_SUCCESS = 2; 51 | /** 52 | * 显示失败状态 53 | */ 54 | public static final int ICON_TYPE_FAIL = 3; 55 | /** 56 | * 显示信息状态 57 | */ 58 | public static final int ICON_TYPE_INFO = 4; 59 | 60 | /** 61 | * 默认成功图标 62 | */ 63 | public int SUCCESS_ICON = R.mipmap.qmui_icon_notify_done; 64 | /** 65 | * 默认失败图标 66 | */ 67 | public int ERROR_ICON = R.mipmap.qmui_icon_notify_error; 68 | /** 69 | * 默认提示信息图标 70 | */ 71 | public int INFO_ICON = R.mipmap.qmui_icon_notify_done; 72 | 73 | private static Handler sHandler = new Handler(Looper.getMainLooper()); 74 | private MyDialog dialog; 75 | private final GraduallyTextView loadText; 76 | private final ImageView img; 77 | private final TextView msg; 78 | private final ProgressBar progressBar; 79 | private final LinearLayout layout; 80 | private FadeInTextView loadText2; 81 | private Context mContext; 82 | private int currentType; 83 | private int dismissTime = 1000; 84 | private View view; 85 | /** 86 | * 消失监听 87 | */ 88 | private DismissListener listener; 89 | 90 | 91 | public interface DismissListener 92 | { 93 | void onDimissListener(); 94 | } 95 | 96 | public TipLoadDialog setDismissListener(DismissListener dismissListener) 97 | { 98 | this.listener = dismissListener; 99 | return this; 100 | } 101 | 102 | public TipLoadDialog(Context context) 103 | { 104 | this(context, "", ICON_TYPE_LOADING); 105 | } 106 | 107 | public TipLoadDialog(Context context, String info, int type) 108 | { 109 | this.mContext = context; 110 | this.currentType = type; 111 | view = LayoutInflater.from(context).inflate(R.layout.tip_dialog_view, null); 112 | layout = (LinearLayout) view.findViewById(R.id.dialog_view); 113 | img = (ImageView) view.findViewById(R.id.tip_img); 114 | msg = (TextView) view.findViewById(R.id.tip_text); 115 | progressBar = (ProgressBar) view.findViewById(R.id.lv_circularring); 116 | loadText = (GraduallyTextView) view.findViewById(R.id.loading_text); 117 | loadText2 = (FadeInTextView) view.findViewById(R.id.loading_text2); 118 | changeUi(info, type); 119 | setNoShadowTheme(); 120 | } 121 | 122 | private void changeUi(String info, int type) 123 | { 124 | loadText.setText(info); 125 | loadText2.setTextString(info + ".", "..."); 126 | msg.setText(info); 127 | 128 | if (type == ICON_TYPE_SUCCESS) 129 | { 130 | img.setImageDrawable(ContextCompat.getDrawable(mContext, SUCCESS_ICON)); 131 | img.setVisibility(View.VISIBLE); 132 | msg.setVisibility(View.VISIBLE); 133 | progressBar.setVisibility(View.GONE); 134 | loadText.setVisibility(View.GONE); 135 | loadText2.setVisibility(View.GONE); 136 | } else if (type == ICON_TYPE_FAIL) 137 | { 138 | img.setImageDrawable(ContextCompat.getDrawable(mContext, ERROR_ICON)); 139 | img.setVisibility(View.VISIBLE); 140 | msg.setVisibility(View.VISIBLE); 141 | progressBar.setVisibility(View.GONE); 142 | loadText.setVisibility(View.GONE); 143 | loadText2.setVisibility(View.GONE); 144 | } else if (type == ICON_TYPE_INFO) 145 | { 146 | img.setImageDrawable(ContextCompat.getDrawable(mContext, INFO_ICON)); 147 | img.setVisibility(View.VISIBLE); 148 | msg.setVisibility(View.VISIBLE); 149 | progressBar.setVisibility(View.GONE); 150 | loadText.setVisibility(View.GONE); 151 | loadText2.setVisibility(View.GONE); 152 | } else if (type == ICON_TYPE_LOADING) 153 | { 154 | img.setVisibility(View.GONE); 155 | msg.setVisibility(View.GONE); 156 | progressBar.setVisibility(View.VISIBLE); 157 | loadText.setVisibility(View.VISIBLE); 158 | loadText2.setVisibility(View.GONE); 159 | } else if (type == ICON_TYPE_LOADING2) 160 | { 161 | img.setVisibility(View.GONE); 162 | msg.setVisibility(View.GONE); 163 | progressBar.setVisibility(View.VISIBLE); 164 | loadText.setVisibility(View.GONE); 165 | loadText2.setVisibility(View.VISIBLE); 166 | } 167 | } 168 | 169 | /** 170 | * 设置成功图标 171 | * 注意:如果要更改icon需要在setMsg方法之前调用此方法,否则无效 172 | * 173 | * @param resId 174 | * @return 175 | */ 176 | public TipLoadDialog setSuccessIcon(int resId) 177 | { 178 | SUCCESS_ICON = resId; 179 | return this; 180 | } 181 | 182 | /** 183 | * 设置错误图标 184 | * 注意:如果要更改icon需要在setMsg方法之前调用此方法 185 | * 186 | * @param resId 187 | * @return 188 | */ 189 | public TipLoadDialog setErrorIcon(int resId) 190 | { 191 | ERROR_ICON = resId; 192 | return this; 193 | } 194 | 195 | /** 196 | * 设置提示图标 197 | * 注意:如果要更改icon需要在setMsg方法之前调用此方法 198 | * 199 | * @param resId icon的资源路径 200 | * @return 201 | */ 202 | public TipLoadDialog setInfoIcon(int resId) 203 | { 204 | INFO_ICON = resId; 205 | return this; 206 | } 207 | 208 | /** 209 | * 设置消息和样式 210 | * 211 | * @param info 212 | * @param type 213 | */ 214 | public TipLoadDialog setMsgAndType(String info, int type) 215 | { 216 | this.currentType = type; 217 | changeUi(info, type); 218 | 219 | if (type != ICON_TYPE_LOADING) 220 | { 221 | img.post(new Runnable() 222 | { 223 | @Override 224 | public void run() 225 | { 226 | /** 227 | * 88dp = width - paddingLeft -paddingRight ; 228 | * 1.icon的宽度<88dp,则设置msg的最大宽度为88dp 229 | * 2.icon的宽度>88dp,则设置msg的最大宽度为icon宽度 230 | * 231 | * 88太小 设置为200 232 | */ 233 | int maxWidth = DimenUtils.dpToPxInt(200); 234 | int width = img.getWidth(); 235 | if (maxWidth > width) 236 | { 237 | msg.setMaxWidth(maxWidth); 238 | } else 239 | { 240 | msg.setMaxWidth(width); 241 | } 242 | } 243 | }); 244 | } 245 | return this; 246 | } 247 | 248 | /** 249 | * 设置背景,包括圆角和背景颜色 250 | * 251 | * @param drawableId 252 | * @return 253 | */ 254 | public TipLoadDialog setBackground(int drawableId) 255 | { 256 | layout.setBackgroundResource(drawableId); 257 | return this; 258 | } 259 | 260 | /** 261 | * 设置默认主题,无阴影 262 | * 263 | * @return 264 | */ 265 | public TipLoadDialog setNoShadowTheme() 266 | { 267 | if (dialog != null) 268 | { 269 | FrameLayout parent = (FrameLayout) layout.getParent(); 270 | parent.removeAllViews(); 271 | } 272 | dialog = new MyDialog(mContext, R.style.loading_dialog_no_shadow); 273 | initDialog(); 274 | return this; 275 | } 276 | 277 | /** 278 | * 设置浮动层有阴影主题 279 | * 280 | * @return 281 | */ 282 | public TipLoadDialog setShadowTheme() 283 | { 284 | if (dialog != null) 285 | { 286 | FrameLayout parent = (FrameLayout) layout.getParent(); 287 | parent.removeAllViews(); 288 | } 289 | dialog = new MyDialog(mContext, R.style.loading_dialog_with_shadow); 290 | initDialog(); 291 | return this; 292 | } 293 | 294 | /** 295 | * 自定义dialog主题 296 | * 297 | * @param themeId 298 | * @return 299 | */ 300 | public TipLoadDialog setDialogTheme(int themeId) 301 | { 302 | if (dialog != null) 303 | { 304 | FrameLayout parent = (FrameLayout) layout.getParent(); 305 | parent.removeAllViews(); 306 | } 307 | dialog = new MyDialog(mContext, themeId); 308 | initDialog(); 309 | return this; 310 | } 311 | 312 | private void initDialog() 313 | { 314 | dialog.setCancelable(true); 315 | dialog.setCanceledOnTouchOutside(false); 316 | dialog.setContentView(layout, new LinearLayout.LayoutParams( 317 | LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)); 318 | } 319 | 320 | /** 321 | * 设置msg字体颜色 322 | * 323 | * @param resColorId 324 | * @return 325 | */ 326 | public TipLoadDialog setMsgColor(int resColorId) 327 | { 328 | msg.setTextColor(resColorId); 329 | return this; 330 | } 331 | 332 | /** 333 | * 设置msg字体大小 334 | * 335 | * @param sp 336 | * @return 337 | */ 338 | public TipLoadDialog setMsgSize(int sp) 339 | { 340 | msg.setTextSize(TypedValue.COMPLEX_UNIT_SP, sp); 341 | return this; 342 | } 343 | 344 | /** 345 | * 设置progressbar color 346 | * 注意:只是在api 21以上才有用 347 | * 348 | * @param color 349 | * @return 350 | */ 351 | public TipLoadDialog setProgressbarColor(int color) 352 | { 353 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) 354 | { 355 | progressBar.setIndeterminateTintMode(PorterDuff.Mode.SRC_ATOP); 356 | progressBar.setIndeterminateTintList(ColorStateList.valueOf(color)); 357 | } 358 | return this; 359 | } 360 | 361 | /** 362 | * 设置加载文字颜色 363 | * 364 | * @param color 365 | * @return 366 | */ 367 | public TipLoadDialog setLoadingTextColor(int color) 368 | { 369 | loadText.setTextColor(color); 370 | return this; 371 | } 372 | 373 | /** 374 | * 设置加载文字大小 375 | * 376 | * @param sp 377 | * @return 378 | */ 379 | public TipLoadDialog setLoadingTextSize(int sp) 380 | { 381 | loadText.setTextSize(TypedValue.COMPLEX_UNIT_SP, sp); 382 | return this; 383 | } 384 | 385 | /** 386 | * 设置加载一次文字的动画时间 387 | * 388 | * @param duration 389 | * @return 390 | */ 391 | public TipLoadDialog setLoadingTime(int duration) 392 | { 393 | loadText.setDuration(duration); 394 | return this; 395 | } 396 | 397 | /** 398 | * 设置tip提示框时间 399 | * 400 | * @param duration 毫秒 401 | * @return 402 | */ 403 | public TipLoadDialog setTipTime(int duration) 404 | { 405 | this.dismissTime = duration; 406 | return this; 407 | } 408 | 409 | /** 410 | * 配置是否能返回键取消加载框 411 | * 412 | * @param flag 413 | */ 414 | public void setCancelable(boolean flag) 415 | { 416 | dialog.setCancelable(flag); 417 | } 418 | 419 | /** 420 | * 配置是否能点击框外取消加载框 421 | * 422 | * @param cancel 423 | */ 424 | public void setCanceledOnTouchOutside(boolean cancel) 425 | { 426 | dialog.setCanceledOnTouchOutside(cancel); 427 | } 428 | 429 | /** 430 | * 是否显示 431 | * 432 | * @return 433 | */ 434 | public boolean isShowing() 435 | { 436 | return dialog.isShowing(); 437 | } 438 | 439 | /** 440 | * 显示,默认提示框(非加载框)1s延迟后消失 441 | */ 442 | public void show() 443 | { 444 | dialog.show(); 445 | if (loadText.getVisibility() == View.VISIBLE) 446 | { 447 | loadText.startLoading(); 448 | } 449 | if (loadText2.getVisibility() == View.VISIBLE) 450 | { 451 | loadText2.startFadeInAnimation(); 452 | } 453 | //移除所有的message和callback, 454 | // 防止返回键dismiss后,callback没移除 455 | sHandler.removeCallbacksAndMessages(null); 456 | if (this.currentType != ICON_TYPE_LOADING && this.currentType != ICON_TYPE_LOADING2) 457 | { 458 | if (loadText2.isLoading()) 459 | { 460 | loadText2.stopFadeInAnimation(); 461 | } 462 | if (loadText.isLoading()) 463 | { 464 | loadText.stopLoading(); 465 | } 466 | sHandler.postDelayed(new Runnable() 467 | { 468 | @Override 469 | public void run() 470 | { 471 | dismiss(); 472 | } 473 | }, dismissTime); 474 | } 475 | } 476 | 477 | /** 478 | * 消失 479 | */ 480 | public void dismiss() 481 | { 482 | dialog.dismiss(); 483 | if (loadText.isLoading()) 484 | { 485 | loadText.stopLoading(); 486 | } 487 | if (loadText2.isLoading()) 488 | { 489 | loadText2.stopFadeInAnimation(); 490 | } 491 | if (listener != null) 492 | { 493 | listener.onDimissListener(); 494 | } 495 | } 496 | 497 | class MyDialog extends Dialog 498 | { 499 | 500 | public MyDialog(@NonNull Context context, @StyleRes int themeResId) 501 | { 502 | super(context, themeResId); 503 | } 504 | 505 | @Override 506 | public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) 507 | { 508 | if (keyCode == KeyEvent.KEYCODE_BACK) 509 | { 510 | //拦截back键,防止loadview的内存泄漏 511 | dialog.dismiss(); 512 | if (loadText.isLoading()) 513 | { 514 | loadText.stopLoading(); 515 | } 516 | if (loadText2.isLoading()) 517 | { 518 | loadText2.stopFadeInAnimation(); 519 | } 520 | } 521 | return super.onKeyDown(keyCode, event); 522 | } 523 | } 524 | 525 | } 526 | --------------------------------------------------------------------------------