kotlin转化

This commit is contained in:
lijia 2022-08-30 17:29:34 +08:00
parent 89164dbd44
commit 90200b5348
173 changed files with 15630 additions and 44 deletions

View File

@ -11,6 +11,7 @@
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
<option value="$PROJECT_DIR$/mylibrary" />
</set>
</option>
</GradleProjectSettings>

View File

@ -25,6 +25,12 @@
<entry key="..\:/2022work2/dhhy-cargo/app/src/main/res/layout/order_details_all.xml" value="0.2171875" />
<entry key="..\:/2022work2/dhhy-cargo/app/src/main/res/layout/order_details_loading_all.xml" value="0.2171875" />
<entry key="..\:/2022work2/dhhy-cargo/app/src/main/res/layout/order_item.xml" value="0.2682291666666667" />
<entry key="..\:/goodluckapp/dhhy-cargo/app/src/main/res/layout/activity_address_switch.xml" value="0.18125" />
<entry key="..\:/goodluckapp/dhhy-cargo/app/src/main/res/layout/activity_choice_address.xml" value="0.25" />
<entry key="..\:/goodluckapp/dhhy-cargo/app/src/main/res/layout/activity_dis_car.xml" value="0.19947916666666668" />
<entry key="..\:/goodluckapp/dhhy-cargo/app/src/main/res/layout/activity_search_address.xml" value="0.159375" />
<entry key="..\:/goodluckapp/dhhy-cargo/app/src/main/res/layout/item_cargo.xml" value="0.36614583333333334" />
<entry key="..\:/goodluckapp/dhhy-cargo/app/src/main/res/layout/my.xml" value="0.33" />
</map>
</option>
</component>

View File

@ -83,40 +83,20 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
implementation 'org.jetbrains:annotations:15.0'
//implementation files('libs\\AMap2DMap_6.0.0_AMapSearch_7.9.0_20210331.jar')
// implementation files('libs\\AMap_Location_V5.3.1_20210331.jar')
//implementation files('libs\\Android_Lite3DMap_SDK_V1.2.0_20210412.jar')
// implementation files('libs\\AMap2DMap_6.0.0_AMapSearch_7.9.0_20210331.jar')
//implementation files('libs\\android-support-v4.jar')
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
//
implementation 'com.github.bumptech.glide:glide:4.11.0'
// implementation 'org.jetbrains:annotations:15.0'
implementation 'top.zibin:Luban:1.1.3'
//okhttp
implementation 'com.squareup.okhttp3:okhttp:3.2.0'
//gson
implementation 'com.google.code.gson:gson:2.8.5'
//
implementation 'com.haozhang.libary:android-slanted-textview:1.2'
//
implementation 'com.scwang.smart:refresh-layout-kernel:2.0.1'
implementation 'com.scwang.smart:refresh-header-material:2.0.1'
implementation 'com.scwang.smart:refresh-footer-ball:2.0.1' //
implementation 'com.scwang.smart:refresh-footer-classics:2.0.1' //
implementation 'com.alibaba:fastjson:1.2.61'
//
//
implementation 'com.lxj:xpopup:2.2.8'
//
implementation 'com.github.jenly1314.AppUpdater:app-updater:1.1.0'
implementation 'com.github.jenly1314.AppUpdater:app-dialog:1.1.0'
//
implementation 'com.github.zhpanvip:BannerViewPager:3.5.4'
//
//implementation 'com.github.gzu-liyujiang:AndroidPicker:Tag'
implementation 'com.github.gzu-liyujiang.AndroidPicker:WheelPicker:3.1.1'
implementation 'com.github.gzu-liyujiang.AndroidPicker:AddressPicker:3.1.1'
//EventBus
@ -125,13 +105,6 @@ dependencies {
//
implementation 'cn.hutool:hutool-all:5.7.11'
//UI库
implementation 'com.github.tamsiree.RxTool:RxUI:2.6.2'
//
implementation 'com.github.tamsiree.RxTool:RxCamera:2.6.2'
//Zxing扫描与生成二维码条形码
implementation 'com.github.tamsiree.RxTool:RxFeature:2.6.2'
//ArcGis For Android工具库API100.1
implementation 'com.github.tamsiree.RxTool:RxArcGisKit:2.6.2'
//
// SDK根据宿主App是否使用相关业务按需引入
// SDK
@ -142,21 +115,10 @@ dependencies {
//xui
implementation 'com.github.xuexiangjys:XUI:1.1.8'
implementation "io.reactivex.rxjava3:rxjava:3.1.4"
implementation "io.reactivex.rxjava3:rxandroid:3.0.0"
// implementation "com.squareup.retrofit2:adapter-rxjava3:2.9.0"
implementation 'com.github.LuckSiege.PictureSelector:picture_library:v2.2.9'
// implementation 'io.github.lucksiege:pictureselector:v3.0.9'
implementation 'com.github.getActivity:XToast:8.2'
implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.6'
implementation 'com.github.tbruyelle:rxpermissions:0.12'
implementation 'com.amap.api:3dmap:8.0.0'
implementation 'com.amap.api:location:5.4.0'
implementation 'com.amap.api:search:7.9.0'
implementation project(path: ':mylibrary')
}

View File

@ -12,7 +12,7 @@
"filters": [],
"versionCode": 27,
"versionName": "3.0.7",
"outputFile": "dhhy-cargo-0718_16-12-3.0.7.apk"
"outputFile": "dhhy-cargo-0830_17-18-3.0.7.apk"
}
]
}

View File

@ -211,7 +211,7 @@
android:layout_width="@dimen/dp_22"
android:layout_height="@dimen/dp_22"
android:layout_marginLeft="@dimen/dp_4"
android:background="@drawable/selector_location"></ImageView>
></ImageView>
</LinearLayout>
<com.oneclouds.cargo.util.view.BaseRecyclerView

View File

@ -30,7 +30,7 @@
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_marginLeft="@dimen/dp_6"
android:background="@color/transparent"
android:background="#00000000"
android:hint="请输入车牌号/手机号进行搜索"
android:inputType="text|textAutoComplete"
android:singleLine="true"

View File

@ -39,7 +39,7 @@
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_marginLeft="@dimen/dp_6"
android:background="@color/transparent"
android:background="#00000000"
android:hint="请输入关键字"
android:inputType="text|textAutoComplete"
android:singleLine="true"

View File

@ -31,4 +31,5 @@
<color name="tab_select">@color/color_theme</color>
<color name="tab_select_no">#C9C9C9</color>
<color name="gray">#999999</color>
<color name="red">#FF0000</color>
</resources>

View File

@ -1,5 +1,8 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
apply from: "compile.gradle"
buildscript {
ext.kotlin_version = "1.5.0"
repositories {
google()
// jcenter() //
@ -18,6 +21,7 @@ buildscript {
}
dependencies {
classpath "com.android.tools.build:gradle:4.2.0"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}

92
compile.gradle Normal file
View File

@ -0,0 +1,92 @@
def SupportVersion = '28.0.0'
def ButterKnifeVersion = '10.0.0'
def CrashActivityVersion = '2.2.0'
def StatusBarVersion = '2.3.3'
def GsonVersion = '2.8.6'
def PhotoPickerVersion = 'v2.6.1'
//def PhotoPickerVersion = 'v2.7.2'
def GlideVersion = '4.12.0'
def AgentWebVersion = 'v4.1.9-androidx'
def NiceDialogVersion = '1.1.9'
def AndPermissionVersion = '2.0.3'
def BannerVersion = '1.4.10'
def SmartRefreshLayoutVersion = '1.1.0-alpha-12'
def MultideXVersion = '2.0.1'
def RXJavaVersion = '3.0.12'
def RXAndroidVersion = '3.0.0'
def RetrofitVersion = '2.9.0'
def OkHttpVersion = '4.9.1'
def AutoSizeVersion = '1.1.2'
def FlycoTabLayoutVersion = '2.1.2@aar'
def ZxingVersion = '1.3.8'
def BaseRecyclerViewAdapterHelper = '3.0.6'
def MagicIndicator = '1.7.0'
def PickerView = '4.1.9'
def NiceSpinner = '1.4.4'
def Countdownview = '2.1.6'
def Xpopup = '2.2.8'
def CheckVersionLib = '2.4.1_androidx'
def GooglePlayVersion = '15.0.1'
def Streamsupport = '1.7.3'
def NewbieGuideVersion = 'v2.4.0'
def CountdownviewVersion = '2.1.6'
def JpushVersion = '3.1.8'
def JcoreVersion = '1.2.7'
def BuglyVersion = 'latest.release'
project.ext {
android = [
compileSdkVersion: 30,
buildToolsVersion: "30.0.3",
applicationId : "com.dahe.examine",
minSdkVersion : 21,
targetSdkVersion : 30,
versionCode : 5,
versionName : "1.0.5",
]
dependencies = [
"appcompat-v7" : "com.android.support:appcompat-v7:${SupportVersion}",
"support-v4" : "com.android.support:support-v4:${SupportVersion}",
"support-design" : "com.android.support:design:${SupportVersion}",
"recyclerview" : "com.android.support:recyclerview-v7:${SupportVersion}",
"butterknife" : "com.jakewharton:butterknife:${ButterKnifeVersion}",
"butterknife-compiler" : "com.jakewharton:butterknife-compiler:${ButterKnifeVersion}",
"customactivityoncrash": "cat.ereza:customactivityoncrash:${CrashActivityVersion}",
"gson" : "com.google.code.gson:gson:${GsonVersion}",
"PhotoPicker" : "com.github.LuckSiege.PictureSelector:picture_library:${PhotoPickerVersion}",
"PhotoPicker" : "io.github.lucksiege:pictureselector:${PhotoPickerVersion}",
"agentweb" : "com.github.Justson.AgentWeb:agentweb-core:${AgentWebVersion}",
"statusbaruitl" : "com.github.niorgai:StatusBarCompat:${StatusBarVersion}",
"glide" : "com.github.bumptech.glide:glide:${GlideVersion}",
"glide-compiler" : "com.github.bumptech.glide:compiler:${GlideVersion}",
"glide-okhttps" : "com.github.bumptech.glide:okhttp3-integration:${GlideVersion}",
"NiceDialog" : "com.github.Othershe:NiceDialog:${NiceDialogVersion}",
"Banner" : "com.youth.banner:banner:${BannerVersion}",
"RefreshLayout" : "com.scwang.smartrefresh:SmartRefreshLayout:${SmartRefreshLayoutVersion}",
"Multidex" : "androidx.multidex:multidex:${MultideXVersion}",
"rxjava" : "io.reactivex.rxjava3:rxjava:${RXJavaVersion}",
"rxandroid" : "io.reactivex.rxjava3:rxandroid:${RXAndroidVersion}",
"retrofit" : "com.squareup.retrofit2:retrofit:${RetrofitVersion}",
"converter-gson" : "com.squareup.retrofit2:converter-gson:${RetrofitVersion}",
"adapter-rxjava2" : "com.squareup.retrofit2:adapter-rxjava3:${RetrofitVersion}",
"okhttp" : "com.squareup.okhttp3:okhttp:${OkHttpVersion}",
"logging-interceptor" : "com.squareup.okhttp3:logging-interceptor:${OkHttpVersion}",
"AutoSize" : "me.jessyan:autosize:${AutoSizeVersion}",
"FlycoTabLayout" : "com.flyco.tablayout:FlycoTabLayout_Lib:${FlycoTabLayoutVersion}",
"AndPermission" : "com.yanzhenjie:permission:${AndPermissionVersion}",
// "Zxing" : "cn.bingoogolapple:bga-qrcode-zxing:${ZxingVersion}",
"Zxing" : "com.github.bingoogolapple.BGAQRCode-Android:zxing:${ZxingVersion}",
"BaseRecyclerViewAdapterHelper" :"com.github.CymChad:BaseRecyclerViewAdapterHelper:${BaseRecyclerViewAdapterHelper}",
"MagicIndicator" :"com.github.hackware1993:MagicIndicator:${MagicIndicator}",
"NiceSpinner" :"com.github.arcadefire:nice-spinner:${NiceSpinner}",
"Countdownview" :"com.github.iwgang:countdownview:${Countdownview}",
"Xpopup" :"com.lxj:xpopup:${Xpopup}",
"CheckVersionLib" :"com.github.AlexLiuSheng:CheckVersionLib:${CheckVersionLib}",
"Bugly" :"com.tencent.bugly:crashreport:${BuglyVersion}",
"Streamsupport" :"net.sourceforge.streamsupport:streamsupport:${Streamsupport}",
"PickerView" :"com.contrarywind:Android-PickerView:${PickerView}",
"Permissionx" :'com.guolindev.permissionx:permissionx:1.6.4',
"3Dmap" :'com.amap.api:3dmap:8.0.0',
"Location" :'com.amap.api:location:5.4.0',
"Search" :'com.amap.api:search:7.9.0'
]
}

1
mylibrary/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

78
mylibrary/build.gradle Normal file
View File

@ -0,0 +1,78 @@
plugins {
id 'com.android.library'
id 'kotlin-android'
// id 'com.jakewharton.butterknife'
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
defaultConfig {
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
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_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.1'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.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["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["Multidex"]
api rootProject.ext.dependencies["NiceDialog"]
api rootProject.ext.dependencies["glide-okhttps"]
// api rootProject.ext.dependencies["Permissionx"]
api rootProject.ext.dependencies["3Dmap"]
api rootProject.ext.dependencies["Location"]
api rootProject.ext.dependencies["Search"]
}

View File

21
mylibrary/proguard-rules.pro vendored Normal file
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

View File

@ -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)
}
}

View File

@ -0,0 +1,28 @@
<?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="com.dahe.mylibrary.glide.AppGlideModule"
android:value="AppGlideModule"/>
</application>
</manifest>

View File

@ -0,0 +1,137 @@
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.smartrefresh.layout.SmartRefreshLayout;
import com.scwang.smartrefresh.layout.api.DefaultRefreshFooterCreator;
import com.scwang.smartrefresh.layout.api.DefaultRefreshHeaderCreator;
import com.scwang.smartrefresh.layout.api.RefreshFooter;
import com.scwang.smartrefresh.layout.api.RefreshHeader;
import com.scwang.smartrefresh.layout.api.RefreshLayout;
import com.scwang.smartrefresh.layout.footer.ClassicsFooter;
import com.scwang.smartrefresh.layout.header.ClassicsHeader;
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() {
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);
}
}
}

View File

@ -0,0 +1,31 @@
package com.dahe.mylibrary.adapter;
import android.widget.CheckBox;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.viewholder.BaseViewHolder;
import com.dahe.mylibrary.R;
import com.dahe.mylibrary.bean.CarBean;
import com.dahe.mylibrary.bean.NodeBean;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class CarAdapter extends BaseQuickAdapter<CarBean, BaseViewHolder> {
public CarAdapter(int layoutResId, @Nullable List<CarBean> data) {
super(R.layout.item_car_select, data);
}
@Override
protected void convert(@NotNull BaseViewHolder helper, CarBean item) {
helper.setText(R.id.tv_title, item.getVehicle())
.setText(R.id.tv_lxr, "司机信息:"+item.getDriverName() + " " + item.getDriverPhone())
.setText(R.id.tv_zz, "载重(Kg):"+item.getApprovedLoad())
.setText(R.id.tv_ckg, "长宽高(毫米):"+item.getOutlineLong()+"*"+item.getOutlineWide()+"*"+item.getOutlineHigh());
CheckBox cb = helper.getView(R.id.cb);
cb.setChecked(item.isSelect());
}
}

View File

@ -0,0 +1,41 @@
package com.dahe.mylibrary.adapter;
import android.widget.TextView;
import androidx.annotation.Nullable;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.viewholder.BaseViewHolder;
import com.dahe.mylibrary.R;
import com.dahe.mylibrary.bean.StateBean;
import java.util.List;
public class CenterSimAdapter extends BaseQuickAdapter<StateBean, BaseViewHolder> {
private StateBean selectString=null;
public CenterSimAdapter(int layoutResId, @Nullable List<StateBean> data, StateBean selectString) {
super(R.layout.item_select, data);
this.selectString = selectString;
}
@Override
protected void convert(BaseViewHolder helper, StateBean item) {
helper.setText(R.id.tv_content,item.getDictLabel());
TextView tv = helper.getView(R.id.tv_content);
if (selectString!=null&&item.getDictValue()!=null){
if (item.getDictValue().equals(selectString.getDictValue())){
tv.setSelected(true);
}else{
tv.setSelected(false);
}
}
}
public void setSelect(StateBean selectString){
this.selectString = selectString;
}
}

View File

@ -0,0 +1,272 @@
package com.dahe.mylibrary.adapter;
import android.content.Context;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
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.bumptech.glide.load.resource.bitmap.CenterCrop;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.bumptech.glide.request.RequestOptions;
import com.dahe.mylibrary.R;
import com.dahe.mylibrary.callback.OnItemLongClickListener;
import com.luck.picture.lib.config.PictureMimeType;
import com.luck.picture.lib.entity.LocalMedia;
import com.luck.picture.lib.listener.OnItemClickListener;
import com.luck.picture.lib.tools.DateUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* @authorluck
* @date2016-7-27 23:02
* @describeGridImageAdapter
*/
public class GridImageAdapter extends
RecyclerView.Adapter<GridImageAdapter.ViewHolder> {
public static final String TAG = "PictureSelector";
public static final int TYPE_CAMERA = 1;
public static final int TYPE_PICTURE = 2;
public boolean IS_ONLY_SHOW = false;
private final Context ctx;
private LayoutInflater mInflater;
private List<LocalMedia> list = new ArrayList<>();
private int selectMax = 9;
/**
* 点击添加图片跳转
*/
private onAddPicClickListener mOnAddPicClickListener;
public interface onAddPicClickListener {
void onAddPicClick();
void onDelPicClick(int postion,LocalMedia localMedia);
}
/**
* 删除
*/
public void delete(int position) {
try {
if (position != RecyclerView.NO_POSITION && list.size() > position) {
list.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, list.size());
}
} catch (Exception e) {
e.printStackTrace();
}
}
public GridImageAdapter(Context context, onAddPicClickListener mOnAddPicClickListener) {
this.ctx = context;
this.mInflater = LayoutInflater.from(context);
this.mOnAddPicClickListener = mOnAddPicClickListener;
}
public void setSelectMax(int selectMax) {
this.selectMax = selectMax;
}
public void setList(List<LocalMedia> list) {
this.list = list;
}
public void setListNotif(List<LocalMedia> list) {
if (null!=list&&list.size()>0){
this.list = list;
notifyDataSetChanged();
}
}
public List<LocalMedia> getData() {
return list == null ? new ArrayList<>() : list;
}
public void remove(int position) {
if (list != null && position < list.size()) {
list.remove(position);
}
}
public static class ViewHolder extends RecyclerView.ViewHolder {
ImageView mImg;
ImageView mIvDel;
TextView tvDuration;
public ViewHolder(View view) {
super(view);
mImg = view.findViewById(R.id.fiv);
mIvDel = view.findViewById(R.id.iv_del);
tvDuration = view.findViewById(R.id.tv_duration);
}
}
@Override
public int getItemCount() {
if (list.size() < selectMax&&!IS_ONLY_SHOW) {
return list.size() + 1;
} else {
return list.size();
}
}
@Override
public int getItemViewType(int position) {
if (isShowAddItem(position)) {
return TYPE_CAMERA;
} else {
return TYPE_PICTURE;
}
}
/**
* 创建ViewHolder
*/
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = mInflater.inflate(R.layout.gv_filter_image, viewGroup, false);
return new ViewHolder(view);
}
private boolean isShowAddItem(int position) {
if (IS_ONLY_SHOW){
return false;
}
int size = list.size();
return position == size;
}
public void setIsOnlyShow(boolean b){
this.IS_ONLY_SHOW = b;
}
/**
* 设置值
*/
@Override
public void onBindViewHolder(final ViewHolder viewHolder, final int position) {
//少于8张显示继续添加的图标
if (getItemViewType(position) == TYPE_CAMERA) {
viewHolder.mImg.setImageResource(R.drawable.id_select_z);
// viewHolder.mImg.setImageResource(R.drawable.ic_add_image);
viewHolder.mImg.setOnClickListener(v -> mOnAddPicClickListener.onAddPicClick());
viewHolder.mIvDel.setVisibility(View.INVISIBLE);
} else {
viewHolder.mIvDel.setVisibility(IS_ONLY_SHOW?View.GONE:View.VISIBLE);
viewHolder.mIvDel.setOnClickListener(view -> {
int index = viewHolder.getAbsoluteAdapterPosition();
// 这里有时会返回-1造成数据下标越界,具体可参考getAdapterPosition()源码
// 通过源码分析应该是bindViewHolder()暂未绘制完成导致知道原因的也可联系我~感谢
if (index != RecyclerView.NO_POSITION && list.size() > index) {
mOnAddPicClickListener.onDelPicClick(index, list.get(index));
// list.remove(index);
// notifyItemRemoved(index);
// notifyItemRangeChanged(index, list.size());
}
});
LocalMedia media = list.get(position);
if (media == null
|| TextUtils.isEmpty(media.getPath())) {
return;
}
int chooseModel = media.getChooseModel();
String path;
if (media.isCut() && !media.isCompressed()) {
// 裁剪过
path = media.getCutPath();
} else if (media.isCompressed() || (media.isCut() && media.isCompressed())) {
// 压缩过,或者裁剪同时压缩过,以最终压缩过图片为准
path = media.getCompressPath();
} else {
// 原图
path = media.getPath();
}
Log.i(TAG, "原图地址::" + media.getPath());
if (media.isCut()) {
Log.i(TAG, "裁剪地址::" + media.getCutPath());
}
if (media.isCompressed()) {
Log.i(TAG, "压缩地址::" + media.getCompressPath());
Log.i(TAG, "压缩后文件大小::" + new File(media.getCompressPath()).length() / 1024 + "k");
}
if (!TextUtils.isEmpty(media.getAndroidQToPath())) {
Log.i(TAG, "Android Q特有地址::" + media.getAndroidQToPath());
}
if (media.isOriginal()) {
Log.i(TAG, "是否开启原图功能::" + true);
Log.i(TAG, "开启原图功能后地址::" + media.getOriginalPath());
}
long duration = media.getDuration();
viewHolder.tvDuration.setVisibility(PictureMimeType.isHasVideo(media.getMimeType())
? View.VISIBLE : View.GONE);
if (chooseModel == PictureMimeType.ofAudio()) {
viewHolder.tvDuration.setVisibility(View.VISIBLE);
viewHolder.tvDuration.setCompoundDrawablesRelativeWithIntrinsicBounds
(R.drawable.picture_icon_audio, 0, 0, 0);
} else {
viewHolder.tvDuration.setCompoundDrawablesRelativeWithIntrinsicBounds
(R.drawable.picture_icon_video, 0, 0, 0);
}
viewHolder.tvDuration.setText(DateUtils.formatDurationTime(duration));
if (chooseModel == PictureMimeType.ofAudio()) {
viewHolder.mImg.setImageResource(R.drawable.picture_audio_placeholder);
} else {
RequestOptions requestOptions = RequestOptions.fitCenterTransform().transform(new CenterCrop(), new RoundedCorners(5));
Glide.with(ctx)
.load(PictureMimeType.isContent(path) && !media.isCut() && !media.isCompressed() ? Uri.parse(path)
: path)
.centerCrop()
.apply(requestOptions)//圆角半径
.placeholder(R.drawable.id_select_loading)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(viewHolder.mImg);
}
//itemView 的点击事件
if (mItemClickListener != null) {
viewHolder.itemView.setOnClickListener(v -> {
int adapterPosition = viewHolder.getAdapterPosition();
mItemClickListener.onItemClick(v, adapterPosition);
});
}
if (mItemLongClickListener != null) {
viewHolder.itemView.setOnLongClickListener(v -> {
int adapterPosition = viewHolder.getAdapterPosition();
mItemLongClickListener.onItemLongClick(viewHolder, adapterPosition, v);
return true;
});
}
}
}
private OnItemClickListener mItemClickListener;
public void setOnItemClickListener(OnItemClickListener l) {
this.mItemClickListener = l;
}
private OnItemLongClickListener mItemLongClickListener;
public void setItemLongClickListener(OnItemLongClickListener l) {
this.mItemLongClickListener = l;
}
}

View File

@ -0,0 +1,30 @@
package com.dahe.mylibrary.adapter;
import android.widget.CheckBox;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.viewholder.BaseViewHolder;
import com.dahe.mylibrary.R;
import com.dahe.mylibrary.bean.NodeBean;
import com.dahe.mylibrary.utils.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class NodeAdapter extends BaseQuickAdapter<NodeBean, BaseViewHolder> {
public NodeAdapter(int layoutResId, @Nullable List<NodeBean> data) {
super(R.layout.item_node_select, data);
}
@Override
protected void convert(@NotNull BaseViewHolder helper, NodeBean item) {
helper.setText(R.id.tv_title, item.getNode())
.setText(R.id.tv_lxr, StringUtils.isEmpty(item.getDocking())?"":item.getDocking() + " " + (StringUtils.isEmpty(item.getDockingPhone())?"":item.getDockingPhone()))
.setText(R.id.tv_addres, item.getFreighter());
CheckBox cb = helper.getView(R.id.cb);
cb.setChecked("1".equals(item.isSelect())?true:false);
}
}

View File

@ -0,0 +1,38 @@
package com.dahe.mylibrary.adapter;
import androidx.annotation.Nullable;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.viewholder.BaseViewHolder;
import com.dahe.mylibrary.R;
import com.dahe.mylibrary.bean.DictBean;
import com.dahe.mylibrary.bean.StateBean;
import java.util.List;
public class SelectDicAdapter extends BaseQuickAdapter<StateBean, BaseViewHolder> {
private int selectPos = -1;
public SelectDicAdapter(int layoutResId, @Nullable List<StateBean> data, int selectPos) {
super(R.layout.item_dic_select, data);
this.selectPos = selectPos;
}
@Override
protected void convert(BaseViewHolder helper, StateBean item) {
helper.setText(R.id.tv_content,item.getDictLabel());
// TextView tv = helper.getView(R.id.tv_content);
// if (item.equals(selectString)){
// tv.setSelected(true);
// }else{
// tv.setSelected(false);
// }
}
public void setSelect(int selectString){
this.selectPos = selectString;
}
}

View File

@ -0,0 +1,250 @@
package com.dahe.mylibrary.base;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
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 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.smartrefresh.layout.SmartRefreshLayout;
import com.scwang.smartrefresh.layout.api.RefreshLayout;
import com.scwang.smartrefresh.layout.constant.RefreshState;
import com.scwang.smartrefresh.layout.listener.OnRefreshLoadMoreListener;
import qiu.niorgai.StatusBarCompat;
public abstract class BaseActivity 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;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayout());
mContext = this;
setStatusBarColor(R.color.colorPrimaryDark);
initView(savedInstanceState);
initDate();
}
/**
* 标题栏的颜色 文字白色
*/
public void setStatusBarCancelLightColor() {
StatusBar.cancelLightStatusBar(this);
}
/**
* 设置沉浸式标题栏 标题栏的颜色
*/
public void setStatusBarColor(int 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);
}
/**
* 设置透明沉浸式标题栏
*/
public void setStatusBarColorToLight() {
StatusBar.translucentStatusBar(this, false);
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);
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);
}
/**
* 显示右边标题
*
* @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);
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);
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 int getLayout();
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();
}
/**
* 设置刷新控件
*
* @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();
}
}

View File

@ -0,0 +1,321 @@
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.ImageButton;
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 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.smartrefresh.layout.SmartRefreshLayout;
import com.scwang.smartrefresh.layout.api.RefreshLayout;
import com.scwang.smartrefresh.layout.constant.RefreshState;
import com.scwang.smartrefresh.layout.listener.OnRefreshLoadMoreListener;
import qiu.niorgai.StatusBarCompat;
/**
* <p>
* Fragment基类封装了懒加载的实现
* <p>
* 1Viewpager + Fragment情况下fragment的生命周期因Viewpager的缓存机制而失去了具体意义
* 该抽象类自定义一个新的回调方法当fragment可见状态改变时会触发的回调方法
*
* @see #onFragmentVisibleChange(boolean)
* @see #onFragmentFirstVisible()
*/
public abstract class BaseFragment 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;
@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) {
if (getContentViewLayoutID() != 0) {
mContext = getActivity();
return inflater.inflate(getContentViewLayoutID(), container, false);
} else {
return super.onCreateView(inflater, container, savedInstanceState);
}
}
protected abstract int getContentViewLayoutID();
/**
* 标题栏的颜色 文字白色
*/
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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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 {
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -0,0 +1,102 @@
package com.dahe.mylibrary.cuspop;
import android.content.Context;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.listener.OnItemClickListener;
import com.dahe.mylibrary.R;
import com.dahe.mylibrary.adapter.CarAdapter;
import com.dahe.mylibrary.bean.CarBean;
import com.dahe.mylibrary.net.JsonUtils;
import com.lxj.xpopup.core.CenterPopupView;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
public class CarSelPopupView extends CenterPopupView {
private Context context;
private List<CarBean> data;
public CarSelPopupView(Context context, String data) {
super(context);
this.context = context;
ArrayList<CarBean> nodeBeans = JsonUtils.getInstance().jsonToList(data, CarBean.class);
this.data = nodeBeans;
}
@Override
protected int getImplLayoutId() {
return R.layout.view_node;
}
@Override
protected void onCreate() {
super.onCreate();
TextView tvTitle = (TextView) findViewById(R.id.tvTitle);
ImageView ivCha = (ImageView) findViewById(R.id.ivCha);
LinearLayout llCha = (LinearLayout) findViewById(R.id.llCha);
Button btnOK = (Button) findViewById(R.id.btnOK);
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(context,RecyclerView.VERTICAL,false));
recyclerView.setHasFixedSize(true);
CarAdapter nodeAdapter = new CarAdapter(-1,data);
recyclerView.setAdapter(nodeAdapter);
tvTitle.setText("关联司机");
nodeAdapter.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(@NonNull @NotNull BaseQuickAdapter<?, ?> adapter, @NonNull @NotNull View view, int position) {
CarBean nodeSelectBean = data.get(position);
nodeSelectBean.setSelect(!nodeSelectBean.isSelect());
nodeAdapter.notifyItemChanged(position);
}
});
btnOK.setOnClickListener(v -> {
if (listener!=null){
// ArrayList<CarBean> temp = new ArrayList<>();
// for (int i = 0; i < data.size(); i++) {
// CarBean nodeSelectBean = data.get(i);
// if ("1".equals(nodeSelectBean.isSelect())){
// temp.add(nodeSelectBean);
// }
//
// }
// if (temp.size()<=0){
// ToastUtils.showToast(context,"至少存在一个节点");
// return;
// }
listener.okClick(JsonUtils.getInstance().toJson(nodeAdapter.getData()));
// temp = null;
dismiss();
}
});
llCha.setOnClickListener(v -> {
dismiss();
});
}
private OnOkListener listener;
public CarSelPopupView setOnOkListener(OnOkListener listener) {
this.listener = listener;
return this;
}
public interface OnOkListener {
void okClick(String data);
}
}

View File

@ -0,0 +1,90 @@
package com.dahe.mylibrary.cuspop;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.listener.OnItemClickListener;
import com.dahe.mylibrary.R;
import com.dahe.mylibrary.adapter.CenterSimAdapter;
import com.dahe.mylibrary.bean.StateBean;
import com.luck.picture.lib.decoration.GridSpacingItemDecoration;
import com.lxj.xpopup.impl.PartShadowPopupView;
import java.util.List;
/**
* Description: 自定义局部阴影弹窗
* Create by dance, at 2018/12/21
*/
public class CenterPopupView extends PartShadowPopupView {
private Context ctx;
private RecyclerView recyclerView;
private List<StateBean> wordList;
private CenterSimAdapter adapter;
private StateBean selectString;
public CenterPopupView(@NonNull Activity context, List<StateBean> wordList, StateBean selectString) {
super(context);
this.wordList= wordList;
this.selectString = selectString;
}
@Override
protected int getImplLayoutId() {
return R.layout.custom_part_shadow_popup;
}
@Override
protected void onCreate() {
super.onCreate();
recyclerView = findViewById(R.id.recyclerView);
GridLayoutManager gridLayoutManager = new GridLayoutManager(ctx, 4);
recyclerView.addItemDecoration(new GridSpacingItemDecoration(4, 20, false));
recyclerView.setLayoutManager(gridLayoutManager);
adapter = new CenterSimAdapter(-1, wordList,selectString);
recyclerView.setAdapter(adapter);
adapter.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(@NonNull BaseQuickAdapter adapter, @NonNull View view, int position) {
if (listener!=null){
listener.selectChange(wordList.get(position),position);
}
((CenterSimAdapter)adapter).setSelect(wordList.get(position));
adapter.notifyDataSetChanged();
dismiss();
}
});
}
@Override
protected void onShow() {
super.onShow();
Log.e("tag", "CustomPartShadowPopupView onShow");
}
@Override
protected void onDismiss() {
super.onDismiss();
Log.e("tag", "CustomPartShadowPopupView onDismiss");
}
private OnSelectChangeListener listener;
public CenterPopupView setOnSelectChangeListener(OnSelectChangeListener listener){
this.listener = listener;
return this;
}
public interface OnSelectChangeListener{
void selectChange(StateBean item ,int postion);
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -0,0 +1,35 @@
package com.dahe.mylibrary.glide;
import android.content.Context;
import androidx.annotation.NonNull;
import com.bumptech.glide.Glide;
import com.bumptech.glide.Registry;
import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader;
import com.bumptech.glide.load.model.GlideUrl;
import org.jetbrains.annotations.NotNull;
import java.io.InputStream;
import okhttp3.OkHttpClient;
/**
* @ClassName AppGlideModule
* @Author 用户
* @Date 2021/10/11 10:13
* @Description TODO
*/
@GlideModule
public class AppGlideModule extends com.bumptech.glide.module.AppGlideModule {
@Override
public void registerComponents(@NonNull @NotNull Context context, @NonNull @NotNull Glide glide, @NonNull @NotNull Registry registry) {
super.registerComponents(context, glide, registry);
OkHttpClient client = UnsafeOkHttpClient.getUnsafeOkHttpClient();
registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(client));
}
}

View File

@ -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);
}
}
}

View File

@ -0,0 +1,73 @@
package com.dahe.mylibrary.net;
import java.io.Serializable;
/**
* 返回通用的实体类
*/
public class CommonResponseBean<T> implements Serializable {
private T data;
private int code;
private String info;
private String msg;
private String url;
private String fileName;
private boolean success;
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 getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
// }
}
}

View File

@ -0,0 +1,62 @@
package com.dahe.mylibrary.net;
import android.text.TextUtils;
import android.util.Log;
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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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) {
}
}

View File

@ -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
}
}
}
}

View File

@ -0,0 +1,110 @@
package com.dahe.mylibrary.recycleviewswipe;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.view.View;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.dahe.mylibrary.R;
public class MyDecoration extends RecyclerView.ItemDecoration{
public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
private Drawable mDivider;
private int mOrientation;
/**
* 分割线缩进值
*/
private int inset;
private Paint paint;
/**
* @param context
* @param orientation layout的方向
* @param drawable 引入的drawable的ID
* @param inset 分割线缩进值
*/
public MyDecoration(Context context, int orientation, int drawable, int inset) {
mDivider = context.getResources().getDrawable(drawable);
this.inset = inset;
paint = new Paint();
paint.setColor(context.getResources().getColor(R.color.white));
paint.setStyle(Paint.Style.FILL);
paint.setAntiAlias(true);
setOrientation(orientation);
}
public void setOrientation(int orientation) {
if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
throw new IllegalArgumentException("invalid orientation");
}
mOrientation = orientation;
}
@Override
public void onDraw(Canvas c, RecyclerView parent) {
if (mOrientation == VERTICAL_LIST) {
drawVertical(c, parent);
} else {
drawHorizontal(c, parent);
}
}
private void drawVertical(Canvas c, RecyclerView parent) {
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
final int childCount = parent.getChildCount();
//最后一个item不画分割线
for (int i = 0; i < childCount - 1; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
final int top = child.getBottom() + params.bottomMargin;
final int bottom = top + mDivider.getIntrinsicHeight();
if (inset > 0) {
c.drawRect(left, top, right, bottom, paint);
mDivider.setBounds(left + inset, top, right - inset, bottom);
} else {
mDivider.setBounds(left, top, right, bottom);
}
mDivider.draw(c);
}
}
private void drawHorizontal(Canvas c, RecyclerView parent) {
final int top = parent.getPaddingTop();
final int bottom = parent.getHeight() - parent.getPaddingBottom();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount - 1; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
final int left = child.getRight() + params.rightMargin;
final int right = left + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
//由于Divider也有宽高每一个Item需要向下或者向右偏移
@Override
public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
if (mOrientation == VERTICAL_LIST) {
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
} else {
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
}
}
}

View File

@ -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);
}
}
}
}
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -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 asdf(String imageBase64){
byte[] decodedString = Base64.decode(imageBase64, Base64.DEFAULT);
return BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
}
}

View File

@ -0,0 +1,193 @@
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 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);
}
}

View File

@ -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]"代表第二位可以为358中的一个"\\d{9}"代表后面是可以是09的数字有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); //强制隐藏键盘
}
}

View File

@ -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进制就是360x43是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;
}
}

View File

@ -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;
}
}

View File

@ -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); //还原背景色
}
}

View File

@ -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;
// }
// });
// }
}

View File

@ -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;
}
});
}
}

View File

@ -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);
}
}
}

View File

@ -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 "";
}
}

View File

@ -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 {
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -0,0 +1,366 @@
package com.dahe.mylibrary.utils;
import android.app.Activity;
import android.graphics.Color;
import android.view.View;
import android.widget.ImageView;
import androidx.core.content.ContextCompat;
import com.dahe.mylibrary.R;
import com.dahe.mylibrary.adapter.GridImageAdapter;
import com.dahe.mylibrary.dialog.DialogPhotoSelect;
import com.dahe.mylibrary.net.CommonResponseBean;
import com.dahe.mylibrary.weight.GlideEngine;
import com.luck.picture.lib.PictureSelector;
import com.luck.picture.lib.config.PictureConfig;
import com.luck.picture.lib.config.PictureMimeType;
import com.luck.picture.lib.entity.LocalMedia;
import com.luck.picture.lib.listener.OnResultCallbackListener;
import com.luck.picture.lib.style.PictureCropParameterStyle;
import com.luck.picture.lib.style.PictureParameterStyle;
import com.luck.picture.lib.style.PictureSelectorUIStyle;
import com.luck.picture.lib.tools.SdkVersionUtils;
import java.lang.ref.WeakReference;
import java.util.List;
public class SelectPhotoUtils4 implements View.OnClickListener {
private Activity ctx;
private OnResultCallbackListener listener;
private GridImageAdapter mAdapter;
public void selectSimple(Activity ctx,ImageView imageView, OnResultCallbackListener callbackListener){
this.ctx = ctx;
this.listener = callbackListener;
imageView.setOnClickListener(this);
imageView.performClick();
}
private final GridImageAdapter.onAddPicClickListener onAddPicClickListener = new GridImageAdapter.onAddPicClickListener() {
@Override
public void onAddPicClick() {
PictureSelector.create(ctx)
.openGallery(PictureMimeType.ofImage())
.imageEngine(GlideEngine.createGlideEngine())
.selectionMode(PictureConfig.MULTIPLE)// 多选 or 单选 PictureConfig.MULTIPLE or PictureConfig.SINGLE
.maxSelectNum(6)
.isPreviewImage(true)// 是否可预览图片 true or fals
.isGif(false)// 是否显示gif图片 true or false
.isCamera(true)// 是否显示拍照按钮 true or false
.isEnableCrop(true)// 是否裁剪 true or false
.selectionData(mAdapter.getData())// 是否传入已选图片
.circleDimmedLayer(false)// 是否圆形裁剪 true or false
.freeStyleCropEnabled(true)// 裁剪框是否可拖拽 true or false
.minimumCompressSize(30)// 小于100kb的图片不压缩
.showCropFrame(true)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false true or false
.showCropGrid(true)// 是否显示裁剪矩形网格 圆形裁剪时建议设为false true or false
// .rotateEnabled(true) // 裁剪是否可旋转图片 true or false
.scaleEnabled(true)// 裁剪是否可放大缩小图片 true or false
.forResult(new MyResultCallback(mAdapter));
}
@Override
public void onDelPicClick(int postion, LocalMedia localMedia) {
// DataManager.getInstance().remove(localMedia.getId()+"")
// .compose(DataManager.setThread())
// .subscribe(new BaseObserver(ctx, new RxHttpCallBack(ctx) {
// @Override
// public void onSuccess(CommonResponseBean t) {
// super.onSuccess(t);
//// list.remove(index);
// mAdapter.getData().remove(postion);
// mAdapter.notifyItemRemoved(postion);
// mAdapter.notifyItemRangeChanged(postion, mAdapter.getData().size());
// }
// }));
}
};
/**
* 返回结果回调
*/
private class MyResultCallback implements OnResultCallbackListener<LocalMedia> {
private WeakReference<GridImageAdapter> mAdapterWeakReference;
public MyResultCallback(GridImageAdapter adapter) {
super();
this.mAdapterWeakReference = new WeakReference<>(adapter);
}
@Override
public void onResult(List<LocalMedia> result) {
// for (LocalMedia media : result) {
// Log.i(TAG, "是否压缩:" + media.isCompressed());
// Log.i(TAG, "压缩:" + media.getCompressPath());
// Log.i(TAG, "原图:" + media.getPath());
// Log.i(TAG, "绝对路径:" + media.getRealPath());
// Log.i(TAG, "是否裁剪:" + media.isCut());
// Log.i(TAG, "裁剪:" + media.getCutPath());
// Log.i(TAG, "是否开启原图:" + media.isOriginal());
// Log.i(TAG, "原图路径:" + media.getOriginalPath());
// Log.i(TAG, "Android Q 特有Path:" + media.getAndroidQToPath());
// Log.i(TAG, "宽高: " + media.getWidth() + "x" + media.getHeight());
// Log.i(TAG, "Size: " + media.getSize());
//
// Log.i("MMM", "onResult: " + media.toString());
// // TODO 可以通过PictureSelectorExternalUtils.getExifInterface();方法获取一些额外的资源信息如旋转角度经纬度等信息
// }
listener.onResult(result);
if (mAdapterWeakReference.get() != null) {
mAdapterWeakReference.get().setList(result);
mAdapterWeakReference.get().notifyDataSetChanged();
}
}
@Override
public void onCancel() {
// Log.i(TAG, "PictureSelector Cancel");
}
}
private PictureCropParameterStyle mCropParameterStyle;
private PictureParameterStyle getDefaultStyle() {
// 相册主题
PictureParameterStyle mPictureParameterStyle = new PictureParameterStyle();
// 是否改变状态栏字体颜色(黑白切换)
mPictureParameterStyle.isChangeStatusBarFontColor = false;
// 是否开启右下角已完成(0/9)风格
mPictureParameterStyle.isOpenCompletedNumStyle = false;
// 是否开启类似QQ相册带数字选择风格
mPictureParameterStyle.isOpenCheckNumStyle = false;
// 相册状态栏背景色
mPictureParameterStyle.pictureStatusBarColor = Color.parseColor("#393a3e");
// 相册列表标题栏背景色
mPictureParameterStyle.pictureTitleBarBackgroundColor = Color.parseColor("#393a3e");
// 相册父容器背景色
mPictureParameterStyle.pictureContainerBackgroundColor = ContextCompat.getColor(ctx, R.color.black);
// 相册列表标题栏右侧上拉箭头
mPictureParameterStyle.pictureTitleUpResId = R.drawable.picture_icon_arrow_up;
// 相册列表标题栏右侧下拉箭头
mPictureParameterStyle.pictureTitleDownResId = R.drawable.picture_icon_arrow_down;
// 相册文件夹列表选中圆点
mPictureParameterStyle.pictureFolderCheckedDotStyle = R.drawable.picture_orange_oval;
// 相册返回箭头
mPictureParameterStyle.pictureLeftBackIcon = R.drawable.picture_icon_back;
// 标题栏字体颜色
mPictureParameterStyle.pictureTitleTextColor = ContextCompat.getColor(ctx, R.color.picture_color_white);
// 相册右侧取消按钮字体颜色 废弃 改用.pictureRightDefaultTextColor和.pictureRightDefaultTextColor
mPictureParameterStyle.pictureCancelTextColor = ContextCompat.getColor(ctx, R.color.picture_color_white);
// 选择相册目录背景样式
// mPictureParameterStyle.pictureAlbumStyle = R.drawable.picture_new_item_select_bg;
// 相册列表勾选图片样式
mPictureParameterStyle.pictureCheckedStyle = R.drawable.picture_checkbox_selector;
// 相册列表底部背景色
mPictureParameterStyle.pictureBottomBgColor = ContextCompat.getColor(ctx, R.color.picture_color_grey);
// 已选数量圆点背景样式
mPictureParameterStyle.pictureCheckNumBgStyle = R.drawable.picture_num_oval;
// 相册列表底下预览文字色值(预览按钮可点击时的色值)
mPictureParameterStyle.picturePreviewTextColor = ContextCompat.getColor(ctx, R.color.picture_color_fa632d);
// 相册列表底下不可预览文字色值(预览按钮不可点击时的色值)
mPictureParameterStyle.pictureUnPreviewTextColor = ContextCompat.getColor(ctx, R.color.picture_color_white);
// 相册列表已完成色值(已完成 可点击色值)
mPictureParameterStyle.pictureCompleteTextColor = ContextCompat.getColor(ctx, R.color.picture_color_fa632d);
// 相册列表未完成色值(请选择 不可点击色值)
mPictureParameterStyle.pictureUnCompleteTextColor = ContextCompat.getColor(ctx, R.color.picture_color_white);
// 预览界面底部背景色
mPictureParameterStyle.picturePreviewBottomBgColor = ContextCompat.getColor(ctx, R.color.picture_color_grey);
// 外部预览界面删除按钮样式
mPictureParameterStyle.pictureExternalPreviewDeleteStyle = R.drawable.picture_icon_delete;
// 原图按钮勾选样式 需设置.isOriginalImageControl(true); 才有效
mPictureParameterStyle.pictureOriginalControlStyle = R.drawable.picture_original_wechat_checkbox;
// 原图文字颜色 需设置.isOriginalImageControl(true); 才有效
mPictureParameterStyle.pictureOriginalFontColor = ContextCompat.getColor(ctx, R.color.white);
// 外部预览界面是否显示删除按钮
mPictureParameterStyle.pictureExternalPreviewGonePreviewDelete = true;
// 设置NavBar Color SDK Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP有效
mPictureParameterStyle.pictureNavBarColor = Color.parseColor("#393a3e");
// 文件夹字体颜色
mPictureParameterStyle.folderTextColor = Color.parseColor("#4d4d4d");
// 文件夹字体大小
mPictureParameterStyle.folderTextSize = 16;
// // 自定义相册右侧文本内容设置
// mPictureParameterStyle.pictureRightDefaultText = "";
// // 自定义相册未完成文本内容
// mPictureParameterStyle.pictureUnCompleteText = "";
// // 自定义相册完成文本内容
// mPictureParameterStyle.pictureCompleteText = "";
// // 自定义相册列表不可预览文字
// mPictureParameterStyle.pictureUnPreviewText = "";
// // 自定义相册列表预览文字
// mPictureParameterStyle.picturePreviewText = "";
//
// // 自定义相册标题字体大小
// mPictureParameterStyle.pictureTitleTextSize = 18;
// // 自定义相册右侧文字大小
// mPictureParameterStyle.pictureRightTextSize = 14;
// // 自定义相册预览文字大小
// mPictureParameterStyle.picturePreviewTextSize = 14;
// // 自定义相册完成文字大小
// mPictureParameterStyle.pictureCompleteTextSize = 14;
// // 自定义原图文字大小
// mPictureParameterStyle.pictureOriginalTextSize = 14;
// 裁剪主题
mCropParameterStyle = new PictureCropParameterStyle(
ContextCompat.getColor(ctx, R.color.picture_color_grey),
ContextCompat.getColor(ctx, R.color.picture_color_grey),
Color.parseColor("#393a3e"),
ContextCompat.getColor(ctx, R.color.white),
mPictureParameterStyle.isChangeStatusBarFontColor);
return mPictureParameterStyle;
}
/**
* 相机拍照
*/
private void doTakePhoto(Activity ctx) {
// 裁剪主题
mCropParameterStyle = new PictureCropParameterStyle(
ContextCompat.getColor(ctx, R.color.picture_color_grey),
ContextCompat.getColor(ctx, R.color.picture_color_grey),
Color.parseColor("#393a3e"),
ContextCompat.getColor(ctx, R.color.white),
false);
PictureSelector.create(ctx)
.openCamera(PictureMimeType.ofImage())
.imageEngine(GlideEngine.createGlideEngine())
.setPictureCropStyle(mCropParameterStyle)// 动态自定义裁剪主题
.minSelectNum(1)
.maxSelectNum(1)
.isSingleDirectReturn(true)// 单选模式下是否直接返回PictureConfig.SINGLE模式下有效
// .setPictureUIStyle(PictureSelectorUIStyle.ofDefaultStyle())
.isEnableCrop(true)// 是否裁剪 true or false
.isCompress(true)// 是否压缩 true or false
.isGif(false)// 是否显示gif图片 true or false
.circleDimmedLayer(false)// 是否圆形裁剪 true or false
.freeStyleCropEnabled(true)// 裁剪框是否可拖拽 true or false
.cutOutQuality(30)// 裁剪压缩质量 默认90 int
.minimumCompressSize(30)// 小于100kb的图片不压缩
.showCropFrame(true)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false true or false
.showCropGrid(true)// 是否显示裁剪矩形网格 圆形裁剪时建议设为false true or false
.rotateEnabled(true) // 裁剪是否可旋转图片 true or false
.scaleEnabled(true)// 裁剪是否可放大缩小图片 true or false
.forResult(listener);
// 单独拍照
// PictureSelector.create(ctx)
// .openCamera(PictureMimeType.ofAll())// 单独拍照也可录像或也可音频 看你传入的类型是图片or视频
// .theme(R.style.picture_default_style)// 主题样式设置 具体参考 values/styles
// .imageEngine(GlideEngine.createGlideEngine())// 外部传入图片加载引擎必传项
// .maxSelectNum(1)// 最大图片选择数量
// .minSelectNum(1)// 最小选择数量
// .closeAndroidQChangeWH(true)//如果图片有旋转角度则对换宽高默认为true
// .closeAndroidQChangeVideoWH(!SdkVersionUtils.checkedAndroid_Q())// 如果视频有旋转角度则对换宽高默认false
// .selectionMode(cb_choose_mode.isChecked() ?
// PictureConfig.MULTIPLE : PictureConfig.SINGLE)// 多选 or 单选
// .loadCacheResourcesCallback(GlideCacheEngine.createCacheEngine())// 获取图片资源缓存主要是解决华为10部分机型在拷贝文件过多时会出现卡的问题这里可以判断只在会出现一直转圈问题机型上使用
// .isPreviewImage(cb_preview_img.isChecked())// 是否可预览图片
// .isPreviewVideo(cb_preview_video.isChecked())// 是否可预览视频
// .isEnablePreviewAudio(cb_preview_audio.isChecked()) // 是否可播放音频
// .isCamera(cb_isCamera.isChecked())// 是否显示拍照按钮
// .isEnableCrop(cb_crop.isChecked())// 是否裁剪
// .isCompress(cb_compress.isChecked())// 是否压缩
// .compressQuality(60)// 图片压缩后输出质量
// .glideOverride(160, 160)// glide 加载宽高越小图片列表越流畅但会影响列表图片浏览的清晰度
// .withAspectRatio(aspect_ratio_x, aspect_ratio_y)// 裁剪比例 如16:9 3:2 3:4 1:1 可自定义
// .hideBottomControls(!cb_hide.isChecked())// 是否显示uCrop工具栏默认不显示
// .isGif(cb_isGif.isChecked())// 是否显示gif图片
// .freeStyleCropEnabled(cb_styleCrop.isChecked())// 裁剪框是否可拖拽
// .circleDimmedLayer(cb_crop_circular.isChecked())// 是否圆形裁剪
// .showCropFrame(cb_showCropFrame.isChecked())// 是否显示裁剪矩形边框 圆形裁剪时建议设为false
// .showCropGrid(cb_showCropGrid.isChecked())// 是否显示裁剪矩形网格 圆形裁剪时建议设为false
// .isOpenClickSound(cb_voice.isChecked())// 是否开启点击声音
// .selectionData(mAdapter.getData())// 是否传入已选图片
// .cutOutQuality(90)// 裁剪输出质量 默认100
// .minimumCompressSize(100)// 小于100kb的图片不压缩
// .forResult(new MyResultCallback(mAdapter));
}
//从本地相册中选择
private void doSelectPhoto(Activity ctx) {
PictureSelector.create(ctx)
.openGallery(PictureMimeType.ofImage())
.imageEngine(GlideEngine.createGlideEngine())
.selectionMode(PictureConfig.SINGLE)// 多选 or 单选 PictureConfig.MULTIPLE or PictureConfig.SINGLE
.isPreviewImage(true)// 是否可预览图片 true or fals
.isGif(false)// 是否显示gif图片 true or false
.isCamera(false)// 是否显示拍照按钮 true or false
.isEnableCrop(true)// 是否裁剪 true or false
.isCompress(true)// 是否压缩 true or false
.circleDimmedLayer(false)// 是否圆形裁剪 true or false
.freeStyleCropEnabled(true)// 裁剪框是否可拖拽 true or false
.cutOutQuality(30)// 裁剪压缩质量 默认90 int
.minimumCompressSize(30)// 小于100kb的图片不压缩
.showCropFrame(true)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false true or false
.showCropGrid(true)// 是否显示裁剪矩形网格 圆形裁剪时建议设为false true or false
.rotateEnabled(true) // 裁剪是否可旋转图片 true or false
.scaleEnabled(true)// 裁剪是否可放大缩小图片 true or false
.forResult(listener);
// .forResult(PictureConfig.CHOOSE_REQUEST);
}
@Override
public void onClick(View view) {
// PictureSelector.create(ctx)
// .openGallery(PictureMimeType.ofImage())
// .imageEngine(GlideEngine.createGlideEngine())
// .selectionMode(PictureConfig.SINGLE)// 多选 or 单选 PictureConfig.MULTIPLE or PictureConfig.SINGLE
// .isSingleDirectReturn(true)
// .maxSelectNum(1)
// .minSelectNum(1)
// .isPreviewImage(true)// 是否可预览图片 true or fals
// .isGif(false)// 是否显示gif图片 true or false
// .isCamera(true)// 是否显示拍照按钮 true or false
// .isEnableCrop(true)// 是否裁剪 true or false
// .isCompress(true)// 是否压缩 true or false
// .circleDimmedLayer(false)// 是否圆形裁剪 true or false
// .freeStyleCropEnabled(true)// 裁剪框是否可拖拽 true or false
// .cutOutQuality(30)// 裁剪压缩质量 默认90 int
// .minimumCompressSize(100)// 小于100kb的图片不压缩
// .showCropFrame(true)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false true or false
// .showCropGrid(true)// 是否显示裁剪矩形网格 圆形裁剪时建议设为false true or false
// .rotateEnabled(true) // 裁剪是否可旋转图片 true or false
// .scaleEnabled(true)// 裁剪是否可放大缩小图片 true or false
// .forResult(listener);
DialogPhotoSelect dialogPhotoSelect = new DialogPhotoSelect(ctx);
dialogPhotoSelect.show();
dialogPhotoSelect.setOnSelectClickListener(new DialogPhotoSelect.onSelectClickListener() {
@Override
public void onTakePhoto() {
doTakePhoto(ctx);
}
@Override
public void onSelectPhoto() {
doSelectPhoto(ctx);
}
});
}
}

View File

@ -0,0 +1,353 @@
package com.dahe.mylibrary.utils;
import android.app.Activity;
import android.graphics.Color;
import android.view.View;
import android.widget.ImageView;
import androidx.core.content.ContextCompat;
import com.dahe.mylibrary.R;
import com.dahe.mylibrary.adapter.GridImageAdapter;
import com.dahe.mylibrary.dialog.DialogPhotoSelect;
import com.dahe.mylibrary.weight.GlideEngine;
import com.luck.picture.lib.PictureSelector;
import com.luck.picture.lib.config.PictureConfig;
import com.luck.picture.lib.config.PictureMimeType;
import com.luck.picture.lib.entity.LocalMedia;
import com.luck.picture.lib.listener.OnResultCallbackListener;
import com.luck.picture.lib.style.PictureCropParameterStyle;
import com.luck.picture.lib.style.PictureParameterStyle;
import java.lang.ref.WeakReference;
import java.util.List;
public class SelectPhotoUtils5 implements View.OnClickListener {
private SelectPhotoUtils5 selectPhotoUtils5;
private Activity ctx;
private OnResultCallbackListener listener;
private GridImageAdapter mAdapter;
public void selectSimple(Activity ctx, ImageView imageView, OnResultCallbackListener callbackListener) {
this.ctx = ctx;
this.listener = callbackListener;
imageView.setOnClickListener(this);
imageView.performClick();
}
private final GridImageAdapter.onAddPicClickListener onAddPicClickListener = new GridImageAdapter.onAddPicClickListener() {
@Override
public void onAddPicClick() {
PictureSelector.create(ctx)
.openGallery(PictureMimeType.ofImage())
.imageEngine(GlideEngine.createGlideEngine())
.selectionMode(PictureConfig.MULTIPLE)// 多选 or 单选 PictureConfig.MULTIPLE or PictureConfig.SINGLE
.maxSelectNum(6)
.isPreviewImage(true)// 是否可预览图片 true or fals
.isGif(false)// 是否显示gif图片 true or false
.isCamera(true)// 是否显示拍照按钮 true or false
.isEnableCrop(false)// 是否裁剪 true or false
.selectionData(mAdapter.getData())// 是否传入已选图片
.circleDimmedLayer(false)// 是否圆形裁剪 true or false
.freeStyleCropEnabled(true)// 裁剪框是否可拖拽 true or false
.minimumCompressSize(30)// 小于100kb的图片不压缩
.showCropFrame(true)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false true or false
.showCropGrid(true)// 是否显示裁剪矩形网格 圆形裁剪时建议设为false true or false
// .rotateEnabled(true) // 裁剪是否可旋转图片 true or false
.scaleEnabled(true)// 裁剪是否可放大缩小图片 true or false
.forResult(new MyResultCallback(mAdapter));
}
@Override
public void onDelPicClick(int postion, LocalMedia localMedia) {
// DataManager.getInstance().remove(localMedia.getId()+"")
// .compose(DataManager.setThread())
// .subscribe(new BaseObserver(ctx, new RxHttpCallBack(ctx) {
// @Override
// public void onSuccess(CommonResponseBean t) {
// super.onSuccess(t);
//// list.remove(index);
// mAdapter.getData().remove(postion);
// mAdapter.notifyItemRemoved(postion);
// mAdapter.notifyItemRangeChanged(postion, mAdapter.getData().size());
// }
// }));
}
};
/**
* 返回结果回调
*/
private class MyResultCallback implements OnResultCallbackListener<LocalMedia> {
private WeakReference<GridImageAdapter> mAdapterWeakReference;
public MyResultCallback(GridImageAdapter adapter) {
super();
this.mAdapterWeakReference = new WeakReference<>(adapter);
}
@Override
public void onResult(List<LocalMedia> result) {
// for (LocalMedia media : result) {
// Log.i(TAG, "是否压缩:" + media.isCompressed());
// Log.i(TAG, "压缩:" + media.getCompressPath());
// Log.i(TAG, "原图:" + media.getPath());
// Log.i(TAG, "绝对路径:" + media.getRealPath());
// Log.i(TAG, "是否裁剪:" + media.isCut());
// Log.i(TAG, "裁剪:" + media.getCutPath());
// Log.i(TAG, "是否开启原图:" + media.isOriginal());
// Log.i(TAG, "原图路径:" + media.getOriginalPath());
// Log.i(TAG, "Android Q 特有Path:" + media.getAndroidQToPath());
// Log.i(TAG, "宽高: " + media.getWidth() + "x" + media.getHeight());
// Log.i(TAG, "Size: " + media.getSize());
//
// Log.i("MMM", "onResult: " + media.toString());
// // TODO 可以通过PictureSelectorExternalUtils.getExifInterface();方法获取一些额外的资源信息如旋转角度经纬度等信息
// }
listener.onResult(result);
if (mAdapterWeakReference.get() != null) {
mAdapterWeakReference.get().setList(result);
mAdapterWeakReference.get().notifyDataSetChanged();
}
}
@Override
public void onCancel() {
// Log.i(TAG, "PictureSelector Cancel");
}
}
private PictureCropParameterStyle mCropParameterStyle;
private PictureParameterStyle getDefaultStyle() {
// 相册主题
PictureParameterStyle mPictureParameterStyle = new PictureParameterStyle();
// 是否改变状态栏字体颜色(黑白切换)
mPictureParameterStyle.isChangeStatusBarFontColor = false;
// 是否开启右下角已完成(0/9)风格
mPictureParameterStyle.isOpenCompletedNumStyle = false;
// 是否开启类似QQ相册带数字选择风格
mPictureParameterStyle.isOpenCheckNumStyle = false;
// 相册状态栏背景色
mPictureParameterStyle.pictureStatusBarColor = Color.parseColor("#393a3e");
// 相册列表标题栏背景色
mPictureParameterStyle.pictureTitleBarBackgroundColor = Color.parseColor("#393a3e");
// 相册父容器背景色
mPictureParameterStyle.pictureContainerBackgroundColor = ContextCompat.getColor(ctx, R.color.black);
// 相册列表标题栏右侧上拉箭头
mPictureParameterStyle.pictureTitleUpResId = R.drawable.picture_icon_arrow_up;
// 相册列表标题栏右侧下拉箭头
mPictureParameterStyle.pictureTitleDownResId = R.drawable.picture_icon_arrow_down;
// 相册文件夹列表选中圆点
mPictureParameterStyle.pictureFolderCheckedDotStyle = R.drawable.picture_orange_oval;
// 相册返回箭头
mPictureParameterStyle.pictureLeftBackIcon = R.drawable.picture_icon_back;
// 标题栏字体颜色
mPictureParameterStyle.pictureTitleTextColor = ContextCompat.getColor(ctx, R.color.picture_color_white);
// 相册右侧取消按钮字体颜色 废弃 改用.pictureRightDefaultTextColor和.pictureRightDefaultTextColor
mPictureParameterStyle.pictureCancelTextColor = ContextCompat.getColor(ctx, R.color.picture_color_white);
// 选择相册目录背景样式
// mPictureParameterStyle.pictureAlbumStyle = R.drawable.picture_new_item_select_bg;
// 相册列表勾选图片样式
mPictureParameterStyle.pictureCheckedStyle = R.drawable.picture_checkbox_selector;
// 相册列表底部背景色
mPictureParameterStyle.pictureBottomBgColor = ContextCompat.getColor(ctx, R.color.picture_color_grey);
// 已选数量圆点背景样式
mPictureParameterStyle.pictureCheckNumBgStyle = R.drawable.picture_num_oval;
// 相册列表底下预览文字色值(预览按钮可点击时的色值)
mPictureParameterStyle.picturePreviewTextColor = ContextCompat.getColor(ctx, R.color.picture_color_fa632d);
// 相册列表底下不可预览文字色值(预览按钮不可点击时的色值)
mPictureParameterStyle.pictureUnPreviewTextColor = ContextCompat.getColor(ctx, R.color.picture_color_white);
// 相册列表已完成色值(已完成 可点击色值)
mPictureParameterStyle.pictureCompleteTextColor = ContextCompat.getColor(ctx, R.color.picture_color_fa632d);
// 相册列表未完成色值(请选择 不可点击色值)
mPictureParameterStyle.pictureUnCompleteTextColor = ContextCompat.getColor(ctx, R.color.picture_color_white);
// 预览界面底部背景色
mPictureParameterStyle.picturePreviewBottomBgColor = ContextCompat.getColor(ctx, R.color.picture_color_grey);
// 外部预览界面删除按钮样式
mPictureParameterStyle.pictureExternalPreviewDeleteStyle = R.drawable.picture_icon_delete;
// 原图按钮勾选样式 需设置.isOriginalImageControl(true); 才有效
mPictureParameterStyle.pictureOriginalControlStyle = R.drawable.picture_original_wechat_checkbox;
// 原图文字颜色 需设置.isOriginalImageControl(true); 才有效
mPictureParameterStyle.pictureOriginalFontColor = ContextCompat.getColor(ctx, R.color.white);
// 外部预览界面是否显示删除按钮
mPictureParameterStyle.pictureExternalPreviewGonePreviewDelete = true;
// 设置NavBar Color SDK Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP有效
mPictureParameterStyle.pictureNavBarColor = Color.parseColor("#393a3e");
// 文件夹字体颜色
mPictureParameterStyle.folderTextColor = Color.parseColor("#4d4d4d");
// 文件夹字体大小
mPictureParameterStyle.folderTextSize = 16;
// // 自定义相册右侧文本内容设置
// mPictureParameterStyle.pictureRightDefaultText = "";
// // 自定义相册未完成文本内容
// mPictureParameterStyle.pictureUnCompleteText = "";
// // 自定义相册完成文本内容
// mPictureParameterStyle.pictureCompleteText = "";
// // 自定义相册列表不可预览文字
// mPictureParameterStyle.pictureUnPreviewText = "";
// // 自定义相册列表预览文字
// mPictureParameterStyle.picturePreviewText = "";
//
// // 自定义相册标题字体大小
// mPictureParameterStyle.pictureTitleTextSize = 18;
// // 自定义相册右侧文字大小
// mPictureParameterStyle.pictureRightTextSize = 14;
// // 自定义相册预览文字大小
// mPictureParameterStyle.picturePreviewTextSize = 14;
// // 自定义相册完成文字大小
// mPictureParameterStyle.pictureCompleteTextSize = 14;
// // 自定义原图文字大小
// mPictureParameterStyle.pictureOriginalTextSize = 14;
// 裁剪主题
mCropParameterStyle = new PictureCropParameterStyle(
ContextCompat.getColor(ctx, R.color.picture_color_grey),
ContextCompat.getColor(ctx, R.color.picture_color_grey),
Color.parseColor("#393a3e"),
ContextCompat.getColor(ctx, R.color.white),
mPictureParameterStyle.isChangeStatusBarFontColor);
return mPictureParameterStyle;
}
/**
* 相机拍照
*/
private void doTakePhoto(Activity ctx) {
// 裁剪主题
mCropParameterStyle = new PictureCropParameterStyle(
ContextCompat.getColor(ctx, R.color.picture_color_grey),
ContextCompat.getColor(ctx, R.color.picture_color_grey),
Color.parseColor("#393a3e"),
ContextCompat.getColor(ctx, R.color.white),
false);
PictureSelector.create(ctx)
.openCamera(PictureMimeType.ofImage())
.imageEngine(GlideEngine.createGlideEngine())
.setPictureCropStyle(mCropParameterStyle)// 动态自定义裁剪主题
.minSelectNum(1)
.maxSelectNum(1)
.isSingleDirectReturn(true)// 单选模式下是否直接返回PictureConfig.SINGLE模式下有效
// .setPictureUIStyle(PictureSelectorUIStyle.ofDefaultStyle())
.isEnableCrop(false)// 是否裁剪 true or false
.isCompress(true)// 是否压缩 true or false
.isGif(false)// 是否显示gif图片 true or false
.circleDimmedLayer(false)// 是否圆形裁剪 true or false
.freeStyleCropEnabled(true)// 裁剪框是否可拖拽 true or false
.cutOutQuality(30)// 裁剪压缩质量 默认90 int
.minimumCompressSize(30)// 小于100kb的图片不压缩
.showCropFrame(true)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false true or false
.showCropGrid(true)// 是否显示裁剪矩形网格 圆形裁剪时建议设为false true or false
.rotateEnabled(true) // 裁剪是否可旋转图片 true or false
.scaleEnabled(true)// 裁剪是否可放大缩小图片 true or false
.forResult(listener);
// 单独拍照
// PictureSelector.create(ctx)
// .openCamera(PictureMimeType.ofAll())// 单独拍照也可录像或也可音频 看你传入的类型是图片or视频
// .theme(R.style.picture_default_style)// 主题样式设置 具体参考 values/styles
// .imageEngine(GlideEngine.createGlideEngine())// 外部传入图片加载引擎必传项
// .maxSelectNum(1)// 最大图片选择数量
// .minSelectNum(1)// 最小选择数量
// .closeAndroidQChangeWH(true)//如果图片有旋转角度则对换宽高默认为true
// .closeAndroidQChangeVideoWH(!SdkVersionUtils.checkedAndroid_Q())// 如果视频有旋转角度则对换宽高默认false
// .selectionMode(cb_choose_mode.isChecked() ?
// PictureConfig.MULTIPLE : PictureConfig.SINGLE)// 多选 or 单选
// .loadCacheResourcesCallback(GlideCacheEngine.createCacheEngine())// 获取图片资源缓存主要是解决华为10部分机型在拷贝文件过多时会出现卡的问题这里可以判断只在会出现一直转圈问题机型上使用
// .isPreviewImage(cb_preview_img.isChecked())// 是否可预览图片
// .isPreviewVideo(cb_preview_video.isChecked())// 是否可预览视频
// .isEnablePreviewAudio(cb_preview_audio.isChecked()) // 是否可播放音频
// .isCamera(cb_isCamera.isChecked())// 是否显示拍照按钮
// .isEnableCrop(cb_crop.isChecked())// 是否裁剪
// .isCompress(cb_compress.isChecked())// 是否压缩
// .compressQuality(60)// 图片压缩后输出质量
// .glideOverride(160, 160)// glide 加载宽高越小图片列表越流畅但会影响列表图片浏览的清晰度
// .withAspectRatio(aspect_ratio_x, aspect_ratio_y)// 裁剪比例 如16:9 3:2 3:4 1:1 可自定义
// .hideBottomControls(!cb_hide.isChecked())// 是否显示uCrop工具栏默认不显示
// .isGif(cb_isGif.isChecked())// 是否显示gif图片
// .freeStyleCropEnabled(cb_styleCrop.isChecked())// 裁剪框是否可拖拽
// .circleDimmedLayer(cb_crop_circular.isChecked())// 是否圆形裁剪
// .showCropFrame(cb_showCropFrame.isChecked())// 是否显示裁剪矩形边框 圆形裁剪时建议设为false
// .showCropGrid(cb_showCropGrid.isChecked())// 是否显示裁剪矩形网格 圆形裁剪时建议设为false
// .isOpenClickSound(cb_voice.isChecked())// 是否开启点击声音
// .selectionData(mAdapter.getData())// 是否传入已选图片
// .cutOutQuality(90)// 裁剪输出质量 默认100
// .minimumCompressSize(100)// 小于100kb的图片不压缩
// .forResult(new MyResultCallback(mAdapter));
}
//从本地相册中选择
private void doSelectPhoto(Activity ctx) {
PictureSelector.create(ctx)
.openGallery(PictureMimeType.ofImage())
.imageEngine(GlideEngine.createGlideEngine())
.selectionMode(PictureConfig.SINGLE)// 多选 or 单选 PictureConfig.MULTIPLE or PictureConfig.SINGLE
.isPreviewImage(true)// 是否可预览图片 true or fals
.isGif(false)// 是否显示gif图片 true or false
.isCamera(false)// 是否显示拍照按钮 true or false
.isEnableCrop(false)// 是否裁剪 true or false
.isCompress(true)// 是否压缩 true or false
.circleDimmedLayer(false)// 是否圆形裁剪 true or false
.freeStyleCropEnabled(true)// 裁剪框是否可拖拽 true or false
.cutOutQuality(30)// 裁剪压缩质量 默认90 int
.minimumCompressSize(30)// 小于100kb的图片不压缩
.showCropFrame(true)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false true or false
.showCropGrid(true)// 是否显示裁剪矩形网格 圆形裁剪时建议设为false true or false
.rotateEnabled(true) // 裁剪是否可旋转图片 true or false
.scaleEnabled(true)// 裁剪是否可放大缩小图片 true or false
.forResult(listener);
// .forResult(PictureConfig.CHOOSE_REQUEST);
}
@Override
public void onClick(View view) {
// PictureSelector.create(ctx)
// .openGallery(PictureMimeType.ofImage())
// .imageEngine(GlideEngine.createGlideEngine())
// .selectionMode(PictureConfig.SINGLE)// 多选 or 单选 PictureConfig.MULTIPLE or PictureConfig.SINGLE
// .isSingleDirectReturn(true)
// .maxSelectNum(1)
// .minSelectNum(1)
// .isPreviewImage(true)// 是否可预览图片 true or fals
// .isGif(false)// 是否显示gif图片 true or false
// .isCamera(true)// 是否显示拍照按钮 true or false
// .isEnableCrop(true)// 是否裁剪 true or false
// .isCompress(true)// 是否压缩 true or false
// .circleDimmedLayer(false)// 是否圆形裁剪 true or false
// .freeStyleCropEnabled(true)// 裁剪框是否可拖拽 true or false
// .cutOutQuality(30)// 裁剪压缩质量 默认90 int
// .minimumCompressSize(100)// 小于100kb的图片不压缩
// .showCropFrame(true)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false true or false
// .showCropGrid(true)// 是否显示裁剪矩形网格 圆形裁剪时建议设为false true or false
// .rotateEnabled(true) // 裁剪是否可旋转图片 true or false
// .scaleEnabled(true)// 裁剪是否可放大缩小图片 true or false
// .forResult(listener);
DialogPhotoSelect dialogPhotoSelect = new DialogPhotoSelect(ctx);
dialogPhotoSelect.show();
dialogPhotoSelect.setOnSelectClickListener(new DialogPhotoSelect.onSelectClickListener() {
@Override
public void onTakePhoto() {
doTakePhoto(ctx);
}
@Override
public void onSelectPhoto() {
doSelectPhoto(ctx);
}
});
}
}

View File

@ -0,0 +1,318 @@
package com.dahe.mylibrary.utils;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.text.TextUtils;
import android.view.View;
import android.widget.ImageView;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.dahe.mylibrary.R;
import com.dahe.mylibrary.adapter.GridImageAdapter;
import com.dahe.mylibrary.dialog.DialogPhotoSelect;
import com.dahe.mylibrary.net.CommonResponseBean;
import com.dahe.mylibrary.weight.FullyGridLayoutManager;
import com.dahe.mylibrary.weight.GlideEngine;
import com.luck.picture.lib.PictureSelector;
import com.luck.picture.lib.config.PictureConfig;
import com.luck.picture.lib.config.PictureMimeType;
import com.luck.picture.lib.decoration.GridSpacingItemDecoration;
import com.luck.picture.lib.entity.LocalMedia;
import com.luck.picture.lib.listener.OnResultCallbackListener;
import com.luck.picture.lib.tools.ScreenUtils;
import java.lang.ref.WeakReference;
import java.util.List;
public class SelectPhotoUtils6 implements View.OnClickListener {
private Activity ctx;
private OnResultCallbackListener listener;
private GridImageAdapter mAdapter;
private Build build;
private SelectPhotoUtils6(Build build, Activity ctx) {
this.build = build;
this.ctx = ctx;
this.listener = build.listener;
if (null == listener) {
ToastUtils.showToast(ctx, "请初始化回调listener");
return;
}
if (build.isSingle) {//单选
if (null == build.imageView) {
ToastUtils.showToast(ctx, "请初始化ImageView");
return;
}
selectSimple(build.imageView);
} else {//多选
if (null == build.recyclerView || !(build.recyclerView instanceof RecyclerView)) {
ToastUtils.showToast(ctx, "请初始化RecycleView");
return;
}
selectMul(build.recyclerView);
}
}
public static class Build {
private int maxSelect;
private boolean isSingle;
private boolean isOnlyShow;
private ImageView imageView;
private RecyclerView recyclerView;
private List<LocalMedia> pics;
private OnResultCallbackListener listener;
public Build maxSelect(int max) {
this.maxSelect = max;
return this;
}
public Build isSingle(boolean isSingle) {
this.isSingle = isSingle;
return this;
}
public Build isOnlyShow(boolean isOnlyShow) {
this.isOnlyShow = isOnlyShow;
return this;
}
public Build imageview(ImageView imageView) {
this.imageView = imageView;
return this;
}
public Build recycleview(RecyclerView recyclerView) {
this.recyclerView = recyclerView;
return this;
}
public Build newPics(List<LocalMedia> pics) {
this.pics = pics;
return this;
}
public Build resultListener(OnResultCallbackListener listener) {
this.listener = listener;
return this;
}
public SelectPhotoUtils6 create(Activity ctx) {
return new SelectPhotoUtils6(this, ctx);
}
}
public GridImageAdapter getmAdapter() {
return mAdapter;
}
public void selectSimple(ImageView imageView) {
imageView.setOnClickListener(this);
}
public void selectMul(RecyclerView recyclerView) {
FullyGridLayoutManager manager = new FullyGridLayoutManager(ctx,
4, GridLayoutManager.VERTICAL, false);
recyclerView.addItemDecoration(new GridSpacingItemDecoration(40,
ScreenUtils.dip2px(ctx, 8), true
));
recyclerView.setLayoutManager(manager);
mAdapter = new GridImageAdapter(ctx, onAddPicClickListener);
mAdapter.setSelectMax(build.maxSelect);
mAdapter.setIsOnlyShow(build.isOnlyShow);
recyclerView.setAdapter(mAdapter);
mAdapter.setOnItemClickListener((v, position) -> {
List<LocalMedia> selectList = mAdapter.getData();
if (selectList.size() > 0) {
LocalMedia media = selectList.get(position);
String mimeType = media.getMimeType();
int mediaType = PictureMimeType.getMimeType(mimeType);
switch (mediaType) {
case PictureConfig.TYPE_VIDEO:
// 预览视频
PictureSelector.create(ctx)
.themeStyle(R.style.picture_default_style)
// .setPictureStyle(mPictureParameterStyle)// 动态自定义相册主题
.externalPictureVideo(TextUtils.isEmpty(media.getAndroidQToPath()) ? media.getPath() : media.getAndroidQToPath());
break;
case PictureConfig.TYPE_AUDIO:
// 预览音频
PictureSelector.create(ctx)
.externalPictureAudio(PictureMimeType.isContent(media.getPath()) ? media.getAndroidQToPath() : media.getPath());
break;
default:
// 预览图片 可自定长按保存路径
// PictureWindowAnimationStyle animationStyle = new PictureWindowAnimationStyle();
// animationStyle.activityPreviewEnterAnimation = R.anim.picture_anim_up_in;
// animationStyle.activityPreviewExitAnimation = R.anim.picture_anim_down_out;
PictureSelector.create(ctx)
.themeStyle(R.style.picture_default_style) // xml设置主题
// .setPictureStyle(mPictureParameterStyle)// 动态自定义相册主题
//.setPictureWindowAnimationStyle(animationStyle)// 自定义页面启动动画
.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)// 设置相册Activity方向不设置默认使用系统
.isNotPreviewDownload(true)// 预览图片长按是否可以下载
//.bindCustomPlayVideoCallback(new MyVideoSelectedPlayCallback(getContext()))// 自定义播放回调控制用户可以使用自己的视频播放界面
.imageEngine(GlideEngine.createGlideEngine())// 外部传入图片加载引擎必传项
.openExternalPreview(position, selectList);
break;
}
}
});
}
private final GridImageAdapter.onAddPicClickListener onAddPicClickListener = new GridImageAdapter.onAddPicClickListener() {
@Override
public void onAddPicClick() {
PictureSelector.create(ctx)
.openGallery(PictureMimeType.ofImage())
.imageEngine(GlideEngine.createGlideEngine())
.selectionMode(build.isSingle ? PictureConfig.SINGLE : PictureConfig.MULTIPLE)// 多选 or 单选 PictureConfig.MULTIPLE or PictureConfig.SINGLE
.maxSelectNum(build.maxSelect)
.isPreviewImage(true)// 是否可预览图片 true or fals
.isGif(false)// 是否显示gif图片 true or false
.isCamera(true)// 是否显示拍照按钮 true or false
.isEnableCrop(false)// 是否裁剪 true or false
.selectionData(mAdapter.getData())// 是否传入已选图片
.isCompress(true)// 是否压缩 true or false
.circleDimmedLayer(false)// 是否圆形裁剪 true or false
.freeStyleCropEnabled(false)// 裁剪框是否可拖拽 true or false
.cutOutQuality(30)// 裁剪压缩质量 默认90 int
.minimumCompressSize(30)// 小于100kb的图片不压缩
.showCropFrame(false)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false true or false
.showCropGrid(false)// 是否显示裁剪矩形网格 圆形裁剪时建议设为false true or false
// .rotateEnabled(true) // 裁剪是否可旋转图片 true or false
.scaleEnabled(false)// 裁剪是否可放大缩小图片 true or false
.forResult(new MyResultCallback(mAdapter));
}
@Override
public void onDelPicClick(int postion, LocalMedia localMedia) {
// DataManager.getInstance().remove(localMedia.getId() + "")
// .compose(DataManager.setThread())
// .subscribe(new BaseObserver(ctx, new RxHttpCallBack(ctx) {
// @Override
// public void onSuccess(CommonResponseBean t) {
// super.onSuccess(t);
//// list.remove(index);
// mAdapter.getData().remove(postion);
// mAdapter.notifyItemRemoved(postion);
// mAdapter.notifyItemRangeChanged(postion, mAdapter.getData().size());
// }
// }));
}
};
/**
* 返回结果回调
*/
private class MyResultCallback implements OnResultCallbackListener<LocalMedia> {
private WeakReference<GridImageAdapter> mAdapterWeakReference;
public MyResultCallback(GridImageAdapter adapter) {
super();
this.mAdapterWeakReference = new WeakReference<>(adapter);
}
@Override
public void onResult(List<LocalMedia> result) {
// for (LocalMedia media : result) {
// Log.i(TAG, "是否压缩:" + media.isCompressed());
// Log.i(TAG, "压缩:" + media.getCompressPath());
// Log.i(TAG, "原图:" + media.getPath());
// Log.i(TAG, "绝对路径:" + media.getRealPath());
// Log.i(TAG, "是否裁剪:" + media.isCut());
// Log.i(TAG, "裁剪:" + media.getCutPath());
// Log.i(TAG, "是否开启原图:" + media.isOriginal());
// Log.i(TAG, "原图路径:" + media.getOriginalPath());
// Log.i(TAG, "Android Q 特有Path:" + media.getAndroidQToPath());
// Log.i(TAG, "宽高: " + media.getWidth() + "x" + media.getHeight());
// Log.i(TAG, "Size: " + media.getSize());
//
// Log.i("MMM", "onResult: " + media.toString());
// // TODO 可以通过PictureSelectorExternalUtils.getExifInterface();方法获取一些额外的资源信息如旋转角度经纬度等信息
// }
listener.onResult(result);
if (mAdapterWeakReference.get() != null) {
mAdapterWeakReference.get().setList(result);
mAdapterWeakReference.get().notifyDataSetChanged();
}
}
@Override
public void onCancel() {
// Log.i(TAG, "PictureSelector Cancel");
}
}
/**
* 相机拍照
*/
private void doTakePhoto(Activity ctx) {
PictureSelector.create(ctx)
.openCamera(PictureMimeType.ofImage())
.imageEngine(GlideEngine.createGlideEngine())
.isEnableCrop(false)// 是否裁剪 true or false
.isCompress(true)// 是否压缩 true or false
.isGif(false)// 是否显示gif图片 true or false
.circleDimmedLayer(false)// 是否圆形裁剪 true or false
.freeStyleCropEnabled(false)// 裁剪框是否可拖拽 true or false
.cutOutQuality(30)// 裁剪压缩质量 默认90 int
.minimumCompressSize(30)// 小于100kb的图片不压缩
.showCropFrame(false)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false true or false
.showCropGrid(false)// 是否显示裁剪矩形网格 圆形裁剪时建议设为false true or false
.rotateEnabled(false) // 裁剪是否可旋转图片 true or false
.scaleEnabled(false)// 裁剪是否可放大缩小图片 true or false
.forResult(listener);
}
//从本地相册中选择
private void doSelectPhoto(Activity ctx) {
PictureSelector.create(ctx)
.openGallery(PictureMimeType.ofImage())
.imageEngine(GlideEngine.createGlideEngine())
.selectionMode(PictureConfig.SINGLE)// 多选 or 单选 PictureConfig.MULTIPLE or PictureConfig.SINGLE
.isPreviewImage(true)// 是否可预览图片 true or fals
.isGif(false)// 是否显示gif图片 true or false
.isCamera(false)// 是否显示拍照按钮 true or false
.isEnableCrop(false)// 是否裁剪 true or false
.isCompress(true)// 是否压缩 true or false
.circleDimmedLayer(false)// 是否圆形裁剪 true or false
.freeStyleCropEnabled(false)// 裁剪框是否可拖拽 true or false
.cutOutQuality(30)// 裁剪压缩质量 默认90 int
.minimumCompressSize(30)// 小于100kb的图片不压缩
.showCropFrame(false)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false true or false
.showCropGrid(false)// 是否显示裁剪矩形网格 圆形裁剪时建议设为false true or false
// .rotateEnabled(true) // 裁剪是否可旋转图片 true or false
.scaleEnabled(false)// 裁剪是否可放大缩小图片 true or false
.forResult(listener);
// .forResult(PictureConfig.CHOOSE_REQUEST);
}
@Override
public void onClick(View view) {
DialogPhotoSelect dialogPhotoSelect = new DialogPhotoSelect(ctx);
dialogPhotoSelect.show();
dialogPhotoSelect.setOnSelectClickListener(new DialogPhotoSelect.onSelectClickListener() {
@Override
public void onTakePhoto() {
doTakePhoto(ctx);
}
@Override
public void onSelectPhoto() {
doSelectPhoto(ctx);
}
});
}
}

View File

@ -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;
}
}
}

View File

@ -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 = 0;
/*发送验证码*/
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);
}
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}
}
});
}
}

View File

@ -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;
}

View File

@ -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");
}
}

View File

@ -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

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -0,0 +1,37 @@
package com.dahe.mylibrary.wapper;
import android.widget.TextView;
import androidx.annotation.Nullable;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.viewholder.BaseViewHolder;
import com.dahe.mylibrary.R;
import java.util.List;
public class SelectSimAdapter extends BaseQuickAdapter<String, BaseViewHolder> {
private String selectString = "";
public SelectSimAdapter(int layoutResId, @Nullable List<String> data, String selectString) {
super(R.layout.item_select, data);
this.selectString = selectString;
}
@Override
protected void convert(BaseViewHolder helper, String item) {
helper.setText(R.id.tv_content,item);
TextView tv = helper.getView(R.id.tv_content);
if (item.equals(selectString)){
tv.setSelected(true);
}else{
tv.setSelected(false);
}
}
public void setSelect(String selectString){
this.selectString = selectString;
}
}

View File

@ -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);
}
}

View File

@ -0,0 +1,104 @@
package com.dahe.mylibrary.weight;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
/**
* authorluck
* projectPictureSelector
* packagecom.luck.picture.ui
* email893855882@qq.com
* data16/12/31
*/
public class FullyGridLayoutManager extends GridLayoutManager {
public FullyGridLayoutManager(Context context, int spanCount) {
super(context, spanCount);
}
public FullyGridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) {
super(context, spanCount, orientation, reverseLayout);
}
private int[] mMeasuredDimension = new int[2];
@Override
public void onMeasure(RecyclerView.Recycler recycler, 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();
}
}
}
}

View File

@ -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) {
}
}

View File

@ -0,0 +1,233 @@
package com.dahe.mylibrary.weight;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PointF;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.graphics.drawable.RoundedBitmapDrawable;
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.BitmapImageViewTarget;
import com.bumptech.glide.request.target.ImageViewTarget;
import com.dahe.mylibrary.R;
import com.luck.picture.lib.engine.ImageEngine;
import com.luck.picture.lib.listener.OnImageCompleteCallback;
import com.luck.picture.lib.tools.MediaUtils;
import com.luck.picture.lib.widget.longimage.ImageSource;
import com.luck.picture.lib.widget.longimage.ImageViewState;
import com.luck.picture.lib.widget.longimage.SubsamplingScaleImageView;
/**
* @authorluck
* @date2019-11-13 17:02
* @describeGlide加载引擎
*/
public class GlideEngine implements ImageEngine {
/**
* 加载图片
*
* @param context
* @param url
* @param imageView
*/
@Override
public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) {
Glide.with(context)
.load(url)
.into(imageView);
}
/**
* 加载网络图片适配长图方案
* # 注意此方法只有加载网络图片才会回调
*
* @param context
* @param url
* @param imageView
* @param longImageView
* @param callback 网络图片加载回调监听 {link after version 2.5.1 Please use the #OnImageCompleteCallback#}
*/
@Override
public void loadImage(@NonNull Context context, @NonNull String url,
@NonNull final ImageView imageView,
final SubsamplingScaleImageView longImageView, final OnImageCompleteCallback callback) {
Glide.with(context)
.asBitmap()
.load(url)
.into(new ImageViewTarget<Bitmap>(imageView) {
@Override
public void onLoadStarted(@Nullable Drawable placeholder) {
super.onLoadStarted(placeholder);
if (callback != null) {
callback.onShowLoading();
}
}
@Override
public void onLoadFailed(@Nullable Drawable errorDrawable) {
super.onLoadFailed(errorDrawable);
if (callback != null) {
callback.onHideLoading();
}
}
@Override
protected void setResource(@Nullable Bitmap resource) {
if (callback != null) {
callback.onHideLoading();
}
if (resource != null) {
boolean eqLongImage = MediaUtils.isLongImg(resource.getWidth(),
resource.getHeight());
longImageView.setVisibility(eqLongImage ? View.VISIBLE : View.GONE);
imageView.setVisibility(eqLongImage ? View.GONE : View.VISIBLE);
if (eqLongImage) {
// 加载长图
longImageView.setQuickScaleEnabled(true);
longImageView.setZoomEnabled(true);
longImageView.setDoubleTapZoomDuration(100);
longImageView.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_CROP);
longImageView.setDoubleTapZoomDpi(SubsamplingScaleImageView.ZOOM_FOCUS_CENTER);
longImageView.setImage(ImageSource.bitmap(resource),
new ImageViewState(0, new PointF(0, 0), 0));
} else {
// 普通图片
imageView.setImageBitmap(resource);
}
}
}
});
}
/**
* 加载网络图片适配长图方案
* # 注意此方法只有加载网络图片才会回调
*
* @param context
* @param url
* @param imageView
* @param longImageView
* @ 已废弃
*/
@Override
public void loadImage(@NonNull Context context, @NonNull String url,
@NonNull final ImageView imageView,
final SubsamplingScaleImageView longImageView) {
Glide.with(context)
.asBitmap()
.load(url)
.into(new ImageViewTarget<Bitmap>(imageView) {
@Override
protected void setResource(@Nullable Bitmap resource) {
if (resource != null) {
boolean eqLongImage = MediaUtils.isLongImg(resource.getWidth(),
resource.getHeight());
longImageView.setVisibility(eqLongImage ? View.VISIBLE : View.GONE);
imageView.setVisibility(eqLongImage ? View.GONE : View.VISIBLE);
if (eqLongImage) {
// 加载长图
longImageView.setQuickScaleEnabled(true);
longImageView.setZoomEnabled(true);
longImageView.setDoubleTapZoomDuration(100);
longImageView.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_CROP);
longImageView.setDoubleTapZoomDpi(SubsamplingScaleImageView.ZOOM_FOCUS_CENTER);
longImageView.setImage(ImageSource.bitmap(resource),
new ImageViewState(0, new PointF(0, 0), 0));
} else {
// 普通图片
imageView.setImageBitmap(resource);
}
}
}
});
}
/**
* 加载相册目录
*
* @param context 上下文
* @param url 图片路径
* @param imageView 承载图片ImageView
*/
@Override
public void loadFolderImage(@NonNull final Context context, @NonNull String url, @NonNull final ImageView imageView) {
Glide.with(context)
.asBitmap()
.load(url)
.override(180, 180)
.centerCrop()
.sizeMultiplier(0.5f)
.apply(new RequestOptions().placeholder(R.drawable.picture_image_placeholder))
.into(new BitmapImageViewTarget(imageView) {
@Override
protected void setResource(Bitmap resource) {
RoundedBitmapDrawable circularBitmapDrawable =
RoundedBitmapDrawableFactory.
create(context.getResources(), resource);
circularBitmapDrawable.setCornerRadius(8);
imageView.setImageDrawable(circularBitmapDrawable);
}
});
}
/**
* 加载gif
*
* @param context 上下文
* @param url 图片路径
* @param imageView 承载图片ImageView
*/
@Override
public void loadAsGifImage(@NonNull Context context, @NonNull String url,
@NonNull ImageView imageView) {
Glide.with(context)
.asGif()
.load(url)
.into(imageView);
}
/**
* 加载图片列表图片
*
* @param context 上下文
* @param url 图片路径
* @param imageView 承载图片ImageView
*/
@Override
public void loadGridImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) {
Glide.with(context)
.load(url)
.override(200, 200)
.centerCrop()
.apply(new RequestOptions().placeholder(R.drawable.picture_image_placeholder))
.into(imageView);
}
private GlideEngine() {
}
private static GlideEngine instance;
public static GlideEngine createGlideEngine() {
if (null == instance) {
synchronized (GlideEngine.class) {
if (null == instance) {
instance = new GlideEngine();
}
}
}
return instance;
}
}

View File

@ -0,0 +1,231 @@
package com.dahe.mylibrary.weight;
import android.graphics.Rect;
import android.os.Build;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.chad.library.adapter.base.BaseSectionQuickAdapter;
import com.chad.library.adapter.base.entity.SectionEntity;
import com.chad.library.adapter.base.viewholder.BaseViewHolder;
import java.util.ArrayList;
import java.util.List;
/**
* 应用于RecyclerView的GridLayoutManager水平方向上固定间距大小从而使条目宽度自适应<br>
* 配合Brvah的Section使用不对Head生效仅对每个Head的子Grid列表生效<br>
* Section Grid中Item的宽度应设为MATCH_PARAENT
*
* @author : renpeng
* @since : 2018/9/29
*/
public class GridSectionAverageGapItemDecoration extends RecyclerView.ItemDecoration {
private class Section {
public int startPos = 0;
public int endPos = 0;
public int getCount() {
return endPos - startPos + 1;
}
public boolean contains(int pos) {
return pos >= startPos && pos <= endPos;
}
@Override
public String toString() {
return "Section{" +
"startPos=" + startPos +
", endPos=" + endPos +
'}';
}
}
private float gapHorizontalDp;
private float gapVerticalDp;
private float sectionEdgeHPaddingDp;
private float sectionEdgeVPaddingDp;
private int gapHSizePx = -1;
private int gapVSizePx = -1;
private int sectionEdgeHPaddingPx;
private int eachItemHPaddingPx; //每个条目应该在水平方向上加的padding 总大小=paddingLeft+paddingRight
private int sectionEdgeVPaddingPx;
private List<Section> mSectionList = new ArrayList<>();
private BaseSectionQuickAdapter mAdapter;
private RecyclerView.AdapterDataObserver mDataObserver = new RecyclerView.AdapterDataObserver() {
@Override
public void onChanged() {
markSections();
}
@Override
public void onItemRangeChanged(int positionStart, int itemCount) {
markSections();
}
@Override
public void onItemRangeChanged(int positionStart, int itemCount, @Nullable Object payload) {
markSections();
}
@Override
public void onItemRangeInserted(int positionStart, int itemCount) {
markSections();
}
@Override
public void onItemRangeRemoved(int positionStart, int itemCount) {
markSections();
}
@Override
public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
markSections();
}
};
/**
* @param gapHorizontalDp item之间的水平间距
* @param gapVerticalDp item之间的垂直间距
* @param sectionEdgeHPaddingDp section左右两端的padding大小
* @param sectionEdgeVPaddingDp section上下两端的padding大小
*/
public GridSectionAverageGapItemDecoration(float gapHorizontalDp, float gapVerticalDp, float sectionEdgeHPaddingDp, float sectionEdgeVPaddingDp) {
this.gapHorizontalDp = gapHorizontalDp;
this.gapVerticalDp = gapVerticalDp;
this.sectionEdgeHPaddingDp = sectionEdgeHPaddingDp;
this.sectionEdgeVPaddingDp = sectionEdgeVPaddingDp;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
if (parent.getLayoutManager() instanceof GridLayoutManager && parent.getAdapter() instanceof BaseSectionQuickAdapter) {
GridLayoutManager layoutManager = (GridLayoutManager) parent.getLayoutManager();
BaseSectionQuickAdapter<SectionEntity, BaseViewHolder> adapter = (BaseSectionQuickAdapter) parent.getAdapter();
if (mAdapter != adapter) {
setUpWithAdapter(adapter);
}
int spanCount = layoutManager.getSpanCount();
int position = parent.getChildAdapterPosition(view) - mAdapter.getHeaderLayoutCount();
SectionEntity entity = adapter.getItem(position);
if (entity == null || entity.isHeader()) {
//不处理header
outRect.set(0, 0, 0, 0);
// Log.w("GridAverageGapItem", "pos=" + position + "," + outRect.toShortString());
return;
}
Section section = findSectionLastItemPos(position);
if (gapHSizePx < 0 || gapVSizePx < 0) {
transformGapDefinition(parent, spanCount);
}
outRect.top = gapVSizePx;
outRect.bottom = 0;
//下面的visualPos为单个Section内的视觉Pos
int visualPos = position + 1 - section.startPos;
if (visualPos % spanCount == 1) {
//第一列
outRect.left = sectionEdgeHPaddingPx;
outRect.right = eachItemHPaddingPx - sectionEdgeHPaddingPx;
} else if (visualPos % spanCount == 0) {
//最后一列
outRect.left = eachItemHPaddingPx - sectionEdgeHPaddingPx;
outRect.right = sectionEdgeHPaddingPx;
} else {
outRect.left = gapHSizePx - (eachItemHPaddingPx - sectionEdgeHPaddingPx);
outRect.right = eachItemHPaddingPx - outRect.left;
}
if (visualPos - spanCount <= 0) {
//第一行
outRect.top = sectionEdgeVPaddingPx;
}
if (isLastRow(visualPos, spanCount, section.getCount())) {
//最后一行
outRect.bottom = sectionEdgeVPaddingPx;
// Log.w("GridAverageGapItem", "last row pos=" + position);
}
// Log.w("GridAverageGapItem", "pos=" + position + ",vPos=" + visualPos + "," + outRect.toShortString());
} else {
super.getItemOffsets(outRect, view, parent, state);
}
}
private void setUpWithAdapter(BaseSectionQuickAdapter<SectionEntity, BaseViewHolder> adapter) {
if (mAdapter != null) {
mAdapter.unregisterAdapterDataObserver(mDataObserver);
}
mAdapter = adapter;
mAdapter.registerAdapterDataObserver(mDataObserver);
markSections();
}
private void markSections() {
if (mAdapter != null) {
BaseSectionQuickAdapter<SectionEntity, BaseViewHolder> adapter = mAdapter;
mSectionList.clear();
SectionEntity sectionEntity = null;
Section section = new Section();
for (int i = 0, size = adapter.getItemCount(); i < size; i++) {
sectionEntity = adapter.getItem(i);
if (sectionEntity != null && sectionEntity.isHeader()) {
//找到新Section起点
if (section != null && i != 0) {
//已经有待添加的section
section.endPos = i - 1;
mSectionList.add(section);
}
section = new Section();
section.startPos = i + 1;
} else {
section.endPos = i;
}
}
//处理末尾情况
if (!mSectionList.contains(section)) {
mSectionList.add(section);
}
// Log.w("GridAverageGapItem", "section list=" + mSectionList);
}
}
private void transformGapDefinition(RecyclerView parent, int spanCount) {
DisplayMetrics displayMetrics = new DisplayMetrics();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
parent.getDisplay().getMetrics(displayMetrics);
}
gapHSizePx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, gapHorizontalDp, displayMetrics);
gapVSizePx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, gapVerticalDp, displayMetrics);
sectionEdgeHPaddingPx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, sectionEdgeHPaddingDp, displayMetrics);
sectionEdgeVPaddingPx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, sectionEdgeVPaddingDp, displayMetrics);
eachItemHPaddingPx = (sectionEdgeHPaddingPx * 2 + gapHSizePx * (spanCount - 1)) / spanCount;
}
private Section findSectionLastItemPos(int curPos) {
for (Section section : mSectionList) {
if (section.contains(curPos)) {
return section;
}
}
return null;
}
private boolean isLastRow(int visualPos, int spanCount, int sectionItemCount) {
int lastRowCount = sectionItemCount % spanCount;
lastRowCount = lastRowCount == 0 ? spanCount : lastRowCount;
return visualPos > sectionItemCount - lastRowCount;
}
}

View File

@ -0,0 +1,93 @@
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;
import android.widget.ImageButton;
import com.dahe.mylibrary.utils.BaseUtils;
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();
}
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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];
}
};
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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>

View File

@ -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>

View File

@ -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

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