初始化

This commit is contained in:
2024-10-21 10:31:06 +08:00
parent 80a5170bbf
commit b64a200deb
364 changed files with 24276 additions and 0 deletions
+15
View File
@@ -0,0 +1,15 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
+116
View File
@@ -0,0 +1,116 @@
plugins {
id 'com.android.library'
id 'kotlin-android'
// id 'com.jakewharton.butterknife'
}
android {
compileSdkVersion rootProject.ext.android["compileSdkVersion"]
defaultConfig {
minSdkVersion rootProject.ext.android["minSdkVersion"]
targetSdkVersion rootProject.ext.android["targetSdkVersion"]
versionCode rootProject.ext.android["versionCode"]
versionName rootProject.ext.android["versionName"]
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = '11'
}
buildFeatures {
viewBinding = true
}
// // 添加模块名称
namespace = "com.dahe.mylibrary"
}
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
api rootProject.ext.dependencies["gson"]
api rootProject.ext.dependencies["glide"]
annotationProcessor rootProject.ext.dependencies["glide-compiler"]
api rootProject.ext.dependencies["agentweb"]
api rootProject.ext.dependencies["Banner"]
api rootProject.ext.dependencies["RefreshLayout"]
api rootProject.ext.dependencies["Header"]
api rootProject.ext.dependencies["Footer"]
api rootProject.ext.dependencies["rxjava"]
api rootProject.ext.dependencies["rxandroid"]
api rootProject.ext.dependencies["retrofit"]
api rootProject.ext.dependencies["converter-gson"]
api rootProject.ext.dependencies["adapter-rxjava2"]
api rootProject.ext.dependencies["okhttp"]
api rootProject.ext.dependencies["logging-interceptor"]
// api rootProject.ext.dependencies["recyclerview"]
api rootProject.ext.dependencies["AutoSize"]
api rootProject.ext.dependencies["statusbaruitl"]
api rootProject.ext.dependencies["BaseRecyclerViewAdapterHelper"]
api rootProject.ext.dependencies["PhotoPicker"]
api rootProject.ext.dependencies["PickerView"]
api rootProject.ext.dependencies["Xpopup"]
api rootProject.ext.dependencies["Countdownview"]
api rootProject.ext.dependencies["CheckVersionLib"]
api rootProject.ext.dependencies["Bugly"]
api rootProject.ext.dependencies["Zxing"]
api rootProject.ext.dependencies["Multidex"]
api rootProject.ext.dependencies["FlycoTabLayout"]
api rootProject.ext.dependencies["NiceDialog"]
api rootProject.ext.dependencies["MagicIndicator"]
api rootProject.ext.dependencies["glide-okhttps"]
api rootProject.ext.dependencies["Permissionx"]
api rootProject.ext.dependencies["NiceSpinner"]
api 'pub.devrel:easypermissions:3.0.0'
api 'io.github.lucksiege:compress:v3.11.2'
api 'androidx.cardview:cardview:1.0.0'
api rootProject.ext.dependencies["WheelPicker"]
api rootProject.ext.dependencies["AddressPicker"]
// api 'com.gyf.cactus:cactus:1.1.3-beta13'
// implementation "io.github.cymchad:BaseRecyclerViewAdapterHelper:4.0.1"
//友盟基础库(必须)
// api 'com.umeng.umsdk:common:9.4.4'
// api 'com.umeng.umsdk:asms:1.4.1'
//
// //友盟推送库
// api 'com.umeng.umsdk:push:6.4.5'
//
// api 'com.umeng.umsdk:huawei-umengaccs:1.3.5'
// api 'com.huawei.hms:push:5.3.0.304'
// api('com.aliyun.ams:alicloud-android-hotfix:3.3.0') {
// exclude(module: 'alicloud-android-ut')
// exclude(module: 'alicloud-android-utdid')
// exclude(module: 'alicloud-android-utils')
// }
api 'com.aliyun.dpa:oss-android-sdk:2.9.5'
}
View File
+21
View File
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
@@ -0,0 +1,24 @@
package com.dahe.mylibrary
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.dahe.mylibrary.test", appContext.packageName)
}
}
+29
View File
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.dahe.mylibrary">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:supportsRtl="true">
<meta-data
android:name="design_width_in_dp"
android:value="360" />
<meta-data
android:name="design_height_in_dp"
android:value="640" />
<!-- <meta-data-->
<!-- android:name=".AppGlideModule"-->
<!-- android:value="AppGlideModule"/>-->
</application>
</manifest>
@@ -0,0 +1,138 @@
package com.dahe.mylibrary;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.os.Bundle;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.scwang.smart.refresh.footer.ClassicsFooter;
import com.scwang.smart.refresh.header.ClassicsHeader;
import com.scwang.smart.refresh.layout.SmartRefreshLayout;
import com.scwang.smart.refresh.layout.api.RefreshFooter;
import com.scwang.smart.refresh.layout.api.RefreshHeader;
import com.scwang.smart.refresh.layout.api.RefreshLayout;
import com.scwang.smart.refresh.layout.listener.DefaultRefreshFooterCreator;
import com.scwang.smart.refresh.layout.listener.DefaultRefreshHeaderCreator;
import java.lang.ref.WeakReference;
import java.util.LinkedList;
import java.util.List;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
/**
* Created by Administrator on 2018/7/15 0015.
*/
public class CommonBaseLibrary {
public volatile static CommonBaseLibrary mInstance = null;
private static Application mApplication = null;
public static WeakReference<Activity> topActivity;
public static List<Activity> activityList = new LinkedList<>();
private static Retrofit mRetrofit;
static {
SmartRefreshLayout.setDefaultRefreshHeaderCreator(new DefaultRefreshHeaderCreator() {
@Override
public RefreshHeader createRefreshHeader(Context context, RefreshLayout layout) {
return new ClassicsHeader(context);
}
});
SmartRefreshLayout.setDefaultRefreshFooterCreator(new DefaultRefreshFooterCreator() {
@Override
public RefreshFooter createRefreshFooter(Context context, RefreshLayout layout) {
return new ClassicsFooter(context);
}
});
}
public CommonBaseLibrary() {
}
public static CommonBaseLibrary getInstance() {
System.out.println("ceshi");
if (null == mInstance) {
synchronized (CommonBaseLibrary.class) {
if (null == mInstance) {
mInstance = new CommonBaseLibrary();
}
}
}
return mInstance;
}
public CommonBaseLibrary init(Application application, String baseUrl) {
mApplication = application;
application.registerActivityLifecycleCallbacks(mCallbacks);
Gson gson = new GsonBuilder().setDateFormat("yyy-MM-dd HH:mm:ss").create();
mRetrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.build();
// .addConverterFactory(GsonConverterFactory.create(gson))
return this;
}
public static Application getApplication() {
return mApplication;
}
public static Retrofit getRetrofit() {
if (null == mRetrofit)
throw new NullPointerException("please call CommonBaseLibrary.getInstance().init() first in application!");
return mRetrofit;
}
private static Application.ActivityLifecycleCallbacks mCallbacks = new Application.ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle bundle) {
activityList.add(activity);
setTopActivityWeakRef(activity);
}
@Override
public void onActivityStarted(Activity activity) {
setTopActivityWeakRef(activity);
}
@Override
public void onActivityResumed(Activity activity) {
setTopActivityWeakRef(activity);
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
}
@Override
public void onActivityDestroyed(Activity activity) {
activityList.remove(activity);
}
};
private static void setTopActivityWeakRef(Activity activity) {
if (topActivity == null || !activity.equals(topActivity.get())) {
topActivity = new WeakReference<>(activity);
}
}
}
@@ -0,0 +1,206 @@
package com.dahe.mylibrary.adapter
import android.content.Context
import android.net.Uri
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.dahe.mylibrary.R
import com.dahe.mylibrary.callback.OnItemLongClickListener
import com.luck.picture.lib.config.PictureMimeType
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.utils.DateUtils
/**
* @authorluck
* @date2016-7-27 23:02
* @describeGridImageAdapter
*/
class GridImageAdapter(context: Context?, result: List<LocalMedia>?) :
RecyclerView.Adapter<GridImageAdapter.ViewHolder?>() {
private val mInflater: LayoutInflater
val data = ArrayList<LocalMedia>()
var selectMax = 9
/**
* 删除
*/
fun delete(position: Int) {
try {
if (position != RecyclerView.NO_POSITION && data.size > position) {
data.removeAt(position)
notifyItemRemoved(position)
notifyItemRangeChanged(position, data.size)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
fun remove(position: Int) {
if (position < data.size) {
data.removeAt(position)
}
}
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
var mImg: ImageView
var mIvDel: ImageView
var tvDuration: TextView
init {
mImg = view.findViewById(R.id.fiv)
mIvDel = view.findViewById(R.id.iv_del)
tvDuration = view.findViewById(R.id.tv_duration)
}
}
override fun getItemCount(): Int {
return if (data.size < selectMax) {
data.size + 1
} else {
data.size
}
}
override fun getItemViewType(position: Int): Int {
return if (isShowAddItem(position)) {
TYPE_CAMERA
} else {
TYPE_PICTURE
}
}
/**
* 创建ViewHolder
*/
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): ViewHolder {
val view = mInflater.inflate(R.layout.gv_filter_image, viewGroup, false)
return ViewHolder(view)
}
private fun isShowAddItem(position: Int): Boolean {
val size = data.size
return position == size
}
/**
* 设置值
*/
override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
//少于MaxSize张,显示继续添加的图标
if (getItemViewType(position) == TYPE_CAMERA) {
viewHolder.mImg.setImageResource(R.drawable.ic_add_image)
viewHolder.mImg.setOnClickListener {
if (mItemClickListener != null) {
mItemClickListener!!.openPicture()
}
}
viewHolder.mIvDel.visibility = View.INVISIBLE
} else {
viewHolder.mIvDel.visibility = View.VISIBLE
viewHolder.mIvDel.setOnClickListener { view: View? ->
val index = viewHolder.absoluteAdapterPosition
if (index != RecyclerView.NO_POSITION && data.size > index) {
data.removeAt(index)
notifyItemRemoved(index)
notifyItemRangeChanged(index, data.size)
}
}
val media = data[position]
val chooseModel = media.chooseModel
val path = media.availablePath
val duration = media.duration
viewHolder.tvDuration.visibility =
if (PictureMimeType.isHasVideo(media.mimeType)) View.VISIBLE else View.GONE
if (chooseModel == SelectMimeType.ofAudio()) {
viewHolder.tvDuration.visibility = View.VISIBLE
viewHolder.tvDuration.setCompoundDrawablesRelativeWithIntrinsicBounds(
R.drawable.ps_ic_audio,
0,
0,
0
)
} else {
viewHolder.tvDuration.setCompoundDrawablesRelativeWithIntrinsicBounds(
R.drawable.ps_ic_video,
0,
0,
0
)
}
viewHolder.tvDuration.text = DateUtils.formatDurationTime(duration)
if (chooseModel == SelectMimeType.ofAudio()) {
viewHolder.mImg.setImageResource(R.drawable.ps_audio_placeholder)
} else {
Glide.with(viewHolder.itemView.context)
.load(
if (PictureMimeType.isContent(path) && !media.isCut && !media.isCompressed) Uri.parse(
path
) else path
)
.centerCrop()
.placeholder(R.color.app_color_f6)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(viewHolder.mImg)
}
//itemView 的点击事件
if (mItemClickListener != null) {
viewHolder.itemView.setOnClickListener { v: View? ->
val adapterPosition = viewHolder.absoluteAdapterPosition
mItemClickListener!!.onItemClick(v, adapterPosition)
}
}
if (mItemLongClickListener != null) {
viewHolder.itemView.setOnLongClickListener { v: View? ->
val adapterPosition = viewHolder.absoluteAdapterPosition
mItemLongClickListener!!.onItemLongClick(viewHolder, adapterPosition, v)
true
}
}
}
}
private var mItemClickListener: OnItemClickListener? = null
fun setOnItemClickListener(l: OnItemClickListener?) {
mItemClickListener = l
}
interface OnItemClickListener {
/**
* Item click event
*
* @param v
* @param position
*/
fun onItemClick(v: View?, position: Int)
/**
* Open PictureSelector
*/
fun openPicture()
}
private var mItemLongClickListener: OnItemLongClickListener? = null
init {
mInflater = LayoutInflater.from(context)
data.addAll(result!!)
}
fun setItemLongClickListener(l: OnItemLongClickListener?) {
mItemLongClickListener = l
}
companion object {
const val TAG = "PictureSelector"
const val TYPE_CAMERA = 1
const val TYPE_PICTURE = 2
}
}
@@ -0,0 +1,313 @@
package com.dahe.mylibrary.base;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.ColorRes;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.viewbinding.ViewBinding;
import com.dahe.mylibrary.R;
import com.dahe.mylibrary.callback.RefreshCallBack;
import com.dahe.mylibrary.utils.BarUtils;
import com.dahe.mylibrary.utils.ConvertUtils;
import com.dahe.mylibrary.utils.StatusBar;
import com.dahe.mylibrary.utils.ToastUtils;
import com.scwang.smart.refresh.layout.SmartRefreshLayout;
import com.scwang.smart.refresh.layout.api.RefreshLayout;
import com.scwang.smart.refresh.layout.constant.RefreshState;
import com.scwang.smart.refresh.layout.listener.OnRefreshLoadMoreListener;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import qiu.niorgai.StatusBarCompat;
public abstract class BaseActivity<VB extends ViewBinding> extends AppCompatActivity {
protected Context mContext;
protected final int DEFAULT_STATUS_BAR_ALPHA = 0;
private static final String TAG = "BaseActivity";
protected Toolbar mToolbar;
protected int mRefreshPage = 1;
protected int mRefreshCount = 15;
private int statusColor = -1;
public VB binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = createBinding();
if (binding == null)
return;
setContentView(binding.getRoot());
mContext = this;
setStatusBarColorToLight();
initView(savedInstanceState);
initDate();
}
private VB createBinding() {
try {
Class<VB> vbClass = getVBClass();
Method inflateMethod = vbClass.getMethod("inflate", LayoutInflater.class);
inflateMethod.setAccessible(true);
return (VB) inflateMethod.invoke(null, getLayoutInflater());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private Class<VB> getVBClass() {
ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();
Class<VB> vbClass = (Class<VB>) type.getActualTypeArguments()[0];
return vbClass;
}
// protected abstract VB getViewBinding();
/**
* 标题栏的颜色 文字白色
*/
public void setStatusBarCancelLightColor() {
StatusBar.cancelLightStatusBar(this);
}
/**
* 设置沉浸式标题栏 标题栏的颜色
*/
public void setStatusBarColor(int color) {
statusColor = color;
StatusBarCompat.setStatusBarColor(this, ContextCompat.getColor(mContext, color), DEFAULT_STATUS_BAR_ALPHA);
StatusBar.changeToLightStatusBar(this); //黑色 下边白色
// StatusBar.cancelLightStatusBar(this);
}
/**
* 设置沉浸式标题栏 标题栏的颜色
*/
public void setStatusBarColor() {
// StatusBarCompat.setStatusBarColor(this, ContextCompat.getColor(mContext, color), DEFAULT_STATUS_BAR_ALPHA);
// StatusBar.changeToLightStatusBar(this); //黑色 下边白色
StatusBar.cancelLightStatusBar(this);
}
/**
* 设置沉浸式标题栏 里面是Fragment
*/
public void setStatusBarColorInFragment() {
StatusBarCompat.translucentStatusBar(this);
}
/**
* 设置透明沉浸式标题栏
* * true标题栏无背景,false标题栏有背景
*/
public void setStatusBarColorToLight() {
StatusBar.translucentStatusBar(this, true);
StatusBar.changeToLightStatusBar(this);
}
/**
* 设置透明沉浸式标题栏
* true标题栏无背景,false标题栏有背景
*/
public void setStatusBarColorToLight(boolean isHide) {
StatusBar.translucentStatusBar(this, isHide);
StatusBar.changeToLightStatusBar(this);
}
/**
* 设置标题
*/
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
protected void setTitleBar(String title, View.OnClickListener listener) {
mToolbar = (Toolbar) findViewById(R.id.common_toolbar);
if (!TextUtils.isEmpty(title))
((TextView) findViewById(R.id.common_toolBar_title)).setText(title);
mToolbar.setNavigationIcon(R.drawable.left_black);
mToolbar.setNavigationOnClickListener(listener);
}
/**
* 设置标题
*/
protected void setTitleBar(String title) {
mToolbar = (Toolbar) findViewById(R.id.common_toolbar);
if (!TextUtils.isEmpty(title))
((TextView) findViewById(R.id.common_toolBar_title)).setText(title);
}
/**
* 设置标题
*/
protected void setTitleBar(String title, boolean isBack) {
mToolbar = (Toolbar) findViewById(R.id.common_toolbar);
mToolbar.setBackgroundColor(statusColor == -1 ? Color.TRANSPARENT : ContextCompat.getColor(mContext, statusColor));
if (isBack) {
mToolbar.setNavigationIcon(R.drawable.left_black);
mToolbar.setNavigationOnClickListener(view -> finish());
}
if (!TextUtils.isEmpty(title))
((TextView) findViewById(R.id.common_toolBar_title)).setText(title);
}
/**
* 显示右边标题
*
* @param title
* @param listener
* @param isVisible
* @param right
*/
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
protected void setTitleBar(String title, View.OnClickListener listener, boolean isVisible, String right, View.OnClickListener rightListener) {
mToolbar = (Toolbar) findViewById(R.id.common_toolbar);
mToolbar.setBackgroundColor(Color.TRANSPARENT);
if (!TextUtils.isEmpty(title))
((TextView) findViewById(R.id.common_toolBar_title)).setText(title);
TextView mTextRight = (TextView) findViewById(R.id.common_toolBar_text_right);
if (isVisible) {
mTextRight.setVisibility(View.VISIBLE);
mTextRight.setText(right);
mTextRight.setOnClickListener(rightListener);
}
mToolbar.setNavigationIcon(R.drawable.left_black);
mToolbar.setNavigationOnClickListener(listener);
}
/**
* 设置距离顶部距离
*/
protected void setStatusHeightParams(View llContent) {
RelativeLayout.LayoutParams closeLayoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
closeLayoutParams.topMargin = ConvertUtils.dp2px(8) + BarUtils.getStatusBarHeight();
// closeLayoutParams.topMargin = BarUtils.getStatusBarHeight();
llContent.setLayoutParams(closeLayoutParams);
}
protected abstract void initView(Bundle savedInstanceState);
protected abstract void initDate();
protected void showToast(Object message) {
ToastUtils.showToast(this, message instanceof String ? message + "" : getResources().getString((int) message));
}
protected void canCelToast() {
ToastUtils.cancelToast();
}
// protected void showToast(Object message,int time) {
// ToastUtils.showToast(this, message instanceof String ? message + "" : getResources().getString((int) message),time);
// }
@Override
protected void onDestroy() {
super.onDestroy();
//释放持有,防止泄露
binding = null;
}
/**
* 设置刷新控件
*
* @param refreshLayout
* @param callBack 访问网络回调
*/
protected void setRefresh(final SmartRefreshLayout refreshLayout, final RefreshCallBack callBack) {
refreshLayout.setEnableOverScrollDrag(true)
.setOnRefreshLoadMoreListener(new OnRefreshLoadMoreListener() {
@Override
public void onLoadMore(@NonNull RefreshLayout refreshLayout) {
mRefreshPage++;
callBack.getRefreshDate(2, mRefreshPage, mRefreshCount);
}
@Override
public void onRefresh(@NonNull RefreshLayout refreshLayout) {
mRefreshPage = 1;
callBack.getRefreshDate(1, mRefreshPage, mRefreshCount);
}
});
}
/**
* 网络访问完成 刷新控件
*
* @param refreshLayout
* @param isLoadMore false禁用下拉加载更多
*/
protected void setFinishRefresh(final SmartRefreshLayout refreshLayout, boolean isLoadMore) {
if (refreshLayout != null && refreshLayout.getState() == RefreshState.Refreshing)
refreshLayout.finishRefresh();
else if (refreshLayout != null && refreshLayout.getState() == RefreshState.Loading)
refreshLayout.finishLoadMore();
if (!isLoadMore) {
refreshLayout.finishLoadMore(); //加载完成
refreshLayout.finishLoadMoreWithNoMoreData(); //全部加载完成,没有数据了调用此方法
}
// refreshLayout.setEnableLoadMore(isLoadMore);
}
public void onClick(View view) {
}
/**
* 获取Drawable
*
* @param id
* @return
*/
protected Drawable getDrawableV4(@DrawableRes int id) {
return ContextCompat.getDrawable(this, id);
}
/**
* 获取Color
*
* @param id
* @return
*/
protected int getColorV4(@ColorRes int id) {
return ContextCompat.getColor(this, id);
}
@Override
public void onResume() {
super.onResume();
}
@Override
public void onPause() {
super.onPause();
}
}
@@ -0,0 +1,341 @@
package com.dahe.mylibrary.base;
import android.content.Context;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.viewbinding.ViewBinding;
import com.dahe.mylibrary.R;
import com.dahe.mylibrary.callback.RefreshCallBack;
import com.dahe.mylibrary.utils.StatusBar;
import com.dahe.mylibrary.utils.ToastUtils;
import com.scwang.smart.refresh.layout.SmartRefreshLayout;
import com.scwang.smart.refresh.layout.api.RefreshLayout;
import com.scwang.smart.refresh.layout.constant.RefreshState;
import com.scwang.smart.refresh.layout.listener.OnRefreshLoadMoreListener;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import qiu.niorgai.StatusBarCompat;
/**
* <p>
* Fragment基类,封装了懒加载的实现
* <p>
* 1、Viewpager + Fragment情况下,fragment的生命周期因Viewpager的缓存机制而失去了具体意义
* 该抽象类自定义一个新的回调方法,当fragment可见状态改变时会触发的回调方法
*
* @see #onFragmentVisibleChange(boolean)
* @see #onFragmentFirstVisible()
*/
public abstract class BaseFragment<VB extends ViewBinding> extends Fragment {
private boolean isFragmentVisible;
private boolean isReuseView;
private boolean isFirstVisible;
private boolean isPause;
private View rootView;
private static final String TAG = "BaseFragment";
protected Context mContext;
protected int mRefreshPage = 1;
protected int mRefreshCount = 20;
protected Toolbar mToolbar;
protected final int DEFAULT_STATUS_BAR_ALPHA = 0;
public VB binding;
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
Log.i(TAG, "onViewCreated: " + (rootView == null) + "---getUserVisibleHint()" + getUserVisibleHint() + "---isFirstVisible" + isFirstVisible);
//如果setUserVisibleHint()在rootView创建前调用时,那么
//就等到rootView创建完后才回调onFragmentVisibleChange(true)
//保证onFragmentVisibleChange()的回调发生在rootView创建完成之后,以便支持ui操作
if (rootView == null) {
rootView = view;
if (getUserVisibleHint()) {
if (isFirstVisible) {
onFragmentFirstVisible();
isFirstVisible = false;
}
onFragmentVisibleChange(isFirstVisible);
isFragmentVisible = true;
}
}
super.onViewCreated(isReuseView && rootView != null ? rootView : view, savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
ParameterizedType superClass = (ParameterizedType) getClass().getGenericSuperclass();
try {
Class<VB> cls = (Class<VB>) superClass.getActualTypeArguments()[0];
Method method = cls.getMethod("inflate", LayoutInflater.class, ViewGroup.class, Boolean.TYPE);
method.setAccessible(true);
binding = (VB) method.invoke(null, inflater,container, Boolean.FALSE);
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
if (binding!=null&&binding.getRoot()!=null) {
mContext = getActivity();
return binding.getRoot();
} else {
return super.onCreateView(inflater, container, savedInstanceState);
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
/**
* 标题栏的颜色 文字白色
*/
public void setStatusBarCancelLightColor() {
StatusBar.cancelLightStatusBar(getActivity());
}
/**
* 设置沉浸式标题栏 标题栏的颜色
*/
public void setStatusBarColor(int color) {
StatusBarCompat.setStatusBarColor(getActivity(), ContextCompat.getColor(mContext, color), DEFAULT_STATUS_BAR_ALPHA);
StatusBar.changeToLightStatusBar(getActivity());
}
/**
* 设置沉浸式标题栏 里面是Fragment
*/
public void setStatusBarColorInFragment() {
StatusBarCompat.translucentStatusBar(getActivity());
}
public void setStatusBarColorToLight() {
StatusBar.translucentStatusBar(getActivity(), true);
StatusBar.changeToLightStatusBar(getActivity());
}
@Override
public void onDestroy() {
initVariable();
super.onDestroy();
}
protected void showToast(Object message) {
ToastUtils.showToast(mContext, message instanceof String ? message + "" : getResources().getString((int) message));
}
/**
* 设置刷新控件
*
* @param refreshLayout
* @param callBack 访问网络回调
*/
protected void setRefresh(final SmartRefreshLayout refreshLayout, final RefreshCallBack callBack) {
refreshLayout.setEnableOverScrollDrag(true)
.setOnRefreshLoadMoreListener(new OnRefreshLoadMoreListener() {
@Override
public void onLoadMore(@NonNull RefreshLayout refreshLayout) {
mRefreshPage++;
callBack.getRefreshDate(2, mRefreshPage, mRefreshCount);
}
@Override
public void onRefresh(@NonNull RefreshLayout refreshLayout) {
mRefreshPage = 1;
callBack.getRefreshDate(1, mRefreshPage, mRefreshCount);
}
});
}
/**
* 网络访问完成 刷新控件
*
* @param refreshLayout
* @param isLoadMore false禁用下拉加载更多
*/
protected void setFinishRefresh(final SmartRefreshLayout refreshLayout, boolean isLoadMore) {
if (refreshLayout.getState() == RefreshState.Refreshing)
refreshLayout.finishRefresh();
else if (refreshLayout.getState() == RefreshState.Loading)
refreshLayout.finishLoadMore();
if (!isLoadMore){
refreshLayout.finishLoadMore(); //加载完成
refreshLayout.finishLoadMoreWithNoMoreData(); //全部加载完成,没有数据了调用此方法
}
// refreshLayout.setEnableLoadMore(isLoadMore);
}
/**
* 设置标题
*/
protected void setTitleBar(String title, View.OnClickListener listener) {
mToolbar = (Toolbar) rootView.findViewById(R.id.common_toolbar);
if (!TextUtils.isEmpty(title))
((TextView) rootView.findViewById(R.id.common_toolBar_title)).setText(title);
mToolbar.setNavigationIcon(R.drawable.black_back);
mToolbar.setNavigationOnClickListener(listener);
}
/**
* 设置标题
*/
protected void setTitleBar(String title) {
mToolbar = (Toolbar) rootView.findViewById(R.id.common_toolbar);
if (!TextUtils.isEmpty(title))
((TextView) rootView.findViewById(R.id.common_toolBar_title)).setText(title);
}
/**
* 设置标题
*/
protected void setTitleBar(String title, boolean isRight, View.OnClickListener listener) {
mToolbar = (Toolbar) rootView.findViewById(R.id.common_toolbar);
if (!TextUtils.isEmpty(title)) {
((TextView) rootView.findViewById(R.id.common_toolBar_title)).setText(title);
((RelativeLayout) rootView.findViewById(R.id.rlMessage)).setVisibility(isRight ? View.VISIBLE : View.GONE);
(rootView.findViewById(R.id.rlMessage)).setOnClickListener(listener);
}
}
/**
* 设置标题
*/
protected void setTitleBar(String title, boolean isRight,String message, View.OnClickListener listener) {
mToolbar = (Toolbar) rootView.findViewById(R.id.common_toolbar);
if (!TextUtils.isEmpty(title)) {
((TextView) rootView.findViewById(R.id.common_toolBar_title)).setText(title);
((RelativeLayout) rootView.findViewById(R.id.rlMessage)).setVisibility(isRight ? View.VISIBLE : View.GONE);
((TextView) rootView.findViewById(R.id.tvMessage)).setText(message);
(rootView.findViewById(R.id.rlMessage)).setOnClickListener(listener);
}
}
/**
* 设置标题
*/
protected void setBadView(boolean isRight) {
if (null != ((TextView) rootView.findViewById(R.id.tvCount))) {
((TextView) rootView.findViewById(R.id.tvCount)).setVisibility(isRight ? View.VISIBLE : View.GONE);
}
}
protected void setCount(int count) {
if (count > 100) {
((TextView) rootView.findViewById(R.id.tvCount)).setText("99··");
} else {
((TextView) rootView.findViewById(R.id.tvCount)).setText(count + "");
}
}
//setUserVisibleHint()在Fragment创建时会先被调用一次,传入isVisibleToUser = false
//如果当前Fragment可见,那么setUserVisibleHint()会再次被调用一次,传入isVisibleToUser = true
//如果Fragment从可见->不可见,那么setUserVisibleHint()也会被调用,传入isVisibleToUser = false
//总结:setUserVisibleHint()除了Fragment的可见状态发生变化时会被回调外,在new Fragment()时也会被回调
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
Log.i(TAG, "isFirstVisible: " + isFirstVisible + "--isVisibleToUser" + isVisibleToUser + "--rootView == null" + (rootView == null));
super.setUserVisibleHint(isVisibleToUser);
//setUserVisibleHint()有可能在fragment的生命周期外被调用
if (rootView == null) {
return;
}
if (isFirstVisible && isVisibleToUser) {
onFragmentFirstVisible();
isFirstVisible = false;
isFragmentVisible = true;
return;
}
if (isVisibleToUser) {
onFragmentVisibleChange(true);
isFragmentVisible = true;
return;
}
if (isFragmentVisible) {
isFragmentVisible = false;
onFragmentVisibleChange(false);
}
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initVariable();
}
private void initVariable() {
isFirstVisible = true;
isFragmentVisible = false;
isPause = false;
rootView = null;
isReuseView = true;
}
@Override
public void onPause() {
isPause = true;
super.onPause();
}
@Override
public void onResume() {
if (isPause && getUserVisibleHint())
onFragmentVisibleChange(true);
super.onResume();
}
/**
* @param isReuse
*/
protected void reuseView(boolean isReuse) {
isReuseView = isReuse;
}
/**
* 去除setUserVisibleHint()多余的回调场景,保证只有当fragment可见状态发生变化时才回调
* 回调时机在view创建完后,所以支持ui操作,解决在setUserVisibleHint()里进行ui操作有可能报null异常的问题
* <p>
* 可在该回调方法里进行一些ui显示与隐藏
*
* @param isVisible true 不可见 -> 可见
* false 可见 -> 不可见
*/
protected abstract void onFragmentVisibleChange(boolean isVisible);
/**
* 在fragment首次可见时回调,可用于加载数据,防止每次进入都重复加载数据
*/
protected abstract void onFragmentFirstVisible();
protected boolean isFragmentVisible() {
return isFragmentVisible;
}
}
@@ -0,0 +1,38 @@
package com.dahe.mylibrary.base
/**
* @ClassName BaseSingleton
* @Author 用户
* @Date 2023/12/29 09:49
* @Description //要实现单例类,就只需要继承这个 BaseSingleton 即可
//P为参数,T为返回值
*/
abstract class BaseSingleton<in P, out T> {
@Volatile
private var instance: T? = null
//抽象方法,需要我们在具体的单例子类当中实现此方法
protected abstract fun creator(param: P?): T
fun getInstance(param: P?): T =
instance ?: synchronized(this) {
instance ?: creator(param).also { instance = it }
}
}
abstract class BaseSingNoParam<out T> {
@Volatile
private var instance: T? = null
//抽象方法,需要我们在具体的单例子类当中实现此方法
protected abstract fun creator(): T
fun getInstance(): T =
instance ?: synchronized(this) {
instance ?: creator().also { instance = it }
}
}
@@ -0,0 +1,45 @@
package com.dahe.mylibrary.base
/**
* @ClassName SingletonHolder
* @Author john
* @Date 2024/2/5 15:35
* @Description TODO
*/
open class SingletonHolder<out T, in A>(creator: (A) -> T) {
private var creator: ((A) -> T)? = creator
@Volatile
private var instance: T? = null
//对上述方法的一种更简洁的写法
fun getInstance(arg: A): T =
instance ?: synchronized(this) {
instance ?: creator!!(arg).apply {
instance = this
}
}
}
open class SingletonNoPHolder<out T>(creator: () -> T) {
private var creator: (() -> T)? = creator
@Volatile
private var instance: T? = null
//对上述方法的一种更简洁的写法
fun getInstance(): T =
instance ?: synchronized(this) {
instance ?: creator!!().apply {
instance = this
}
}
}
//使用
//class SkinManager private constructor(context: Context) {
// companion object : SingletonHolder<SkinManager, Context>(::SkinManager)
//}
@@ -0,0 +1,100 @@
package com.dahe.mylibrary.bean;
import java.io.Serializable;
public class CarBean implements Serializable {
// private String approved_load;
// private String driver_name;
// private String current_load;
// private String car_number;
// private String outline_wide;
// private String outline_long;
// private String driver_phone;
// private Integer car_id;
// private String outline_high;
private boolean isSelect;
private String vehicle;
private String carId;
private String outlineWide;
private String outlineHigh;
private String outlineLong;
private String approvedLoad;
private String driverName;
private String driverPhone;
public String getVehicle() {
return vehicle;
}
public void setVehicle(String vehicle) {
this.vehicle = vehicle;
}
public String getCarId() {
return carId;
}
public void setCarId(String carId) {
this.carId = carId;
}
public String getOutlineWide() {
return outlineWide;
}
public void setOutlineWide(String outlineWide) {
this.outlineWide = outlineWide;
}
public String getOutlineHigh() {
return outlineHigh;
}
public void setOutlineHigh(String outlineHigh) {
this.outlineHigh = outlineHigh;
}
public String getOutlineLong() {
return outlineLong;
}
public void setOutlineLong(String outlineLong) {
this.outlineLong = outlineLong;
}
public String getApprovedLoad() {
return approvedLoad;
}
public void setApprovedLoad(String approvedLoad) {
this.approvedLoad = approvedLoad;
}
public String getDriverName() {
return driverName;
}
public void setDriverName(String driverName) {
this.driverName = driverName;
}
public String getDriverPhone() {
return driverPhone;
}
public void setDriverPhone(String driverPhone) {
this.driverPhone = driverPhone;
}
public boolean isSelect() {
return isSelect;
}
public void setSelect(boolean select) {
isSelect = select;
}
}
@@ -0,0 +1,154 @@
package com.dahe.mylibrary.bean;
import java.io.Serializable;
public class DictBean implements Serializable {
private String searchValue;
private String createBy;
private String createTime;
private String updateBy;
private String updateTime;
private String remark;
private String dictCode;
private String dictSort;
private String dictLabel;
private String dictValue;
private String dictType;
private String cssClass;
private String listClass;
private String isDefault;
private String status;
public DictBean() {
}
public DictBean(String dictValue, String dictLabel) {
this.dictValue = dictValue;
this.dictLabel = dictLabel;
}
public String getSearchValue() {
return searchValue;
}
public void setSearchValue(String searchValue) {
this.searchValue = searchValue;
}
public String getCreateBy() {
return createBy;
}
public void setCreateBy(String createBy) {
this.createBy = createBy;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public String getUpdateBy() {
return updateBy;
}
public void setUpdateBy(String updateBy) {
this.updateBy = updateBy;
}
public String getUpdateTime() {
return updateTime;
}
public void setUpdateTime(String updateTime) {
this.updateTime = updateTime;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public String getDictCode() {
return dictCode;
}
public void setDictCode(String dictCode) {
this.dictCode = dictCode;
}
public String getDictSort() {
return dictSort;
}
public void setDictSort(String dictSort) {
this.dictSort = dictSort;
}
public String getDictLabel() {
return dictLabel;
}
public void setDictLabel(String dictLabel) {
this.dictLabel = dictLabel;
}
public String getDictValue() {
return dictValue;
}
public void setDictValue(String dictValue) {
this.dictValue = dictValue;
}
public String getDictType() {
return dictType;
}
public void setDictType(String dictType) {
this.dictType = dictType;
}
public String getCssClass() {
return cssClass;
}
public void setCssClass(String cssClass) {
this.cssClass = cssClass;
}
public String getListClass() {
return listClass;
}
public void setListClass(String listClass) {
this.listClass = listClass;
}
public String getIsDefault() {
return isDefault;
}
public void setIsDefault(String isDefault) {
this.isDefault = isDefault;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
@@ -0,0 +1,354 @@
package com.dahe.mylibrary.bean;
import java.io.Serializable;
public class NodeBean implements Serializable {
private String searchValue;
private String createBy;
private String createTime;
private String updateBy;
private String updateTime;
private String remark;
private String planId;
private String nodeId;
private String nodeType;
private String orderId;
private String nodeName;
private String address;
private String contacts;
private String contactsPhone;
private String contacts_phone;
private String provinceId;
private String provinceName;
private String cityId;
private String cityName;
private String countyId;
private String countyName;
private String planIndex;
private String remarks;
private String node_name;
private String warehouseId;
private String warehouseName;
private String isSelect;
private String w_child_id;
private String firstNameCode;
private String wChildId;
private String waybillId;
private String freighter;
private String freighterId;
private String node;
private String state;
private String isSelectOld;
private String dockingPhone;
private String docking;
public String getwChildId() {
return wChildId;
}
public void setwChildId(String wChildId) {
this.wChildId = wChildId;
}
public String getWaybillId() {
return waybillId;
}
public void setWaybillId(String waybillId) {
this.waybillId = waybillId;
}
public String getFreighter() {
return freighter;
}
public void setFreighter(String freighter) {
this.freighter = freighter;
}
public String getFreighterId() {
return freighterId;
}
public void setFreighterId(String freighterId) {
this.freighterId = freighterId;
}
public String getNode() {
return node;
}
public void setNode(String node) {
this.node = node;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getIsSelectOld() {
return isSelectOld;
}
public void setIsSelectOld(String isSelectOld) {
this.isSelectOld = isSelectOld;
}
public String getDockingPhone() {
return dockingPhone;
}
public void setDockingPhone(String dockingPhone) {
this.dockingPhone = dockingPhone;
}
public String getDocking() {
return docking;
}
public void setDocking(String docking) {
this.docking = docking;
}
public String getWarehouseId() {
return warehouseId;
}
public void setWarehouseId(String warehouseId) {
this.warehouseId = warehouseId;
}
public String getWarehouseName() {
return warehouseName;
}
public void setWarehouseName(String warehouseName) {
this.warehouseName = warehouseName;
}
public String getFirstNameCode() {
return firstNameCode;
}
public void setFirstNameCode(String firstNameCode) {
this.firstNameCode = firstNameCode;
}
public String getW_child_id() {
return w_child_id;
}
public void setW_child_id(String w_child_id) {
this.w_child_id = w_child_id;
}
public String isSelect() {
return isSelect;
}
public void setSelect(String select) {
isSelect = select;
}
public String getNode_name() {
return node_name;
}
public void setNode_name(String node_name) {
this.node_name = node_name;
}
public String getContacts_phone() {
return contacts_phone;
}
public void setContacts_phone(String contacts_phone) {
this.contacts_phone = contacts_phone;
}
public String getSearchValue() {
return searchValue;
}
public void setSearchValue(String searchValue) {
this.searchValue = searchValue;
}
public String getCreateBy() {
return createBy;
}
public void setCreateBy(String createBy) {
this.createBy = createBy;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public String getUpdateBy() {
return updateBy;
}
public void setUpdateBy(String updateBy) {
this.updateBy = updateBy;
}
public String getUpdateTime() {
return updateTime;
}
public void setUpdateTime(String updateTime) {
this.updateTime = updateTime;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public String getPlanId() {
return planId;
}
public void setPlanId(String planId) {
this.planId = planId;
}
public String getNodeId() {
return nodeId;
}
public void setNodeId(String nodeId) {
this.nodeId = nodeId;
}
public String getNodeType() {
return nodeType;
}
public void setNodeType(String nodeType) {
this.nodeType = nodeType;
}
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public String getNodeName() {
return nodeName;
}
public void setNodeName(String nodeName) {
this.nodeName = nodeName;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getContacts() {
return contacts;
}
public void setContacts(String contacts) {
this.contacts = contacts;
}
public String getContactsPhone() {
return contactsPhone;
}
public void setContactsPhone(String contactsPhone) {
this.contactsPhone = contactsPhone;
}
public String getProvinceId() {
return provinceId;
}
public void setProvinceId(String provinceId) {
this.provinceId = provinceId;
}
public String getProvinceName() {
return provinceName;
}
public void setProvinceName(String provinceName) {
this.provinceName = provinceName;
}
public String getCityId() {
return cityId;
}
public void setCityId(String cityId) {
this.cityId = cityId;
}
public String getCityName() {
return cityName;
}
public void setCityName(String cityName) {
this.cityName = cityName;
}
public String getCountyId() {
return countyId;
}
public void setCountyId(String countyId) {
this.countyId = countyId;
}
public String getCountyName() {
return countyName;
}
public void setCountyName(String countyName) {
this.countyName = countyName;
}
public String getPlanIndex() {
return planIndex;
}
public void setPlanIndex(String planIndex) {
this.planIndex = planIndex;
}
public String getRemarks() {
return remarks;
}
public void setRemarks(String remarks) {
this.remarks = remarks;
}
}
@@ -0,0 +1,151 @@
package com.dahe.mylibrary.bean;
import java.io.Serializable;
public class StateBean implements Serializable {
private String searchValue;
private String createBy;
private String createTime;
private String updateBy;
private String updateTime;
private String remark;
private String dictCode;
private String dictSort;
private String dictLabel;
private String dictValue;
private String dictType;
private String cssClass;
private String listClass;
private String isDefault;
private String status;
public StateBean(String dictLabel, String dictValue) {
this.dictLabel = dictLabel;
this.dictValue = dictValue;
}
public String getSearchValue() {
return searchValue;
}
public void setSearchValue(String searchValue) {
this.searchValue = searchValue;
}
public String getCreateBy() {
return createBy;
}
public void setCreateBy(String createBy) {
this.createBy = createBy;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public String getUpdateBy() {
return updateBy;
}
public void setUpdateBy(String updateBy) {
this.updateBy = updateBy;
}
public String getUpdateTime() {
return updateTime;
}
public void setUpdateTime(String updateTime) {
this.updateTime = updateTime;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public String getDictCode() {
return dictCode;
}
public void setDictCode(String dictCode) {
this.dictCode = dictCode;
}
public String getDictSort() {
return dictSort;
}
public void setDictSort(String dictSort) {
this.dictSort = dictSort;
}
public String getDictLabel() {
return dictLabel;
}
public void setDictLabel(String dictLabel) {
this.dictLabel = dictLabel;
}
public String getDictValue() {
return dictValue;
}
public void setDictValue(String dictValue) {
this.dictValue = dictValue;
}
public String getDictType() {
return dictType;
}
public void setDictType(String dictType) {
this.dictType = dictType;
}
public String getCssClass() {
return cssClass;
}
public void setCssClass(String cssClass) {
this.cssClass = cssClass;
}
public String getListClass() {
return listClass;
}
public void setListClass(String listClass) {
this.listClass = listClass;
}
public String getIsDefault() {
return isDefault;
}
public void setIsDefault(String isDefault) {
this.isDefault = isDefault;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public static class ParamsDTO {
}
}
@@ -0,0 +1,29 @@
package com.dahe.mylibrary.bean;
import java.io.Serializable;
public class TipsBean implements Serializable {
private String title;
private String content;
public TipsBean(String title, String content) {
this.title = title;
this.content = content;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
@@ -0,0 +1,93 @@
package com.dahe.mylibrary.bean;
import java.io.Serializable;
public class VersionBean implements Serializable {
private ParamsDao data;
public ParamsDao getData() {
return data;
}
public void setData(ParamsDao data) {
this.data = data;
}
public static class ParamsDao implements Serializable{
private int versionId;
private int version;
private String versionName;
private String introduce;
private String updateType;
private String createTime;
private String remark;
private String apkUrl;
public String getApkUrl() {
return apkUrl;
}
public void setApkUrl(String apkUrl) {
this.apkUrl = apkUrl;
}
public int getVersionId() {
return versionId;
}
public void setVersionId(int versionId) {
this.versionId = versionId;
}
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
public String getVersionName() {
return versionName;
}
public void setVersionName(String versionName) {
this.versionName = versionName;
}
public String getIntroduce() {
return introduce;
}
public void setIntroduce(String introduce) {
this.introduce = introduce;
}
public String getUpdateType() {
return updateType;
}
public void setUpdateType(String updateType) {
this.updateType = updateType;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
}
}
@@ -0,0 +1,14 @@
package com.dahe.mylibrary.callback;
import android.view.View;
import androidx.recyclerview.widget.RecyclerView;
/**
* @authorluck
* @date2020-01-13 17:58
* @describe:长按事件
*/
public interface OnItemLongClickListener {
void onItemLongClick(RecyclerView.ViewHolder holder, int position, View v);
}
@@ -0,0 +1,11 @@
package com.dahe.mylibrary.callback
/**
* @ClassName OnMyDatePickedListener
* @Author john
* @Date 2024/3/1 10:26
* @Description TODO
*/
fun interface OnMyDatePickedListener {
fun onDatePicked(date: String)
}
@@ -0,0 +1,14 @@
package com.dahe.mylibrary.callback;
/**
* 刷新的回调
*/
public interface RefreshCallBack {
/**
* @param stat 1刷新 2加载更多
* @param page 当前页数
* @param count 当前count
*/
void getRefreshDate(int stat, int page, int count);
}
@@ -0,0 +1,108 @@
package com.dahe.mylibrary.dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.TextView;
import androidx.annotation.NonNull;
import com.dahe.mylibrary.R;
/**
* 头像选择 dialog
*
* @Description:
* @Author: tao
* @CreateDate: 2018/7/26 10:34
*/
public class DialogPhotoSelect extends MyBaseDialog {
private TextView take_photo;
private TextView select_photo;
private TextView do_cancel;
private onSelectClickListener onSelectClickListener;
public void setOnSelectClickListener(onSelectClickListener onSelectClickListener) {
this.onSelectClickListener = onSelectClickListener;
}
public DialogPhotoSelect(@NonNull Context context) {
super(context);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dialog_photo_select);
initView();
initListener();
}
private void initView() {
take_photo = findViewById( R.id.take_photo);
select_photo = findViewById(R.id.select_photo);
do_cancel = findViewById(R.id.do_cancel);
}
private void initListener() {
//拍照
take_photo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dismiss();
onSelectClickListener.onTakePhoto();
}
});
//相册选择
select_photo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dismiss();
onSelectClickListener.onSelectPhoto();
}
});
do_cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dismiss();
}
});
}
@Override
public void init(@NonNull Context context) {
Window window = getWindow();
window.setWindowAnimations(R.style.BottomAnim);
window.setGravity( Gravity.BOTTOM);
//默认的Dialog只有5/6左右的宽度,改为全屏宽度,由dialog的布局自己来决定实际显示宽度
window.getDecorView().setPadding(0, 0, 0, 0);
WindowManager.LayoutParams lp = window.getAttributes();
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
window.setAttributes(lp);
}
@Override
public boolean isCancelAble() {
return true;
}
public interface onSelectClickListener {
void onTakePhoto();
void onSelectPhoto();
}
}
@@ -0,0 +1,55 @@
package com.dahe.mylibrary.dialog;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.Gravity;
import android.view.Window;
import android.view.WindowManager;
import androidx.annotation.NonNull;
import com.dahe.mylibrary.R;
/**
* Dialog 基类 基类 基类
* <p>
* 以后再写Dialog,都要继承这个
*
* @Description:
* @Author: tao
* @CreateDate: 2018/7/26 10:29
*/
public class MyBaseDialog extends Dialog {
public MyBaseDialog(@NonNull Context context) {
super(context, R.style.MyBaseDialog);
init(context);
}
public void init(@NonNull Context context) {
Window window = getWindow();
window.setWindowAnimations(R.style.BottomAnim);
window.setGravity(Gravity.CENTER);
//默认的Dialog只有5/6左右的宽度,改为全屏宽度,由dialog的布局自己来决定实际显示宽度
window.getDecorView().setPadding(0, 0, 0, 0);
WindowManager.LayoutParams lp = window.getAttributes();
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
window.setAttributes(lp);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setCancelable(isCancelAble());
setCanceledOnTouchOutside(isCancelAble());
}
public boolean isCancelAble() {
return false;
}
}
@@ -0,0 +1,21 @@
package com.dahe.mylibrary.dialog;
import android.app.Dialog;
import android.content.Context;
/**
* Created by Allen Liu on 2017/2/23.
*/
public class VersionDialog extends Dialog {
private int res;
public VersionDialog(Context context, int theme, int res) {
super(context, theme);
getWindow().setBackgroundDrawableResource(android.R.color.transparent);
// TODO 自动生成的构造函数存根
setContentView(res);
this.res = res;
setCanceledOnTouchOutside(false);
}
}
@@ -0,0 +1,117 @@
package com.dahe.mylibrary.glide;
import android.content.Context;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.dahe.mylibrary.R;
import com.luck.picture.lib.engine.ImageEngine;
import com.luck.picture.lib.utils.ActivityCompatHelper;
/**
* @authorluck
* @date2019-11-13 17:02
* @describeGlide加载引擎
*/
public class GlideEngine implements ImageEngine {
/**
* 加载图片
*
* @param context 上下文
* @param url 资源url
* @param imageView 图片承载控件
*/
@Override
public void loadImage(Context context, String url, ImageView imageView) {
if (!ActivityCompatHelper.assertValidRequest(context)) {
return;
}
Glide.with(context)
.load(url)
.into(imageView);
}
@Override
public void loadImage(Context context, ImageView imageView, String url, int maxWidth, int maxHeight) {
if (!ActivityCompatHelper.assertValidRequest(context)) {
return;
}
Glide.with(context)
.load(url)
.override(maxWidth, maxHeight)
.into(imageView);
}
/**
* 加载相册目录封面
*
* @param context 上下文
* @param url 图片路径
* @param imageView 承载图片ImageView
*/
@Override
public void loadAlbumCover(Context context, String url, ImageView imageView) {
if (!ActivityCompatHelper.assertValidRequest(context)) {
return;
}
Glide.with(context)
.asBitmap()
.load(url)
.override(180, 180)
.sizeMultiplier(0.5f)
.transform(new CenterCrop(), new RoundedCorners(8))
.placeholder(com.luck.picture.lib.R.drawable.ps_image_placeholder)
.into(imageView);
}
/**
* 加载图片列表图片
*
* @param context 上下文
* @param url 图片路径
* @param imageView 承载图片ImageView
*/
@Override
public void loadGridImage(Context context, String url, ImageView imageView) {
if (!ActivityCompatHelper.assertValidRequest(context)) {
return;
}
Glide.with(context)
.load(url)
.override(200, 200)
.centerCrop()
.placeholder(com.luck.picture.lib.R.drawable.ps_image_placeholder)
.into(imageView);
}
@Override
public void pauseRequests(Context context) {
if (!ActivityCompatHelper.assertValidRequest(context)) {
return;
}
Glide.with(context).pauseRequests();
}
@Override
public void resumeRequests(Context context) {
if (!ActivityCompatHelper.assertValidRequest(context)) {
return;
}
Glide.with(context).resumeRequests();
}
private GlideEngine() {
}
private static final class InstanceHolder {
static final GlideEngine instance = new GlideEngine();
}
public static GlideEngine createGlideEngine() {
return InstanceHolder.instance;
}
}
@@ -0,0 +1,67 @@
package com.dahe.mylibrary.glide;
import java.security.cert.CertificateException;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import okhttp3.OkHttpClient;
/**
* @ClassName UnsafeOkHttpClient
* @Author 用户
* @Date 2021/10/11 10:16
* @Description TODO
*/
public class UnsafeOkHttpClient {
public static OkHttpClient getUnsafeOkHttpClient() {
try {
// Create a trust manager that does not validate certificate chains
final TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[]{};
}
}
};
// Install the all-trusting trust manager
final SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
// Create an ssl socket factory with our all-trusting manager
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]);
builder.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
builder.connectTimeout(20, TimeUnit.SECONDS);
builder.readTimeout(20,TimeUnit.SECONDS);
OkHttpClient okHttpClient = builder.build();
return okHttpClient;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
@@ -0,0 +1,91 @@
package com.dahe.mylibrary.net;
import java.io.Serializable;
import java.util.ArrayList;
/**
* 返回通用的实体类
*/
public class CommonResponseBean<T> implements Serializable {
private T data;
private int code;
private String msg;
// 数据未封装 无奈呀
private boolean captchaEnabled;
private String img;
private String uuid;
private int total;
private T rows;
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public T getRows() {
return rows;
}
public void setRows(T rows) {
this.rows = rows;
}
public boolean isCaptchaEnabled() {
return captchaEnabled;
}
public void setCaptchaEnabled(boolean captchaEnabled) {
this.captchaEnabled = captchaEnabled;
}
public String getImg() {
return img;
}
public void setImg(String img) {
this.img = img;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
@@ -0,0 +1,30 @@
package com.dahe.mylibrary.net
import java.io.Serializable
/**
* 返回通用的实体类
*/
class CommonResponseBean2<T> : Serializable {
var data : T? = null
var code = 0
var msg: String? = null
// 数据未封装 无奈呀
var isCaptchaEnabled = false
var img: String? = null
var uuid: String? = null
var total = 0
var rows: T? = null
private set
fun setRows(rows: T) {
this.rows = rows
}
fun setData(data: T) {
this.data = data
}
}
@@ -0,0 +1,22 @@
package com.dahe.mylibrary.net;
public class ErrorResponse {
private int code;
private String msg;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
@@ -0,0 +1,60 @@
package com.dahe.mylibrary.net;
import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;
/**
* 文件上传Interceptor
*/
public class FileInterceptor implements Interceptor {
private static final String TAG = "FileInterceptor";
private File mFile;
public FileInterceptor(File mFile) {
this.mFile = mFile;
}
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
request = request.newBuilder()
.post(RequestBody.create(MediaType.parse("application/file; charset=utf-8"), mFile))
.build();
Response response = chain.proceed(request);
Log.i(TAG, "url= " + request.body());
Log.i(TAG, "method= " + request.method());
ResponseBody responseBody = response.body();
//为了不消耗buffer,我们这里使用source先获得buffer对象,然后clone()后使用
BufferedSource source = responseBody.source();
source.request(Long.MAX_VALUE); // Buffer the entire body.
//获得返回的数据
Buffer buffer = source.buffer();
//使用前clone()下,避免直接消耗
String responseBodyStr = buffer.clone().readString(Charset.forName("UTF-8"));
Log.i(TAG, "result-body= " + responseBodyStr);
try {
JSONObject jsonObject = new JSONObject(responseBodyStr);
responseBody = ResponseBody.create(MediaType.parse("application/json; charset=utf-8"), jsonObject.getString("response"));
} catch (JSONException e) {
e.printStackTrace();
}
response = response.newBuilder().body(responseBody).build();
return response;
}
}
@@ -0,0 +1,74 @@
package com.dahe.mylibrary.net;
import com.google.gson.Gson;
import org.json.JSONObject;
import java.io.IOException;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;
import retrofit2.Converter;
public class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final Gson gson;
private final Type type;
public GsonResponseBodyConverter(Gson gson, Type type) {
this.gson = gson;
this.type = type;
}
@Override
public T convert(ResponseBody value) throws IOException {
//为了不消耗buffer,我们这里使用source先获得buffer对象,然后clone()后使用
BufferedSource source = value.source();
source.request(Long.MAX_VALUE); // Buffer the entire body.
//获得返回的数据
Buffer buffer = source.buffer();
//使用前clone()下,避免直接消耗
String responseBodyStr = buffer.clone().readString(Charset.forName("UTF-8"));
try {
JSONObject jsonObject = new JSONObject(responseBodyStr);
int code = jsonObject.optInt("code");
if (-1 == code) {
jsonObject.put("data", new JSONObject());
// ErrorResponse errorResponse = gson.fromJson(response, ErrorResponse.class);
//抛一个自定义ResultException 传入失败时候的状态码,和信息
throw new ResultException(-1, "errorResponse.getMsg()");
// return gson.fromJson(responseBodyStr,type);
}
} catch (Exception e) {
e.printStackTrace();
}
return gson.fromJson(responseBodyStr, type);
// String response = value.string();
// //先将返回的json数据解析到Response中,如果code==200,则解析到我们的实体基类中,否则抛异常
// Response httpResult = gson.fromJson(response, Response.class);
// if (httpResult.code()==200){
// //200的时候就直接解析,不可能出现解析异常。因为我们实体基类中传入的泛型,就是数据成功时候的格式
// return gson.fromJson(response,type);
// }else {
// ErrorResponse errorResponse = gson.fromJson(response,ErrorResponse.class);
// //抛一个自定义ResultException 传入失败时候的状态码,和信息
// try {
// throw new ResultException(errorResponse.getCode(),errorResponse.getMsg());
// } catch (ResultException e) {
// e.printStackTrace();
// }
// return null;
// }
}
}
@@ -0,0 +1,67 @@
package com.dahe.mylibrary.net;
import android.text.TextUtils;
import android.util.Log;
import com.google.zxing.common.StringUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.IOException;
import java.nio.charset.Charset;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;
/**
* json的Interceptor
*/
public class JsonInterceptor implements Interceptor {
private static final String TAG = "JsonInterceptor";
public JsonInterceptor() {
}
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
ResponseBody responseBody = response.body();
//为了不消耗buffer,我们这里使用source先获得buffer对象,然后clone()后使用
BufferedSource source = responseBody.source();
source.request(Long.MAX_VALUE); // Buffer the entire body.
//获得返回的数据
Buffer buffer = source.buffer();
//使用前clone()下,避免直接消耗
String responseBodyStr = buffer.clone().readString(Charset.forName("UTF-8"));
Log.i(TAG, "result-body= " + responseBodyStr);
try {
JSONObject jsonObject = new JSONObject(responseBodyStr);
String str = jsonObject.optString("data");
int code = jsonObject.optInt("code");
// if (-1 == code) {
// jsonObject.put("data", new JSONObject());
// throw new ResultException();
// } else {
// if (TextUtils.isEmpty(str)) {
// jsonObject.put("data", new JSONObject());
// }
// }
String data = jsonObject.toString();
responseBody = ResponseBody.create(MediaType.parse("application/json; charset=utf-8"), data);
} catch (Exception e) {
e.printStackTrace();
}
response = response.newBuilder().body(responseBody).build();
return response;
}
}
@@ -0,0 +1,91 @@
package com.dahe.mylibrary.net;
import android.util.Log;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonIOException;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import org.json.JSONException;
import org.json.JSONObject;
import java.lang.reflect.Type;
import java.util.ArrayList;
/**
* 利用Gson反射对象类型,将json转化为对象
*/
public class JsonUtils {
private Gson mGson = null;
private static JsonUtils mUtils;
public static JsonUtils getInstance() {
if (mUtils == null) {
return new JsonUtils();
} else {
return mUtils;
}
}
public Gson getGson() {
if (null == mGson) {
mGson = new GsonBuilder().serializeNulls().create();
}
return mGson;
}
public String toJson(Object o){
return getGson().toJson(o);
}
/**
* 将json数组转化为List
*
* @param json json字符串
* @param classOfT 对应实体类型
* @return 实体列表
*/
public <T> ArrayList<T> jsonToList(String json, Class<T> classOfT) {
try {
if (mGson == null) {
// 不要直接new Gson是为了避免放回结果为null的这种情况
mGson = new GsonBuilder().serializeNulls().create();
}
Type type = new TypeToken<ArrayList<JsonObject>>() {
}.getType();
ArrayList<JsonObject> jsonObjs = mGson.fromJson(json, type);
ArrayList<T> listOfT = new ArrayList<T>();
for (JsonObject jsonObj : jsonObjs) {
listOfT.add(mGson.fromJson(jsonObj, classOfT));
}
return listOfT;
} catch (Exception e) {
return null;
}
}
public <T> T fromJson(String json, Class<T> type) throws JsonIOException, JsonSyntaxException {
try {
JSONObject object = new JSONObject(json);
json = object.getString("response");
Log.i("fromJson: ", json);
} catch (JSONException e) {
e.printStackTrace();
}
return getGson().fromJson(json, type);
}
public <T> T fromJson(String json, Type type) {
return getGson().fromJson(json, type);
}
public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {
return getGson().fromJson(reader, typeOfT);
}
}
@@ -0,0 +1,47 @@
package com.dahe.mylibrary.net;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Administrator on 2018\8\26 0026.
*/
public class PagerBean<T> {
private int total;
private int count;
private int more;
private ArrayList<T> rows;
public ArrayList<T> getRows() {
return rows;
}
public void setRows(ArrayList<T> rows) {
this.rows = rows;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public int getMore() {
return more;
}
public void setMore(int more) {
this.more = more;
}
}
@@ -0,0 +1,46 @@
package com.dahe.mylibrary.net;
import java.io.Serializable;
/**
* 返回通用的实体类
*/
public class PagingBean<T> implements Serializable {
private T data;
private int code;
private String count;
private String msg;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getCount() {
return count;
}
public void setCount(String count) {
this.count = count;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
@@ -0,0 +1,44 @@
package com.dahe.mylibrary.net;
import com.google.gson.Gson;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Converter;
import retrofit2.Retrofit;
public class ResponseConverterFactory extends Converter.Factory {
public static ResponseConverterFactory create() {
return create(new Gson());
}
public static ResponseConverterFactory create(Gson gson) {
return new ResponseConverterFactory(gson);
}
private final Gson gson;
private ResponseConverterFactory(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
this.gson = gson;
}
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
//返回我们自定义的Gson响应体变换器
return new GsonResponseBodyConverter<>(gson, type);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
//返回我们自定义的Gson响应体变换器
return new GsonResponseBodyConverter<>(gson,type);
}
}
@@ -0,0 +1,12 @@
package com.dahe.mylibrary.net;
public class ResultException extends Exception {
public ResultException() {
super();
// TODO Auto-generated constructor stub
}
public ResultException(int code, String msg) {
}
}
@@ -0,0 +1,122 @@
package com.dahe.mylibrary.pop
import android.content.Context
import android.widget.Button
import com.dahe.mylibrary.R
import com.dahe.mylibrary.adapter.GridImageAdapter
import com.dahe.mylibrary.utils.SelectPicUtils
import com.dahe.mylibrary.utils.ToastUtils
import com.dahe.mylibrary.weight.GlideEngine
import com.dahe.mylibrary.weight.ImageFileCompressEngine
import com.luck.picture.lib.basic.PictureSelectionCameraModel
import com.luck.picture.lib.basic.PictureSelectionModel
import com.luck.picture.lib.basic.PictureSelector
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnResultCallbackListener
import com.lxj.xpopup.core.BottomPopupView
import kotlin.math.min
/**
* @ClassName PopBottomPic
* @Author john
* @Date 2024/1/31 11:11
* @Description TODO
*/
class PopBottomPic(
context: Context,
myAdapter: GridImageAdapter,
onPicResultListener: onPicResultListener
) : BottomPopupView(context) {
private var listener: onPicResultListener
var myAdapter: GridImageAdapter
init {
this.listener = onPicResultListener
this.myAdapter = myAdapter
}
override fun getImplLayoutId() = R.layout.choice_car_timg
override fun onCreate() {
super.onCreate()
var paizhao = findViewById<Button>(R.id.btn_paizhao)
var xiangce = findViewById<Button>(R.id.btnXiangce)
paizhao.setOnClickListener {
// 单独拍照
val cameraModel: PictureSelectionCameraModel = PictureSelector.create(context)
.openCamera(SelectMimeType.TYPE_IMAGE)
// .setCameraInterceptListener(getCustomCameraEvent())//自定义相机
// .setRecordAudioInterceptListener(MainActivity.MeOnRecordAudioInterceptListener())//录音回调事件
// .setCropEngine(ImageFileCropEngine())//裁剪
.setCompressEngine(ImageFileCompressEngine())//压缩
// .setSelectLimitTipsListener(MainActivity.MeOnSelectLimitTipsListener())//拦截自定义提示
// .setAddBitmapWatermarkListener(getAddBitmapWatermarkListener())//给图片添加水印
// .setVideoThumbnailListener(getVideoThumbnailEventListener())//处理视频缩略图
// .setCustomLoadingListener(getCustomLoadingListener())//自定义loading
// .setSandboxFileEngine(MainActivity.MeSandboxFileEngine())//自定义沙盒文件处理
// .isOriginalControl(cb_original.isChecked())//是否开启原图功能
// .setPermissionDescriptionListener(getPermissionDescriptionListener())//权限说明
// .setOutputAudioDir(getSandboxAudioOutputPath())//创建音频自定义输出目录
.setSelectedData(myAdapter.data)
cameraModel.forResult(object : OnResultCallbackListener<LocalMedia> {
override fun onResult(result: ArrayList<LocalMedia>?) {
if (listener != null) {
result?.let { it1 -> listener.onResult(it1) }
}
dismiss()
}
override fun onCancel() {
dismiss()
}
})
}
xiangce.setOnClickListener {
// 进入相册
val selectionModel: PictureSelectionModel = PictureSelector.create(context)
.openGallery(SelectMimeType.TYPE_IMAGE)
.isDisplayCamera(false)//关闭拍照
.setImageEngine(GlideEngine.createGlideEngine())
.setCompressEngine(ImageFileCompressEngine())
.isPreviewImage(true)
.isMaxSelectEnabledMask(true)
.setMaxSelectNum(6)
.isGif(false)
.setSelectedData(myAdapter.data)
selectionModel.forResult(object : OnResultCallbackListener<LocalMedia> {
override fun onResult(result: ArrayList<LocalMedia>) {
if (listener != null) {
result?.let { it1 -> listener.onResult(it1) }
}
dismiss()
}
override fun onCancel() {
dismiss()
}
})
}
}
private fun openCam() {
PictureSelector.create(context)
.openCamera(SelectMimeType.TYPE_IMAGE)
}
// private listener : onPicResultListener
fun interface onPicResultListener {
fun onResult(result: java.util.ArrayList<LocalMedia>)
}
// fun setOnPicResultListener(listener: onPicResultListener){
// this.listener
// }
}
@@ -0,0 +1,43 @@
package com.dahe.mylibrary.recycleviewswipe;
import android.graphics.Rect;
import android.view.View;
import androidx.recyclerview.widget.RecyclerView;
public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {
private int spanCount; //列数
private int spacing; //间隔
private boolean includeEdge; //是否包含边缘
public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge) {
this.spanCount = spanCount;
this.spacing = spacing;
this.includeEdge = includeEdge;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
//这里是关键,需要根据你有几列来判断
int position = parent.getChildAdapterPosition(view); // item position
int column = position % spanCount; // item column
if (includeEdge) {
outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing)
outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing)
if (position < spanCount) { // top edge
outRect.top = spacing;
}
outRect.bottom = spacing; // item bottom
} else {
outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing)
outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f / spanCount) * spacing)
if (position >= spanCount) {
outRect.top = spacing; // item top
}
}
}
}
@@ -0,0 +1,156 @@
package com.dahe.mylibrary.recycleviewswipe;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.view.View;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
public class RecycleViewDivider extends RecyclerView.ItemDecoration {
private Paint mPaint;
//分割线
private Drawable mDivider;
//分割线高度,默认是1px
private int mDividerHeight = 1;
//列表的方向:LinearLayoutManager.VERTICAL或LinearLayoutManager.HORIZONTAL
private int mOrientation;
private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
/**
*
* 默认分割线:高度为2px,颜色为灰色
* 获取属性值,
*
* @param context
* @param orientation 列表方向
*/
public RecycleViewDivider(Context context, int orientation){
if (orientation != LinearLayoutManager.VERTICAL && orientation != LinearLayoutManager.HORIZONTAL) {
throw new IllegalArgumentException("请输入正确的参数!");
}
mOrientation = orientation;
final TypedArray array = context.obtainStyledAttributes(ATTRS);
mDivider = array.getDrawable(0);
array.recycle();
mDividerHeight = mDivider.getIntrinsicHeight();
}
/**
* 自定义分割线
*
* @param context
* @param orientation 列表方向
* @param drawableId 分割线图片
*/
public RecycleViewDivider(Context context, int orientation, int drawableId) {
if (orientation != LinearLayoutManager.VERTICAL && orientation != LinearLayoutManager.HORIZONTAL) {
throw new IllegalArgumentException("请输入正确的参数!");
}
mOrientation = orientation;
mDivider = ContextCompat.getDrawable(context, drawableId);
mDividerHeight = mDivider.getIntrinsicHeight();
}
/**
* 自定义分割线
*
* @param orientation 列表方向
* @param dividerHeight 分割线高度
* @param dividerColor 分割线颜色
*/
public RecycleViewDivider(int orientation, int dividerHeight, int dividerColor) {
if (orientation != LinearLayoutManager.VERTICAL && orientation != LinearLayoutManager.HORIZONTAL) {
throw new IllegalArgumentException("请输入正确的参数!");
}
mOrientation = orientation;
mDividerHeight = dividerHeight;
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(dividerColor);
mPaint.setStyle(Paint.Style.FILL);
}
//获取分割线尺寸
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
if (mOrientation == LinearLayoutManager.VERTICAL) {
outRect.set(0, 0, 0, mDividerHeight);
} else {
outRect.set(0, 0, mDividerHeight, 0);
}
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c, parent, state);
if(mOrientation==LinearLayoutManager.VERTICAL){
drawVerticalLine(c,parent);
}else{
drawHorizontalLine(c,parent);
}
}
//为横方向item, 画分割线
private void drawHorizontalLine(Canvas canvas, RecyclerView parent) {
final int top = parent.getPaddingTop();
final int bottom = parent.getMeasuredHeight() - parent.getPaddingBottom();
final int childSize = parent.getChildCount();
for (int i = 0; i < childSize - 1; i++) {
if ((i+1) % 3 != 0) {
final View child = parent.getChildAt(i);
RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();
final int left = child.getRight() + layoutParams.rightMargin;
final int right = left + mDividerHeight;
if (mDivider != null) {
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(canvas);
}
if (mPaint != null) {
canvas.drawRect(left, top, right, bottom, mPaint);
}
}
}
}
//为竖方向item, 画分割线
private void drawVerticalLine(Canvas canvas, RecyclerView parent) {
final int left = parent.getPaddingLeft();
final int right = parent.getMeasuredWidth() - parent.getPaddingRight();
final int childSize = parent.getChildCount();
for (int i = 0; i < childSize; i++) {
if (i < childSize -1) {
final View child = parent.getChildAt(i);
RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();
final int top = child.getBottom() + layoutParams.bottomMargin;
final int bottom = top + mDividerHeight;
if (mDivider != null) {
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(canvas);
}
if (mPaint != null) {
canvas.drawRect(left, top, right, bottom, mPaint);
}
}
}
}
}
@@ -0,0 +1,330 @@
package com.dahe.mylibrary.utils;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import androidx.annotation.NonNull;
import com.dahe.mylibrary.CommonBaseLibrary;
import java.util.List;
/**
* <pre>
* author: Blankj
* blog : http://blankj.com
* time : 2016/09/23
* desc : Activity相关工具类
* </pre>
*/
public class ActivityUtils {
public ActivityUtils() {
throw new UnsupportedOperationException("u can't instantiate me...");
}
/**
* 启动Activity
*
* @param context
* @param clz
* @param bundle
*/
public static void startActivity(@NonNull Context context, @NonNull Class<?> clz, Bundle bundle) {
Intent intent = new Intent(context, clz);
if (null != bundle) intent.putExtras(bundle);
context.startActivity(intent);
}
/**
* 启动Activity
*
* @param context
* @param clz
* @param bundle
*/
public static void startPushActivity(@NonNull Context context, @NonNull Class<?> clz, Bundle bundle) {
Intent intent = new Intent(context, clz);
if (null != bundle){
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtras(bundle);
}
context.startActivity(intent);
}
/**
* 启动Activity
*
* @param context
* @param clz
*/
public static void startActivity(@NonNull Context context, @NonNull Class<?> clz) {
startActivity(context, clz, null);
}
/**
* 启动Activity
*
* @param activity
* @param clz
* @param bundle
*/
public static void startActivityForResult(@NonNull Activity activity, @NonNull Class<?> clz, Bundle bundle, int requestCode) {
Intent intent = new Intent(activity, clz);
if (null != bundle) intent.putExtras(bundle);
activity.startActivityForResult(intent, requestCode);
}
/**
* 启动Activity
*
* @param activity
* @param clz
*/
public static void startActivityForResult(@NonNull Activity activity, @NonNull Class<?> clz, int requestCode) {
startActivityForResult(activity, clz, null, requestCode);
}
// /**
// * 跳转登录界面
// *
// * @param context
// * @param finishOthers 是否结束其他的activity true结束 false 不结束
// */
// public static void openLoginActivity(@NonNull Context context, boolean finishOthers) {
// Intent intent = new Intent(context, LoginMainActivity.class);
// Bundle bundle = new Bundle();
// bundle.putBoolean("finishOthers", finishOthers);
// intent.putExtras(bundle);
// context.startActivity(intent);
// }
// /**
// * 启动前必须登录Activity
// *
// * @param context
// * @param clz
// */
// public static void startActivityByLogin(@NonNull Context context, @NonNull Class<?> clz) {
// startActivityByLogin(context, clz, null);
// }
/**
* 回到桌面
*/
public static void startHomeActivity(Context context) {
Intent homeIntent = new Intent(Intent.ACTION_MAIN);
homeIntent.addCategory(Intent.CATEGORY_HOME);
context.startActivity(homeIntent);
}
/**
* 获取Activity栈链表
*
* @return Activity栈链表
*/
public static List<Activity> getActivityList() {
return CommonBaseLibrary.activityList;
}
/**
* 获取启动项Activity
*
* @param packageName 包名
* @return 启动项Activity
*/
public static String getLauncherActivity(@NonNull final String packageName) {
Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PackageManager pm = CommonBaseLibrary.getApplication().getPackageManager();
List<ResolveInfo> info = pm.queryIntentActivities(intent, 0);
for (ResolveInfo aInfo : info) {
if (aInfo.activityInfo.packageName.equals(packageName)) {
return aInfo.activityInfo.name;
}
}
return "no " + packageName;
}
/**
* 获取栈顶Activity
*
* @return 栈顶Activity
*/
public static Activity getTopActivity() {
if (CommonBaseLibrary.topActivity != null) {
Activity activity = CommonBaseLibrary.topActivity.get();
if (activity != null) {
return activity;
}
}
List<Activity> activities = CommonBaseLibrary.activityList;
int size = activities.size();
return size > 0 ? activities.get(size - 1) : null;
}
/**
* 判断Activity是否存在栈中
*
* @param activity activity
* @return {@code true}: 存在<br>{@code false}: 不存在
*/
public static boolean isActivityExistsInStack(@NonNull final Activity activity) {
List<Activity> activities = CommonBaseLibrary.activityList;
for (Activity aActivity : activities) {
if (aActivity.equals(activity)) {
return true;
}
}
return false;
}
/**
* 判断Activity是否存在栈中
*
* @param clz activity类
* @return {@code true}: 存在<br>{@code false}: 不存在
*/
public static boolean isActivityExistsInStack(@NonNull final Class<?> clz) {
List<Activity> activities = CommonBaseLibrary.activityList;
for (Activity aActivity : activities) {
if (aActivity.getClass().equals(clz)) {
return true;
}
}
return false;
}
/**
* 结束Activity
*
* @param activity activity
*/
public static void finishActivity(@NonNull final Activity activity) {
activity.finish();
}
/**
* 结束Activity
*
* @param clz activity类
*/
public static void finishActivity(@NonNull final Class<?> clz) {
List<Activity> activities = CommonBaseLibrary.activityList;
for (Activity activity : activities) {
if (activity.getClass().equals(clz)) {
activity.finish();
}
}
}
/**
* 结束到指定Activity
*
* @param activity activity
* @param isIncludeSelf 是否结束该activity自己
*/
public static boolean finishToActivity(@NonNull final Activity activity,
final boolean isIncludeSelf) {
List<Activity> activities = CommonBaseLibrary.activityList;
for (int i = activities.size() - 1; i >= 0; --i) {
Activity aActivity = activities.get(i);
if (aActivity.equals(activity)) {
if (isIncludeSelf) {
finishActivity(aActivity);
}
return true;
}
finishActivity(aActivity);
}
return false;
}
/**
* 结束到指定Activity
*
* @param isIncludeSelf 是否结束该activity自己
*/
public static boolean finishToActivity(@NonNull final Class<?> clz,
final boolean isIncludeSelf) {
List<Activity> activities = CommonBaseLibrary.activityList;
for (int i = activities.size() - 1; i >= 0; --i) {
Activity aActivity = activities.get(i);
if (aActivity.getClass().equals(clz)) {
if (isIncludeSelf) {
finishActivity(aActivity);
}
return true;
}else{
finishActivity(aActivity);
}
// finishActivity(aActivity);
}
return false;
}
/**
* 结束除最新之外的同类型Activity
* <p>也就是让栈中最多只剩下一种类型的Activity</p>
*
* @param clz activity类
*/
public static void finishOtherActivitiesExceptNewest(@NonNull final Class<?> clz) {
List<Activity> activities = CommonBaseLibrary.activityList;
boolean flag = false;
for (int i = activities.size() - 1; i >= 0; i--) {
Activity activity = activities.get(i);
if (activity.getClass().equals(clz)) {
if (flag) {
finishActivity(activity);
} else {
flag = true;
}
} else {
finishActivity(activity);
}
}
}
/**
* 清除除本activity之外所有的activity
*
* @param clz 本activity的类名
*/
public static void finishOtherActivities(@NonNull final Class<?> clz) {
List<Activity> activities = CommonBaseLibrary.activityList;
for (Activity activity : activities) {
if (!activity.getClass().equals(clz)) {
finishActivity(activity);
}
}
}
/**
* 结束所有activity
*/
public static void finishAllActivities() {
List<Activity> activityList = CommonBaseLibrary.activityList;
for (int i = activityList.size() - 1; i >= 0; --i) {// 从栈顶开始移除
Activity activity = activityList.get(i);
activity.finish();// 在onActivityDestroyed发生remove
}
}
private static Context getActivityOrApp() {
Activity topActivity = getTopActivity();
return topActivity == null ? CommonBaseLibrary.getApplication() : topActivity;
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,678 @@
package com.dahe.mylibrary.utils;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Point;
import android.os.Build;
import android.util.Log;
import android.util.TypedValue;
import android.view.Display;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewGroup.MarginLayoutParams;
import android.view.Window;
import android.view.WindowManager;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.annotation.RequiresPermission;
import androidx.drawerlayout.widget.DrawerLayout;
import com.dahe.mylibrary.CommonBaseLibrary;
import java.lang.reflect.Method;
import static android.Manifest.permission.EXPAND_STATUS_BAR;
/**
* getStatusBarHeight : 获取状态栏高度(px)
* setStatusBarVisibility : 设置状态栏是否可见
* isStatusBarVisible : 判断状态栏是否可见
* setStatusBarLightMode : 设置状态栏是否为浅色模式
* addMarginTopEqualStatusBarHeight : 为 view 增加 MarginTop 为状态栏高度
* subtractMarginTopEqualStatusBarHeight: 为 view 减少 MarginTop 为状态栏高度
* setStatusBarColor : 设置状态栏颜色
* setStatusBarColor4Drawer : 为 DrawerLayout 设置状态栏颜色
* getActionBarHeight : 获取 ActionBar 高度
* setNotificationBarVisibility : 设置通知栏是否可见
* getNavBarHeight : 获取导航栏高度
* setNavBarVisibility : 设置导航栏是否可见
* isNavBarVisible : 判断导航栏是否可见
* setNavBarColor : 设置导航栏颜色
* getNavBarColor : 获取导航栏颜色
* isSupportNavBar : 判断是否支持导航栏
*/
public final class BarUtils {
///////////////////////////////////////////////////////////////////////////
// status bar
///////////////////////////////////////////////////////////////////////////
private static final String TAG_STATUS_BAR = "TAG_STATUS_BAR";
private static final String TAG_OFFSET = "TAG_OFFSET";
private static final int KEY_OFFSET = -123;
private BarUtils() {
throw new UnsupportedOperationException("u can't instantiate me...");
}
/**
* Return the status bar's height.
*
* @return the status bar's height
*/
public static int getStatusBarHeight() {
Resources resources = Resources.getSystem();
int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
return resources.getDimensionPixelSize(resourceId);
}
/**
* Set the status bar's visibility.
*
* @param activity The activity.
* @param isVisible True to set status bar visible, false otherwise.
*/
public static void setStatusBarVisibility(@NonNull final Activity activity,
final boolean isVisible) {
setStatusBarVisibility(activity.getWindow(), isVisible);
}
/**
* Set the status bar's visibility.
*
* @param window The window.
* @param isVisible True to set status bar visible, false otherwise.
*/
public static void setStatusBarVisibility(@NonNull final Window window,
final boolean isVisible) {
if (isVisible) {
window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
showStatusBarView(window);
addMarginTopEqualStatusBarHeight(window);
} else {
window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
hideStatusBarView(window);
subtractMarginTopEqualStatusBarHeight(window);
}
}
/**
* Return whether the status bar is visible.
*
* @param activity The activity.
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isStatusBarVisible(@NonNull final Activity activity) {
int flags = activity.getWindow().getAttributes().flags;
return (flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0;
}
/**
* Set the status bar's light mode.
*
* @param activity The activity.
* @param isLightMode True to set status bar light mode, false otherwise.
*/
public static void setStatusBarLightMode(@NonNull final Activity activity,
final boolean isLightMode) {
setStatusBarLightMode(activity.getWindow(), isLightMode);
}
/**
* Set the status bar's light mode.
*
* @param window The window.
* @param isLightMode True to set status bar light mode, false otherwise.
*/
public static void setStatusBarLightMode(@NonNull final Window window,
final boolean isLightMode) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
View decorView = window.getDecorView();
if (decorView != null) {
int vis = decorView.getSystemUiVisibility();
if (isLightMode) {
vis |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
} else {
vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
}
decorView.setSystemUiVisibility(vis);
}
}
}
/**
* Is the status bar light mode.
*
* @param activity The activity.
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isStatusBarLightMode(@NonNull final Activity activity) {
return isStatusBarLightMode(activity.getWindow());
}
/**
* Is the status bar light mode.
*
* @param window The window.
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isStatusBarLightMode(@NonNull final Window window) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
View decorView = window.getDecorView();
if (decorView != null) {
int vis = decorView.getSystemUiVisibility();
return (vis & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0;
}
}
return false;
}
/**
* Add the top margin size equals status bar's height for view.
*
* @param view The view.
*/
public static void addMarginTopEqualStatusBarHeight(@NonNull View view) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
view.setTag(TAG_OFFSET);
Object haveSetOffset = view.getTag(KEY_OFFSET);
if (haveSetOffset != null && (Boolean) haveSetOffset) return;
MarginLayoutParams layoutParams = (MarginLayoutParams) view.getLayoutParams();
layoutParams.setMargins(layoutParams.leftMargin,
layoutParams.topMargin + getStatusBarHeight(),
layoutParams.rightMargin,
layoutParams.bottomMargin);
view.setTag(KEY_OFFSET, true);
}
/**
* Subtract the top margin size equals status bar's height for view.
*
* @param view The view.
*/
public static void subtractMarginTopEqualStatusBarHeight(@NonNull View view) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
Object haveSetOffset = view.getTag(KEY_OFFSET);
if (haveSetOffset == null || !(Boolean) haveSetOffset) return;
MarginLayoutParams layoutParams = (MarginLayoutParams) view.getLayoutParams();
layoutParams.setMargins(layoutParams.leftMargin,
layoutParams.topMargin - getStatusBarHeight(),
layoutParams.rightMargin,
layoutParams.bottomMargin);
view.setTag(KEY_OFFSET, false);
}
private static void addMarginTopEqualStatusBarHeight(final Window window) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
View withTag = window.getDecorView().findViewWithTag(TAG_OFFSET);
if (withTag == null) return;
addMarginTopEqualStatusBarHeight(withTag);
}
private static void subtractMarginTopEqualStatusBarHeight(final Window window) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
View withTag = window.getDecorView().findViewWithTag(TAG_OFFSET);
if (withTag == null) return;
subtractMarginTopEqualStatusBarHeight(withTag);
}
/**
* Set the status bar's color.
*
* @param activity The activity.
* @param color The status bar's color.
*/
public static View setStatusBarColor(@NonNull final Activity activity,
@ColorInt final int color) {
return setStatusBarColor(activity, color, false);
}
/**
* Set the status bar's color.
*
* @param activity The activity.
* @param color The status bar's color.
* @param isDecor True to add fake status bar in DecorView,
* false to add fake status bar in ContentView.
*/
public static View setStatusBarColor(@NonNull final Activity activity,
@ColorInt final int color,
final boolean isDecor) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return null;
transparentStatusBar(activity);
return applyStatusBarColor(activity, color, isDecor);
}
/**
* Set the status bar's color.
*
* @param fakeStatusBar The fake status bar view.
* @param color The status bar's color.
*/
public static void setStatusBarColor(@NonNull final View fakeStatusBar,
@ColorInt final int color) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
Activity activity = getActivityByView(fakeStatusBar);
if (activity == null) return;
transparentStatusBar(activity);
fakeStatusBar.setVisibility(View.VISIBLE);
ViewGroup.LayoutParams layoutParams = fakeStatusBar.getLayoutParams();
layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
layoutParams.height = getStatusBarHeight();
fakeStatusBar.setBackgroundColor(color);
}
/**
* Set the custom status bar.
*
* @param fakeStatusBar The fake status bar view.
*/
public static void setStatusBarCustom(@NonNull final View fakeStatusBar) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
Activity activity = getActivityByView(fakeStatusBar);
if (activity == null) return;
transparentStatusBar(activity);
fakeStatusBar.setVisibility(View.VISIBLE);
ViewGroup.LayoutParams layoutParams = fakeStatusBar.getLayoutParams();
if (layoutParams == null) {
layoutParams = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
getStatusBarHeight()
);
fakeStatusBar.setLayoutParams(layoutParams);
} else {
layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
layoutParams.height = getStatusBarHeight();
}
}
/**
* Set the status bar's color for DrawerLayout.
* <p>DrawLayout must add {@code android:fitsSystemWindows="true"}</p>
*
* @param drawer The DrawLayout.
* @param fakeStatusBar The fake status bar view.
* @param color The status bar's color.
*/
public static void setStatusBarColor4Drawer(@NonNull final DrawerLayout drawer,
@NonNull final View fakeStatusBar,
@ColorInt final int color) {
setStatusBarColor4Drawer(drawer, fakeStatusBar, color, false);
}
/**
* Set the status bar's color for DrawerLayout.
* <p>DrawLayout must add {@code android:fitsSystemWindows="true"}</p>
*
* @param drawer The DrawLayout.
* @param fakeStatusBar The fake status bar view.
* @param color The status bar's color.
* @param isTop True to set DrawerLayout at the top layer, false otherwise.
*/
public static void setStatusBarColor4Drawer(@NonNull final DrawerLayout drawer,
@NonNull final View fakeStatusBar,
@ColorInt final int color,
final boolean isTop) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
Activity activity = getActivityByView(fakeStatusBar);
if (activity == null) return;
transparentStatusBar(activity);
drawer.setFitsSystemWindows(false);
setStatusBarColor(fakeStatusBar, color);
for (int i = 0, count = drawer.getChildCount(); i < count; i++) {
drawer.getChildAt(i).setFitsSystemWindows(false);
}
if (isTop) {
hideStatusBarView(activity);
} else {
setStatusBarColor(activity, color, false);
}
}
private static View applyStatusBarColor(final Activity activity,
final int color,
boolean isDecor) {
ViewGroup parent = isDecor ?
(ViewGroup) activity.getWindow().getDecorView() :
(ViewGroup) activity.findViewById(android.R.id.content);
View fakeStatusBarView = parent.findViewWithTag(TAG_STATUS_BAR);
if (fakeStatusBarView != null) {
if (fakeStatusBarView.getVisibility() == View.GONE) {
fakeStatusBarView.setVisibility(View.VISIBLE);
}
fakeStatusBarView.setBackgroundColor(color);
} else {
fakeStatusBarView = createStatusBarView(activity, color);
parent.addView(fakeStatusBarView);
}
return fakeStatusBarView;
}
private static void hideStatusBarView(final Activity activity) {
hideStatusBarView(activity.getWindow());
}
private static void hideStatusBarView(final Window window) {
ViewGroup decorView = (ViewGroup) window.getDecorView();
View fakeStatusBarView = decorView.findViewWithTag(TAG_STATUS_BAR);
if (fakeStatusBarView == null) return;
fakeStatusBarView.setVisibility(View.GONE);
}
private static void showStatusBarView(final Window window) {
ViewGroup decorView = (ViewGroup) window.getDecorView();
View fakeStatusBarView = decorView.findViewWithTag(TAG_STATUS_BAR);
if (fakeStatusBarView == null) return;
fakeStatusBarView.setVisibility(View.VISIBLE);
}
private static View createStatusBarView(final Activity activity,
final int color) {
View statusBarView = new View(activity);
statusBarView.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight()));
statusBarView.setBackgroundColor(color);
statusBarView.setTag(TAG_STATUS_BAR);
return statusBarView;
}
private static void transparentStatusBar(final Activity activity) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
Window window = activity.getWindow();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
int option = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
window.getDecorView().setSystemUiVisibility(option);
window.setStatusBarColor(Color.TRANSPARENT);
} else {
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
///////////////////////////////////////////////////////////////////////////
// action bar
///////////////////////////////////////////////////////////////////////////
/**
* Return the action bar's height.
*
* @return the action bar's height
*/
public static int getActionBarHeight() {
TypedValue tv = new TypedValue();
if (CommonBaseLibrary.getApplication().getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
return TypedValue.complexToDimensionPixelSize(
tv.data, CommonBaseLibrary.getApplication().getResources().getDisplayMetrics()
);
}
return 0;
}
///////////////////////////////////////////////////////////////////////////
// notification bar
///////////////////////////////////////////////////////////////////////////
/**
* Set the notification bar's visibility.
* <p>Must hold {@code <uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />}</p>
*
* @param isVisible True to set notification bar visible, false otherwise.
*/
@RequiresPermission(EXPAND_STATUS_BAR)
public static void setNotificationBarVisibility(final boolean isVisible) {
String methodName;
if (isVisible) {
methodName = (Build.VERSION.SDK_INT <= 16) ? "expand" : "expandNotificationsPanel";
} else {
methodName = (Build.VERSION.SDK_INT <= 16) ? "collapse" : "collapsePanels";
}
invokePanels(methodName);
}
private static void invokePanels(final String methodName) {
try {
@SuppressLint("WrongConstant")
Object service = CommonBaseLibrary.getApplication().getSystemService("statusbar");
@SuppressLint("PrivateApi")
Class<?> statusBarManager = Class.forName("android.app.StatusBarManager");
Method expand = statusBarManager.getMethod(methodName);
expand.invoke(service);
} catch (Exception e) {
e.printStackTrace();
}
}
///////////////////////////////////////////////////////////////////////////
// navigation bar
///////////////////////////////////////////////////////////////////////////
/**
* Return the navigation bar's height.
*
* @return the navigation bar's height
*/
public static int getNavBarHeight() {
Resources res = Resources.getSystem();
int resourceId = res.getIdentifier("navigation_bar_height", "dimen", "android");
if (resourceId != 0) {
return res.getDimensionPixelSize(resourceId);
} else {
return 0;
}
}
/**
* Set the navigation bar's visibility.
*
* @param activity The activity.
* @param isVisible True to set navigation bar visible, false otherwise.
*/
public static void setNavBarVisibility(@NonNull final Activity activity, boolean isVisible) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
setNavBarVisibility(activity.getWindow(), isVisible);
}
/**
* Set the navigation bar's visibility.
*
* @param window The window.
* @param isVisible True to set navigation bar visible, false otherwise.
*/
public static void setNavBarVisibility(@NonNull final Window window, boolean isVisible) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
final ViewGroup decorView = (ViewGroup) window.getDecorView();
for (int i = 0, count = decorView.getChildCount(); i < count; i++) {
final View child = decorView.getChildAt(i);
final int id = child.getId();
if (id != View.NO_ID) {
String resourceEntryName = CommonBaseLibrary.getApplication()
.getResources()
.getResourceEntryName(id);
if ("navigationBarBackground".equals(resourceEntryName)) {
child.setVisibility(isVisible ? View.VISIBLE : View.INVISIBLE);
}
}
}
final int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
if (isVisible) {
decorView.setSystemUiVisibility(decorView.getSystemUiVisibility() & ~uiOptions);
} else {
decorView.setSystemUiVisibility(decorView.getSystemUiVisibility() | uiOptions);
}
}
/**
* Return whether the navigation bar visible.
* <p>Call it in onWindowFocusChanged will get right result.</p>
*
* @param activity The activity.
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isNavBarVisible(@NonNull final Activity activity) {
return isNavBarVisible(activity.getWindow());
}
/**
* 判断是否显示了导航栏
* (说明这里的context 一定要是activity的context 否则类型转换失败)
*
* @param context
* @return
*/
// public static boolean isShowNavBar(Context context) {
// if (null == context) {
// node_return false;
// }
// /**
// * 获取应用区域高度
// */
// Rect outRect1 = new Rect();
// try {
// ((Activity) context).getWindow().getDecorView().getWindowVisibleDisplayFrame(outRect1);
// } catch (ClassCastException e) {
// e.printStackTrace();
// node_return false;
// }
// int activityHeight = outRect1.height();
// /**
// * 获取状态栏高度
// */
// int statuBarHeight = WindowDispaly.getStatusBarHeight();
// /**
// * 屏幕物理高度 减去 状态栏高度
// */
// int remainHeight = WindowDispaly.getRealHeight() - statuBarHeight;
// /**
// * 剩余高度跟应用区域高度相等 说明导航栏没有显示 否则相反
// */
// if (activityHeight == remainHeight) {
// node_return false;
// } else {
// node_return true;
// }
//
// }
/**
* Return whether the navigation bar visible.
* <p>Call it in onWindowFocusChanged will get right result.</p>
*
* @param window The window.
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isNavBarVisible(@NonNull final Window window) {
boolean isVisible = false;
ViewGroup decorView = (ViewGroup) window.getDecorView();
for (int i = 0, count = decorView.getChildCount(); i < count; i++) {
final View child = decorView.getChildAt(i);
final int id = child.getId();
if (id != View.NO_ID) {
String resourceEntryName = CommonBaseLibrary.getApplication()
.getResources()
.getResourceEntryName(id);
if ("navigationBarBackground".equals(resourceEntryName)
&& child.getVisibility() == View.VISIBLE) {
isVisible = true;
break;
}
}
}
if (isVisible) {
int visibility = decorView.getSystemUiVisibility();
isVisible = (visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
}
return isVisible;
}
/**
* Set the navigation bar's color.
*
* @param activity The activity.
* @param color The navigation bar's color.
*/
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
public static void setNavBarColor(@NonNull final Activity activity, @ColorInt final int color) {
setNavBarColor(activity.getWindow(), color);
}
/**
* Set the navigation bar's color.
*
* @param window The window.
* @param color The navigation bar's color.
*/
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
public static void setNavBarColor(@NonNull final Window window, @ColorInt final int color) {
window.setNavigationBarColor(color);
}
/**
* Return the color of navigation bar.
*
* @param activity The activity.
* @return the color of navigation bar
*/
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
public static int getNavBarColor(@NonNull final Activity activity) {
return getNavBarColor(activity.getWindow());
}
/**
* Return the color of navigation bar.
*
* @param window The window.
* @return the color of navigation bar
*/
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
public static int getNavBarColor(@NonNull final Window window) {
return window.getNavigationBarColor();
}
/**
* Return whether the navigation bar visible.
*
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isSupportNavBar() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
WindowManager wm = (WindowManager) CommonBaseLibrary.getApplication().getSystemService(Context.WINDOW_SERVICE);
if (wm == null) return false;
Display display = wm.getDefaultDisplay();
Point size = new Point();
Point realSize = new Point();
display.getSize(size);
display.getRealSize(realSize);
return realSize.y != size.y || realSize.x != size.x;
}
boolean menu = ViewConfiguration.get(CommonBaseLibrary.getApplication()).hasPermanentMenuKey();
boolean back = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
return !menu && !back;
}
private static Activity getActivityByView(@NonNull final View view) {
Context context = view.getContext();
while (context instanceof ContextWrapper) {
if (context instanceof Activity) {
return (Activity) context;
}
context = ((ContextWrapper) context).getBaseContext();
}
Log.e("BarUtils", "the view's Context is not an Activity.");
return null;
}
}
@@ -0,0 +1,13 @@
package com.dahe.mylibrary.utils;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Base64;
public class Base64Utils {
public static Bitmap base64ToBitmap(String imageBase64){
byte[] decodedString = Base64.decode(imageBase64, Base64.DEFAULT);
return BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
}
}
@@ -0,0 +1,195 @@
package com.dahe.mylibrary.utils;
import android.content.Context;
import android.content.SharedPreferences;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
/**
* 轻量级数据存储工具类
*
* @author Administrator
*/
public class BaseSPUtils {
/**
* 保存在手机里面的文件名
*/
public static final String FILE_NAME = "sp_data";
public static final String USER_INFO_KEY = "user_info_key";
public static final String USER_TOKEN_KEY = "user_token_key";
public static final String NET_SERVICE_TEST = "net_service_test";
public static final String SEARRH_CACHE = "search_cache";
public static final String NAVI_PH_EDIT_CACHE = "navi_ph_edit_cache";
public static final String FIRST_OPEN = "first_open";
public static final String KEY_PRIVACY_AGREEMENT = "privacy_agreement";
/**
* 保存数据的方法,我们需要拿到保存数据的具体类型,然后根据类型调用不同的保存方法
*
* @param context
* @param key
* @param object
*/
public static void put(Context context, String key, Object object) {
SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
if (object instanceof String) {
editor.putString(key, (String) object);
} else if (object instanceof Integer) {
editor.putInt(key, (Integer) object);
} else if (object instanceof Boolean) {
editor.putBoolean(key, (Boolean) object);
} else if (object instanceof Float) {
editor.putFloat(key, (Float) object);
} else if (object instanceof Long) {
editor.putLong(key, (Long) object);
} else {
editor.putString(key, object.toString());
}
SharedPreferencesCompat.apply(editor);
}
/**
* 得到保存数据的方法,我们根据默认值得到保存的数据的具体类型,然后调用相对于的方法获取值
*
* @param context
* @param key
* @param defaultObject
* @return
*/
public static Object get(Context context, String key, Object defaultObject) {
SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
if (defaultObject instanceof String) {
return sp.getString(key, (String) defaultObject);
} else if (defaultObject instanceof Integer) {
return sp.getInt(key, (Integer) defaultObject);
} else if (defaultObject instanceof Boolean) {
return sp.getBoolean(key, (Boolean) defaultObject);
} else if (defaultObject instanceof Float) {
return sp.getFloat(key, (Float) defaultObject);
} else if (defaultObject instanceof Long) {
return sp.getLong(key, (Long) defaultObject);
}
return null;
}
/**
* 移除某个key值已经对应的值
*
* @param context
* @param key
*/
public static void remove(Context context, String key) {
SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.remove(key);
SharedPreferencesCompat.apply(editor);
}
/**
* 清除所有数据
*
* @param context
*/
public static void clear(Context context) {
SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.clear();
SharedPreferencesCompat.apply(editor);
}
/**
* 查询某个key是否已经存在
*
* @param context
* @param key
* @return
*/
public static boolean contains(Context context, String key) {
SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
return sp.contains(key);
}
/**
* 返回所有的键值对
*
* @param context
* @return
*/
public static Map<String, ?> getAll(Context context) {
SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
return sp.getAll();
}
/**
* 创建一个解决SharedPreferencesCompat.apply方法的一个兼容类
*
* @author zhy
*/
private static class SharedPreferencesCompat {
private static final Method sApplyMethod = findApplyMethod();
/**
* 反射查找apply的方法
*
* @return
*/
@SuppressWarnings(
{"unchecked", "rawtypes"})
private static Method findApplyMethod() {
try {
Class clz = SharedPreferences.Editor.class;
return clz.getMethod("apply");
} catch (NoSuchMethodException e) {
}
return null;
}
/**
* 如果找到则使用apply执行,否则使用commit
*
* @param editor
*/
public static void apply(SharedPreferences.Editor editor) {
try {
if (sApplyMethod != null) {
sApplyMethod.invoke(editor);
return;
}
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
}
editor.commit();
}
}
/*****---------------------------------------------***/
/**
* 是否含有用户信息
*
* @param context
* @return
*/
public static boolean hasUserInfo(Context context) {
return contains(context, USER_INFO_KEY);
}
/**
* 清除用户信息
*
* @param context
* @return
*/
public static void cleanUserInfo(Context context) {
remove(context, USER_INFO_KEY);
}
}
@@ -0,0 +1,243 @@
package com.dahe.mylibrary.utils;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.provider.ContactsContract;
import android.text.TextUtils;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import androidx.appcompat.app.AppCompatActivity;
import com.dahe.mylibrary.R;
import com.shehuan.nicedialog.BaseNiceDialog;
import com.shehuan.nicedialog.NiceDialog;
import com.shehuan.nicedialog.ViewConvertListener;
import com.shehuan.nicedialog.ViewHolder;
import java.util.Locale;
public class BaseUtils {
/**
* 验证手机格式
*/
public static boolean isMobileNO(String mobiles) {
String telRegex = "[1][3456789]\\d{9}";
// "[1]"代表第1位为数字1"[358]"代表第二位可以为3、5、8中的一个,"\\d{9}"代表后面是可以是0~9的数字,有9位。
if (TextUtils.isEmpty(mobiles)) return false;
else return mobiles.matches(telRegex);
}
/**
* 获取语言
*
* @param context
* @return
*/
public static int getLanguage(Context context) {
Locale curLocale = getLocale(context);
String language = curLocale.getLanguage();
String country = curLocale.getCountry();
if (language.equals(Locale.CHINA.getLanguage())) {
//0是简体中文,1是繁体中文
return country.equals(Locale.SIMPLIFIED_CHINESE.getCountry()) ? 0 : 1;
} else if (language.equals(Locale.ENGLISH.getLanguage())) {
//英语
return 2;
} else if (language.equals("th")) {
//泰文
return 3;
} else if (language.equals(Locale.KOREAN.getLanguage())) {
//韩文
return 4;
} else if (language.equals("vi")) {
//越南语
return 5;
} else if (language.equals(Locale.JAPAN.getLanguage())) {
//日语
return 6;
} else if (language.equals("in")) {
//印尼语
return 7;
} else {
return 2;
}
}
//获取Locale
private static Locale getLocale(Context context) {
Locale locale;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
locale = context.getResources().getConfiguration().getLocales().get(0);
} else {
locale = context.getResources().getConfiguration().locale;
}
return locale;
}
/**
* 拨打电话(直接拨打电话)
* @param phoneNum 电话号码
*/
public static void callPhone(AppCompatActivity context , String phoneNum){
NiceDialog.init()
.setLayoutId(R.layout.dialog_phone)
.setConvertListener(new ViewConvertListener() {
@Override
protected void convertView(ViewHolder viewHolder, BaseNiceDialog baseNiceDialog) {
viewHolder.setText(R.id.message, phoneNum);
viewHolder.setOnClickListener(R.id.ok, new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_CALL);
Uri data = Uri.parse("tel:" + phoneNum);
intent.setData(data);
context.startActivity(intent);
baseNiceDialog.dismiss();
}
});
viewHolder.setOnClickListener(R.id.cancel, new View.OnClickListener() {
@Override
public void onClick(View v) {
baseNiceDialog.dismiss();
}
});
}
})
.setWidth(260).show(context.getSupportFragmentManager());
}
/**
* 获取VersionCode
*
* @param context
* @return
*/
public static String geVersionCode(Context context) {
try {
PackageInfo packageInfo = context.getPackageManager()
.getPackageInfo(context.getPackageName(), 0);
return packageInfo.versionName;
} catch (Exception e) {
return "1.0.0";
}
}
/**
* 跳转qq
*
* @param context
* @return
*/
public static String goToQQ(Context context, String qqNumber) {
try {
context.getPackageManager().getApplicationInfo("com.tencent.mobileqq",
PackageManager.GET_UNINSTALLED_PACKAGES);
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("mqqwpa://im/chat?chat_type=wpa&uin=" + qqNumber + "&version=1")));
} catch (PackageManager.NameNotFoundException e) {
return "客服为qq在线,联系客服请先安装qq";
}
return "";
}
/**
* 跳转手机通讯录 选择联系人 并返回联系人信息
*
* @param context
* @param uri
* @return
*/
public static String[] getPhoneContacts(Context context, Uri uri) {
String[] contact = new String[2];
ContentResolver cr = context.getContentResolver();
Cursor cursor = cr.query(uri, null, null, null, null);
if (cursor != null && cursor.getCount() != 0) {
cursor.moveToFirst();
int nameFieldColumnIndex = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
contact[0] = cursor.getString(nameFieldColumnIndex);
String ContactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
Cursor phone = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=" + ContactId, null, null);
if (phone != null && phone.getCount() != 0) {
phone.moveToFirst();
contact[1] = phone.getString(phone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)).trim().replace(" ", "").toString();
} else {
contact[1] = "";
}
phone.close();
cursor.close();
} else {
return null;
}
return contact;
}
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*/
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* 根据手机的分辨率从 px(像素) 的单位 转成为 dp
*/
public static int px2dip(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
/**
* 将sp值转换为px值,保证文字大小不变
*
* @param spValue
* @param spValue DisplayMetrics类中属性scaledDensity
* @return
*/
public static int sp2px(Context context, float spValue) {
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (spValue * fontScale + 0.5f);
}
/**
* 强制隐藏输入法键盘
*
* @param context Context
* @param view EditText
*/
public static void hideInput(Context context, View view) {
InputMethodManager inputMethodManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
/**
* 隐藏软键盘(只适用于Activity,不适用于Fragment)
*/
public static void hideSoftKeyboard(Activity activity) {
View view = activity.getCurrentFocus();
if (view != null) {
InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
}
//view为接受软键盘输入的视图,SHOW_FORCED表示强制显示
public static void hideSoftKeyboard(Activity activity, View view) {
InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(view, InputMethodManager.SHOW_FORCED);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0); //强制隐藏键盘
}
}
@@ -0,0 +1,76 @@
package com.dahe.mylibrary.utils;
import java.io.UnsupportedEncodingException;
public class CNPinyinIndex {
//自动获取汉子的首字母
static final int GB_SP_DIFF = 160;
// 存放国标一级汉字不同读音的起始区位码
static final int[] secPosValueList = {1601, 1637, 1833, 2078, 2274, 2302,
2433, 2594, 2787, 3106, 3212, 3472, 3635, 3722, 3730, 3858, 4027,
4086, 4390, 4558, 4684, 4925, 5249, 5600};
// 存放国标一级汉字不同读音的起始区位码对应读音
static final char[] firstLetter = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'w', 'x',
'y', 'z'};
public static String getSpells(String characters) {
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < characters.length(); i++) {
char ch = characters.charAt(i);
if ((ch >> 7) == 0) {
// 判断是否为汉字,如果左移7为为0就不是汉字,否则是汉字
} else {
char spell = getFirstLetter(ch);
buffer.append(String.valueOf(spell));
}
}
return buffer.toString();
}
// 获取一个汉字的首字母
public static Character getFirstLetter(char ch) {
byte[] uniCode = null;
try {
uniCode = String.valueOf(ch).getBytes("GBK");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
if (uniCode[0] < 128 && uniCode[0] > 0) { // 非汉字
return null;
} else {
return convert(uniCode);
}
}
/**
* 获取一个汉字的拼音首字母。 GB码两个字节分别减去160,转换成10进制码组合就可以得到区位码
* 例如汉字“你”的GB码是0xC4/0xE3,分别减去0xA0160)就是0x24/0x43
* 0x24转成10进制就是36,0x43是67,那么它的区位码就是3667,在对照表中读音为‘n’
*/
static char convert(byte[] bytes) {
char result = '-';
int secPosValue = 0;
int i;
for (i = 0; i < bytes.length; i++) {
bytes[i] -= GB_SP_DIFF;
}
secPosValue = bytes[0] * 100 + bytes[1];
for (i = 0; i < 23; i++) {
if (secPosValue >= secPosValueList[i]
&& secPosValue < secPosValueList[i + 1]) {
result = firstLetter[i];
break;
}
}
return result;
}
}
@@ -0,0 +1,645 @@
package com.dahe.mylibrary.utils;
import android.annotation.SuppressLint;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.view.View;
import com.dahe.mylibrary.CommonBaseLibrary;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
/**
* bytes2Bits, bits2Bytes : bytes 与 bits 互转
* bytes2Chars, chars2Bytes : bytes 与 chars 互转
* bytes2HexString, hexString2Bytes : bytes 与 hexString 互转
* memorySize2Byte, byte2MemorySize : 以 unit 为单位的内存大小与字节数互转
* byte2FitMemorySize : 字节数转合适内存大小
* timeSpan2Millis, millis2TimeSpan : 以 unit 为单位的时间长度与毫秒时间戳互转
* millis2FitTimeSpan : 毫秒时间戳转合适时间长度
* input2OutputStream, output2InputStream : inputStream 与 outputStream 互转
* inputStream2Bytes, bytes2InputStream : inputStream 与 bytes 互转
* outputStream2Bytes, bytes2OutputStream : outputStream 与 bytes 互转
* inputStream2String, string2InputStream : inputStream 与 string 按编码互转
* outputStream2String, string2OutputStream: outputStream 与 string 按编码互转
* bitmap2Bytes, bytes2Bitmap : bitmap 与 bytes 互转
* drawable2Bitmap, bitmap2Drawable : drawable 与 bitmap 互转
* drawable2Bytes, bytes2Drawable : drawable 与 bytes 互转
* view2Bitmap : view 转 Bitmap
* dp2px, px2dp : dp 与 px 互转
* sp2px, px2sp : sp 与 px 互转
*/
public final class ConvertUtils {
private ConvertUtils() {
throw new UnsupportedOperationException("u can't instantiate me...");
}
private static final char hexDigits[] =
{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
/**
* Bytes to bits.
*
* @param bytes The bytes.
* @return bits
*/
public static String bytes2Bits(final byte[] bytes) {
if (bytes == null || bytes.length == 0) return "";
StringBuilder sb = new StringBuilder();
for (byte aByte : bytes) {
for (int j = 7; j >= 0; --j) {
sb.append(((aByte >> j) & 0x01) == 0 ? '0' : '1');
}
}
return sb.toString();
}
/**
* Bits to bytes.
*
* @param bits The bits.
* @return bytes
*/
public static byte[] bits2Bytes(String bits) {
int lenMod = bits.length() % 8;
int byteLen = bits.length() / 8;
// add "0" until length to 8 times
if (lenMod != 0) {
for (int i = lenMod; i < 8; i++) {
bits = "0" + bits;
}
byteLen++;
}
byte[] bytes = new byte[byteLen];
for (int i = 0; i < byteLen; ++i) {
for (int j = 0; j < 8; ++j) {
bytes[i] <<= 1;
bytes[i] |= bits.charAt(i * 8 + j) - '0';
}
}
return bytes;
}
/**
* Bytes to chars.
*
* @param bytes The bytes.
* @return chars
*/
public static char[] bytes2Chars(final byte[] bytes) {
if (bytes == null) return null;
int len = bytes.length;
if (len <= 0) return null;
char[] chars = new char[len];
for (int i = 0; i < len; i++) {
chars[i] = (char) (bytes[i] & 0xff);
}
return chars;
}
/**
* Chars to bytes.
*
* @param chars The chars.
* @return bytes
*/
public static byte[] chars2Bytes(final char[] chars) {
if (chars == null || chars.length <= 0) return null;
int len = chars.length;
byte[] bytes = new byte[len];
for (int i = 0; i < len; i++) {
bytes[i] = (byte) (chars[i]);
}
return bytes;
}
/**
* Bytes to hex string.
* <p>e.g. bytes2HexString(new byte[] { 0, (byte) 0xa8 }) returns "00A8"</p>
*
* @param bytes The bytes.
* @return hex string
*/
public static String bytes2HexString(final byte[] bytes) {
if (bytes == null) return "";
int len = bytes.length;
if (len <= 0) return "";
char[] ret = new char[len << 1];
for (int i = 0, j = 0; i < len; i++) {
ret[j++] = hexDigits[bytes[i] >> 4 & 0x0f];
ret[j++] = hexDigits[bytes[i] & 0x0f];
}
return new String(ret);
}
/**
* Hex string to bytes.
* <p>e.g. hexString2Bytes("00A8") returns { 0, (byte) 0xA8 }</p>
*
* @param hexString The hex string.
* @return the bytes
*/
public static byte[] hexString2Bytes(String hexString) {
if (isSpace(hexString)) return null;
int len = hexString.length();
if (len % 2 != 0) {
hexString = "0" + hexString;
len = len + 1;
}
char[] hexBytes = hexString.toUpperCase().toCharArray();
byte[] ret = new byte[len >> 1];
for (int i = 0; i < len; i += 2) {
ret[i >> 1] = (byte) (hex2Int(hexBytes[i]) << 4 | hex2Int(hexBytes[i + 1]));
}
return ret;
}
private static int hex2Int(final char hexChar) {
if (hexChar >= '0' && hexChar <= '9') {
return hexChar - '0';
} else if (hexChar >= 'A' && hexChar <= 'F') {
return hexChar - 'A' + 10;
} else {
throw new IllegalArgumentException();
}
}
/**
* Size of memory in unit to size of byte.
*
* @param memorySize Size of memory.
* @param unit The unit of memory size.
* <ul>
* <li>{@link MemoryConstants#BYTE}</li>
* <li>{@link MemoryConstants#KB}</li>
* <li>{@link MemoryConstants#MB}</li>
* <li>{@link MemoryConstants#GB}</li>
* </ul>
* @return size of byte
*/
public static long memorySize2Byte(final long memorySize,
@MemoryConstants.Unit final int unit) {
if (memorySize < 0) return -1;
return memorySize * unit;
}
/**
* Size of byte to size of memory in unit.
*
* @param byteSize Size of byte.
* @param unit The unit of memory size.
* <ul>
* <li>{@link MemoryConstants#BYTE}</li>
* <li>{@link MemoryConstants#KB}</li>
* <li>{@link MemoryConstants#MB}</li>
* <li>{@link MemoryConstants#GB}</li>
* </ul>
* @return size of memory in unit
*/
public static double byte2MemorySize(final long byteSize,
@MemoryConstants.Unit final int unit) {
if (byteSize < 0) return -1;
return (double) byteSize / unit;
}
/**
* Size of byte to fit size of memory.
* <p>to three decimal places</p>
*
* @param byteSize Size of byte.
* @return fit size of memory
*/
@SuppressLint("DefaultLocale")
public static String byte2FitMemorySize(final long byteSize) {
if (byteSize < 0) {
return "shouldn't be less than zero!";
} else if (byteSize < MemoryConstants.KB) {
return String.format("%.3fB", (double) byteSize);
} else if (byteSize < MemoryConstants.MB) {
return String.format("%.3fKB", (double) byteSize / MemoryConstants.KB);
} else if (byteSize < MemoryConstants.GB) {
return String.format("%.3fMB", (double) byteSize / MemoryConstants.MB);
} else {
return String.format("%.3fGB", (double) byteSize / MemoryConstants.GB);
}
}
/**
* Time span in unit to milliseconds.
*
* @param timeSpan The time span.
* @param unit The unit of time span.
* <ul>
* <li>{@link TimeConstants#MSEC}</li>
* <li>{@link TimeConstants#SEC }</li>
* <li>{@link TimeConstants#MIN }</li>
* <li>{@link TimeConstants#HOUR}</li>
* <li>{@link TimeConstants#DAY }</li>
* </ul>
* @return milliseconds
*/
public static long timeSpan2Millis(final long timeSpan, @TimeConstants.Unit final int unit) {
return timeSpan * unit;
}
/**
* Milliseconds to time span in unit.
*
* @param millis The milliseconds.
* @param unit The unit of time span.
* <ul>
* <li>{@link TimeConstants#MSEC}</li>
* <li>{@link TimeConstants#SEC }</li>
* <li>{@link TimeConstants#MIN }</li>
* <li>{@link TimeConstants#HOUR}</li>
* <li>{@link TimeConstants#DAY }</li>
* </ul>
* @return time span in unit
*/
public static long millis2TimeSpan(final long millis, @TimeConstants.Unit final int unit) {
return millis / unit;
}
/**
* Milliseconds to fit time span.
*
* @param millis The milliseconds.
* <p>millis &lt;= 0, node_return null</p>
* @param precision The precision of time span.
* <ul>
* <li>precision = 0, node_return null</li>
* <li>precision = 1, node_return 天</li>
* <li>precision = 2, node_return 天, 小时</li>
* <li>precision = 3, node_return 天, 小时, 分钟</li>
* <li>precision = 4, node_return 天, 小时, 分钟, 秒</li>
* <li>precision &gt;= 5node_return 天, 小时, 分钟, 秒, 毫秒</li>
* </ul>
* @return fit time span
*/
@SuppressLint("DefaultLocale")
public static String millis2FitTimeSpan(long millis, int precision) {
if (millis <= 0 || precision <= 0) return null;
StringBuilder sb = new StringBuilder();
String[] units = {"", "小时", "分钟", "", "毫秒"};
int[] unitLen = {86400000, 3600000, 60000, 1000, 1};
precision = Math.min(precision, 5);
for (int i = 0; i < precision; i++) {
if (millis >= unitLen[i]) {
long mode = millis / unitLen[i];
millis -= mode * unitLen[i];
sb.append(mode).append(units[i]);
}
}
return sb.toString();
}
/**
* Input stream to output stream.
*
* @param is The input stream.
* @return output stream
*/
public static ByteArrayOutputStream input2OutputStream(final InputStream is) {
if (is == null) return null;
try {
ByteArrayOutputStream os = new ByteArrayOutputStream();
byte[] b = new byte[MemoryConstants.KB];
int len;
while ((len = is.read(b, 0, MemoryConstants.KB)) != -1) {
os.write(b, 0, len);
}
return os;
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* Output stream to input stream.
*
* @param out The output stream.
* @return input stream
*/
public ByteArrayInputStream output2InputStream(final OutputStream out) {
if (out == null) return null;
return new ByteArrayInputStream(((ByteArrayOutputStream) out).toByteArray());
}
/**
* Input stream to bytes.
*
* @param is The input stream.
* @return bytes
*/
public static byte[] inputStream2Bytes(final InputStream is) {
if (is == null) return null;
return input2OutputStream(is).toByteArray();
}
/**
* Bytes to input stream.
*
* @param bytes The bytes.
* @return input stream
*/
public static InputStream bytes2InputStream(final byte[] bytes) {
if (bytes == null || bytes.length <= 0) return null;
return new ByteArrayInputStream(bytes);
}
/**
* Output stream to bytes.
*
* @param out The output stream.
* @return bytes
*/
public static byte[] outputStream2Bytes(final OutputStream out) {
if (out == null) return null;
return ((ByteArrayOutputStream) out).toByteArray();
}
/**
* Bytes to output stream.
*
* @param bytes The bytes.
* @return output stream
*/
public static OutputStream bytes2OutputStream(final byte[] bytes) {
if (bytes == null || bytes.length <= 0) return null;
ByteArrayOutputStream os = null;
try {
os = new ByteArrayOutputStream();
os.write(bytes);
return os;
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
try {
if (os != null) {
os.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* Input stream to string.
*
* @param is The input stream.
* @param charsetName The name of charset.
* @return string
*/
public static String inputStream2String(final InputStream is, final String charsetName) {
if (is == null || isSpace(charsetName)) return "";
try {
return new String(inputStream2Bytes(is), charsetName);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return "";
}
}
/**
* String to input stream.
*
* @param string The string.
* @param charsetName The name of charset.
* @return input stream
*/
public static InputStream string2InputStream(final String string, final String charsetName) {
if (string == null || isSpace(charsetName)) return null;
try {
return new ByteArrayInputStream(string.getBytes(charsetName));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}
/**
* Output stream to string.
*
* @param out The output stream.
* @param charsetName The name of charset.
* @return string
*/
public static String outputStream2String(final OutputStream out, final String charsetName) {
if (out == null || isSpace(charsetName)) return "";
try {
return new String(outputStream2Bytes(out), charsetName);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return "";
}
}
/**
* String to output stream.
*
* @param string The string.
* @param charsetName The name of charset.
* @return output stream
*/
public static OutputStream string2OutputStream(final String string, final String charsetName) {
if (string == null || isSpace(charsetName)) return null;
try {
return bytes2OutputStream(string.getBytes(charsetName));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}
/**
* Bitmap to bytes.
*
* @param bitmap The bitmap.
* @param format The format of bitmap.
* @return bytes
*/
public static byte[] bitmap2Bytes(final Bitmap bitmap, final Bitmap.CompressFormat format) {
if (bitmap == null) return null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(format, 100, baos);
return baos.toByteArray();
}
/**
* Bytes to bitmap.
*
* @param bytes The bytes.
* @return bitmap
*/
public static Bitmap bytes2Bitmap(final byte[] bytes) {
return (bytes == null || bytes.length == 0)
? null
: BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
}
/**
* Drawable to bitmap.
*
* @param drawable The drawable.
* @return bitmap
*/
public static Bitmap drawable2Bitmap(final Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
if (bitmapDrawable.getBitmap() != null) {
return bitmapDrawable.getBitmap();
}
}
Bitmap bitmap;
if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
bitmap = Bitmap.createBitmap(1, 1,
drawable.getOpacity() != PixelFormat.OPAQUE
? Bitmap.Config.ARGB_8888
: Bitmap.Config.RGB_565);
} else {
bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(),
drawable.getOpacity() != PixelFormat.OPAQUE
? Bitmap.Config.ARGB_8888
: Bitmap.Config.RGB_565);
}
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
/**
* Bitmap to drawable.
*
* @param bitmap The bitmap.
* @return drawable
*/
public static Drawable bitmap2Drawable(final Bitmap bitmap) {
return bitmap == null ? null : new BitmapDrawable(CommonBaseLibrary.getApplication().getResources(), bitmap);
}
/**
* Drawable to bytes.
*
* @param drawable The drawable.
* @param format The format of bitmap.
* @return bytes
*/
public static byte[] drawable2Bytes(final Drawable drawable,
final Bitmap.CompressFormat format) {
return drawable == null ? null : bitmap2Bytes(drawable2Bitmap(drawable), format);
}
/**
* Bytes to drawable.
*
* @param bytes The bytes.
* @return drawable
*/
public static Drawable bytes2Drawable(final byte[] bytes) {
return bytes == null ? null : bitmap2Drawable(bytes2Bitmap(bytes));
}
/**
* View to bitmap.
*
* @param view The view.
* @return bitmap
*/
public static Bitmap view2Bitmap(final View view) {
if (view == null) return null;
Bitmap ret =
Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(ret);
Drawable bgDrawable = view.getBackground();
if (bgDrawable != null) {
bgDrawable.draw(canvas);
} else {
canvas.drawColor(Color.WHITE);
}
view.draw(canvas);
return ret;
}
/**
* Value of dp to value of px.
*
* @param dpValue The value of dp.
* @return value of px
*/
public static int dp2px(final float dpValue) {
final float scale = Resources.getSystem().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* Value of px to value of dp.
*
* @param pxValue The value of px.
* @return value of dp
*/
public static int px2dp(final float pxValue) {
final float scale = Resources.getSystem().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
/**
* Value of sp to value of px.
*
* @param spValue The value of sp.
* @return value of px
*/
public static int sp2px(final float spValue) {
final float fontScale = Resources.getSystem().getDisplayMetrics().scaledDensity;
return (int) (spValue * fontScale + 0.5f);
}
/**
* Value of px to value of sp.
*
* @param pxValue The value of px.
* @return value of sp
*/
public static int px2sp(final float pxValue) {
final float fontScale = Resources.getSystem().getDisplayMetrics().scaledDensity;
return (int) (pxValue / fontScale + 0.5f);
}
///////////////////////////////////////////////////////////////////////////
// other utils methods
///////////////////////////////////////////////////////////////////////////
private static boolean isSpace(final String s) {
if (s == null) return true;
for (int i = 0, len = s.length(); i < len; ++i) {
if (!Character.isWhitespace(s.charAt(i))) {
return false;
}
}
return true;
}
}
@@ -0,0 +1,38 @@
package com.dahe.mylibrary.utils;
import android.os.CountDownTimer;
import android.widget.TextView;
public class CountDownTimerUtils extends CountDownTimer {
private TextView mTextView;
/**
* @param millisInFuture The number of millis in the future from the call
* to {@link #start()} until the countdown is done and {@link #onFinish()}
* is called.
* @param countDownInterval The interval along the way to receive
* {@link #onTick(long)} callbacks.
*/
public CountDownTimerUtils(TextView textView, long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
this.mTextView = textView;
}
@Override
public void onTick(long millisUntilFinished) {
mTextView.setClickable(false); //设置不可点击
mTextView.setText(millisUntilFinished / 1000 + "秒后重新发送"); //设置倒计时时间
// mTextView.setBackgroundResource(R.drawable.bg_identify_code_press); //设置按钮为灰色,这时是不能点击的
// SpannableString spannableString = new SpannableString(mTextView.getText().toString()); //获取按钮上的文字
// ForegroundColorSpan span = new ForegroundColorSpan(Color.RED);
// spannableString.setSpan(span, 0, 2, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);//将倒计时的时间设置为红色
// mTextView.setText(spannableString);
}
@Override
public void onFinish() {
mTextView.setText("获取验证码");
mTextView.setClickable(true);//重新获得点击
// mTextView.setBackgroundResource(R.drawable.bg_identify_code_normal); //还原背景色
}
}
@@ -0,0 +1,243 @@
package com.dahe.mylibrary.utils;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Environment;
import android.os.Looper;
import android.os.SystemClock;
import android.util.Log;
import android.widget.Toast;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Field;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import static android.os.Environment.DIRECTORY_ALARMS;
/**
* <h3>全局捕获异常</h3>
* <br>
* 当程序发生Uncaught异常的时候,有该类来接管程序,并记录错误日志
*
*/
@SuppressLint("SimpleDateFormat")
public class CrashHandler implements Thread.UncaughtExceptionHandler {
public static String TAG = "MyCrash";
// 系统默认的UncaughtException处理类
private Thread.UncaughtExceptionHandler mDefaultHandler;
private static CrashHandler instance = new CrashHandler();
private Context mContext;
// 用来存储设备信息和异常信息
private Map<String, String> infos = new HashMap<String, String>();
// 用于格式化日期,作为日志文件名的一部分
private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
/** 保证只有一个CrashHandler实例 */
private CrashHandler() {
}
/** 获取CrashHandler实例 ,单例模式 */
public static CrashHandler getInstance() {
return instance;
}
/**
* 初始化
*
* @param context
*/
public void init(Context context) {
mContext = context;
// 获取系统默认的UncaughtException处理器
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
// 设置该CrashHandler为程序的默认处理器
Thread.setDefaultUncaughtExceptionHandler(this);
FileUtil.removeFileByTime(getGlobalpath());
// autoClear(5);
}
/**
* 当UncaughtException发生时会转入该函数来处理
*/
@Override
public void uncaughtException(Thread thread, Throwable ex) {
if (!handleException(ex) && mDefaultHandler != null) {
// 如果用户没有处理则让系统默认的异常处理器来处理
mDefaultHandler.uncaughtException(thread, ex);
} else {
SystemClock.sleep(3000);
// 退出程序
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(1);
}
}
/**
* 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
*
* @param ex
* @return true:如果处理了该异常信息; 否则返回false.
*/
private boolean handleException(Throwable ex) {
if (ex == null)
return false;
try {
// 使用Toast来显示异常信息
new Thread() {
@Override
public void run() {
Looper.prepare();
Toast.makeText(mContext, "很抱歉,程序出现异常,即将重启.",
Toast.LENGTH_LONG).show();
Looper.loop();
}
}.start();
// 收集设备参数信息
collectDeviceInfo(mContext);
// 保存日志文件
saveCrashInfoFile(ex);
SystemClock.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
/**
* 收集设备参数信息
*
* @param ctx
*/
public void collectDeviceInfo(Context ctx) {
try {
PackageManager pm = ctx.getPackageManager();
PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(),
PackageManager.GET_ACTIVITIES);
if (pi != null) {
String versionName = pi.versionName + "";
String versionCode = pi.versionCode + "";
infos.put("versionName", versionName);
infos.put("versionCode", versionCode);
}
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, "an error occured when collect package info", e);
}
Field[] fields = Build.class.getDeclaredFields();
for (Field field : fields) {
try {
field.setAccessible(true);
infos.put(field.getName(), field.get(null).toString());
} catch (Exception e) {
Log.e(TAG, "an error occured when collect crash info", e);
}
}
}
/**
* 保存错误信息到文件中
* @param ex
* @return 返回文件名称,便于将文件传送到服务器
* @throws Exception
*/
private String saveCrashInfoFile(Throwable ex) throws Exception {
StringBuffer sb = new StringBuffer();
try {
SimpleDateFormat sDateFormat = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss");
String date = sDateFormat.format(new java.util.Date());
sb.append("\r\n" + date + "\n");
for (Map.Entry<String, String> entry : infos.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
sb.append(key + "=" + value + "\n");
}
Writer writer = new StringWriter();
PrintWriter printWriter = new PrintWriter(writer);
ex.printStackTrace(printWriter);
Throwable cause = ex.getCause();
while (cause != null) {
cause.printStackTrace(printWriter);
cause = cause.getCause();
}
printWriter.flush();
printWriter.close();
String result = writer.toString();
sb.append(result);
String fileName = writeFile(sb.toString());
return fileName;
} catch (Exception e) {
Log.e(TAG, "an error occured while writing file...", e);
sb.append("an error occured while writing file...\r\n");
writeFile(sb.toString());
}
return null;
}
private String writeFile(String sb) throws Exception {
String time = formatter.format(new Date());
String fileName = "crash-" + time + ".log";
// if (FileUtil.hasSdcard()) {
String path = getGlobalpath();
File dir = new File(path);
if (!dir.exists())
dir.mkdirs();
String filePath = path + fileName;
File txtFile = new File(filePath);
if (!txtFile.exists())
txtFile.createNewFile();
FileOutputStream fos = new FileOutputStream(txtFile, true);
fos.write(sb.getBytes());
fos.flush();
fos.close();
// }
return fileName;
}
public static String getGlobalpath() {
return Environment.getExternalStorageDirectory().getAbsolutePath()
+ File.separator + "crash" + File.separator;
}
public static void setTag(String tag) {
TAG = tag;
}
/**
* 文件删除
* @param day 文件保存天数
*/
// public void autoClear(final int autoClearDay) {
// FileUtil.delete(getGlobalpath(), new FilenameFilter() {
//
// @Override
// public boolean accept(File file, String filename) {
// String s = FileUtil.getFileNameWithoutExtension(filename);
// int day = autoClearDay < 0 ? autoClearDay : -1 * autoClearDay;
// String date = "crash-" + DateUtil.getOtherDay(day);
// return date.compareTo(s) >= 0;
// }
// });
// }
}
@@ -0,0 +1,218 @@
package com.dahe.mylibrary.utils;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Environment;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Field;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @ClassName CrashHandler2
* @Author 用户
* @Date 2023/9/27 11:17
* @Description TODO
*/
public class CrashHandler2 implements Thread.UncaughtExceptionHandler {
// 用于打印日志的 TAG 标识符
public static final String TAG = "octopus.CrashHandler";
// 系统默认的UncaughtException处理类
private Thread.UncaughtExceptionHandler mDefaultHandler;
// 程序的Context对象
private Context mContext;
// 用来存储设备信息和异常信息
private Map<String, String> mInfos = new HashMap<String, String>();
// 用于格式化日期,作为日志文件名的一部分
private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
// 单例模式
private static CrashHandler2 INSTANCE = new CrashHandler2();
private CrashHandler2() {
}
public static CrashHandler2 getInstance() {
return INSTANCE;
}
/**
* 初始化该类, 向系统中注册
* @param context
*/
public void init(Context context) {
mContext = context;
// 获取系统默认的 UncaughtException 处理器
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
// 设置该 CrashHandler 为程序的默认处理器
Thread.setDefaultUncaughtExceptionHandler(this);
}
/*
* 出现未捕获的异常时, 会自动回调该方法
* (non-Javadoc)
* @see java.lang.Thread.UncaughtExceptionHandler#uncaughtException(java.lang.Thread, java.lang.Throwable)
*/
@Override
public void uncaughtException(Thread thread, Throwable ex) {
/*
* 调用 handleException() 方法处理该线程
* 如果返回 true 说明处理成功, 如果返回 false 则调用默认的异常处理器来处理
* 一般情况下该方法都会成功处理
*/
if (!handleException(ex) && mDefaultHandler != null) {
// 如果用户没有处理则让系统默认的异常处理器来处理
mDefaultHandler.uncaughtException(thread, ex);
} else {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
Log.e(TAG, "error : ", e);
}
// 退出程序
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(1);
}
}
/**
* 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
* @param ex
* 异常信息
* @return
* true:如果处理了该异常信息;否则返回false.
*/
private boolean handleException(Throwable ex) {
if (ex == null) {
return false;
}
/*
* 使用Toast来显示异常信息,
* 由于在主线程会阻塞,
* 不能实时出现 Toast 信息,
* 这里我们在子线程中处理 Toast 信息
*/
new Thread() {
@Override
public void run() {
Looper.prepare();
Toast.makeText(mContext, "很抱歉,程序出现异常,即将退出.", Toast.LENGTH_LONG)
.show();
Looper.loop();
}
}.start();
// 收集设备参数信息
collectDeviceInfo(mContext);
// 保存日志文件
saveCrashInfo2File(ex);
return true;
}
/**
* 收集设备参数信息, 将手机到的信息存储到
* @param ctx
* 上下文对象
*/
public void collectDeviceInfo(Context ctx) {
try {
//获取包管理器
PackageManager pm = ctx.getPackageManager();
//获取包信息
PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(),
PackageManager.GET_ACTIVITIES);
if (pi != null) {
//版本号
String versionName = pi.versionName == null ? "null"
: pi.versionName;
//版本代码
String versionCode = pi.versionCode + "";
//将版本信息存放到 成员变量 Map<String, String> mInfos 中
this.mInfos.put("versionName", versionName);
this.mInfos.put("versionCode", versionCode);
}
} catch (Exception e) {
Log.e(TAG, "an error occured when collect package info", e);
}
//获取 Build 中定义的变量, 使用反射方式获取, 该类中定义了设备相关的变量信息
Field[] fields = Build.class.getDeclaredFields();
//遍历获取额变量, 将这些信息存放到成员变量 Map<String, String> mInfos 中
for (Field field : fields) {
try {
//设置 Build 成员变量可访问
field.setAccessible(true);
//将 设备相关的信息存放到 mInfos 成员变量中
mInfos.put(field.getName(), field.get(null).toString());
Log.d(TAG, field.getName() + " : " + field.get(null));
} catch (Exception e) {
Log.e(TAG, "an error occured when collect crash info", e);
}
}
}
/**
* 保存错误信息到文件中
* @param ex
* @return 返回文件名称,便于将文件传送到服务器
*/
private String saveCrashInfo2File(Throwable ex) {
//存储相关的字符串信息
StringBuffer sb = new StringBuffer();
//将成员变量 Map<String, String> mInfos 中的数据 存储到 StringBuffer sb 中
for (Map.Entry<String, String> entry : this.mInfos.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
sb.append(key + "=" + value + "\n");
}
//将 StringBuffer sb 中的字符串写出到文件中
Writer writer = new StringWriter();
PrintWriter printWriter = new PrintWriter(writer);
ex.printStackTrace(printWriter);
Throwable cause = ex.getCause();
while (cause != null) {
cause.printStackTrace(printWriter);
cause = cause.getCause();
}
printWriter.close();
String result = writer.toString();
sb.append(result);
try {
long timestamp = System.currentTimeMillis();
String time = formatter.format(new Date());
String fileName = "crash-" + time + "-" + timestamp + ".txt";
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
//获取文件输出路径
String path = Environment.getExternalStorageDirectory()
+ "/crashinfo/";
//创建文件夹和文件
File dir = new File(path);
if (!dir.exists()) {
dir.mkdirs();
}
//创建输出流
FileOutputStream fos = new FileOutputStream(path + fileName);
//向文件中写出数据
fos.write(sb.toString().getBytes());
fos.close();
}
return fileName;
} catch (Exception e) {
Log.e(TAG, "an error occured while writing file...", e);
}
return null;
}
}
@@ -0,0 +1,89 @@
package com.dahe.mylibrary.utils;
import android.util.Log;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import static com.dahe.mylibrary.utils.CrashHandler.TAG;
public class FileUtil {
//移除文件,获取文件时间与当前时间对比,我这时间定位5天,删除五天前的文件
public static void removeFileByTime(String dirPath) {
//获取目录下所有文件
List<File> allFile = getDirAllFile(new File(dirPath));
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//获取当前时间
Date end = new Date(System.currentTimeMillis());
try {
end = dateFormat.parse(dateFormat.format(new Date(System.currentTimeMillis())));
} catch (Exception e){
Log.d(TAG, "dataformat exeption e " + e.toString());
}
Log.d(TAG, "getNeedRemoveFile dirPath = " +dirPath);
for (File file : allFile) {//ComDef
try {
//文件时间减去当前时间
Date start = dateFormat.parse(dateFormat.format(new Date(file.lastModified())));
long diff = end.getTime() - start.getTime();//这样得到的差值是微秒级别
long days = diff / (1000 * 60 * 60 * 24);
// if(ComDef.LOGMAXKEEPTIME <= days){
if(5 <= days){
deleteFile(file);
}
} catch (Exception e){
Log.d(TAG, "dataformat exeption e " + e.toString());
}
}
}
//删除文件夹及文件夹下所有文件
public static void deleteFile(File file) {
if (file.isDirectory()) {
File[] files = file.listFiles();
for (int i = 0; i < files.length; i++) {
File f = files[i];
deleteFile(f);
}
file.delete();
} else if (file.exists()) {
file.delete();
}
}
//获取指定目录下一级文件
public static List<File> getDirAllFile(File file) {
List<File> fileList = new ArrayList<>();
File[] fileArray = file.listFiles();
if(fileArray == null)
return fileList;
for (File f : fileArray) {
fileList.add(f);
}
fileSortByTime(fileList);
return fileList;
}
//对文件进行时间排序
public static void fileSortByTime(List<File> fileList) {
Collections.sort(fileList, new Comparator<File>() {
public int compare(File p1, File p2) {
if (p1.lastModified() < p2.lastModified()) {
return -1;
}
return 1;
}
});
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,204 @@
package com.dahe.mylibrary.utils;
import android.content.Context;
import android.widget.ImageView;
import androidx.core.content.ContextCompat;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.MultiTransformation;
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.bumptech.glide.request.RequestOptions;
import com.dahe.mylibrary.weight.GlideCircleWithBorder;
/**
* Created by Administrator on 2017/11/27 0027.
* 图片加载工具类
*/
public class ImageLoader {
public static ImageLoader mInstance = null;
public static ImageLoader getInstance() {
if (null == mInstance) {
synchronized (ImageLoader.class) {
if (null == mInstance) {
mInstance = new ImageLoader();
}
}
}
return mInstance;
}
/**
* 普通的加载图片 带占位图
*
* @param context
* @param url
* @param imageView
* @param multiTransformation 同时设置scaleType在设置圆角或者圆形
*/
public void loadingImage(Context context, final Object url, final ImageView imageView, MultiTransformation multiTransformation, int placeholder) {
RequestOptions requestOptions = new RequestOptions();
if (null != context) {
if (placeholder != -1)
requestOptions = requestOptions.placeholder(placeholder).error(placeholder);
if (null != multiTransformation)
requestOptions = requestOptions.transform(multiTransformation);
Glide.with(context).load(url).apply(requestOptions).into(imageView);
}
}
/**
* 普通的加载图片
*
* @param context
* @param url
* @param imageView
*/
public void loadingImage(Context context, final Object url, final ImageView imageView) {
loadingImage(context, url, imageView, null, -1);
}
/**
* 普通的加载图片 带展位图
*
* @param context
* @param url
* @param imageView
*/
public void loadImage(Context context, final Object url, final ImageView imageView, RequestOptions requestOptions, int placeholder) {
if (null != context) {
if (placeholder != -1)
requestOptions = requestOptions.placeholder(placeholder).error(placeholder);
Glide.with(context).load(url).centerCrop().apply(requestOptions).into(imageView);
}
}
/**
* 普通的加载图片 不带占位图的
*
* @param context
* @param url
* @param imageView
*/
@Deprecated
public void loadImage(Context context, final Object url, final ImageView imageView) {
loadImage(context, url, imageView, -1);
}
/**
* 普通的加载图片 不带占位图的
*
* @param context
* @param url
* @param imageView
*/
public void loadImage(Context context, final Object url, final ImageView imageView, int placeholder) {
RequestOptions requestOptions = new RequestOptions();
loadImage(context, url, imageView, requestOptions, placeholder);
}
/**
* 加载圆形图片
*
* @param context
* @param url
* @param imageView
*/
public void loadCircleImage(Context context, Object url, ImageView imageView, int placeholder) {
if (null != context) {
loadImage(context, url, imageView, RequestOptions.circleCropTransform(), placeholder);
}
}
/**
* 加载圆形图片
*
* @param context
* @param url
* @param imageView
*/
public void loadCircleImage(Context context, Object url, ImageView imageView) {
if (null != context) {
loadCircleImage(context, url, imageView, -1);
}
}
/**
* 加载圆角图片
*
* @param context
* @param url
* @param round
* @param imageView
*/
public void loadRoundImage(Context context, Object url, int round, ImageView imageView, int placeholder) {
if (null != context) {
RequestOptions requestOptions = RequestOptions.fitCenterTransform().transform(new CenterCrop(), new RoundedCorners(round));
// RequestOptions requestOptions = new RequestOptions();
// requestOptions.transform(new GlideRoundTransform(context, round));
loadImage(context, url, imageView, requestOptions, placeholder);
}
}
/**
* 加载圆角图片
*
* @param context
* @param url
* @param round
* @param imageView
*/
public void loadRoundImage(Context context, Object url, int round, ImageView imageView) {
if (null != context) {
loadRoundImage(context, url, round, imageView, -1);
}
}
/**
* 加载圆形带圆环图片
*
* @param context
* @param url
* @param imageView
*/
public void loadCircleWithBorderImage(Context context, Object url, int borderWidth, int borderColor, ImageView imageView, int placeholder) {
if (null != context) {
RequestOptions requestOptions = new RequestOptions();
requestOptions.transform(new GlideCircleWithBorder(context, borderWidth, ContextCompat.getColor(context, borderColor)));
loadImage(context, url, imageView, requestOptions, placeholder);
}
}
/**
* 加载圆形带圆环图片
*
* @param context
* @param url
* @param imageView
*/
public void loadCircleWithBorderImage(Context context, Object url,RequestOptions requestOptions, int borderWidth, int borderColor, ImageView imageView, int placeholder) {
if (null != context) {
requestOptions.transform(new GlideCircleWithBorder(context, borderWidth, ContextCompat.getColor(context, borderColor)));
loadImage(context, url, imageView, requestOptions, placeholder);
}
}
/**
* 加载圆形带圆环图片
*
* @param context
* @param url
* @param imageView
*/
public void loadCircleWithBorderImage(Context context, Object url, int borderWidth, int borderColor, ImageView imageView) {
if (null != context) {
loadCircleWithBorderImage(context, url, borderWidth, borderColor, imageView, -1);
}
}
}
@@ -0,0 +1,60 @@
package com.dahe.mylibrary.utils;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.security.MessageDigest;
public class MD5Utils {
private static final int BUFFERSIZE = 8196;
private static final String ALGORITHM = "MD5";
private static final String CHARSET = "UTF-8";
public MD5Utils() {
}
public static String md5(String input) {
return md5(input, CHARSET);
}
private static String md5(String input, String charsetName) {
try {
MessageDigest md5 = MessageDigest.getInstance(ALGORITHM);
byte md5Bytes[] = md5.digest(input.getBytes(charsetName));
return StringUtils.byte2hex(md5Bytes);
} catch (Exception e) {
e.printStackTrace();
}
return input;
}
public static String md5file(File filename) {
BufferedInputStream bufferedInputStream = null;
MessageDigest md;
try {
bufferedInputStream = new BufferedInputStream(new FileInputStream(filename), BUFFERSIZE);
md = MessageDigest.getInstance(ALGORITHM);
byte[] buffer = new byte[BUFFERSIZE];
int i = 0;
while ((i = bufferedInputStream.read(buffer)) != -1) {
md.update(buffer, 0, i);
}
return StringUtils.byte2hex(md.digest());
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
try {
bufferedInputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static String md5reverse(String md5) {
return "";
}
}
@@ -0,0 +1,28 @@
package com.dahe.mylibrary.utils;
import androidx.annotation.IntDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* <pre>
* author: Blankj
* blog : http://blankj.com
* time : 2017/03/13
* desc : constants of memory
* </pre>
*/
public final class MemoryConstants {
public static final int BYTE = 1;
public static final int KB = 1024;
public static final int MB = 1048576;
public static final int GB = 1073741824;
@IntDef({BYTE, KB, MB, GB})
@Retention(RetentionPolicy.SOURCE)
public @interface Unit {
}
}
@@ -0,0 +1,160 @@
package com.dahe.mylibrary.utils;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.util.Log;
/**
* @ClassName MobileInfoUtils
* @Author 用户
* @Date 2022/10/8 10:18
* @Description TODO
*/
public class MobileInfoUtils {
// private SettingDialogPermision dialog_per;
//获取手机类型
private static String getMobileType() {
return Build.MANUFACTURER;
}
//跳转至授权页面
public void jumpStartInterface(Context context) {
Intent intent = new Intent();
try {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Log.e("HLQ_Struggle", "******************当前手机型号为:" + getMobileType());
ComponentName componentName = null;
if (getMobileType().equals("Xiaomi")) { // 红米Note4测试通过
componentName = new ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity");
} else if (getMobileType().equals("Letv")) { // 乐视2测试通过
intent.setAction("com.letv.android.permissionautoboot");
} else if (getMobileType().equals("samsung")) { // 三星Note5测试通过
//componentName = new ComponentName("com.samsung.android.sm_cn", "com.samsung.android.sm.ui.ram.AutoRunActivity");
//componentName = ComponentName.unflattenFromString("com.samsung.android.sm/.ui.ram.RamActivity");// Permission Denial not exported from uid 1000,不允许被其他程序调用
componentName = ComponentName.unflattenFromString("com.samsung.android.sm/.app.dashboard.SmartManagerDashBoardActivity");
} else if (getMobileType().equals("HUAWEI")) { // 华为测试通过
componentName = new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity");//锁屏清理
// componentName = new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.startupmgr.ui.StartupNormalAppListActivity");
// componentName = ComponentName.unflattenFromString("com.huawei.systemmanager/.startupmgr.ui.StartupNormalAppListActivity");//跳自启动管理
//SettingOverlayView.show(context);
} else if (getMobileType().equals("vivo")) { // VIVO测试通过
componentName = ComponentName.unflattenFromString("com.iqoo.secure/.safeguard.PurviewTabActivity");
} else if (getMobileType().equals("Meizu")) { //万恶的魅族
//componentName = ComponentName.unflattenFromString("com.meizu.safe/.permission.PermissionMainActivity");//跳转到手机管家
componentName = ComponentName.unflattenFromString("com.meizu.safe/.permission.SmartBGActivity");//跳转到后台管理页面
} else if (getMobileType().equals("OPPO")) { // OPPO R8205测试通过
componentName = ComponentName.unflattenFromString("com.oppo.safe/.permission.startup.StartupAppListActivity");
} else if (getMobileType().equals("ulong")) { // 360手机 未测试
componentName = new ComponentName("com.yulong.android.coolsafe", ".ui.activity.autorun.AutoRunListActivity");
} else {
// 将用户引导到系统设置页面
if (Build.VERSION.SDK_INT >= 9) {
Log.e("HLQ_Struggle", "APPLICATION_DETAILS_SETTINGS");
intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
intent.setData(Uri.fromParts("package", context.getPackageName(), null));
} else if (Build.VERSION.SDK_INT <= 8) {
intent.setAction(Intent.ACTION_VIEW);
intent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails");
intent.putExtra("com.android.settings.ApplicationPkgName", context.getPackageName());
}
}
intent.setComponent(componentName);
context.startActivity(intent);
// if (getMobileType().equals("Xiaomi")) {
//
// showtip();//显示弹窗(**特别注意**
//
// }
//
// if (getMobileType().equals("samsung")){
//
// new SettingOverlayView().show(context);//
//
// }
} catch (Exception e) {//抛出异常就直接打开设置页面
Log.e("HLQ_Struggle", e.getLocalizedMessage());
intent = new Intent(Settings.ACTION_SETTINGS);
context.startActivity(intent);
}
}
//小米手机显示弹窗
// private void showtip() {
//
// try {
//
// dialog_per=new SettingDialogPermision(context, R.style.CustomDialog4);
//
// dialog_per.getWindow().setType(WindowManager.LayoutParams.TYPE_TOAST);//注意这里改成吐司类型
//
// dialog_per.show();
//
// Log.e("HLQ_Struggle","显示弹窗");
//
// } catch (Exception e) {
//
// e.printStackTrace();
//
// Log.e("HLQ_Struggle", "没有显示弹窗"+e.getMessage());
//
// }
//
// }
}
@@ -0,0 +1,28 @@
package com.dahe.mylibrary.utils;
import java.util.regex.Pattern;
public class PatternUtils {
/**
* 正则表达式:验证密码(包含大小写,数字,特殊字符,6-12位)
*/
// public static final String REGEX_PASSWORD = "^(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*,\\.])[0-9a-zA-Z!@#$%^&*,\\\\.]{6,12}$";
public static final String REGEX_PASSWORD = "^(?=.*[0-9])(?=.*[a-z])(?=.*[!@#$%^&*,\\.])[0-9a-zA-Z!@#$%^&*,\\\\.]{6,12}$";
public static final String REGEX_WORD = "^[A-Za-z]+$";
/**
* 校验密码
*
* @param password
* @return 校验通过返回true,否则返回false
*/
public static boolean isPassword(String password) {
return Pattern.matches(REGEX_PASSWORD, password);
}
public static boolean isLetter(String password){
return Pattern.matches(REGEX_WORD, password);
}
}
@@ -0,0 +1,55 @@
package com.dahe.mylibrary.utils;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
public class PhoneFormatCheckUtils {
/**
* 大陆号码或香港号码均可
*/
public static boolean isPhoneLegal(String str) throws PatternSyntaxException {
return isChinaPhoneLegal(str) || isHKPhoneLegal(str);
}
/**
* 大陆手机号码11位数,匹配格式:前三位固定格式+后8位任意数
* 此方法中前三位格式有:
* 13+任意数
* 145,147,149
* 15+除4的任意数(不要写^4,这样的话字母也会被认为是正确的)
* 166
* 17+3,5,6,7,8
* 18+任意数
* 198,199
*/
public static boolean isChinaPhoneLegal(String str) throws PatternSyntaxException {
// ^ 匹配输入字符串开始的位置
// \d 匹配一个或多个数字,其中 \ 要转义,所以是 \\d
// $ 匹配输入字符串结尾的位置
String regExp = "^((13[0-9])|(14[5,7,9])|(15[0-3,5-9])|(166)|(17[3,5,6,7,8])" +
"|(18[0-9])|(19[8,9]))\\d{8}$";
Pattern p = Pattern.compile(regExp);
Matcher m = p.matcher(str);
return m.matches();
}
/**
* 香港手机号码8位数,5|6|8|9开头+7位任意数
*/
public static boolean isHKPhoneLegal(String str) throws PatternSyntaxException {
// ^ 匹配输入字符串开始的位置
// \d 匹配一个或多个数字,其中 \ 要转义,所以是 \\d
// $ 匹配输入字符串结尾的位置
String regExp = "^(5|6|8|9)\\d{7}$";
Pattern p = Pattern.compile(regExp);
Matcher m = p.matcher(str);
return m.matches();
}
public static String hintPhone(String phone){
return phone.substring(0, 3) + "****" + phone.substring(7, 11);
}
}
@@ -0,0 +1,164 @@
package com.dahe.mylibrary.utils
import androidx.appcompat.app.AppCompatActivity
import com.dahe.mylibrary.base.SingletonNoPHolder
import com.dahe.mylibrary.callback.OnMyDatePickedListener
import com.github.gzuliyujiang.wheelpicker.AddressPicker
import com.github.gzuliyujiang.wheelpicker.BirthdayPicker
import com.github.gzuliyujiang.wheelpicker.DatePicker
import com.github.gzuliyujiang.wheelpicker.OptionPicker
import com.github.gzuliyujiang.wheelpicker.annotation.AddressMode
import com.github.gzuliyujiang.wheelpicker.annotation.DateMode
import com.github.gzuliyujiang.wheelpicker.contract.OnAddressPickedListener
import com.github.gzuliyujiang.wheelpicker.contract.OnOptionPickedListener
import com.github.gzuliyujiang.wheelpicker.entity.DateEntity
import com.github.gzuliyujiang.wheelview.contract.TextProvider
/**
* @ClassName PickUtils
* @Author john
* @Date 2024/2/5 14:48
* @Description 选择器工具类
*/
class PickerUtils private constructor() {
companion object : SingletonNoPHolder<PickerUtils>(::PickerUtils)
/**
* TODO
* 底部弹出生日日期选择
* @param activity
* @param title 日期选择title
* @param dateEntity 默认参数:默认当天
* @param listener
*/
fun showDate(
activity: AppCompatActivity,
title: String = "",
dateEntity: DateEntity = DateEntity.today(),
listener: OnMyDatePickedListener
) {
val picker = BirthdayPicker(activity)
picker.setTitle(title)
picker.setDefaultValue(dateEntity.year, dateEntity.month, dateEntity.day)
picker.setOnDatePickedListener { year, month, day ->
if (listener != null)
listener.onDatePicked("$year-${if (month <= 9) "0${month}" else month}-${if (day <= 9) "0${day}" else day}")
}
picker.wheelLayout.setResetWhenLinkage(false)
picker.show()
}
/**
* TODO
* 底部弹出日期选择
* @param activity
* @param title 日期选择title
* @param listener
*/
fun showDateSim(
activity: AppCompatActivity,
title: String = "日期选择",
listener: OnMyDatePickedListener
) {
val picker = DatePicker(activity)
picker.setTitle(title)
val wheelLayout = picker.wheelLayout
wheelLayout.setDateMode(DateMode.YEAR_MONTH_DAY)
wheelLayout.setDateLabel("", "", "")
picker.setOnDatePickedListener { year, month, day ->
listener.onDatePicked("$year-${if (month <= 9) "0${month}" else month}-${if (day <= 9) "0${day}" else day}")
}
picker.show()
}
/**
* 地址选择
* @param activity AppCompatActivity
* @param lis OnAddressPickedListener
*/
fun showAddress(activity: AppCompatActivity,lis: OnAddressPickedListener) {
val picker = AddressPicker(activity)
picker.setAddressMode(AddressMode.PROVINCE_CITY_COUNTY)
picker.setDefaultValue("河南省", "郑州市", "金水区")
picker.setOnAddressPickedListener(lis)
picker.wheelLayout.setOnLinkageSelectedListener { first, second, third ->
picker.titleView.text = String.format(
"%s%s%s",
picker.firstWheelView.formatItem(first),
picker.secondWheelView.formatItem(second),
picker.thirdWheelView.formatItem(third)
)
}
picker.show()
}
/**
* 选择驾驶证类型
* @param activity
* @param title
* @param listener
*/
fun showSelectCarType(
activity: AppCompatActivity,
title: String = "",
listener: OnOptionPickedListener
) {
OptionPicker(activity)
.run {
setData("A1", "A2", "A3", "B1", "B2", "B3", "C1", "C2")
setDefaultValue("B1")
setTitle(title)
setOnOptionPickedListener(listener)
show()
}
}
/**
*
* @param activity AppCompatActivity
* @param title String
* @param datas MutableList<String>
* @param default String
* @param listener OnOptionPickedListener
*/
fun showSingleSelect(activity: AppCompatActivity,title: String,datas: MutableList<String>,default: String = "",listener: OnOptionPickedListener){
OptionPicker(activity)
.run {
setData(datas)
setDefaultValue(default)
setTitle(title)
setOnOptionPickedListener(listener)
show()
}
}
/**
* 底部弹框-单选
* @param activity AppCompatActivity
* @param title String
* @param listener OnOptionPickedListener
*/
fun <T: TextProvider> showSelectCarColor(
activity: AppCompatActivity,
title: String = "",
default: String = "",
datas: MutableList<T>,
listener: OnOptionPickedListener
) {
OptionPicker(activity)
.run {
setData(datas)
setDefaultValue(default)
setTitle(title)
setOnOptionPickedListener(listener)
show()
}
}
}
@@ -0,0 +1,73 @@
package com.dahe.mylibrary.utils
import android.content.Context
import com.dahe.mylibrary.base.BaseSingleton
import com.dahe.mylibrary.weight.GlideEngine
import com.dahe.mylibrary.weight.ImageFileCompressEngine
import com.luck.picture.lib.basic.PictureSelectionModel
import com.luck.picture.lib.basic.PictureSelector
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.entity.LocalMedia
/**
* @ClassName SelectPicUtils
* @Author john
* @Date 2024/1/31 10:20
* @Description TODO
*/
class SelectPicUtils private constructor(
private val maxNum: Int,
private val minNum: Int,
private val isDisplayCamera: Boolean
) {
private constructor(builder: Builder) : this(
builder.maxNum,
builder.minNum,
builder.isDisplayCamera
)
class Builder {
var maxNum: Int = 6
private set
var minNum: Int = 1
private set
var isDisplayCamera: Boolean = true
private set
var listener: onPicResultListener? = null
private set
fun setMaxNum(maxNum: Int) = apply {
this.maxNum = maxNum
}
fun setMinNum(setMinNum: Int) = apply {
this.minNum = setMinNum
}
fun setiIsDisplayCamera(isDisplayCamera: Boolean) = apply {
this.isDisplayCamera = isDisplayCamera
}
fun setOnPicResultListener(listener : onPicResultListener)= apply {
this.listener = listener
}
fun build() = SelectPicUtils(this)
}
fun openCam(){}
fun interface onPicResultListener {
fun onResult(result: java.util.ArrayList<LocalMedia>)
}
override fun toString(): String {
return "Computer(maxNum='$maxNum', minNum='$minNum', isDisplayCamera=$isDisplayCamera)"
}
}
@@ -0,0 +1,201 @@
package com.dahe.mylibrary.utils;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
/**
* <pre>
* author: Blankj
* blog : http://blankj.com
* time : 2016/08/07
* desc : utils about shell
* </pre>
*/
public final class ShellUtils {
private static final String LINE_SEP = System.getProperty("line.separator");
private ShellUtils() {
throw new UnsupportedOperationException("u can't instantiate me...");
}
/**
* Execute the command.
*
* @param command The command.
* @param isRooted True to use root, false otherwise.
* @return the single {@link CommandResult} instance
*/
public static CommandResult execCmd(final String command, final boolean isRooted) {
return execCmd(new String[]{command}, isRooted, true);
}
/**
* Execute the command.
*
* @param commands The commands.
* @param isRooted True to use root, false otherwise.
* @return the single {@link CommandResult} instance
*/
public static CommandResult execCmd(final List<String> commands, final boolean isRooted) {
return execCmd(commands == null ? null : commands.toArray(new String[]{}), isRooted, true);
}
/**
* Execute the command.
*
* @param commands The commands.
* @param isRooted True to use root, false otherwise.
* @return the single {@link CommandResult} instance
*/
public static CommandResult execCmd(final String[] commands, final boolean isRooted) {
return execCmd(commands, isRooted, true);
}
/**
* Execute the command.
*
* @param command The command.
* @param isRooted True to use root, false otherwise.
* @param isNeedResultMsg True to node_return the message of result, false otherwise.
* @return the single {@link CommandResult} instance
*/
public static CommandResult execCmd(final String command,
final boolean isRooted,
final boolean isNeedResultMsg) {
return execCmd(new String[]{command}, isRooted, isNeedResultMsg);
}
/**
* Execute the command.
*
* @param commands The commands.
* @param isRooted True to use root, false otherwise.
* @param isNeedResultMsg True to node_return the message of result, false otherwise.
* @return the single {@link CommandResult} instance
*/
public static CommandResult execCmd(final List<String> commands,
final boolean isRooted,
final boolean isNeedResultMsg) {
return execCmd(commands == null ? null : commands.toArray(new String[]{}),
isRooted,
isNeedResultMsg);
}
/**
* Execute the command.
*
* @param commands The commands.
* @param isRooted True to use root, false otherwise.
* @param isNeedResultMsg True to node_return the message of result, false otherwise.
* @return the single {@link CommandResult} instance
*/
public static CommandResult execCmd(final String[] commands,
final boolean isRooted,
final boolean isNeedResultMsg) {
int result = -1;
if (commands == null || commands.length == 0) {
return new CommandResult(result, "", "");
}
Process process = null;
BufferedReader successResult = null;
BufferedReader errorResult = null;
StringBuilder successMsg = null;
StringBuilder errorMsg = null;
DataOutputStream os = null;
try {
process = Runtime.getRuntime().exec(isRooted ? "su" : "sh");
os = new DataOutputStream(process.getOutputStream());
for (String command : commands) {
if (command == null) continue;
os.write(command.getBytes());
os.writeBytes(LINE_SEP);
os.flush();
}
os.writeBytes("exit" + LINE_SEP);
os.flush();
result = process.waitFor();
if (isNeedResultMsg) {
successMsg = new StringBuilder();
errorMsg = new StringBuilder();
successResult = new BufferedReader(
new InputStreamReader(process.getInputStream(), "UTF-8")
);
errorResult = new BufferedReader(
new InputStreamReader(process.getErrorStream(), "UTF-8")
);
String line;
if ((line = successResult.readLine()) != null) {
successMsg.append(line);
while ((line = successResult.readLine()) != null) {
successMsg.append(LINE_SEP).append(line);
}
}
if ((line = errorResult.readLine()) != null) {
errorMsg.append(line);
while ((line = errorResult.readLine()) != null) {
errorMsg.append(LINE_SEP).append(line);
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (os != null) {
os.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (successResult != null) {
successResult.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (errorResult != null) {
errorResult.close();
}
} catch (IOException e) {
e.printStackTrace();
}
if (process != null) {
process.destroy();
}
}
return new CommandResult(
result,
successMsg == null ? "" : successMsg.toString(),
errorMsg == null ? "" : errorMsg.toString()
);
}
/**
* The result of command.
*/
public static class CommandResult {
public int result;
public String successMsg;
public String errorMsg;
public CommandResult(final int result, final String successMsg, final String errorMsg) {
this.result = result;
this.successMsg = successMsg;
this.errorMsg = errorMsg;
}
@Override
public String toString() {
return "result: " + result + "\n" +
"successMsg: " + successMsg + "\n" +
"errorMsg: " + errorMsg;
}
}
}
@@ -0,0 +1,148 @@
package com.dahe.mylibrary.utils;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;
import java.util.Timer;
import java.util.TimerTask;
/**
* 文件名:SmsTimeUtils
*/
public class SmsTimeUtils {
/*倒计时时长 单位:秒*/
private final static int COUNT = 60;
/*当前做*/
private static int CURR_COUNT = 10;
/*发送验证码*/
public final static int SETTING_FINANCE_ACCOUNT_TIME = 1;
public final static int WITHDRAW_CASH = 4;
private static long SETTING_FINANCE_ACCOUNT_TIME_END = 0;
private static long WITHDRAW_CASH_END = 0;
private static Timer countdownTimer;
private static TextView tvSendCode;
private static Context mContext;
public static String currPhone;//记录获取验证码的手机号,倒计时结束后清空
/**
* 检查是否超过60秒
* 给当前要从多少开始倒数赋值
*
* @param first true 表示第一次 false不是
* @return 是否需要调用startCountdown(TextView textView),主要用于判断在重新打开页,需不需要继续倒计时
*/
public static boolean check(int type, boolean first) {
long data = System.currentTimeMillis();
long time = 0;
switch (type) {
case SETTING_FINANCE_ACCOUNT_TIME:
time = SETTING_FINANCE_ACCOUNT_TIME_END;
break;
case WITHDRAW_CASH:
time = WITHDRAW_CASH_END;
break;
}
if (data > time) {
/*主要是区别于是否是第一次进入。第一次进入不需要赋值*/
if (!first) {
CURR_COUNT = COUNT;
time = data + COUNT * 1000;
switch (type) {
case SETTING_FINANCE_ACCOUNT_TIME:
SETTING_FINANCE_ACCOUNT_TIME_END = time;
break;
case WITHDRAW_CASH:
WITHDRAW_CASH_END = time;
break;
}
}
return false;
} else {
int the_difference = ((int) (time - data)) / 1000;
CURR_COUNT = the_difference;
return true;
}
}
/**
* 开始倒计时
*
* @param textView 控制倒计时的view
*/
public static void startCountdown(TextView textView, Context context) {
tvSendCode = textView;
mContext = context;
if (countdownTimer == null) {
countdownTimer = new Timer();
countdownTimer.schedule(new TimerTask() {
@Override
public void run() {
Message msg = new Message();
msg.what = CURR_COUNT--;
handler.sendMessage(msg);
}
}, 0, 1000);
}
}
/**
* 开始倒计时
*
* @param textView 控制倒计时的view
*/
public static void startCountdown(TextView textView, Context context,String phone) {
currPhone = phone;
tvSendCode = textView;
mContext = context;
if (countdownTimer == null) {
countdownTimer = new Timer();
countdownTimer.schedule(new TimerTask() {
@Override
public void run() {
Message msg = new Message();
msg.what = CURR_COUNT--;
handler.sendMessage(msg);
}
}, 0, 1000);
}
}
private static Handler handler = new Handler() {
public void handleMessage(Message msg) {
if (msg.what <= 0) {
if (countdownTimer != null) {
countdownTimer.cancel();
countdownTimer = null;
}
currPhone="";
tvSendCode.setText("获取验证码");
tvSendCode.setEnabled(true);
} else {
tvSendCode.setText(msg.what + "s后重新获取");
tvSendCode.setEnabled(false);
}
super.handleMessage(msg);
}
};
public static void stopCountdown(TextView textView, Context context){
tvSendCode = textView;
mContext = context;
if (countdownTimer != null) {
countdownTimer.cancel();
countdownTimer=null;
currPhone="";
SETTING_FINANCE_ACCOUNT_TIME_END =0;
tvSendCode.setText("获取验证码");
tvSendCode.setEnabled(true);
}
}
}
@@ -0,0 +1,111 @@
package com.dahe.mylibrary.utils;
import android.app.Activity;
import android.os.Build;
import android.view.View;
import android.view.Window;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.appbar.CollapsingToolbarLayout;
/**
* Utils for status bar
* Created by qiu on 3/29/16.
*/
public class StatusBar {
//Get alpha color
static int calculateStatusBarColor(int color, int alpha) {
float a = 1 - alpha / 255f;
int red = color >> 16 & 0xff;
int green = color >> 8 & 0xff;
int blue = color & 0xff;
red = (int) (red * a + 0.5);
green = (int) (green * a + 0.5);
blue = (int) (blue * a + 0.5);
return 0xff << 24 | red << 16 | green << 8 | blue;
}
/**
* set statusBarColor
* @param statusColor color
* @param alpha 0 - 255
*/
public static void setStatusBarColor(@NonNull Activity activity, @ColorInt int statusColor, int alpha) {
setStatusBarColor(activity, calculateStatusBarColor(statusColor, alpha));
}
public static void setStatusBarColor(@NonNull Activity activity, @ColorInt int statusColor) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
StatusBarCompatLollipop.setStatusBarColor(activity, statusColor);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
StatusBarCompatKitKat.setStatusBarColor(activity, statusColor);
}
}
public static void translucentStatusBar(@NonNull Activity activity) {
translucentStatusBar(activity, false);
}
/**
* change to full screen mode
* @param hideStatusBarBackground hide status bar alpha Background when SDK > 21, true if hide it
*/
public static void translucentStatusBar(@NonNull Activity activity, boolean hideStatusBarBackground) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
StatusBarCompatLollipop.translucentStatusBar(activity, hideStatusBarBackground);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
StatusBarCompatKitKat.translucentStatusBar(activity);
}
}
public static void setStatusBarColorForCollapsingToolbar(@NonNull Activity activity, AppBarLayout appBarLayout, CollapsingToolbarLayout collapsingToolbarLayout,
Toolbar toolbar, @ColorInt int statusColor) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
StatusBarCompatLollipop.setStatusBarColorForCollapsingToolbar(activity, appBarLayout, collapsingToolbarLayout, toolbar, statusColor);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
StatusBarCompatKitKat.setStatusBarColorForCollapsingToolbar(activity, appBarLayout, collapsingToolbarLayout, toolbar, statusColor);
}
}
public static void changeToLightStatusBar(@NonNull Activity activity) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return;
}
if (activity == null) {
return;
}
Window window = activity.getWindow();
if (window == null) {
return;
}
View decorView = window.getDecorView();
if (decorView == null) {
return;
}
decorView.setSystemUiVisibility(decorView.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
public static void cancelLightStatusBar(@NonNull Activity activity) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return;
}
if (activity == null) {
return;
}
Window window = activity.getWindow();
if (window == null) {
return;
}
View decorView = window.getDecorView();
if (decorView == null) {
return;
}
decorView.setSystemUiVisibility(decorView.getSystemUiVisibility() ^ View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
}
@@ -0,0 +1,221 @@
package com.dahe.mylibrary.utils;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.os.Build;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import androidx.appcompat.widget.Toolbar;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.view.ViewCompat;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.appbar.CollapsingToolbarLayout;
/**
* After kitkat add fake status bar
* Created by qiu on 8/27/16.
*/
@TargetApi(Build.VERSION_CODES.KITKAT)
class StatusBarCompatKitKat {
private static final String TAG_FAKE_STATUS_BAR_VIEW = "statusBarView";
private static final String TAG_MARGIN_ADDED = "marginAdded";
/**
* node_return statusBar's Height in pixels
*/
private static int getStatusBarHeight(Context context) {
int result = 0;
int resId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resId > 0) {
result = context.getResources().getDimensionPixelOffset(resId);
}
return result;
}
/**
* 1. Add fake statusBarView.
* 2. set tag to statusBarView.
*/
private static View addFakeStatusBarView(Activity activity, int statusBarColor, int statusBarHeight) {
Window window = activity.getWindow();
ViewGroup mDecorView = (ViewGroup) window.getDecorView();
View mStatusBarView = new View(activity);
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight);
layoutParams.gravity = Gravity.TOP;
mStatusBarView.setLayoutParams(layoutParams);
mStatusBarView.setBackgroundColor(statusBarColor);
mStatusBarView.setTag(TAG_FAKE_STATUS_BAR_VIEW);
mDecorView.addView(mStatusBarView);
return mStatusBarView;
}
/**
* use reserved order to remove is more quickly.
*/
private static void removeFakeStatusBarViewIfExist(Activity activity) {
Window window = activity.getWindow();
ViewGroup mDecorView = (ViewGroup) window.getDecorView();
View fakeView = mDecorView.findViewWithTag(TAG_FAKE_STATUS_BAR_VIEW);
if (fakeView != null) {
mDecorView.removeView(fakeView);
}
}
/**
* add marginTop to simulate set FitsSystemWindow true
*/
private static void addMarginTopToContentChild(View mContentChild, int statusBarHeight) {
if (mContentChild == null) {
return;
}
if (!TAG_MARGIN_ADDED.equals(mContentChild.getTag())) {
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mContentChild.getLayoutParams();
lp.topMargin += statusBarHeight;
mContentChild.setLayoutParams(lp);
mContentChild.setTag(TAG_MARGIN_ADDED);
}
}
/**
* remove marginTop to simulate set FitsSystemWindow false
*/
private static void removeMarginTopOfContentChild(View mContentChild, int statusBarHeight) {
if (mContentChild == null) {
return;
}
if (TAG_MARGIN_ADDED.equals(mContentChild.getTag())) {
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mContentChild.getLayoutParams();
lp.topMargin -= statusBarHeight;
mContentChild.setLayoutParams(lp);
mContentChild.setTag(null);
}
}
/**
* set StatusBarColor
*
* 1. set Window Flag : WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
* 2. removeFakeStatusBarViewIfExist
* 3. addFakeStatusBarView
* 4. addMarginTopToContentChild
* 5. cancel ContentChild's fitsSystemWindow
*/
static void setStatusBarColor(Activity activity, int statusColor) {
Window window = activity.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
ViewGroup mContentView = (ViewGroup) window.findViewById(Window.ID_ANDROID_CONTENT);
View mContentChild = mContentView.getChildAt(0);
int statusBarHeight = getStatusBarHeight(activity);
removeFakeStatusBarViewIfExist(activity);
addFakeStatusBarView(activity, statusColor, statusBarHeight);
addMarginTopToContentChild(mContentChild, statusBarHeight);
if (mContentChild != null) {
ViewCompat.setFitsSystemWindows(mContentChild, false);
}
}
/**
* translucentStatusBar
*
* 1. set Window Flag : WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
* 2. removeFakeStatusBarViewIfExist
* 3. removeMarginTopOfContentChild
* 4. cancel ContentChild's fitsSystemWindow
*/
static void translucentStatusBar(Activity activity) {
Window window = activity.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
ViewGroup mContentView = (ViewGroup) activity.findViewById(Window.ID_ANDROID_CONTENT);
View mContentChild = mContentView.getChildAt(0);
removeFakeStatusBarViewIfExist(activity);
removeMarginTopOfContentChild(mContentChild, getStatusBarHeight(activity));
if (mContentChild != null) {
ViewCompat.setFitsSystemWindows(mContentChild, false);
}
}
/**
* compat for CollapsingToolbarLayout
*
* 1. set Window Flag : WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
* 2. set FitsSystemWindows for views.
* 3. add Toolbar's height, let it layout from top, then add paddingTop to layout normal.
* 4. removeFakeStatusBarViewIfExist
* 5. removeMarginTopOfContentChild
* 6. add OnOffsetChangedListener to change statusBarView's alpha
*/
static void setStatusBarColorForCollapsingToolbar(Activity activity, final AppBarLayout appBarLayout, final CollapsingToolbarLayout collapsingToolbarLayout,
Toolbar toolbar, int statusColor) {
Window window = activity.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
ViewGroup mContentView = (ViewGroup) window.findViewById(Window.ID_ANDROID_CONTENT);
View mContentChild = mContentView.getChildAt(0);
mContentChild.setFitsSystemWindows(false);
((View) appBarLayout.getParent()).setFitsSystemWindows(false);
appBarLayout.setFitsSystemWindows(false);
collapsingToolbarLayout.setFitsSystemWindows(false);
collapsingToolbarLayout.getChildAt(0).setFitsSystemWindows(false);
toolbar.setFitsSystemWindows(false);
if (toolbar.getTag() == null) {
CollapsingToolbarLayout.LayoutParams lp = (CollapsingToolbarLayout.LayoutParams) toolbar.getLayoutParams();
int statusBarHeight = getStatusBarHeight(activity);
lp.height += statusBarHeight;
toolbar.setLayoutParams(lp);
toolbar.setPadding(toolbar.getPaddingLeft(), toolbar.getPaddingTop() + statusBarHeight, toolbar.getPaddingRight(), toolbar.getPaddingBottom());
toolbar.setTag(true);
}
int statusBarHeight = getStatusBarHeight(activity);
removeFakeStatusBarViewIfExist(activity);
removeMarginTopOfContentChild(mContentChild, statusBarHeight);
final View statusView = addFakeStatusBarView(activity, statusColor, statusBarHeight);
CoordinatorLayout.Behavior behavior = ((CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams()).getBehavior();
if (behavior != null && behavior instanceof AppBarLayout.Behavior) {
int verticalOffset = ((AppBarLayout.Behavior) behavior).getTopAndBottomOffset();
if (Math.abs(verticalOffset) > appBarLayout.getHeight() - collapsingToolbarLayout.getScrimVisibleHeightTrigger()) {
statusView.setAlpha(1f);
} else {
statusView.setAlpha(0f);
}
} else {
statusView.setAlpha(0f);
}
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
if (Math.abs(verticalOffset) > appBarLayout.getHeight() - collapsingToolbarLayout.getScrimVisibleHeightTrigger()) {
if (statusView.getAlpha() == 0) {
statusView.animate().cancel();
statusView.animate().alpha(1f).setDuration(collapsingToolbarLayout.getScrimAnimationDuration()).start();
}
} else {
if (statusView.getAlpha() == 1) {
statusView.animate().cancel();
statusView.animate().alpha(0f).setDuration(collapsingToolbarLayout.getScrimAnimationDuration()).start();
}
}
}
});
}
}
@@ -0,0 +1,193 @@
package com.dahe.mylibrary.utils;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.os.Build;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import androidx.appcompat.widget.Toolbar;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.view.OnApplyWindowInsetsListener;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.appbar.CollapsingToolbarLayout;
/**
* After Lollipop use system method.
* Created by qiu on 8/27/16.
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
class StatusBarCompatLollipop {
/**
* node_return statusBar's Height in pixels
*/
private static int getStatusBarHeight(Context context) {
int result = 0;
int resId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resId > 0) {
result = context.getResources().getDimensionPixelOffset(resId);
}
return result;
}
/**
* set StatusBarColor
*
* 1. set Flags to call setStatusBarColor
* 2. call setSystemUiVisibility to clear translucentStatusBar's Flag.
* 3. set FitsSystemWindows to false
*/
static void setStatusBarColor(Activity activity, int statusColor) {
Window window = activity.getWindow();
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(statusColor);
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
ViewGroup mContentView = (ViewGroup) window.findViewById(Window.ID_ANDROID_CONTENT);
View mChildView = mContentView.getChildAt(0);
if (mChildView != null) {
ViewCompat.setFitsSystemWindows(mChildView, false);
ViewCompat.requestApplyInsets(mChildView);
}
}
/**
* translucentStatusBar(full-screen)
*
* 1. set Flags to full-screen
* 2. set FitsSystemWindows to false
*
* @param hideStatusBarBackground hide statusBar's shadow
*/
static void translucentStatusBar(Activity activity, boolean hideStatusBarBackground) {
Window window = activity.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
if (hideStatusBarBackground) {
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.setStatusBarColor(Color.TRANSPARENT);
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
} else {
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
}
ViewGroup mContentView = (ViewGroup) window.findViewById(Window.ID_ANDROID_CONTENT);
View mChildView = mContentView.getChildAt(0);
if (mChildView != null) {
ViewCompat.setFitsSystemWindows(mChildView, false);
ViewCompat.requestApplyInsets(mChildView);
}
}
/**
* compat for CollapsingToolbarLayout
*
* 1. change to full-screen mode(like translucentStatusBar).
* 2. cancel CollapsingToolbarLayout's WindowInsets, let it layout as normal(now setStatusBarScrimColor is useless).
* 3. set View's FitsSystemWindow to false.
* 4. add Toolbar's height, let it layout from top, then add paddingTop to layout normal.
* 5. change statusBarColor by AppBarLayout's offset.
* 6. add Listener to change statusBarColor
*/
static void setStatusBarColorForCollapsingToolbar(Activity activity, final AppBarLayout appBarLayout, final CollapsingToolbarLayout collapsingToolbarLayout,
Toolbar toolbar, final int statusColor) {
final Window window = activity.getWindow();
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
ViewCompat.setOnApplyWindowInsetsListener(collapsingToolbarLayout, new OnApplyWindowInsetsListener() {
@Override
public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
return insets;
}
});
ViewGroup mContentView = (ViewGroup) window.findViewById(Window.ID_ANDROID_CONTENT);
View mChildView = mContentView.getChildAt(0);
if (mChildView != null) {
ViewCompat.setFitsSystemWindows(mChildView, false);
ViewCompat.requestApplyInsets(mChildView);
}
((View) appBarLayout.getParent()).setFitsSystemWindows(false);
appBarLayout.setFitsSystemWindows(false);
toolbar.setFitsSystemWindows(false);
if (toolbar.getTag() == null) {
CollapsingToolbarLayout.LayoutParams lp = (CollapsingToolbarLayout.LayoutParams) toolbar.getLayoutParams();
int statusBarHeight = getStatusBarHeight(activity);
lp.height += statusBarHeight;
toolbar.setLayoutParams(lp);
toolbar.setPadding(toolbar.getPaddingLeft(), toolbar.getPaddingTop() + statusBarHeight, toolbar.getPaddingRight(), toolbar.getPaddingBottom());
toolbar.setTag(true);
}
CoordinatorLayout.Behavior behavior = ((CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams()).getBehavior();
if (behavior != null && behavior instanceof AppBarLayout.Behavior) {
int verticalOffset = ((AppBarLayout.Behavior) behavior).getTopAndBottomOffset();
if (Math.abs(verticalOffset) > appBarLayout.getHeight() - collapsingToolbarLayout.getScrimVisibleHeightTrigger()) {
window.setStatusBarColor(statusColor);
} else {
window.setStatusBarColor(Color.TRANSPARENT);
}
} else {
window.setStatusBarColor(Color.TRANSPARENT);
}
collapsingToolbarLayout.setFitsSystemWindows(false);
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
if (Math.abs(verticalOffset) > appBarLayout.getHeight() - collapsingToolbarLayout.getScrimVisibleHeightTrigger()) {
if (window.getStatusBarColor() != statusColor) {
startColorAnimation(window.getStatusBarColor(), statusColor, collapsingToolbarLayout.getScrimAnimationDuration(), window);
}
} else {
if (window.getStatusBarColor() != Color.TRANSPARENT) {
startColorAnimation(window.getStatusBarColor(), Color.TRANSPARENT, collapsingToolbarLayout.getScrimAnimationDuration(), window);
}
}
}
});
collapsingToolbarLayout.getChildAt(0).setFitsSystemWindows(false);
collapsingToolbarLayout.setStatusBarScrimColor(statusColor);
}
/**
* use ValueAnimator to change statusBarColor when using collapsingToolbarLayout
*/
static void startColorAnimation(int startColor, int endColor, long duration, final Window window) {
if (sAnimator != null) {
sAnimator.cancel();
}
sAnimator = ValueAnimator.ofArgb(startColor, endColor)
.setDuration(duration);
sAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
if (window != null) {
window.setStatusBarColor((Integer) valueAnimator.getAnimatedValue());
}
}
});
sAnimator.start();
}
private static ValueAnimator sAnimator;
}
@@ -0,0 +1,99 @@
package com.dahe.mylibrary.utils;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
public class StringUtils {
public static String byte2hex(byte[] b) {
String str = "";
String stmp = "";
int length = b.length;
for (int n = 0; n < length; n++) {
stmp = (Integer.toHexString(b[n] & 0XFF));
if (stmp.length() == 1) {
str += "0";
}
str += stmp;
}
return str.toLowerCase();
}
public static String nullToStrTrim(String str) {
if (str == null) {
str = "";
}
return str.trim();
}
public static boolean isNotEmpty(String str) {
return ((str != null) && (str.trim().length() > 0 && !"null".equals(str)));
}
public static boolean isEmpty(String str) {
return !isNotEmpty(str);
}
public static int getRealLength(String str) {
return getRealLength(str, "utf-8");
}
public static int getRealLength(String str, String charsetName) {
str = nullToStrTrim(str);
try {
return str.getBytes(charsetName).length;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return 0;
}
}
public static String encode(String str, String enc) {
String strEncode = "";
try {
if (str != null)
strEncode = URLEncoder.encode(str, enc);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return strEncode;
}
public static String decode(String str, String enc) {
String strDecode = "";
try {
if (str != null)
strDecode = URLDecoder.decode(str, enc);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return strDecode;
}
public static String encode(String str) {
return encode(str, "utf-8");
}
public static String decode(String str) {
return decode(str, "utf-8");
}
}
@@ -0,0 +1,44 @@
package com.dahe.mylibrary.utils;
import androidx.annotation.IntDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* <pre>
* author: Blankj
* blog : http://blankj.com
* time : 2017/03/13
* desc : 时间相关常量
* </pre>
*/
public final class TimeConstants {
/**
* 毫秒与毫秒的倍数
*/
public static final int MSEC = 1;
/**
* 秒与毫秒的倍数
*/
public static final int SEC = 1000;
/**
* 分与毫秒的倍数
*/
public static final int MIN = 60000;
/**
* 时与毫秒的倍数
*/
public static final int HOUR = 3600000;
/**
* 天与毫秒的倍数
*/
public static final int DAY = 86400000;
@IntDef({MSEC, SEC, MIN, HOUR, DAY})
@Retention(RetentionPolicy.SOURCE)
public @interface Unit {
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,145 @@
package com.dahe.mylibrary.utils;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;
import java.util.ArrayList;
import io.reactivex.rxjava3.annotations.NonNull;
public class TimingX {
private volatile static TimingX sTimingX;
private static int sSecond = 0, sStatus = TimingEnum.STOP.val;
private static final Handler sHandler = new TimingXHandler();
private static final ArrayList<TextView> timingViews = new ArrayList<>(8);
private static String time = "";
private TimingX() {
}
public static TimingX builder(){
if(sTimingX == null){
synchronized (TimingX.class){
if(sTimingX == null){
sTimingX = new TimingX();
}
}
}
return sTimingX;
}
private static class TimingXHandler extends Handler {
@Override
public void handleMessage(@NonNull Message msg) {
int status = msg.what;
if (status == TimingEnum.START.val) {
sSecond += 1;
time = format(sSecond);
sHandler.sendEmptyMessageDelayed(status, 1000);
} else if (status == TimingEnum.STOP.val) {
time = format(sSecond);
}
showTime();
}
}
private static void showTime(){
for (TextView timingView : timingViews) {
timingView.setText(time);
}
}
public int getStatus(){
return sStatus;
}
enum TimingEnum {
STOP(0), // 停止计时
START(1), // 开始计时
CLEAR(-1); // 清除计时
int val;
TimingEnum(int val){
this.val = val;
}
}
/**
* 添加需要计时的 view
* @param view
* @return
*/
public TimingX add(TextView view){
if(!timingViews.contains(view)){
timingViews.add(view);
}
return sTimingX;
}
/**
* 移除不需要计时的 view
* @param view
* @return
*/
public TimingX remove(TextView view){
timingViews.remove(view);
return sTimingX;
}
/**
* 开始计时
*/
public void start(){
if(sStatus == TimingEnum.STOP.val){
sStatus = TimingEnum.START.val;
sHandler.sendEmptyMessageDelayed(sStatus, 1000);
}
}
/**
* 停止计时
*/
public void stop(){
if(sStatus == TimingEnum.START.val){
sStatus = TimingEnum.STOP.val;
sHandler.removeMessages(TimingEnum.START.val);
sHandler.sendEmptyMessage(sStatus);
}
}
/**
* 销毁 handler
*/
public void destroy(){
sStatus = TimingEnum.STOP.val;
sSecond = 0;
sHandler.removeMessages(TimingEnum.START.val);
timingViews.clear();
}
/**
* 将秒转化为分秒的形式(00:00)
* @param second
* @return
*/
public static String format(int second) {
StringBuilder sb = new StringBuilder();
int minutes = second / 60;
int sec = second % 60;
if(minutes < 10){
sb.append(0);
}
sb.append(minutes);
sb.append(":");
if(sec < 10){
sb.append(0);
}
sb.append(sec);
return sb.toString();
}
}
@@ -0,0 +1,37 @@
package com.dahe.mylibrary.utils;
import android.content.Context;
import android.text.TextUtils;
import android.widget.Toast;
/**
* Created by Administrator on 2017/11/28 0028.
*/
public class ToastUtils {
public static Toast mToast = null;
public static void showToast(Context mContext, String message) {
if (!TextUtils.isEmpty(message)) {
// if ( mToast != null) {
// mToast.cancel();
// }
// mToast = Toast.makeText(mContext, message, Toast.LENGTH_SHORT);
// mToast.show();
if (mToast == null) {
mToast = Toast.makeText(mContext, message, Toast.LENGTH_SHORT);
} else {
mToast.setText(message);
}
mToast.show();
}
}
public static void cancelToast(){
if (mToast!=null)
mToast.cancel();
}
}
@@ -0,0 +1,157 @@
package com.dahe.mylibrary.weight;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.BounceInterpolator;
import androidx.annotation.Nullable;
import com.dahe.mylibrary.R;
/**
* 自定义View实现拖动并自动吸边效果
* <p>
* 处理滑动和贴边 {@link #onTouchEvent(MotionEvent)}
* 处理事件分发 {@link #dispatchTouchEvent(MotionEvent)}
* </p>
*
* @attr customIsAttach //是否需要自动吸边
* @attr customIsDrag //是否可拖曳
*/
public class AttachButton extends View {
private float mLastRawX;
private float mLastRawY;
private final String TAG = "AttachButton";
private boolean isDrug = false;
private int mRootMeasuredWidth = 0;
private int mRootMeasuredHeight = 0;
private int mRootTopY = 0;
private boolean customIsAttach;
private boolean customIsDrag;
public AttachButton(Context context) {
this(context, null);
}
public AttachButton(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public AttachButton(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initAttrs(context, attrs);
}
/**
* 初始化自定义属性
*/
private void initAttrs(Context context, AttributeSet attrs) {
TypedArray mTypedAttay = context.obtainStyledAttributes(attrs, R.styleable.AttachButton);
customIsAttach = mTypedAttay.getBoolean(R.styleable.AttachButton_customIsAttach, true);
customIsDrag = mTypedAttay.getBoolean(R.styleable.AttachButton_customIsDrag, true);
mTypedAttay.recycle();
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
super.dispatchTouchEvent(event);
return true;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
//判断是否需要滑动
if (customIsDrag) {
//当前手指的坐标
float mRawX = ev.getRawX();
float mRawY = ev.getRawY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN://手指按下
isDrug = false;
//记录按下的位置
mLastRawX = mRawX;
mLastRawY = mRawY;
ViewGroup mViewGroup = (ViewGroup) getParent();
if (mViewGroup != null) {
int[] location = new int[2];
mViewGroup.getLocationInWindow(location);
//获取父布局的高度
mRootMeasuredHeight = mViewGroup.getMeasuredHeight();
mRootMeasuredWidth = mViewGroup.getMeasuredWidth();
//获取父布局顶点的坐标
mRootTopY = location[1];
}
break;
case MotionEvent.ACTION_MOVE://手指滑动
if (mRawX >= 0 && mRawX <= mRootMeasuredWidth && mRawY >= mRootTopY && mRawY <= (mRootMeasuredHeight + mRootTopY)) {
//手指X轴滑动距离
float differenceValueX = mRawX - mLastRawX;
//手指Y轴滑动距离
float differenceValueY = mRawY - mLastRawY;
//判断是否为拖动操作
if (!isDrug) {
if (Math.sqrt(differenceValueX * differenceValueX + differenceValueY * differenceValueY) < 2) {
isDrug = false;
} else {
isDrug = true;
}
}
//获取手指按下的距离与控件本身X轴的距离
float ownX = getX();
//获取手指按下的距离与控件本身Y轴的距离
float ownY = getY();
//理论中X轴拖动的距离
float endX = ownX + differenceValueX;
//理论中Y轴拖动的距离
float endY = ownY + differenceValueY;
//X轴可以拖动的最大距离
float maxX = mRootMeasuredWidth - getWidth();
//Y轴可以拖动的最大距离
float maxY = mRootMeasuredHeight - getHeight();
//X轴边界限制
endX = endX < 0 ? 0 : endX > maxX ? maxX : endX;
//Y轴边界限制
endY = endY < 0 ? 0 : endY > maxY ? maxY : endY;
//开始移动
setX(endX);
setY(endY);
//记录位置
mLastRawX = mRawX;
mLastRawY = mRawY;
}
break;
case MotionEvent.ACTION_UP://手指离开
//根据自定义属性判断是否需要贴边
if (customIsAttach) {
//判断是否为点击事件
if (isDrug) {
float center = mRootMeasuredWidth / 2;
//自动贴边
if (mLastRawX <= center) {
//向左贴边
AttachButton.this.animate()
.setInterpolator(new BounceInterpolator())
.setDuration(500)
.x(0)
.start();
} else {
//向右贴边
AttachButton.this.animate()
.setInterpolator(new BounceInterpolator())
.setDuration(500)
.x(mRootMeasuredWidth - getWidth())
.start();
}
}
}
break;
}
}
//是否拦截事件
return isDrug ? isDrug : super.onTouchEvent(ev);
}
}
@@ -0,0 +1,103 @@
package com.dahe.mylibrary.weight;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
/**
* @authorluck
* @date2016/12/31 2:26 下午
* @describePictureOnlyCameraFragment
*/
public class FullyGridLayoutManager extends GridLayoutManager {
private final int[] mMeasuredDimension = new int[2];
public FullyGridLayoutManager(Context context, int spanCount) {
super(context, spanCount);
}
public FullyGridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) {
super(context, spanCount, orientation, reverseLayout);
}
@Override
public void onMeasure(@NonNull RecyclerView.Recycler recycler, @NonNull RecyclerView.State state, int widthSpec, int heightSpec) {
final int widthMode = View.MeasureSpec.getMode(widthSpec);
final int heightMode = View.MeasureSpec.getMode(heightSpec);
final int widthSize = View.MeasureSpec.getSize(widthSpec);
final int heightSize = View.MeasureSpec.getSize(heightSpec);
int width = 0;
int height = 0;
int count = getItemCount();
int span = getSpanCount();
for (int i = 0; i < count; i++) {
measureScrapChild(recycler, i,
View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
mMeasuredDimension);
if (getOrientation() == HORIZONTAL) {
if (i % span == 0) {
width = width + mMeasuredDimension[0];
}
if (i == 0) {
height = mMeasuredDimension[1];
}
} else {
if (i % span == 0) {
height = height + mMeasuredDimension[1];
}
if (i == 0) {
width = mMeasuredDimension[0];
}
}
}
switch (widthMode) {
case View.MeasureSpec.EXACTLY:
width = widthSize;
case View.MeasureSpec.AT_MOST:
case View.MeasureSpec.UNSPECIFIED:
}
switch (heightMode) {
case View.MeasureSpec.EXACTLY:
height = heightSize;
case View.MeasureSpec.AT_MOST:
case View.MeasureSpec.UNSPECIFIED:
}
setMeasuredDimension(width, height);
}
final RecyclerView.State mState = new RecyclerView.State();
private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
int heightSpec, int[] measuredDimension) {
int itemCount = mState.getItemCount();
if (position < itemCount) {
try {
View view = recycler.getViewForPosition(0);
if (view != null) {
RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,
getPaddingLeft() + getPaddingRight(), p.width);
int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,
getPaddingTop() + getPaddingBottom(), p.height);
view.measure(childWidthSpec, childHeightSpec);
measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;
measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin;
recycler.recycleView(view);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
@@ -0,0 +1,67 @@
package com.dahe.mylibrary.weight;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
import java.security.MessageDigest;
/**
* 加载圆形头像带白色边框
*/
public class GlideCircleWithBorder extends BitmapTransformation {
private Paint mBorderPaint;
private float mBorderWidth;
public GlideCircleWithBorder(Context context, int borderWidth, int borderColor) {
mBorderWidth = Resources.getSystem().getDisplayMetrics().density * borderWidth;
mBorderPaint = new Paint();
mBorderPaint.setDither(true);
mBorderPaint.setAntiAlias(true);
mBorderPaint.setColor(borderColor);
mBorderPaint.setStyle(Paint.Style.STROKE);
mBorderPaint.setStrokeWidth(mBorderWidth);
}
protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
return circleCrop(pool, toTransform);
}
private Bitmap circleCrop(BitmapPool pool, Bitmap source) {
if (source == null) {
return null;
}
int size = (int) (Math.min(source.getWidth(), source.getHeight()) - (mBorderWidth / 2));
int x = (source.getWidth() - size) / 2;
int y = (source.getHeight() - size) / 2;
Bitmap squared = Bitmap.createBitmap(source, x, y, size, size);
Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888);
if (result == null) {
result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
}
//创建画笔 画布 手动描绘边框
Canvas canvas = new Canvas(result);
Paint paint = new Paint();
paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
paint.setAntiAlias(true);
float r = size / 2f;
canvas.drawCircle(r, r, r, paint);
if (mBorderPaint != null) {
float borderRadius = r - mBorderWidth / 2;
canvas.drawCircle(r, r, borderRadius, mBorderPaint);
}
return result;
}
@Override
public void updateDiskCacheKey(MessageDigest messageDigest) {
}
}
@@ -0,0 +1,117 @@
package com.dahe.mylibrary.weight;
import android.content.Context;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.dahe.mylibrary.R;
import com.luck.picture.lib.engine.ImageEngine;
import com.luck.picture.lib.utils.ActivityCompatHelper;
/**
* @authorluck
* @date2019-11-13 17:02
* @describeGlide加载引擎
*/
public class GlideEngine implements ImageEngine {
/**
* 加载图片
*
* @param context 上下文
* @param url 资源url
* @param imageView 图片承载控件
*/
@Override
public void loadImage(Context context, String url, ImageView imageView) {
if (!ActivityCompatHelper.assertValidRequest(context)) {
return;
}
Glide.with(context)
.load(url)
.into(imageView);
}
@Override
public void loadImage(Context context, ImageView imageView, String url, int maxWidth, int maxHeight) {
if (!ActivityCompatHelper.assertValidRequest(context)) {
return;
}
Glide.with(context)
.load(url)
.override(maxWidth, maxHeight)
.into(imageView);
}
/**
* 加载相册目录封面
*
* @param context 上下文
* @param url 图片路径
* @param imageView 承载图片ImageView
*/
@Override
public void loadAlbumCover(Context context, String url, ImageView imageView) {
if (!ActivityCompatHelper.assertValidRequest(context)) {
return;
}
Glide.with(context)
.asBitmap()
.load(url)
.override(180, 180)
.sizeMultiplier(0.5f)
.transform(new CenterCrop(), new RoundedCorners(8))
.placeholder(R.drawable.ps_image_placeholder)
.into(imageView);
}
/**
* 加载图片列表图片
*
* @param context 上下文
* @param url 图片路径
* @param imageView 承载图片ImageView
*/
@Override
public void loadGridImage(Context context, String url, ImageView imageView) {
if (!ActivityCompatHelper.assertValidRequest(context)) {
return;
}
Glide.with(context)
.load(url)
.override(200, 200)
.centerCrop()
.placeholder(R.drawable.ps_image_placeholder)
.into(imageView);
}
@Override
public void pauseRequests(Context context) {
if (!ActivityCompatHelper.assertValidRequest(context)) {
return;
}
Glide.with(context).pauseRequests();
}
@Override
public void resumeRequests(Context context) {
if (!ActivityCompatHelper.assertValidRequest(context)) {
return;
}
Glide.with(context).resumeRequests();
}
private GlideEngine() {
}
private static final class InstanceHolder {
static final GlideEngine instance = new GlideEngine();
}
public static GlideEngine createGlideEngine() {
return InstanceHolder.instance;
}
}
@@ -0,0 +1,44 @@
package com.dahe.mylibrary.weight
import android.content.Context
import android.net.Uri
import com.luck.picture.lib.config.PictureMimeType
import com.luck.picture.lib.engine.CompressFileEngine
import com.luck.picture.lib.interfaces.OnKeyValueResultCallbackListener
import com.luck.picture.lib.utils.DateUtils
import top.zibin.luban.Luban
import top.zibin.luban.OnNewCompressListener
import java.io.File
/**
* @ClassName ImageFileCompressEngine
* @Author john
* @Date 2024/1/31 14:50
* @Description TODO
*/
class ImageFileCompressEngine : CompressFileEngine {
override fun onStartCompress(
context: Context?,
source: ArrayList<Uri>?,
call: OnKeyValueResultCallbackListener?
) {
Luban.with(context).load(source).ignoreBy(100).setRenameListener { filePath ->
val indexOf = filePath.lastIndexOf(".")
val postfix = if (indexOf != -1) filePath.substring(indexOf) else ".jpg"
DateUtils.getCreateFileName("CMP_") + postfix
}.filter { path ->
if (PictureMimeType.isUrlHasImage(path) && !PictureMimeType.isHasHttp(path)) {
true
} else !PictureMimeType.isUrlHasGif(path)
}.setCompressListener(object : OnNewCompressListener {
override fun onStart() {}
override fun onSuccess(source: String, compressFile: File) {
call?.onCallback(source, compressFile.absolutePath)
}
override fun onError(source: String, e: Throwable) {
call?.onCallback(source, null)
}
}).launch()
}
}
@@ -0,0 +1,91 @@
package com.dahe.mylibrary.weight;
import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.animation.OvershootInterpolator;
public class MovedImageButton extends androidx.appcompat.widget.AppCompatImageButton {
private int lastX;
private int lastY;
private float screenWidth;
public MovedImageButton(Context context) {
super(context);
}
public MovedImageButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MovedImageButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
DisplayMetrics dm = getResources().getDisplayMetrics();
screenWidth = dm.widthPixels;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
lastX = x;
lastY = y;
break;
case MotionEvent.ACTION_MOVE:
int offsetX = x-lastX;
int offsetY = y-lastY;
//第一种方法
// layout(getLeft()+offsetX,
// getTop()+offsetY,
// getRight()+offsetX,
// getBottom()+offsetY);
//第二种方法
offsetLeftAndRight(offsetX);
offsetTopAndBottom(offsetY);
break;
case MotionEvent.ACTION_UP:
adsorbAnim(event.getRawX(), event.getRawY());
break;
}
return super.onTouchEvent(event);
}
private void adsorbAnim(float rawX, float rawY){
//靠顶吸附
// if (rawY <= BaseUtils.dip2px(getContext(),200)){//注意rawY包含了标题栏的高
// animate().setDuration(400)
// .setInterpolator(new OvershootInterpolator())
// .yBy(-getY()-getHeight()/2.0f)
// .start();
// }else
if (rawX >= screenWidth/2){//靠右吸附
animate().setDuration(400)
.setInterpolator(new OvershootInterpolator())
.xBy(screenWidth - getX() - getWidth())
.start();
}else {//靠左吸附
ObjectAnimator animator = ObjectAnimator.ofFloat(this, "x", getX(), 0);
animator.setInterpolator(new OvershootInterpolator());
animator.setDuration(400);
animator.start();
}
}
}
@@ -0,0 +1,191 @@
package com.dahe.mylibrary.weight;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.Nullable;
import com.dahe.mylibrary.R;
import com.dahe.mylibrary.utils.ToastUtils;
public class MySlideBar extends RelativeLayout implements View.OnClickListener {
private boolean canSelect;
private TextView tvT1;
private TextView tvT2;
private TextView tvT3;
private TextView tvT4;
private TextView tvC1;
private TextView tvC2;
private TextView tvC3;
private TextView tvC4;
private View view1;
private View view2;
public MySlideBar(Context context) {
this(context, null);
}
public MySlideBar(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public MySlideBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
this(context, attrs, 0, 0);
}
public MySlideBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
View inflate = View.inflate(context, R.layout.view_slide_bar, this);
tvT1 = (TextView) findViewById(R.id.tv_title1);
tvT2 = (TextView) findViewById(R.id.tv_title2);
tvT3 = (TextView) findViewById(R.id.tv_title3);
tvT4 = (TextView) findViewById(R.id.tv_title4);
tvC1 = (TextView) findViewById(R.id.tv_conten1);
tvC2 = (TextView) findViewById(R.id.tv_content2);
tvC3 = (TextView) findViewById(R.id.tv_content3);
tvC4 = (TextView) findViewById(R.id.tv_content4);
view1 = (View) findViewById(R.id.view1);
view2 = (View) findViewById(R.id.view2);
LinearLayout ll1 = (LinearLayout) findViewById(R.id.ll1);
LinearLayout ll2 = (LinearLayout) findViewById(R.id.ll2);
LinearLayout ll3 = (LinearLayout) findViewById(R.id.ll3);
LinearLayout ll4 = (LinearLayout) findViewById(R.id.ll4);
ll1.setOnClickListener(this);
ll2.setOnClickListener(this);
ll3.setOnClickListener(this);
ll4.setOnClickListener(this);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MySlideBar);
int integer = a.getInteger(R.styleable.MySlideBar_proress, -1);
canSelect = a.getBoolean(R.styleable.MySlideBar_canSelect, false);
changeProress(integer,true);
a.recycle();
}
@Override
public void onClick(View v) {
if (canSelect) {
int id = v.getId();
if (id == R.id.ll1) {
changeProress(0,canSelect);
} else if (id == R.id.ll2) {
changeProress(1,canSelect);
} else if (id == R.id.ll3) {
changeProress(2,canSelect);
} else if (id == R.id.ll4) {
changeProress(3,canSelect);
}
}
}
public void setProress(int proress){
changeProress(proress,canSelect);
}
private void changeProress(int integer,boolean canSelect){
if (listener!=null&&canSelect){
listener.onChange(integer);
}
if (0 == integer) {
tvT1.setBackgroundResource(R.drawable.select_slide_title);
tvT2.setBackgroundResource(R.drawable.select_slide_title);
tvT3.setBackgroundResource(R.drawable.select_slide_title);
tvT4.setBackgroundResource(R.drawable.select_slide_title);
tvT1.setText("1");
tvT2.setText("2");
tvT3.setText("3");
tvT4.setText("4");
tvT1.setSelected(true);
tvT2.setSelected(false);
tvT3.setSelected(false);
tvT4.setSelected(false);
view1.setBackgroundResource(R.color.color_d5);
view2.setBackgroundResource(R.color.color_d5);
tvC1.setTextColor(getResources().getColor(R.color.mine_top_bg));
tvC2.setTextColor(getResources().getColor(R.color.color_9));
tvC3.setTextColor(getResources().getColor(R.color.color_9));
tvC4.setTextColor(getResources().getColor(R.color.color_9));
} else if (1 == integer) {
tvT1.setBackgroundResource(R.drawable.ok);
tvT2.setBackgroundResource(R.drawable.select_slide_title);
tvT3.setBackgroundResource(R.drawable.select_slide_title);
tvT4.setBackgroundResource(R.drawable.select_slide_title);
tvT1.setText("");
tvT2.setText("2");
tvT3.setText("3");
tvT4.setText("4");
tvT2.setSelected(true);
tvT3.setSelected(false);
tvT4.setSelected(false);
view1.setBackgroundResource(R.color.mine_top_bg);
view2.setBackgroundResource(R.color.color_d5);
tvC1.setTextColor(getResources().getColor(R.color.black));
tvC2.setTextColor(getResources().getColor(R.color.mine_top_bg));
tvC3.setTextColor(getResources().getColor(R.color.color_9));
tvC4.setTextColor(getResources().getColor(R.color.color_9));
} else if (2 == integer) {
tvT1.setBackgroundResource(R.drawable.ok);
tvT2.setBackgroundResource(R.drawable.ok);
tvT3.setBackgroundResource(R.drawable.select_slide_title);
tvT4.setBackgroundResource(R.drawable.select_slide_title);
tvT1.setText("");
tvT2.setText("");
tvT3.setText("3");
tvT4.setText("4");
tvT3.setSelected(true);
tvT4.setSelected(false);
view1.setBackgroundResource(R.color.mine_top_bg);
view2.setBackgroundResource(R.color.mine_top_bg);
tvC1.setTextColor(getResources().getColor(R.color.black));
tvC2.setTextColor(getResources().getColor(R.color.black));
tvC3.setTextColor(getResources().getColor(R.color.mine_top_bg));
tvC4.setTextColor(getResources().getColor(R.color.color_9));
} else if (3 == integer) {
tvT1.setBackgroundResource(R.drawable.ok);
tvT2.setBackgroundResource(R.drawable.ok);
tvT3.setBackgroundResource(R.drawable.ok);
tvT4.setBackgroundResource(R.drawable.select_slide_title);
tvT1.setText("");
tvT2.setText("");
tvT3.setText("");
tvT4.setText("4");
tvT4.setSelected(true);
tvC1.setTextColor(getResources().getColor(R.color.black));
tvC2.setTextColor(getResources().getColor(R.color.black));
tvC3.setTextColor(getResources().getColor(R.color.black));
tvC4.setTextColor(getResources().getColor(R.color.mine_top_bg));
}
}
public interface OnChangeListener{
void onChange(int progress);
}
private OnChangeListener listener;
public void setOnChangeListener(OnChangeListener listener){
this.listener = listener;
}
}
@@ -0,0 +1,130 @@
package com.dahe.mylibrary.weight;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.graphics.drawable.ColorDrawable;
import android.os.Vibrator;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
import com.dahe.mylibrary.R;
public class SideBar extends View {
// 触摸事件
private OnTouchingLetterChangedListener onTouchingLetterChangedListener;
public static String[] b = { "A", "B", "C", "D", "E", "F", "G", "H", "I",
"J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
"W", "X", "Y", "Z", "#" };
private int choose = -1;
private Paint paint = new Paint();
private TextView mTextDialog;
/**
* 为SideBar设置显示字母的TextView
* @param textDialog
*/
public void setTextView(TextView textDialog) {
this.mTextDialog = textDialog;
}
public SideBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public SideBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SideBar(Context context) {
super(context);
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int height = getHeight();
int width = getWidth();
int singleHeight = height / b.length;// 获取每一个字母的高度
for (int i = 0; i < b.length; i++) {
paint.setColor(Color.rgb(33, 65, 98));
// paint.setColor(Color.WHITE);
paint.setTypeface(Typeface.DEFAULT_BOLD);
paint.setAntiAlias(true);
paint.setTextSize(20);
if (i == choose) {// 选中的状态
paint.setColor(Color.parseColor("#999999"));
paint.setFakeBoldText(true);
}
// x坐标等于中间-字符串宽度的一半
float xPos = width / 2 - paint.measureText(b[i]) / 2;
float yPos = singleHeight * i + singleHeight;
canvas.drawText(b[i], xPos, yPos, paint);
paint.reset();
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
final int action = event.getAction();
final float y = event.getY();
final int oldChoose = choose;
final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener;
final int c = (int) (y / getHeight() * b.length);// 点击y坐标所占总高度的比例*b数组的长度就等于点击b中的个数
switch (action) {
case MotionEvent.ACTION_UP:
setBackground(new ColorDrawable(0x00000000));
choose = -1;//
invalidate();
if (mTextDialog != null) {
mTextDialog.setVisibility(View.INVISIBLE);
}
break;
default:
// setBackgroundResource(R.drawable.sidebar_background);
if (oldChoose != c) {
if (c >= 0 && c < b.length) {
if (listener != null) {
listener.onTouchingLetterChanged(b[c]);
}
if (mTextDialog != null) {
mTextDialog.setText(b[c]);
mTextDialog.setVisibility(View.VISIBLE);
}
choose = c;
invalidate();
}
}
break;
}
return true;
}
/**
* 触摸事件
* @param onTouchingLetterChangedListener
*/
public void setOnTouchingLetterChangedListener(
OnTouchingLetterChangedListener onTouchingLetterChangedListener) {
this.onTouchingLetterChangedListener = onTouchingLetterChangedListener;
}
/**
* 回调接口
*/
public interface OnTouchingLetterChangedListener {
void onTouchingLetterChanged(String s);
}
}
@@ -0,0 +1,508 @@
package com.dahe.mylibrary.weight;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RadialGradient;
import android.graphics.RectF;
import android.graphics.Shader;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import com.dahe.mylibrary.R;
/**
* hei hei hei
*/
public class SwitchView extends View {
private static final int STATE_SWITCH_ON = 4;
private static final int STATE_SWITCH_ON2 = 3;
private static final int STATE_SWITCH_OFF2 = 2;
private static final int STATE_SWITCH_OFF = 1;
private final AccelerateInterpolator interpolator = new AccelerateInterpolator(2);
private final Paint paint = new Paint();
private final Path sPath = new Path();
private final Path bPath = new Path();
private final RectF bRectF = new RectF();
private float sAnim, bAnim;
private RadialGradient shadowGradient;
protected float ratioAspect = 0.68f; // (0,1]
protected float animationSpeed = 0.1f; // (0,1]
private int state;
private int lastState;
private boolean isCanVisibleDrawing = false;
private OnClickListener mOnClickListener;
protected int colorPrimary;
protected int colorPrimaryDark;
protected int colorOff;
protected int colorOffDark;
protected int colorShadow;
protected boolean hasShadow;
protected boolean isOpened;
protected boolean canEnable;
private float sRight;
private float sCenterX, sCenterY;
private float sScale;
private float bOffset;
private float bRadius, bStrokeWidth;
private float bWidth;
private float bLeft;
private float bRight;
private float bOnLeftX, bOn2LeftX, bOff2LeftX, bOffLeftX;
private float shadowReservedHeight;
public SwitchView(Context context) {
this(context, null);
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public SwitchView(Context context, AttributeSet attrs) {
super(context, attrs);
setLayerType(LAYER_TYPE_SOFTWARE, null);
final int DEFAULT_COLOR_PRIMARY = 0xFF4BD763;
final int DEFAULT_COLOR_PRIMARY_DARK = 0xFF3AC652;
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SwitchView);
colorPrimary = a.getColor(R.styleable.SwitchView_primaryColor, DEFAULT_COLOR_PRIMARY);
colorPrimaryDark = a.getColor(R.styleable.SwitchView_primaryColorDark, DEFAULT_COLOR_PRIMARY_DARK);
colorOff = a.getColor(R.styleable.SwitchView_offColor, 0xFFE3E3E3);
colorOffDark = a.getColor(R.styleable.SwitchView_offColorDark, 0xFFBFBFBF);
colorShadow = a.getColor(R.styleable.SwitchView_shadowColor, 0xFF333333);
ratioAspect = a.getFloat(R.styleable.SwitchView_ratioAspect, 0.68f);
hasShadow = a.getBoolean(R.styleable.SwitchView_hasShadow, true);
isOpened = a.getBoolean(R.styleable.SwitchView_isOpened, false);
canEnable = a.getBoolean(R.styleable.SwitchView_canEnable, true);
state = isOpened ? STATE_SWITCH_ON : STATE_SWITCH_OFF;
lastState = state;
a.recycle();
if (colorPrimary == DEFAULT_COLOR_PRIMARY && colorPrimaryDark == DEFAULT_COLOR_PRIMARY_DARK) {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
TypedValue primaryColorTypedValue = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.colorPrimary, primaryColorTypedValue, true);
if (primaryColorTypedValue.data > 0) colorPrimary = primaryColorTypedValue.data;
TypedValue primaryColorDarkTypedValue = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.colorPrimaryDark, primaryColorDarkTypedValue, true);
if (primaryColorDarkTypedValue.data > 0)
colorPrimaryDark = primaryColorDarkTypedValue.data;
}
} catch (Exception ignore) {
}
}
}
public void setColor(int newColorPrimary, int newColorPrimaryDark) {
setColor(newColorPrimary, newColorPrimaryDark, colorOff, colorOffDark);
}
public void setColor(int newColorPrimary, int newColorPrimaryDark, int newColorOff, int newColorOffDark) {
setColor(newColorPrimary, newColorPrimaryDark, newColorOff, newColorOffDark, colorShadow);
}
public void setColor(int newColorPrimary, int newColorPrimaryDark, int newColorOff, int newColorOffDark, int newColorShadow) {
colorPrimary = newColorPrimary;
colorPrimaryDark = newColorPrimaryDark;
colorOff = newColorOff;
colorOffDark = newColorOffDark;
colorShadow = newColorShadow;
invalidate();
}
public void setCanEnable(boolean canEnable){
this.canEnable = canEnable;
invalidate();
}
public void setShadow(boolean shadow) {
hasShadow = shadow;
invalidate();
}
public boolean isOpened() {
return isOpened;
}
public void setOpened(boolean isOpened) {
int wishState = isOpened ? STATE_SWITCH_ON : STATE_SWITCH_OFF;
if (wishState == state) {
return;
}
refreshState(wishState);
}
public void toggleSwitch(boolean isOpened) {
int wishState = isOpened ? STATE_SWITCH_ON : STATE_SWITCH_OFF;
if (wishState == state) {
return;
}
if ((wishState == STATE_SWITCH_ON && (state == STATE_SWITCH_OFF || state == STATE_SWITCH_OFF2))
|| (wishState == STATE_SWITCH_OFF && (state == STATE_SWITCH_ON || state == STATE_SWITCH_ON2))) {
sAnim = 1;
}
bAnim = 1;
refreshState(wishState);
}
private void refreshState(int newState) {
if (!isOpened && newState == STATE_SWITCH_ON) {
isOpened = true;
} else if (isOpened && newState == STATE_SWITCH_OFF) {
isOpened = false;
}
lastState = state;
state = newState;
postInvalidate();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int resultWidth;
if (widthMode == MeasureSpec.EXACTLY) {
resultWidth = widthSize;
} else {
resultWidth = (int) (56 * getResources().getDisplayMetrics().density + 0.5f)
+ getPaddingLeft() + getPaddingRight();
if (widthMode == MeasureSpec.AT_MOST) {
resultWidth = Math.min(resultWidth, widthSize);
}
}
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int resultHeight;
if (heightMode == MeasureSpec.EXACTLY) {
resultHeight = heightSize;
} else {
resultHeight = (int) (resultWidth * ratioAspect) + getPaddingTop() + getPaddingBottom();
if (heightMode == MeasureSpec.AT_MOST) {
resultHeight = Math.min(resultHeight, heightSize);
}
}
setMeasuredDimension(resultWidth, resultHeight);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
isCanVisibleDrawing = w > getPaddingLeft() + getPaddingRight() && h > getPaddingTop() + getPaddingBottom();
if (isCanVisibleDrawing) {
int actuallyDrawingAreaWidth = w - getPaddingLeft() - getPaddingRight();
int actuallyDrawingAreaHeight = h - getPaddingTop() - getPaddingBottom();
int actuallyDrawingAreaLeft;
int actuallyDrawingAreaRight;
int actuallyDrawingAreaTop;
int actuallyDrawingAreaBottom;
if (actuallyDrawingAreaWidth * ratioAspect < actuallyDrawingAreaHeight) {
actuallyDrawingAreaLeft = getPaddingLeft();
actuallyDrawingAreaRight = w - getPaddingRight();
int heightExtraSize = (int) (actuallyDrawingAreaHeight - actuallyDrawingAreaWidth * ratioAspect);
actuallyDrawingAreaTop = getPaddingTop() + heightExtraSize / 2;
actuallyDrawingAreaBottom = getHeight() - getPaddingBottom() - heightExtraSize / 2;
} else {
int widthExtraSize = (int) (actuallyDrawingAreaWidth - actuallyDrawingAreaHeight / ratioAspect);
actuallyDrawingAreaLeft = getPaddingLeft() + widthExtraSize / 2;
actuallyDrawingAreaRight = getWidth() - getPaddingRight() - widthExtraSize / 2;
actuallyDrawingAreaTop = getPaddingTop();
actuallyDrawingAreaBottom = getHeight() - getPaddingBottom();
}
shadowReservedHeight = (int) ((actuallyDrawingAreaBottom - actuallyDrawingAreaTop) * 0.07f);
float sLeft = actuallyDrawingAreaLeft;
float sTop = actuallyDrawingAreaTop + shadowReservedHeight;
sRight = actuallyDrawingAreaRight;
float sBottom = actuallyDrawingAreaBottom - shadowReservedHeight;
float sHeight = sBottom - sTop;
sCenterX = (sRight + sLeft) / 2;
sCenterY = (sBottom + sTop) / 2;
bLeft = sLeft;
bWidth = sBottom - sTop;
bRight = sLeft + bWidth;
final float halfHeightOfS = bWidth / 2; // OfB
bRadius = halfHeightOfS * 0.95f;
bOffset = bRadius * 0.2f; // offset of switching
bStrokeWidth = (halfHeightOfS - bRadius) * 2;
bOnLeftX = sRight - bWidth;
bOn2LeftX = bOnLeftX - bOffset;
bOffLeftX = sLeft;
bOff2LeftX = bOffLeftX + bOffset;
sScale = 1 - bStrokeWidth / sHeight;
sPath.reset();
RectF sRectF = new RectF();
sRectF.top = sTop;
sRectF.bottom = sBottom;
sRectF.left = sLeft;
sRectF.right = sLeft + sHeight;
sPath.arcTo(sRectF, 90, 180);
sRectF.left = sRight - sHeight;
sRectF.right = sRight;
sPath.arcTo(sRectF, 270, 180);
sPath.close();
bRectF.left = bLeft;
bRectF.right = bRight;
bRectF.top = sTop + bStrokeWidth / 2; // bTop = sTop
bRectF.bottom = sBottom - bStrokeWidth / 2; // bBottom = sBottom
float bCenterX = (bRight + bLeft) / 2;
float bCenterY = (sBottom + sTop) / 2;
int red = colorShadow >> 16 & 0xFF;
int green = colorShadow >> 8 & 0xFF;
int blue = colorShadow & 0xFF;
shadowGradient = new RadialGradient(bCenterX, bCenterY, bRadius, Color.argb(200, red, green, blue),
Color.argb(25, red, green, blue), Shader.TileMode.CLAMP);
}
}
private void calcBPath(float percent) {
bPath.reset();
bRectF.left = bLeft + bStrokeWidth / 2;
bRectF.right = bRight - bStrokeWidth / 2;
bPath.arcTo(bRectF, 90, 180);
bRectF.left = bLeft + percent * bOffset + bStrokeWidth / 2;
bRectF.right = bRight + percent * bOffset - bStrokeWidth / 2;
bPath.arcTo(bRectF, 270, 180);
bPath.close();
}
private float calcBTranslate(float percent) {
float result = 0;
switch (state - lastState) {
case 1:
if (state == STATE_SWITCH_OFF2) {
result = bOffLeftX; // off -> off2
} else if (state == STATE_SWITCH_ON) {
result = bOnLeftX - (bOnLeftX - bOn2LeftX) * percent; // on2 -> on
}
break;
case 2:
if (state == STATE_SWITCH_ON) {
result = bOnLeftX - (bOnLeftX - bOffLeftX) * percent; // off2 -> on
} else if (state == STATE_SWITCH_ON2) {
result = bOn2LeftX - (bOn2LeftX - bOffLeftX) * percent; // off -> on2
}
break;
case 3:
result = bOnLeftX - (bOnLeftX - bOffLeftX) * percent; // off -> on
break;
case -1:
if (state == STATE_SWITCH_ON2) {
result = bOn2LeftX + (bOnLeftX - bOn2LeftX) * percent; // on -> on2
} else if (state == STATE_SWITCH_OFF) {
result = bOffLeftX; // off2 -> off
}
break;
case -2:
if (state == STATE_SWITCH_OFF) {
result = bOffLeftX + (bOn2LeftX - bOffLeftX) * percent; // on2 -> off
} else if (state == STATE_SWITCH_OFF2) {
result = bOff2LeftX + (bOnLeftX - bOff2LeftX) * percent; // on -> off2
}
break;
case -3:
result = bOffLeftX + (bOnLeftX - bOffLeftX) * percent; // on -> off
break;
default: // init
case 0:
if (state == STATE_SWITCH_OFF) {
result = bOffLeftX; // off -> off
} else if (state == STATE_SWITCH_ON) {
result = bOnLeftX; // on -> on
}
break;
}
return result - bOffLeftX;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (!isCanVisibleDrawing) return;
paint.setAntiAlias(true);
final boolean isOn = (state == STATE_SWITCH_ON || state == STATE_SWITCH_ON2);
// Draw background
paint.setStyle(Paint.Style.FILL);
paint.setColor(isOn ? colorPrimary : colorOff);
canvas.drawPath(sPath, paint);
sAnim = sAnim - animationSpeed > 0 ? sAnim - animationSpeed : 0;
bAnim = bAnim - animationSpeed > 0 ? bAnim - animationSpeed : 0;
final float dsAnim = interpolator.getInterpolation(sAnim);
final float dbAnim = interpolator.getInterpolation(bAnim);
// Draw background animation
final float scale = sScale * (isOn ? dsAnim : 1 - dsAnim);
final float scaleOffset = (sRight - sCenterX - bRadius) * (isOn ? 1 - dsAnim : dsAnim);
canvas.save();
canvas.scale(scale, scale, sCenterX + scaleOffset, sCenterY);
paint.setColor(0xFFFFFFFF);
canvas.drawPath(sPath, paint);
canvas.restore();
// To prepare center bar path
canvas.save();
canvas.translate(calcBTranslate(dbAnim), shadowReservedHeight);
final boolean isState2 = (state == STATE_SWITCH_ON2 || state == STATE_SWITCH_OFF2);
calcBPath(isState2 ? 1 - dbAnim : dbAnim);
// Use center bar path to draw shadow
if (hasShadow) {
paint.setStyle(Paint.Style.FILL);
paint.setShader(shadowGradient);
canvas.drawPath(bPath, paint);
paint.setShader(null);
}
canvas.translate(0, -shadowReservedHeight);
// draw bar
canvas.scale(0.98f, 0.98f, bWidth / 2, bWidth / 2);
paint.setStyle(Paint.Style.FILL);
paint.setColor(0xffffffff);
canvas.drawPath(bPath, paint);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(bStrokeWidth * 0.5f);
paint.setColor(isOn ? colorPrimaryDark : colorOffDark);
canvas.drawPath(bPath, paint);
canvas.restore();
paint.reset();
if (sAnim > 0 || bAnim > 0) invalidate();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!canEnable)
return super.onTouchEvent(event);
if ((state == STATE_SWITCH_ON || state == STATE_SWITCH_OFF) && (sAnim * bAnim == 0)) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
return true;
case MotionEvent.ACTION_UP:
lastState = state;
bAnim = 1;
if (state == STATE_SWITCH_OFF) {
refreshState(STATE_SWITCH_OFF2);
listener.toggleToOn(this);
} else if (state == STATE_SWITCH_ON) {
refreshState(STATE_SWITCH_ON2);
listener.toggleToOff(this);
}
if (mOnClickListener != null) {
mOnClickListener.onClick(this);
}
break;
}
}
return super.onTouchEvent(event);
}
@Override
public void setOnClickListener(OnClickListener l) {
super.setOnClickListener(l);
mOnClickListener = l;
}
public interface OnStateChangedListener {
void toggleToOn(SwitchView view);
void toggleToOff(SwitchView view);
}
private OnStateChangedListener listener = new OnStateChangedListener() {
@Override
public void toggleToOn(SwitchView view) {
toggleSwitch(true);
}
@Override
public void toggleToOff(SwitchView view) {
toggleSwitch(false);
}
};
public void setOnStateChangedListener(OnStateChangedListener listener) {
if (listener == null) throw new IllegalArgumentException("empty listener");
this.listener = listener;
}
@Override
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
ss.isOpened = isOpened;
return ss;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
this.isOpened = ss.isOpened;
this.state = this.isOpened ? STATE_SWITCH_ON : STATE_SWITCH_OFF;
invalidate();
}
private static final class SavedState extends BaseSavedState {
private boolean isOpened;
SavedState(Parcelable superState) {
super(superState);
}
private SavedState(Parcel in) {
super(in);
isOpened = 1 == in.readInt();
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeInt(isOpened ? 1 : 0);
}
// fixed by Night99 https://github.com/g19980115
@Override
public int describeContents() {
return 0;
}
public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
@Override
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
@Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
}
@@ -0,0 +1,139 @@
package com.dahe.mylibrary.weight.segmentcontrol;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
// 圆角 Drawable 每个角的圆半径可以不同 (使用不同半径圆角图形的时候 使用这个类 以防止 系统提供的用 xml 实现的圆角 Drawable 在2.3 上 出现各个角位置错乱)
/**
* Created by caifangmao on 15/4/22.
*/
public class RadiusDrawable extends Drawable {
private int topLeftRadius;
private int topRightRadius;
private int bottomLeftRadius;
private int bottomRightRadius;
private int left;
private int top;
private int right;
private int bottom;
private final Paint paint;
private final boolean isStroke;
private int strokeWidth = 0;
private int strokeColor = Color.CYAN;
private int fillColor;
private Path path;
public RadiusDrawable(boolean isStroke) {
this(0, isStroke);
}
public RadiusDrawable(int radius, boolean isStroke) {
setRadius(radius);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
this.isStroke = isStroke;
}
public void setStrokeWidth(int width) {
strokeWidth = width;
setBounds(left, top, right, bottom);
}
public void setStrokeColor(int strokeColor) {
this.strokeColor = strokeColor;
}
public void setFillColor(int fillColor) {
this.fillColor = fillColor;
}
public void setRadius(int radius) {
this.topLeftRadius = this.topRightRadius = this.bottomLeftRadius = this.bottomRightRadius = radius;
}
public void setRadius(int topLeftRadius, int topRightRadius, int bottomLeftRadius, int bottomRightRadius) {
this.topLeftRadius = topLeftRadius;
this.topRightRadius = topRightRadius;
this.bottomLeftRadius = bottomLeftRadius;
this.bottomRightRadius = bottomRightRadius;
}
@Override
public void setBounds(int left, int top, int right, int bottom) {
super.setBounds(left, top, right, bottom);
this.left = left;
this.top = top;
this.right = right;
this.bottom = bottom;
if (isStroke) {
int halfStrokeWidth = strokeWidth / 2;
left += halfStrokeWidth;
top += halfStrokeWidth;
right -= halfStrokeWidth;
bottom -= halfStrokeWidth;
}
path = new Path();
path.moveTo(left + topLeftRadius, top);
path.lineTo(right - topRightRadius, top);
path.arcTo(new RectF(right - topRightRadius * 2, top, right, top + topRightRadius * 2),
-90, 90);
// path.quadTo(right, top, right, top + topRightRadius);
path.lineTo(right, bottom - bottomRightRadius);
path.arcTo(new RectF(right - bottomRightRadius * 2, bottom - bottomRightRadius * 2, right,
bottom), 0, 90);
// path.quadTo(right, bottom, right - bottomRightRadius, bottom);
path.lineTo(left + bottomLeftRadius, bottom);
path.arcTo(new RectF(left, bottom - bottomLeftRadius * 2, left + bottomLeftRadius * 2,
bottom), 90, 90);
// path.quadTo(left, bottom, left, bottom - bottomLeftRadius);
path.lineTo(left, top + topLeftRadius);
path.arcTo(new RectF(left, top, left + topLeftRadius * 2, top + topLeftRadius * 2), 180, 90);
// path.quadTo(left, top, left + topLeftRadius, top);
path.close();
}
@Override
public void draw(Canvas canvas) {
if (fillColor != 0) {
paint.setColor(fillColor);
paint.setStyle(Paint.Style.FILL);
canvas.drawPath(path, paint);
}
if (strokeWidth > 0) {
paint.setColor(strokeColor);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.MITER);
paint.setStrokeWidth(strokeWidth);
canvas.drawPath(path, paint);
}
}
@Override
public void setAlpha(int alpha) {
}
@Override
public void setColorFilter(ColorFilter cf) {
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
}
@@ -0,0 +1,526 @@
package com.dahe.mylibrary.weight.segmentcontrol;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Build;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import com.dahe.mylibrary.R;
/**
* Created by 7heaven on 15/4/22.
*/
public class SegmentControl extends View {
private String[] mTexts;
private Rect[] mCacheBounds;
private Rect[] mTextBounds;
private RadiusDrawable mBackgroundDrawable;
private RadiusDrawable mSelectedDrawable;
private int mCurrentIndex;
private int mTouchSlop;
private boolean inTapRegion;
private float mStartX;
private float mStartY;
private float mCurrentX;
private float mCurrentY;
private int mHorizonGap;
private int mVerticalGap;
/** 外边框的width */
private int mBoundWidth = 4;
/** 内边框的width */
private int mSeparatorWidth = mBoundWidth / 2;
private int mSingleChildWidth;
private int mSingleChildHeight;
private Paint mPaint;
private int mTextSize;
private ColorStateList mBackgroundColors;
private ColorStateList mTextColors;
private int mCornerRadius;
private int DEFAULT_SELECTED_COLOR = 0xFF32ADFF;
private int DEFAULT_NORMAL_COLOR = 0xFFFFFFFF;
private Paint.FontMetrics mCachedFM;
public enum Direction {
HORIZONTAL(0), VERTICAL(1);
int value;
Direction(int v) {
value = v;
}
}
private Direction mDirection;
public SegmentControl(Context context) {
this(context, null);
}
public SegmentControl(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SegmentControl(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SegmentControl);
String textArray = ta.getString(R.styleable.SegmentControl_texts);
if (textArray != null) {
mTexts = textArray.split("\\|");
}
mTextSize = ta.getDimensionPixelSize(R.styleable.SegmentControl_android_textSize, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 14, context.getResources().getDisplayMetrics()));
mCornerRadius = ta.getDimensionPixelSize(R.styleable.SegmentControl_cornerRadius, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, context.getResources().getDisplayMetrics()));
mDirection = Direction.values()[ta.getInt(R.styleable.SegmentControl_android_orientation, 0)];
mHorizonGap = ta.getDimensionPixelSize(R.styleable.SegmentControl_horizonGap, 0);
mVerticalGap = ta.getDimensionPixelSize(R.styleable.SegmentControl_verticalGap, 0);
int gap = ta.getDimensionPixelSize(R.styleable.SegmentControl_gaps, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, context.getResources().getDisplayMetrics()));
if(mHorizonGap == 0) {
mHorizonGap = gap;
}
if(mVerticalGap == 0) {
mVerticalGap = gap;
}
mBackgroundDrawable = new RadiusDrawable(mCornerRadius, true);
mBackgroundDrawable.setStrokeWidth(2);
DEFAULT_NORMAL_COLOR = ta.getColor(R.styleable.SegmentControl_normalColor, DEFAULT_NORMAL_COLOR);
DEFAULT_SELECTED_COLOR = ta.getColor(R.styleable.SegmentControl_selectedColor, DEFAULT_SELECTED_COLOR);
mBackgroundColors = ta.getColorStateList(R.styleable.SegmentControl_backgroundColors);
mTextColors = ta.getColorStateList(R.styleable.SegmentControl_textColors);
if (mBackgroundColors == null) {
mBackgroundColors = new ColorStateList(new int[][]{{android.R.attr.state_selected}, {-android.R.attr.state_selected}}, new int[]{DEFAULT_SELECTED_COLOR, DEFAULT_NORMAL_COLOR});
}
if(mTextColors == null){
mTextColors = new ColorStateList(new int[][]{{android.R.attr.state_selected}, {-android.R.attr.state_selected}}, new int[]{DEFAULT_NORMAL_COLOR, DEFAULT_SELECTED_COLOR});
}
mBoundWidth = ta.getDimensionPixelSize(R.styleable.SegmentControl_boundWidth, mBoundWidth);
mSeparatorWidth = ta.getDimensionPixelSize(R.styleable.SegmentControl_separatorWidth, mSeparatorWidth);
ta.recycle();
mBackgroundDrawable = new RadiusDrawable(mCornerRadius, true);
mBackgroundDrawable.setStrokeWidth(mBoundWidth);
mBackgroundDrawable.setStrokeColor(getSelectedBGColor());
mBackgroundDrawable.setFillColor(getNormalBGColor());
if (Build.VERSION.SDK_INT < 16) {
setBackgroundDrawable(mBackgroundDrawable);
} else {
setBackground(mBackgroundDrawable);
}
mSelectedDrawable = new RadiusDrawable(false);
mSelectedDrawable.setFillColor(getSelectedBGColor());
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setTextSize(mTextSize);
mCachedFM = mPaint.getFontMetrics();
int touchSlop = 0;
if (context == null) {
touchSlop = ViewConfiguration.getTouchSlop();
} else {
final ViewConfiguration config = ViewConfiguration.get(context);
touchSlop = config.getScaledTouchSlop();
}
mTouchSlop = touchSlop * touchSlop;
inTapRegion = false;
}
public void setText(String... texts) {
mTexts = texts;
if (mTexts != null) {
requestLayout();
}
}
/**
* 设置文字颜色
*
* @param color 需要设置的颜色
*/
public void setSelectedTextColors(ColorStateList color) {
mTextColors = color;
invalidate();
}
/**
* 设置背景颜色
*
* @param colors 颜色
*/
public void setColors(ColorStateList colors) {
mBackgroundColors = colors;
if (mBackgroundDrawable != null) {
mBackgroundDrawable.setStrokeColor(getSelectedBGColor());
mBackgroundDrawable.setFillColor(getNormalBGColor());
}
if (mSelectedDrawable != null) {
mSelectedDrawable.setFillColor(getSelectedBGColor());
}
invalidate();
}
public void setCornerRadius(int cornerRadius) {
mCornerRadius = cornerRadius;
if (mBackgroundDrawable != null) {
mBackgroundDrawable.setRadius(cornerRadius);
}
invalidate();
}
public void setDirection(Direction direction) {
Direction tDirection = mDirection;
mDirection = direction;
if (tDirection != direction) {
requestLayout();
invalidate();
}
}
public void setTextSize(int textSize_sp) {
setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize_sp);
}
public void setTextSize(int unit, int textSize) {
mPaint.setTextSize((int) (TypedValue.applyDimension(unit, textSize, getContext().getResources().getDisplayMetrics())));
if (textSize != mTextSize) {
mTextSize = textSize;
mCachedFM = mPaint.getFontMetrics();
requestLayout();
}
}
public void setSelectedIndex(int index) {
mCurrentIndex = index;
if(mOnSegmentControlClickListener != null) {
mOnSegmentControlClickListener.onSegmentControlClick(index);
}
invalidate();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width = 0;
int height = 0;
if (mTexts != null && mTexts.length > 0) {
mSingleChildHeight = 0;
mSingleChildWidth = 0;
if (mCacheBounds == null || mCacheBounds.length != mTexts.length) {
mCacheBounds = new Rect[mTexts.length];
}
if (mTextBounds == null || mTextBounds.length != mTexts.length) {
mTextBounds = new Rect[mTexts.length];
}
for (int i = 0; i < mTexts.length; i++) {
String text = mTexts[i];
if(text != null){
if(mTextBounds[i] == null) {
mTextBounds[i] = new Rect();
}
mPaint.getTextBounds(text, 0, text.length(), mTextBounds[i]);
if(mSingleChildWidth < mTextBounds[i].width() + mHorizonGap * 2) {
mSingleChildWidth = mTextBounds[i].width() + mHorizonGap * 2;
}
if(mSingleChildHeight < mTextBounds[i].height() + mVerticalGap * 2) {
mSingleChildHeight = mTextBounds[i].height() + mVerticalGap * 2;
}
}
}
switch (widthMode) {
case MeasureSpec.AT_MOST:
if (mDirection == Direction.HORIZONTAL) {
if (widthSize <= mSingleChildWidth * mTexts.length) {
mSingleChildWidth = widthSize / mTexts.length;
width = widthSize;
} else {
width = mSingleChildWidth * mTexts.length;
}
} else {
width = widthSize <= mSingleChildWidth ? widthSize : mSingleChildWidth;
}
break;
case MeasureSpec.EXACTLY:
width = widthSize;
break;
case MeasureSpec.UNSPECIFIED:
default:
if (mDirection == Direction.HORIZONTAL) {
width = mSingleChildWidth * mTexts.length;
} else {
width = mSingleChildWidth;
}
break;
}
switch (heightMode) {
case MeasureSpec.AT_MOST:
if (mDirection == Direction.VERTICAL) {
if (heightSize <= mSingleChildHeight * mTexts.length) {
mSingleChildHeight = heightSize / mTexts.length;
height = heightSize;
} else {
height = mSingleChildHeight * mTexts.length;
}
} else {
height = heightSize <= mSingleChildHeight ? heightSize : mSingleChildHeight;
}
break;
case MeasureSpec.EXACTLY:
height = heightSize;
break;
case MeasureSpec.UNSPECIFIED:
default:
if (mDirection == Direction.VERTICAL) {
height = mSingleChildHeight * mTexts.length;
} else {
height = mSingleChildHeight;
}
break;
}
switch (mDirection) {
case HORIZONTAL:
if (mSingleChildWidth != width / mTexts.length) {
mSingleChildWidth = width / mTexts.length;
}
mSingleChildHeight = height;
break;
case VERTICAL:
if(mSingleChildHeight != height / mTexts.length) {
mSingleChildHeight = height / mTexts.length;
}
mSingleChildWidth = width;
break;
default:
break;
}
for (int i = 0; i < mTexts.length; i++) {
if (mCacheBounds[i] == null) {
mCacheBounds[i] = new Rect();
}
if (mDirection == Direction.HORIZONTAL) {
mCacheBounds[i].left = i * mSingleChildWidth;
mCacheBounds[i].top = 0;
} else {
mCacheBounds[i].left = 0;
mCacheBounds[i].top = i * mSingleChildHeight;
}
mCacheBounds[i].right = mCacheBounds[i].left + mSingleChildWidth;
mCacheBounds[i].bottom = mCacheBounds[i].top + mSingleChildHeight;
}
} else {
width = widthMode == MeasureSpec.UNSPECIFIED ? 0 : widthSize;
height = heightMode == MeasureSpec.UNSPECIFIED ? 0 : heightSize;
}
setMeasuredDimension(width, height);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
inTapRegion = true;
mStartX = event.getX();
mStartY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
mCurrentX = event.getX();
mCurrentY = event.getY();
int dx = (int) (mCurrentX - mStartX);
int dy = (int) (mCurrentY - mStartY);
int distance = dx * dx + dy * dy;
if (distance > mTouchSlop) {
inTapRegion = false;
}
break;
case MotionEvent.ACTION_UP:
if (inTapRegion) {
int index = 0;
if (mDirection == Direction.HORIZONTAL) {
index = (int) (mStartX / mSingleChildWidth);
} else {
index = (int) (mStartY / mSingleChildHeight);
}
setSelectedIndex(index);
}
break;
default:
break;
}
return true;
}
private int getSelectedTextColor(){
return mTextColors.getColorForState(new int[]{android.R.attr.state_selected}, DEFAULT_NORMAL_COLOR);
}
private int getNormalTextColor(){
return mTextColors.getColorForState(new int[]{-android.R.attr.state_selected}, DEFAULT_SELECTED_COLOR);
}
private int getSelectedBGColor(){
return mBackgroundColors.getColorForState(new int[]{android.R.attr.state_selected}, DEFAULT_SELECTED_COLOR);
}
private int getNormalBGColor(){
return mBackgroundColors.getColorForState(new int[]{-android.R.attr.state_selected}, DEFAULT_NORMAL_COLOR);
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mTexts != null && mTexts.length > 0) {
for (int i = 0; i < mTexts.length; i++) {
//draw separate lines
if (i < mTexts.length - 1) {
mPaint.setColor(getSelectedBGColor());
mPaint.setStrokeWidth(mSeparatorWidth);
if (mDirection == Direction.HORIZONTAL) {
canvas.drawLine(mCacheBounds[i].right, 0, mCacheBounds[i].right, getHeight(), mPaint);
} else {
canvas.drawLine(mCacheBounds[i].left, mSingleChildHeight * (i + 1), mCacheBounds[i].right, mSingleChildHeight * (i + 1), mPaint);
}
}
//draw selected drawable
if (i == mCurrentIndex && mSelectedDrawable != null) {
int topLeftRadius = 0;
int topRightRadius = 0;
int bottomLeftRadius = 0;
int bottomRightRadius = 0;
if(mTexts.length == 1){
topLeftRadius = mCornerRadius;
bottomLeftRadius = mCornerRadius;
topRightRadius = mCornerRadius;
bottomRightRadius = mCornerRadius;
}else{
if (mDirection == Direction.HORIZONTAL) {
if (i == 0) {
topLeftRadius = mCornerRadius;
bottomLeftRadius = mCornerRadius;
} else if (i == mTexts.length - 1) {
topRightRadius = mCornerRadius;
bottomRightRadius = mCornerRadius;
}
} else {
if (i == 0) {
topLeftRadius = mCornerRadius;
topRightRadius = mCornerRadius;
} else if (i == mTexts.length - 1) {
bottomLeftRadius = mCornerRadius;
bottomRightRadius = mCornerRadius;
}
}
}
mSelectedDrawable.setRadius(topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
mSelectedDrawable.setBounds(mCacheBounds[i]);
mSelectedDrawable.draw(canvas);
mPaint.setColor(getSelectedTextColor());
} else {
mPaint.setColor(getNormalTextColor());
}
//draw texts
float baseline = mCacheBounds[i].top + ((mSingleChildHeight - mCachedFM.ascent + mCachedFM.descent) / 2) - mCachedFM.descent;
canvas.drawText(mTexts[i], mCacheBounds[i].left + (mSingleChildWidth - mTextBounds[i].width()) / 2, baseline, mPaint);
}
}
}
// =========================================================
// OnSegmentControlClickListener
// =========================================================
private OnSegmentControlClickListener mOnSegmentControlClickListener;
public void setOnSegmentControlClickListener(OnSegmentControlClickListener listener) {
mOnSegmentControlClickListener = listener;
}
public OnSegmentControlClickListener getOnSegmentControlClicklistener() {
return mOnSegmentControlClickListener;
}
public interface OnSegmentControlClickListener {
void onSegmentControlClick(int index);
}
}
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromYDelta="100%"
android:toYDelta="0%"
android:duration="300"
android:fillAfter="true"
/>
</set>
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fillAfter="true"
android:fromYDelta="0"
android:toYDelta="100%"
/>
</set>
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/text_bg_blue" android:state_selected="true"></item>
<item android:color="@color/black" android:state_selected="false"></item>
<item android:color="@color/black"></item>
</selector>
Binary file not shown.

After

Width:  |  Height:  |  Size: 489 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 897 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 575 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 877 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 751 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 869 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

Some files were not shown because too many files have changed in this diff Show More