Commit 4f1878848ec875f1f50e659cc75d6f63c3981b20
1 parent
224ada73
企业端专属分支
Showing
26 changed files
with
3499 additions
and
42 deletions
build.gradle
| @@ -63,7 +63,7 @@ ext { | @@ -63,7 +63,7 @@ ext { | ||
| 63 | qmui = '1.1.5' | 63 | qmui = '1.1.5' |
| 64 | 64 | ||
| 65 | libLargeImage = '1.0.4-androidx' | 65 | libLargeImage = '1.0.4-androidx' |
| 66 | - libBase = '1.9.9.0' | 66 | + libBase = '2.0.0.7.3' |
| 67 | libVideoQiniu = '1.0.7.2' | 67 | libVideoQiniu = '1.0.7.2' |
| 68 | 68 | ||
| 69 | //阿里路由框架 | 69 | //阿里路由框架 |
config.gradle
lib_media/build.gradle
| @@ -48,7 +48,7 @@ dependencies { | @@ -48,7 +48,7 @@ dependencies { | ||
| 48 | annotationProcessor "com.github.bumptech.glide:compiler:$rootProject.compiler" | 48 | annotationProcessor "com.github.bumptech.glide:compiler:$rootProject.compiler" |
| 49 | 49 | ||
| 50 | //视讯云SDK | 50 | //视讯云SDK |
| 51 | - implementation "com.qmuiteam:qmui:$rootProject.qmui" | 51 | +// implementation "com.qmuiteam:qmui:$rootProject.qmui" |
| 52 | 52 | ||
| 53 | implementation "com.cnlive.libs:base:$rootProject.libBase" | 53 | implementation "com.cnlive.libs:base:$rootProject.libBase" |
| 54 | implementation 'com.github.chrisbanes:PhotoView:2.1.4' | 54 | implementation 'com.github.chrisbanes:PhotoView:2.1.4' |
lib_media/src/main/java/com/cnlive/libs/base/frame/ReflectUtil.java
0 → 100644
| 1 | +package com.cnlive.libs.base.frame; | ||
| 2 | + | ||
| 3 | + | ||
| 4 | +import java.lang.reflect.Constructor; | ||
| 5 | +import java.lang.reflect.Method; | ||
| 6 | +import java.lang.reflect.ParameterizedType; | ||
| 7 | + | ||
| 8 | +public class ReflectUtil { | ||
| 9 | + | ||
| 10 | + private static final String TAG = "ReflectUtil"; | ||
| 11 | + | ||
| 12 | + public static Object invoke(Object obj, String methodName, Object data, Class clazz) { | ||
| 13 | + Object result = null; | ||
| 14 | + try { | ||
| 15 | + Method method = obj.getClass().getMethod(methodName, clazz); | ||
| 16 | + result = method.invoke(obj, data); | ||
| 17 | + } catch (Exception ignored) { | ||
| 18 | + } | ||
| 19 | + return result; | ||
| 20 | + } | ||
| 21 | + | ||
| 22 | + public static Object invoke(Object obj, String methodName, Object data) { | ||
| 23 | + Object result = null; | ||
| 24 | + try { | ||
| 25 | + Method method = obj.getClass().getMethod(methodName, new Class[]{data.getClass()}); | ||
| 26 | + result = method.invoke(obj, data); | ||
| 27 | + } catch (Exception ignored) { | ||
| 28 | + } | ||
| 29 | + return result; | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + public static Object invoke(Object obj, String methodName) { | ||
| 33 | + Object result = null; | ||
| 34 | + try { | ||
| 35 | + Method method = obj.getClass().getMethod(methodName); | ||
| 36 | + result = method.invoke(obj); | ||
| 37 | + } catch (Exception ignored) { | ||
| 38 | + } | ||
| 39 | + return result; | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + public static <R> R instance(int position, Class type, Object data) { | ||
| 43 | + R result = null; | ||
| 44 | + try { | ||
| 45 | + ParameterizedType pt = (ParameterizedType) type.getGenericSuperclass(); | ||
| 46 | + Class<R> clazz = (Class<R>) pt.getActualTypeArguments()[position]; | ||
| 47 | + Constructor constructor = clazz.getConstructor(new Class[]{data.getClass()}); | ||
| 48 | + result = (R) constructor.newInstance(data); | ||
| 49 | + } catch (Exception ignored) { | ||
| 50 | + } | ||
| 51 | + return result; | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + public static <R> R instance(int position, Object object) { | ||
| 55 | + R result = null; | ||
| 56 | + try { | ||
| 57 | + ParameterizedType pt = (ParameterizedType) object.getClass().getGenericSuperclass(); | ||
| 58 | + Class<R> clazz = (Class<R>) pt.getActualTypeArguments()[position]; | ||
| 59 | + result = clazz.newInstance(); | ||
| 60 | + } catch (Exception ignored) { | ||
| 61 | + } | ||
| 62 | + return result; | ||
| 63 | + } | ||
| 64 | +} |
lib_media/src/main/java/com/cnlive/libs/base/frame/activity/MvpActivity.java
0 → 100644
| 1 | +package com.cnlive.libs.base.frame.activity; | ||
| 2 | + | ||
| 3 | +import android.os.Bundle; | ||
| 4 | +import androidx.annotation.NonNull; | ||
| 5 | + | ||
| 6 | +import com.cnlive.libs.base.frame.ReflectUtil; | ||
| 7 | +import com.hannesdorfmann.mosby3.mvp.MvpPresenter; | ||
| 8 | +import com.hannesdorfmann.mosby3.mvp.MvpView; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * MVP Databinding Base Activity | ||
| 12 | + * @param <V> MVP View {@link MvpView} | ||
| 13 | + * @param <P> MVP Presenter {@link MvpPresenter} | ||
| 14 | + */ | ||
| 15 | +public abstract class MvpActivity<V extends MvpView, P extends MvpPresenter<V>> extends com.hannesdorfmann.mosby3.mvp.MvpActivity<V, P> { | ||
| 16 | + | ||
| 17 | + public V view; | ||
| 18 | + | ||
| 19 | + @Override | ||
| 20 | + protected void onCreate(Bundle savedInstanceState) { | ||
| 21 | + super.onCreate(savedInstanceState); | ||
| 22 | + setContentView(getLayoutId()); | ||
| 23 | + } | ||
| 24 | + | ||
| 25 | + protected abstract int getLayoutId(); | ||
| 26 | + | ||
| 27 | + @NonNull | ||
| 28 | + public V createView() { | ||
| 29 | + return ReflectUtil.instance(0, this.getClass(), this); | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + @NonNull | ||
| 33 | + @Override | ||
| 34 | + public P createPresenter() { | ||
| 35 | + return ReflectUtil.instance(1, this); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + @NonNull | ||
| 39 | + @Override | ||
| 40 | + public V getMvpView() { | ||
| 41 | + if (view == null) view = createView(); | ||
| 42 | + return view; | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | +} |
lib_media/src/main/java/com/cnlive/libs/base/frame/activity/MvpBindingActivity.java
0 → 100644
| 1 | +package com.cnlive.libs.base.frame.activity; | ||
| 2 | + | ||
| 3 | +import androidx.databinding.DataBindingUtil; | ||
| 4 | +import androidx.databinding.ViewDataBinding; | ||
| 5 | +import android.os.Bundle; | ||
| 6 | +import androidx.annotation.NonNull; | ||
| 7 | + | ||
| 8 | +import com.cnlive.libs.base.frame.ReflectUtil; | ||
| 9 | +import com.hannesdorfmann.mosby3.mvp.MvpPresenter; | ||
| 10 | +import com.hannesdorfmann.mosby3.mvp.MvpView; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * MVP Databinding Base Activity | ||
| 14 | + * @param <V> MVP View {@link MvpView} | ||
| 15 | + * @param <P> MVP Presenter {@link MvpPresenter} | ||
| 16 | + * @param <D> Databind Page Data | ||
| 17 | + * @param <T> Databind Activity ViewDataBinding {@link ViewDataBinding} | ||
| 18 | + */ | ||
| 19 | +public abstract class MvpBindingActivity<V extends MvpView, P extends MvpPresenter<V>, D, T extends ViewDataBinding> extends MvpActivity<V, P> { | ||
| 20 | + | ||
| 21 | + public T binding; | ||
| 22 | + public D data; | ||
| 23 | + | ||
| 24 | + @Override | ||
| 25 | + protected void onCreate(Bundle savedInstanceState) { | ||
| 26 | + super.onCreate(savedInstanceState); | ||
| 27 | + binding = DataBindingUtil.setContentView(this, getLayoutId()); | ||
| 28 | + ReflectUtil.invoke(binding, "setData", getViewData()); | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + protected D initLayoutData() { | ||
| 32 | + return ReflectUtil.instance(2, this); | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | + @NonNull | ||
| 36 | + public D getViewData() { | ||
| 37 | + if (data == null) data = initLayoutData(); | ||
| 38 | + return data; | ||
| 39 | + } | ||
| 40 | +} |
lib_media/src/main/java/com/cnlive/libs/base/frame/activity/MvpLceActivity.java
0 → 100644
| 1 | +package com.cnlive.libs.base.frame.activity; | ||
| 2 | + | ||
| 3 | +import android.os.Bundle; | ||
| 4 | +import android.view.View; | ||
| 5 | +import android.widget.Toast; | ||
| 6 | + | ||
| 7 | +import androidx.annotation.NonNull; | ||
| 8 | + | ||
| 9 | +import com.hannesdorfmann.mosby3.mvp.MvpPresenter; | ||
| 10 | +import com.hannesdorfmann.mosby3.mvp.lce.LceAnimator; | ||
| 11 | +import com.hannesdorfmann.mosby3.mvp.lce.MvpLceView; | ||
| 12 | + | ||
| 13 | +/** | ||
| 14 | + * Created by Lynn on 2017/8/30. | ||
| 15 | + */ | ||
| 16 | + | ||
| 17 | +public abstract class MvpLceActivity<CV extends View, M, V extends MvpLceView<M>, P extends MvpPresenter<V>> | ||
| 18 | + extends com.hannesdorfmann.mosby3.mvp.MvpActivity<V, P> implements MvpLceView<M> { | ||
| 19 | + | ||
| 20 | + protected View loadingView; | ||
| 21 | + protected CV contentView; | ||
| 22 | + protected View errorView; | ||
| 23 | + | ||
| 24 | + @Override | ||
| 25 | + protected void onCreate(Bundle savedInstanceState) { | ||
| 26 | + super.onCreate(savedInstanceState); | ||
| 27 | + setContentView(getLayoutId()); | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + @Override | ||
| 31 | + public void onContentChanged() { | ||
| 32 | + super.onContentChanged(); | ||
| 33 | + | ||
| 34 | + loadingView = findViewById(loadingViewId()); | ||
| 35 | + contentView = (CV) findViewById(contentViewId()); | ||
| 36 | + errorView = findViewById(errorViewId()); | ||
| 37 | + | ||
| 38 | + if (loadingView == null) { | ||
| 39 | + throw new NullPointerException( | ||
| 40 | + "Loading view is null! Have you specified a loading view in your layout xml file?"); | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + if (contentView == null) { | ||
| 44 | + throw new NullPointerException( | ||
| 45 | + "Content view is null! Have you specified a content view in your layout xml file?"); | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + if (errorView == null) { | ||
| 49 | + throw new NullPointerException( | ||
| 50 | + "Error view is null! Have you specified an error view in your layout xml file?"); | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + @NonNull | ||
| 56 | + public abstract int loadingViewId(); | ||
| 57 | + | ||
| 58 | + @NonNull | ||
| 59 | + public abstract int contentViewId(); | ||
| 60 | + | ||
| 61 | + @NonNull | ||
| 62 | + public abstract int errorViewId(); | ||
| 63 | + | ||
| 64 | + public abstract int getLayoutId(); | ||
| 65 | + | ||
| 66 | + @NonNull | ||
| 67 | + @Override | ||
| 68 | + public P createPresenter() { | ||
| 69 | + return null; | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + @Override | ||
| 73 | + public void showLoading(boolean pullToRefresh) { | ||
| 74 | + | ||
| 75 | + if (!pullToRefresh) { | ||
| 76 | + animateLoadingViewIn(); | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + protected void animateLoadingViewIn() { | ||
| 82 | + LceAnimator.showLoading(loadingView, contentView, errorView); | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | + @Override | ||
| 86 | + public void showContent() { | ||
| 87 | + animateContentViewIn(); | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + protected void animateContentViewIn() { | ||
| 91 | + LceAnimator.showContent(loadingView, contentView, errorView); | ||
| 92 | + } | ||
| 93 | + | ||
| 94 | + protected abstract String getErrorMessage(Throwable e, boolean pullToRefresh); | ||
| 95 | + | ||
| 96 | + protected void showLightError(String msg) { | ||
| 97 | + Toast.makeText(this, msg, Toast.LENGTH_SHORT).show(); | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | + @Override | ||
| 101 | + public void showError(Throwable e, boolean pullToRefresh) { | ||
| 102 | + | ||
| 103 | + String errorMsg = getErrorMessage(e, pullToRefresh); | ||
| 104 | + | ||
| 105 | + if (pullToRefresh) { | ||
| 106 | + showLightError(errorMsg); | ||
| 107 | + } else { | ||
| 108 | + animateErrorViewIn(); | ||
| 109 | + } | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | + protected void animateErrorViewIn() { | ||
| 113 | + LceAnimator.showErrorView(loadingView, contentView, errorView); | ||
| 114 | + } | ||
| 115 | +} |
lib_media/src/main/java/com/cnlive/libs/base/frame/activity/MvpLceBindingActivity.java
0 → 100644
| 1 | +package com.cnlive.libs.base.frame.activity; | ||
| 2 | + | ||
| 3 | +import android.os.Bundle; | ||
| 4 | +import android.view.View; | ||
| 5 | + | ||
| 6 | +import androidx.databinding.DataBindingUtil; | ||
| 7 | +import androidx.databinding.ViewDataBinding; | ||
| 8 | + | ||
| 9 | +import com.hannesdorfmann.mosby3.mvp.MvpPresenter; | ||
| 10 | +import com.hannesdorfmann.mosby3.mvp.lce.MvpLceView; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * Created by Lynn on 2017/8/30. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | +public abstract class MvpLceBindingActivity<CV extends View, M, V extends MvpLceView<M>, P extends MvpPresenter<V>, T extends ViewDataBinding> extends MvpLceActivity<CV, M, V, P> { | ||
| 17 | + | ||
| 18 | + public T binding; | ||
| 19 | + | ||
| 20 | + @Override | ||
| 21 | + protected void onCreate(Bundle savedInstanceState) { | ||
| 22 | + super.onCreate(savedInstanceState); | ||
| 23 | + binding = DataBindingUtil.setContentView(this, getLayoutId()); | ||
| 24 | + } | ||
| 25 | +} |
lib_media/src/main/java/com/cnlive/libs/base/frame/activity/MvpViewStateActivity.java
0 → 100644
| 1 | +package com.cnlive.libs.base.frame.activity; | ||
| 2 | + | ||
| 3 | +import android.os.Bundle; | ||
| 4 | +import android.os.Parcelable; | ||
| 5 | +import androidx.annotation.NonNull; | ||
| 6 | + | ||
| 7 | +import com.cnlive.libs.base.frame.ReflectUtil; | ||
| 8 | +import com.cnlive.libs.base.frame.state.MvpViewState; | ||
| 9 | +import com.cnlive.libs.base.frame.view.MvpStateView; | ||
| 10 | +import com.hannesdorfmann.mosby3.mvp.MvpPresenter; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * Created by xiansong on 2017/8/25. | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | +public abstract class MvpViewStateActivity<V extends MvpStateView<D>, P extends MvpPresenter<V>, D extends Parcelable> extends com.hannesdorfmann.mosby3.mvp.viewstate.MvpViewStateActivity<V, P, MvpViewState<V, D>> { | ||
| 17 | + | ||
| 18 | + public V view; | ||
| 19 | + public MvpViewState<V, D> viewState; | ||
| 20 | + | ||
| 21 | + protected abstract int getLayoutId(); | ||
| 22 | + | ||
| 23 | + @Override | ||
| 24 | + protected void onCreate(Bundle savedInstanceState) { | ||
| 25 | + super.onCreate(savedInstanceState); | ||
| 26 | + setContentView(getLayoutId()); | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + @NonNull | ||
| 30 | + public V createView() { | ||
| 31 | + return ReflectUtil.instance(0, this.getClass(), this); | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + @NonNull | ||
| 35 | + @Override | ||
| 36 | + public P createPresenter() { | ||
| 37 | + return ReflectUtil.instance(1, this); | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + protected D initLayoutData() { | ||
| 41 | + return ReflectUtil.instance(2, this); | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + protected MvpViewState<V, D> initViewState() { | ||
| 45 | + return new MvpViewState<>(initLayoutData()); | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + @NonNull | ||
| 49 | + @Override | ||
| 50 | + public MvpViewState<V, D> createViewState() { | ||
| 51 | + if (viewState == null) { | ||
| 52 | + viewState = initViewState(); | ||
| 53 | + } | ||
| 54 | + return viewState; | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + @NonNull | ||
| 58 | + public D getViewData() { | ||
| 59 | + return getViewState().getViewData(); | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + @NonNull | ||
| 63 | + @Override | ||
| 64 | + public V getMvpView() { | ||
| 65 | + if (view == null) { | ||
| 66 | + view = createView(); | ||
| 67 | + } | ||
| 68 | + return view; | ||
| 69 | + } | ||
| 70 | +} |
lib_media/src/main/java/com/cnlive/libs/base/frame/adapter/DataBindingRecyclerAdapter.java
0 → 100644
| 1 | +package com.cnlive.libs.base.frame.adapter; | ||
| 2 | + | ||
| 3 | +/** | ||
| 4 | + * Created by xiansong on 2017/9/1. | ||
| 5 | + */ | ||
| 6 | + | ||
| 7 | +import androidx.databinding.DataBindingUtil; | ||
| 8 | +import androidx.databinding.ViewDataBinding; | ||
| 9 | +import androidx.annotation.NonNull; | ||
| 10 | +import androidx.recyclerview.widget.RecyclerView; | ||
| 11 | +import android.view.LayoutInflater; | ||
| 12 | +import android.view.View; | ||
| 13 | +import android.view.ViewGroup; | ||
| 14 | + | ||
| 15 | +import com.cnlive.libs.base.frame.ReflectUtil; | ||
| 16 | + | ||
| 17 | +import java.util.List; | ||
| 18 | + | ||
| 19 | + | ||
| 20 | +public abstract class DataBindingRecyclerAdapter<D, T extends ViewDataBinding> extends RecyclerView.Adapter<DataBindingRecyclerAdapter<D, T>.DataBindingViewHolder> { | ||
| 21 | + | ||
| 22 | + class DataBindingViewHolder extends RecyclerView.ViewHolder { | ||
| 23 | + | ||
| 24 | + private ViewDataBinding binding; | ||
| 25 | + | ||
| 26 | + private DataBindingViewHolder(View itemView) { | ||
| 27 | + super(itemView); | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + public void setBinding(ViewDataBinding binding) { | ||
| 31 | + this.binding = binding; | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + public ViewDataBinding getBinding() { | ||
| 35 | + return binding; | ||
| 36 | + } | ||
| 37 | + } | ||
| 38 | + | ||
| 39 | + abstract class Click implements View.OnClickListener { | ||
| 40 | + int position; | ||
| 41 | + | ||
| 42 | + Click(int position) { | ||
| 43 | + this.position = position; | ||
| 44 | + } | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + public interface OnItemClickListener<D> { | ||
| 48 | + void onItemClick(int id, D item); | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + public abstract int getLayoutId(); | ||
| 52 | + | ||
| 53 | + public abstract List<D> getList(); | ||
| 54 | + | ||
| 55 | + private OnItemClickListener<D> listener; | ||
| 56 | + | ||
| 57 | + @Override | ||
| 58 | + public DataBindingViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { | ||
| 59 | + T binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), getLayoutId(), parent, false); | ||
| 60 | + DataBindingViewHolder viewHolder = new DataBindingViewHolder(binding.getRoot()); | ||
| 61 | + viewHolder.setBinding(binding); | ||
| 62 | + return viewHolder; | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + @Override | ||
| 66 | + public void onBindViewHolder(@NonNull final DataBindingViewHolder holder, int position) { | ||
| 67 | + ReflectUtil.invoke(holder.binding, "setData", getList().get(position)); | ||
| 68 | + ReflectUtil.invoke(holder.binding, "setClick", new Click(position) { | ||
| 69 | + @Override | ||
| 70 | + public void onClick(View v) { | ||
| 71 | +// if (listener != null) listener.onItemClick(v.getId(), getList().get(position)); | ||
| 72 | + if (listener != null) | ||
| 73 | + listener.onItemClick(v.getId(), (D) ReflectUtil.invoke(holder.binding, "getData")); | ||
| 74 | + } | ||
| 75 | + }, View.OnClickListener.class); | ||
| 76 | + holder.binding.executePendingBindings(); | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + public D getItem(int location) { | ||
| 80 | + return getList().get(location); | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | + @Override | ||
| 84 | + public int getItemCount() { | ||
| 85 | + return getList() == null ? 0 : getList().size(); | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + public void setItemClickListener(OnItemClickListener<D> listener) { | ||
| 89 | + this.listener = listener; | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + public void addItem(int position, D item) { | ||
| 93 | + if (item == null) return; | ||
| 94 | + getList().add(position, item); | ||
| 95 | + notifyItemInserted(position); | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + public void addItem(D item) { | ||
| 99 | + if (item == null) return; | ||
| 100 | + getList().add(getList().size(), item); | ||
| 101 | + notifyItemInserted(getList().size()); | ||
| 102 | + } | ||
| 103 | + | ||
| 104 | + public void addItems(List<D> items) { | ||
| 105 | + if (items == null) return; | ||
| 106 | + this.getList().addAll(items); | ||
| 107 | + notifyDataSetChanged(); | ||
| 108 | + } | ||
| 109 | + | ||
| 110 | + public boolean containsAll(List<D> items) { | ||
| 111 | + return getList().containsAll(items); | ||
| 112 | + } | ||
| 113 | + | ||
| 114 | + public void updateItem(D tasks, int position) { | ||
| 115 | + if (tasks == null) return; | ||
| 116 | + getList().set(position, tasks); | ||
| 117 | + notifyItemChanged(position); | ||
| 118 | + } | ||
| 119 | + | ||
| 120 | + public void updateItems(List<D> items) { | ||
| 121 | + if (items == null) return; | ||
| 122 | + this.getList().clear(); | ||
| 123 | + this.getList().addAll(items); | ||
| 124 | + notifyDataSetChanged(); | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | + public void removeItem(int index) { | ||
| 128 | + getList().remove(index); | ||
| 129 | + notifyItemRemoved(index); | ||
| 130 | + } | ||
| 131 | + | ||
| 132 | + public void removeAllItems() { | ||
| 133 | + getList().clear(); | ||
| 134 | + notifyDataSetChanged(); | ||
| 135 | + } | ||
| 136 | +} | ||
| 0 | \ No newline at end of file | 137 | \ No newline at end of file |
lib_media/src/main/java/com/cnlive/libs/base/frame/fragment/MvpBindingFragment.java
0 → 100644
| 1 | +package com.cnlive.libs.base.frame.fragment; | ||
| 2 | + | ||
| 3 | +import androidx.databinding.DataBindingUtil; | ||
| 4 | +import androidx.databinding.ViewDataBinding; | ||
| 5 | +import android.os.Bundle; | ||
| 6 | +import androidx.annotation.NonNull; | ||
| 7 | +import androidx.annotation.Nullable; | ||
| 8 | +import android.view.LayoutInflater; | ||
| 9 | +import android.view.View; | ||
| 10 | +import android.view.ViewGroup; | ||
| 11 | + | ||
| 12 | +import com.cnlive.libs.base.frame.ReflectUtil; | ||
| 13 | +import com.hannesdorfmann.mosby3.mvp.MvpPresenter; | ||
| 14 | +import com.hannesdorfmann.mosby3.mvp.MvpView; | ||
| 15 | + | ||
| 16 | +/** | ||
| 17 | + * MVP Databinding Base Fragment | ||
| 18 | + * | ||
| 19 | + * @param <V> MVP View {@link MvpView} | ||
| 20 | + * @param <P> MVP Presenter {@link MvpPresenter} | ||
| 21 | + * @param <D> Databind Page Data | ||
| 22 | + * @param <T> Databind Activity ViewDataBinding {@link ViewDataBinding} | ||
| 23 | + */ | ||
| 24 | +public abstract class MvpBindingFragment<V extends MvpView, P extends MvpPresenter<V>, D, T extends ViewDataBinding> extends MvpFragment<V, P> { | ||
| 25 | + | ||
| 26 | + public T binding; | ||
| 27 | + public D data; | ||
| 28 | + | ||
| 29 | + @Nullable | ||
| 30 | + @Override | ||
| 31 | + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { | ||
| 32 | + binding = DataBindingUtil.inflate(inflater, getLayoutId(), container, false); | ||
| 33 | + ReflectUtil.invoke(binding, "setData", getViewData()); | ||
| 34 | + return binding.getRoot(); | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + protected D initLayoutData() { | ||
| 38 | + return ReflectUtil.instance(2, this); | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + @NonNull | ||
| 42 | + public D getViewData() { | ||
| 43 | + if (data == null) data = initLayoutData(); | ||
| 44 | + return data; | ||
| 45 | + } | ||
| 46 | +} | ||
| 0 | \ No newline at end of file | 47 | \ No newline at end of file |
lib_media/src/main/java/com/cnlive/libs/base/frame/fragment/MvpFragment.java
0 → 100644
| 1 | +package com.cnlive.libs.base.frame.fragment; | ||
| 2 | + | ||
| 3 | +import android.os.Bundle; | ||
| 4 | +import androidx.annotation.NonNull; | ||
| 5 | +import androidx.annotation.Nullable; | ||
| 6 | +import android.view.LayoutInflater; | ||
| 7 | +import android.view.View; | ||
| 8 | +import android.view.ViewGroup; | ||
| 9 | + | ||
| 10 | +import com.cnlive.libs.base.frame.ReflectUtil; | ||
| 11 | +import com.hannesdorfmann.mosby3.mvp.MvpPresenter; | ||
| 12 | +import com.hannesdorfmann.mosby3.mvp.MvpView; | ||
| 13 | + | ||
| 14 | +/** | ||
| 15 | + * MVP Databinding Base Fragment | ||
| 16 | + * | ||
| 17 | + * @param <V> MVP View {@link MvpView} | ||
| 18 | + * @param <P> MVP Presenter {@link MvpPresenter} | ||
| 19 | + */ | ||
| 20 | +public abstract class MvpFragment<V extends MvpView, P extends MvpPresenter<V>> extends com.hannesdorfmann.mosby3.mvp.MvpFragment<V, P> { | ||
| 21 | + | ||
| 22 | + public V view; | ||
| 23 | + | ||
| 24 | + @Nullable | ||
| 25 | + @Override | ||
| 26 | + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { | ||
| 27 | + return inflater.inflate(getLayoutId(), container, false); | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + protected abstract int getLayoutId(); | ||
| 31 | + | ||
| 32 | + @NonNull | ||
| 33 | + public V createView() { | ||
| 34 | + return ReflectUtil.instance(0, this.getClass(), this); | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + @NonNull | ||
| 38 | + @Override | ||
| 39 | + public P createPresenter() { | ||
| 40 | + return ReflectUtil.instance(1, this); | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + @NonNull | ||
| 44 | + @Override | ||
| 45 | + public V getMvpView() { | ||
| 46 | + if (view == null) view = createView(); | ||
| 47 | + return view; | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | +} | ||
| 0 | \ No newline at end of file | 51 | \ No newline at end of file |
lib_media/src/main/java/com/cnlive/libs/base/frame/fragment/MvpLceBindingFragment.java
0 → 100644
| 1 | +package com.cnlive.libs.base.frame.fragment; | ||
| 2 | + | ||
| 3 | +import androidx.databinding.DataBindingUtil; | ||
| 4 | +import androidx.databinding.ViewDataBinding; | ||
| 5 | +import android.os.Bundle; | ||
| 6 | +import androidx.annotation.Nullable; | ||
| 7 | +import android.view.LayoutInflater; | ||
| 8 | +import android.view.View; | ||
| 9 | +import android.view.ViewGroup; | ||
| 10 | + | ||
| 11 | +import com.hannesdorfmann.mosby3.mvp.MvpPresenter; | ||
| 12 | +import com.hannesdorfmann.mosby3.mvp.lce.MvpLceView; | ||
| 13 | + | ||
| 14 | +/** | ||
| 15 | + * Created by Lynn on 2017/8/30. | ||
| 16 | + */ | ||
| 17 | + | ||
| 18 | +public abstract class MvpLceBindingFragment<CV extends View, M, V extends MvpLceView<M>, P extends MvpPresenter<V>, T extends ViewDataBinding> extends MvpLceFragment<CV, M, V, P> { | ||
| 19 | + | ||
| 20 | + public T binding; | ||
| 21 | + | ||
| 22 | + @Nullable | ||
| 23 | + @Override | ||
| 24 | + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { | ||
| 25 | + binding = DataBindingUtil.inflate(inflater, getLayoutId(), container, false); | ||
| 26 | + return binding.getRoot(); | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | +} |
lib_media/src/main/java/com/cnlive/libs/base/frame/fragment/MvpLceFragment.java
0 → 100644
| 1 | +package com.cnlive.libs.base.frame.fragment; | ||
| 2 | + | ||
| 3 | +import android.os.Bundle; | ||
| 4 | +import androidx.annotation.CallSuper; | ||
| 5 | +import androidx.annotation.NonNull; | ||
| 6 | +import androidx.annotation.Nullable; | ||
| 7 | +import android.view.LayoutInflater; | ||
| 8 | +import android.view.View; | ||
| 9 | +import android.view.ViewGroup; | ||
| 10 | +import android.widget.Toast; | ||
| 11 | + | ||
| 12 | +import com.hannesdorfmann.mosby3.mvp.MvpPresenter; | ||
| 13 | +import com.hannesdorfmann.mosby3.mvp.lce.LceAnimator; | ||
| 14 | +import com.hannesdorfmann.mosby3.mvp.lce.MvpLceView; | ||
| 15 | + | ||
| 16 | +/** | ||
| 17 | + * Created by Lynn on 2017/8/30. | ||
| 18 | + */ | ||
| 19 | + | ||
| 20 | +public abstract class MvpLceFragment<CV extends View, M, V extends MvpLceView<M>, P extends MvpPresenter<V>> | ||
| 21 | + extends com.hannesdorfmann.mosby3.mvp.MvpFragment<V, P> implements MvpLceView<M> { | ||
| 22 | + protected View loadingView; | ||
| 23 | + protected CV contentView; | ||
| 24 | + protected View errorView; | ||
| 25 | + | ||
| 26 | + @CallSuper | ||
| 27 | + @Override | ||
| 28 | + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { | ||
| 29 | + super.onViewCreated(view, savedInstanceState); | ||
| 30 | + setUpViews(view); | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + | ||
| 34 | + @Nullable | ||
| 35 | + @Override | ||
| 36 | + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { | ||
| 37 | + return inflater.inflate(getLayoutId(), container, false); | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + public void setUpViews(View view) { | ||
| 41 | + loadingView = view.findViewById(loadingViewId()); | ||
| 42 | + contentView = view.findViewById(contentViewId()); | ||
| 43 | + errorView = view.findViewById(errorViewId()); | ||
| 44 | + | ||
| 45 | + if (loadingView == null) { | ||
| 46 | + throw new NullPointerException( | ||
| 47 | + "Loading view is null! Have you specified a loading view in your layout xml file?"); | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + if (contentView == null) { | ||
| 51 | + throw new NullPointerException( | ||
| 52 | + "Content view is null! Have you specified a content view in your layout xml file?"); | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + if (errorView == null) { | ||
| 56 | + throw new NullPointerException( | ||
| 57 | + "Error view is null! Have you specified a error view in your layout xml file?"); | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | +// errorView.setOnClickListener(new View.OnClickListener() { | ||
| 61 | +// @Override | ||
| 62 | +// public void onClick(View view) { | ||
| 63 | +// onErrorViewClicked(); | ||
| 64 | +// } | ||
| 65 | +// }); | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + | ||
| 69 | + @NonNull | ||
| 70 | + public abstract int loadingViewId(); | ||
| 71 | + | ||
| 72 | + @NonNull | ||
| 73 | + public abstract int contentViewId(); | ||
| 74 | + | ||
| 75 | + @NonNull | ||
| 76 | + public abstract int errorViewId(); | ||
| 77 | + | ||
| 78 | + public abstract int getLayoutId(); | ||
| 79 | + | ||
| 80 | + | ||
| 81 | + @Override | ||
| 82 | + public void showLoading(boolean pullToRefresh) { | ||
| 83 | + if (!pullToRefresh) { | ||
| 84 | + animateLoadingViewIn(); | ||
| 85 | + } | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + protected void animateLoadingViewIn() { | ||
| 89 | + LceAnimator.showLoading(loadingView, contentView, errorView); | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + @Override | ||
| 93 | + public void showContent() { | ||
| 94 | + animateContentViewIn(); | ||
| 95 | + } | ||
| 96 | + | ||
| 97 | + protected void animateContentViewIn() { | ||
| 98 | + LceAnimator.showContent(loadingView, contentView, errorView); | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | + protected abstract String getErrorMessage(Throwable e, boolean pullToRefresh); | ||
| 102 | + | ||
| 103 | + protected void showLightError(String msg) { | ||
| 104 | + if (getActivity() != null) { | ||
| 105 | + Toast.makeText(getActivity(), msg, Toast.LENGTH_SHORT).show(); | ||
| 106 | + } | ||
| 107 | + } | ||
| 108 | + | ||
| 109 | +// protected void onErrorViewClicked() { | ||
| 110 | +// loadData(false); | ||
| 111 | +// } | ||
| 112 | + | ||
| 113 | + @Override | ||
| 114 | + public void showError(Throwable e, boolean pullToRefresh) { | ||
| 115 | + String errorMsg = getErrorMessage(e, pullToRefresh); | ||
| 116 | + if (pullToRefresh) { | ||
| 117 | + showLightError(errorMsg); | ||
| 118 | + } else { | ||
| 119 | + animateErrorViewIn(); | ||
| 120 | + } | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + protected void animateErrorViewIn() { | ||
| 124 | + LceAnimator.showErrorView(loadingView, contentView, errorView); | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | + @Override | ||
| 128 | + public void onDestroyView() { | ||
| 129 | + super.onDestroyView(); | ||
| 130 | + loadingView = null; | ||
| 131 | + contentView = null; | ||
| 132 | + errorView.setOnClickListener(null); | ||
| 133 | + errorView = null; | ||
| 134 | + } | ||
| 135 | +} |
lib_media/src/main/java/com/cnlive/libs/base/frame/fragment/MvpViewStateFragment.java
0 → 100644
| 1 | +package com.cnlive.libs.base.frame.fragment; | ||
| 2 | + | ||
| 3 | +import android.os.Bundle; | ||
| 4 | +import android.os.Parcelable; | ||
| 5 | +import androidx.annotation.NonNull; | ||
| 6 | +import androidx.annotation.Nullable; | ||
| 7 | +import android.view.LayoutInflater; | ||
| 8 | +import android.view.View; | ||
| 9 | +import android.view.ViewGroup; | ||
| 10 | + | ||
| 11 | +import com.cnlive.libs.base.frame.ReflectUtil; | ||
| 12 | +import com.cnlive.libs.base.frame.state.MvpViewState; | ||
| 13 | +import com.cnlive.libs.base.frame.view.MvpStateView; | ||
| 14 | +import com.hannesdorfmann.mosby3.mvp.MvpPresenter; | ||
| 15 | + | ||
| 16 | +/** | ||
| 17 | + * Created by xiansong on 2017/8/29. | ||
| 18 | + */ | ||
| 19 | + | ||
| 20 | +public abstract class MvpViewStateFragment<V extends MvpStateView<D>, P extends MvpPresenter<V>, D extends Parcelable> extends com.hannesdorfmann.mosby3.mvp.viewstate.MvpViewStateFragment<V, P, MvpViewState<V, D>> { | ||
| 21 | + | ||
| 22 | + public V view; | ||
| 23 | + public MvpViewState<V, D> viewState; | ||
| 24 | + | ||
| 25 | + protected abstract int getLayoutId(); | ||
| 26 | + | ||
| 27 | + @Override | ||
| 28 | + @Nullable | ||
| 29 | + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { | ||
| 30 | + return inflater.inflate(getLayoutId(), container, false); | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + @NonNull | ||
| 34 | + public V createView() { | ||
| 35 | + return ReflectUtil.instance(0, this.getClass(), this); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + @Override | ||
| 39 | + @NonNull | ||
| 40 | + public P createPresenter() { | ||
| 41 | + return ReflectUtil.instance(1, this); | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + protected D initLayoutData() { | ||
| 45 | + return ReflectUtil.instance(2, this); | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + protected MvpViewState<V, D> initViewState() { | ||
| 49 | + return new MvpViewState<>(initLayoutData()); | ||
| 50 | + } | ||
| 51 | + | ||
| 52 | + @Override | ||
| 53 | + @NonNull | ||
| 54 | + public MvpViewState<V, D> createViewState() { | ||
| 55 | + if (viewState == null) { | ||
| 56 | + viewState = initViewState(); | ||
| 57 | + } | ||
| 58 | + return viewState; | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + @NonNull | ||
| 62 | + public D getViewData() { | ||
| 63 | + return getViewState().getViewData(); | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + @Override | ||
| 67 | + @NonNull | ||
| 68 | + public V getMvpView() { | ||
| 69 | + if (view == null) { | ||
| 70 | + view = createView(); | ||
| 71 | + } | ||
| 72 | + return view; | ||
| 73 | + } | ||
| 74 | +} | ||
| 0 | \ No newline at end of file | 75 | \ No newline at end of file |
lib_media/src/main/java/com/cnlive/libs/base/frame/state/MvpViewState.java
0 → 100644
| 1 | +package com.cnlive.libs.base.frame.state; | ||
| 2 | + | ||
| 3 | +import android.os.Bundle; | ||
| 4 | +import android.os.Parcelable; | ||
| 5 | + | ||
| 6 | +import androidx.annotation.NonNull; | ||
| 7 | + | ||
| 8 | +import com.cnlive.libs.base.frame.view.MvpStateView; | ||
| 9 | +import com.hannesdorfmann.mosby3.mvp.viewstate.RestorableViewState; | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * Created by xiansong on 2017/8/28. | ||
| 13 | + */ | ||
| 14 | + | ||
| 15 | +public class MvpViewState<V extends MvpStateView<D>, D extends Parcelable> implements RestorableViewState<V> { | ||
| 16 | + | ||
| 17 | + private static final String key_data = "state-data"; | ||
| 18 | + | ||
| 19 | + protected D data; | ||
| 20 | + | ||
| 21 | + public MvpViewState(D data) { | ||
| 22 | + this.data = data; | ||
| 23 | + } | ||
| 24 | + | ||
| 25 | + @NonNull | ||
| 26 | + public D getViewData() { | ||
| 27 | + return data; | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + @Override | ||
| 31 | + public void saveInstanceState(@NonNull Bundle out) { | ||
| 32 | + out.putParcelable(key_data, data); | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | + @Override | ||
| 36 | + public RestorableViewState<V> restoreInstanceState(Bundle in) { | ||
| 37 | + if (in == null) return null; | ||
| 38 | + data = in.getParcelable(key_data); | ||
| 39 | + return this; | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + @Override | ||
| 43 | + public void apply(V view, boolean retained) { | ||
| 44 | + view.onRestoreDataComplete(data); | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + | ||
| 48 | +} |
lib_media/src/main/java/com/cnlive/libs/base/frame/view/MvpStateView.java
0 → 100644
lib_media/src/main/java/com/cnlive/libs/base/util/AlertUtil.java
0 → 100644
| 1 | +package com.cnlive.libs.base.util; | ||
| 2 | + | ||
| 3 | +import android.content.Context; | ||
| 4 | +import android.view.Gravity; | ||
| 5 | +import android.widget.Toast; | ||
| 6 | + | ||
| 7 | +import com.cnlive.media.R; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * Created by xiansong on 2017/9/11. | ||
| 11 | + */ | ||
| 12 | + | ||
| 13 | +public class AlertUtil { | ||
| 14 | + | ||
| 15 | + public static void showDeftToast(Context context, int messageRes) { | ||
| 16 | + Toast.makeText(context,context.getString(messageRes),Toast.LENGTH_SHORT).show(); | ||
| 17 | + } | ||
| 18 | + | ||
| 19 | + public static void showDeftToast(Context context, String message) { | ||
| 20 | + Toast.makeText(context,message,Toast.LENGTH_SHORT).show(); | ||
| 21 | + } | ||
| 22 | + | ||
| 23 | + public static void showLongToast(Context context, String message, int duration){ | ||
| 24 | + Toast.makeText(context,message,Toast.LENGTH_SHORT).show(); | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + /** | ||
| 28 | + * 成功的提示 | ||
| 29 | + * | ||
| 30 | + * @param context | ||
| 31 | + * @param message | ||
| 32 | + */ | ||
| 33 | + public static void showSuccessToast(Context context, String message) { | ||
| 34 | + Toast.makeText(context,message,Toast.LENGTH_SHORT).show(); | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + /** | ||
| 38 | + * 失败的提示 | ||
| 39 | + * | ||
| 40 | + * @param context | ||
| 41 | + * @param message | ||
| 42 | + */ | ||
| 43 | + public static void showFailedToast(Context context, String message) { | ||
| 44 | + Toast.makeText(context,message,Toast.LENGTH_SHORT).show(); | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + /** | ||
| 48 | + * 不比较吐司内容是否相同提示 | ||
| 49 | + * | ||
| 50 | + * @param context | ||
| 51 | + * @param message | ||
| 52 | + */ | ||
| 53 | + public static void showNoEqulesToast(Context context, String message) { | ||
| 54 | + Toast.makeText(context,message,Toast.LENGTH_SHORT).show(); | ||
| 55 | + } | ||
| 56 | +} |
lib_media/src/main/java/com/cnlive/libs/base/util/DoublePressed.java
0 → 100644
| 1 | +package com.cnlive.libs.base.util; | ||
| 2 | + | ||
| 3 | +public class DoublePressed { | ||
| 4 | + private static long time_pressed; | ||
| 5 | + private static long upload_time; | ||
| 6 | + | ||
| 7 | + /** | ||
| 8 | + * 连续点击处理 | ||
| 9 | + * | ||
| 10 | + * @return | ||
| 11 | + */ | ||
| 12 | + public static boolean onDoublePressed() { | ||
| 13 | + return onDoublePressed(false, 2000L); | ||
| 14 | + } | ||
| 15 | + | ||
| 16 | + public static boolean onLongDoublePressed() { | ||
| 17 | + return onDoublePressed(true, 2000L); | ||
| 18 | + } | ||
| 19 | + | ||
| 20 | + public static boolean onDoublePressed(boolean isLong, long time) { | ||
| 21 | + long timeMillis = System.currentTimeMillis(); | ||
| 22 | + boolean doublePressed = time_pressed + time > timeMillis; | ||
| 23 | + | ||
| 24 | + if (isLong) { | ||
| 25 | + time_pressed = timeMillis; | ||
| 26 | + } else if (upload_time < timeMillis) { | ||
| 27 | + upload_time = timeMillis + time; | ||
| 28 | + time_pressed = timeMillis; | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + return doublePressed; | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + public static void onRestart() { | ||
| 35 | + time_pressed = 0; | ||
| 36 | + upload_time = 0; | ||
| 37 | + } | ||
| 38 | +} |
lib_media/src/main/java/com/cnlive/libs/base/util/FileUtils.java
0 → 100644
| 1 | +package com.cnlive.libs.base.util; | ||
| 2 | + | ||
| 3 | +import android.content.Context; | ||
| 4 | +import android.os.Environment; | ||
| 5 | + | ||
| 6 | +import java.io.BufferedInputStream; | ||
| 7 | +import java.io.BufferedOutputStream; | ||
| 8 | +import java.io.File; | ||
| 9 | +import java.io.FileFilter; | ||
| 10 | +import java.io.FileInputStream; | ||
| 11 | +import java.io.FileNotFoundException; | ||
| 12 | +import java.io.FileOutputStream; | ||
| 13 | +import java.io.IOException; | ||
| 14 | +import java.io.InputStream; | ||
| 15 | +import java.io.OutputStream; | ||
| 16 | +import java.net.HttpURLConnection; | ||
| 17 | +import java.net.URL; | ||
| 18 | +import java.security.DigestInputStream; | ||
| 19 | +import java.security.MessageDigest; | ||
| 20 | +import java.security.NoSuchAlgorithmException; | ||
| 21 | +import java.util.ArrayList; | ||
| 22 | +import java.util.List; | ||
| 23 | +import java.util.Locale; | ||
| 24 | +/** | ||
| 25 | + * 作者: 吴奎庆 | ||
| 26 | + * <p> | ||
| 27 | + * 时间: 2018/9/11 | ||
| 28 | + * <p> | ||
| 29 | + * 简介: | ||
| 30 | + */ | ||
| 31 | + | ||
| 32 | +public class FileUtils { | ||
| 33 | + | ||
| 34 | + private static final String LINE_SEP = System.getProperty("line.separator"); | ||
| 35 | + | ||
| 36 | + private FileUtils() { | ||
| 37 | + throw new UnsupportedOperationException("u can't instantiate me..."); | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + /** | ||
| 41 | + * Return the file by path. | ||
| 42 | + * | ||
| 43 | + * @param filePath The path of file. | ||
| 44 | + * @return the file | ||
| 45 | + */ | ||
| 46 | + public static File getFileByPath(final String filePath) { | ||
| 47 | + return isSpace(filePath) ? null : new File(filePath); | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + /** | ||
| 51 | + * Return whether the file exists. | ||
| 52 | + * | ||
| 53 | + * @param filePath The path of file. | ||
| 54 | + * @return {@code true}: yes<br>{@code false}: no | ||
| 55 | + */ | ||
| 56 | + public static boolean isFileExists(final String filePath) { | ||
| 57 | + return isFileExists(getFileByPath(filePath)); | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + /** | ||
| 61 | + * Return whether the file exists. | ||
| 62 | + * | ||
| 63 | + * @param file The file. | ||
| 64 | + * @return {@code true}: yes<br>{@code false}: no | ||
| 65 | + */ | ||
| 66 | + public static boolean isFileExists(final File file) { | ||
| 67 | + return file != null && file.exists(); | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + /** | ||
| 71 | + * Rename the file. | ||
| 72 | + * | ||
| 73 | + * @param filePath The path of file. | ||
| 74 | + * @param newName The new name of file. | ||
| 75 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 76 | + */ | ||
| 77 | + public static boolean rename(final String filePath, final String newName) { | ||
| 78 | + return rename(getFileByPath(filePath), newName); | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + /** | ||
| 82 | + * Rename the file. | ||
| 83 | + * | ||
| 84 | + * @param file The file. | ||
| 85 | + * @param newName The new name of file. | ||
| 86 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 87 | + */ | ||
| 88 | + public static boolean rename(final File file, final String newName) { | ||
| 89 | + // file is null then return false | ||
| 90 | + if (file == null) return false; | ||
| 91 | + // file doesn't exist then return false | ||
| 92 | + if (!file.exists()) return false; | ||
| 93 | + // the new name is space then return false | ||
| 94 | + if (isSpace(newName)) return false; | ||
| 95 | + // the new name equals old name then return true | ||
| 96 | + if (newName.equals(file.getName())) return true; | ||
| 97 | + File newFile = new File(file.getParent() + File.separator + newName); | ||
| 98 | + // the new name of file exists then return false | ||
| 99 | + return !newFile.exists() | ||
| 100 | + && file.renameTo(newFile); | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + /** | ||
| 104 | + * Return whether it is a directory. | ||
| 105 | + * | ||
| 106 | + * @param dirPath The path of directory. | ||
| 107 | + * @return {@code true}: yes<br>{@code false}: no | ||
| 108 | + */ | ||
| 109 | + public static boolean isDir(final String dirPath) { | ||
| 110 | + return isDir(getFileByPath(dirPath)); | ||
| 111 | + } | ||
| 112 | + | ||
| 113 | + /** | ||
| 114 | + * Return whether it is a directory. | ||
| 115 | + * | ||
| 116 | + * @param file The file. | ||
| 117 | + * @return {@code true}: yes<br>{@code false}: no | ||
| 118 | + */ | ||
| 119 | + public static boolean isDir(final File file) { | ||
| 120 | + return file != null && file.exists() && file.isDirectory(); | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + /** | ||
| 124 | + * Return whether it is a file. | ||
| 125 | + * | ||
| 126 | + * @param filePath The path of file. | ||
| 127 | + * @return {@code true}: yes<br>{@code false}: no | ||
| 128 | + */ | ||
| 129 | + public static boolean isFile(final String filePath) { | ||
| 130 | + return isFile(getFileByPath(filePath)); | ||
| 131 | + } | ||
| 132 | + | ||
| 133 | + /** | ||
| 134 | + * Return whether it is a file. | ||
| 135 | + * | ||
| 136 | + * @param file The file. | ||
| 137 | + * @return {@code true}: yes<br>{@code false}: no | ||
| 138 | + */ | ||
| 139 | + public static boolean isFile(final File file) { | ||
| 140 | + return file != null && file.exists() && file.isFile(); | ||
| 141 | + } | ||
| 142 | + | ||
| 143 | + /** | ||
| 144 | + * Create a directory if it doesn't exist, otherwise do nothing. | ||
| 145 | + * 如果不存在创建文件夹 存在就不处理 | ||
| 146 | + * @param dirPath The path of directory. | ||
| 147 | + * @return {@code true}: exists or creates successfully<br>{@code false}: otherwise | ||
| 148 | + */ | ||
| 149 | + public static boolean createOrExistsDir(final String dirPath) { | ||
| 150 | + return createOrExistsDir(getFileByPath(dirPath)); | ||
| 151 | + } | ||
| 152 | + | ||
| 153 | + /** | ||
| 154 | + * Create a directory if it doesn't exist, otherwise do nothing. | ||
| 155 | + * | ||
| 156 | + * @param file The file. | ||
| 157 | + * @return {@code true}: exists or creates successfully<br>{@code false}: otherwise | ||
| 158 | + */ | ||
| 159 | + public static boolean createOrExistsDir(final File file) { | ||
| 160 | + return file != null && (file.exists() ? file.isDirectory() : file.mkdirs()); | ||
| 161 | + } | ||
| 162 | + | ||
| 163 | + /** | ||
| 164 | + * Create a file if it doesn't exist, otherwise do nothing. | ||
| 165 | + * | ||
| 166 | + * @param filePath The path of file. | ||
| 167 | + * @return {@code true}: exists or creates successfully<br>{@code false}: otherwise | ||
| 168 | + */ | ||
| 169 | + public static boolean createOrExistsFile(final String filePath) { | ||
| 170 | + return createOrExistsFile(getFileByPath(filePath)); | ||
| 171 | + } | ||
| 172 | + | ||
| 173 | + /** | ||
| 174 | + * Create a file if it doesn't exist, otherwise do nothing. | ||
| 175 | + * | ||
| 176 | + * @param file The file. | ||
| 177 | + * @return {@code true}: exists or creates successfully<br>{@code false}: otherwise | ||
| 178 | + */ | ||
| 179 | + public static boolean createOrExistsFile(final File file) { | ||
| 180 | + if (file == null) return false; | ||
| 181 | + if (file.exists()) return file.isFile(); | ||
| 182 | + if (!createOrExistsDir(file.getParentFile())) return false; | ||
| 183 | + try { | ||
| 184 | + return file.createNewFile(); | ||
| 185 | + } catch (IOException e) { | ||
| 186 | + e.printStackTrace(); | ||
| 187 | + return false; | ||
| 188 | + } | ||
| 189 | + } | ||
| 190 | + | ||
| 191 | + /** | ||
| 192 | + * Create a file if it doesn't exist, otherwise delete old file before creating. | ||
| 193 | + * | ||
| 194 | + * @param filePath The path of file. | ||
| 195 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 196 | + */ | ||
| 197 | + public static boolean createFileByDeleteOldFile(final String filePath) { | ||
| 198 | + return createFileByDeleteOldFile(getFileByPath(filePath)); | ||
| 199 | + } | ||
| 200 | + | ||
| 201 | + /** | ||
| 202 | + * Create a file if it doesn't exist, otherwise delete old file before creating. | ||
| 203 | + * | ||
| 204 | + * @param file The file. | ||
| 205 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 206 | + */ | ||
| 207 | + public static boolean createFileByDeleteOldFile(final File file) { | ||
| 208 | + if (file == null) return false; | ||
| 209 | + // file exists and unsuccessfully delete then return false | ||
| 210 | + if (file.exists() && !file.delete()) return false; | ||
| 211 | + if (!createOrExistsDir(file.getParentFile())) return false; | ||
| 212 | + try { | ||
| 213 | + return file.createNewFile(); | ||
| 214 | + } catch (IOException e) { | ||
| 215 | + e.printStackTrace(); | ||
| 216 | + return false; | ||
| 217 | + } | ||
| 218 | + } | ||
| 219 | + | ||
| 220 | + /** | ||
| 221 | + * Copy the directory. | ||
| 222 | + * | ||
| 223 | + * @param srcDirPath The path of source directory. | ||
| 224 | + * @param destDirPath The path of destination directory. | ||
| 225 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 226 | + */ | ||
| 227 | + public static boolean copyDir(final String srcDirPath, | ||
| 228 | + final String destDirPath) { | ||
| 229 | + return copyDir(getFileByPath(srcDirPath), getFileByPath(destDirPath)); | ||
| 230 | + } | ||
| 231 | + | ||
| 232 | + /** | ||
| 233 | + * Copy the directory. | ||
| 234 | + * | ||
| 235 | + * @param srcDirPath The path of source directory. | ||
| 236 | + * @param destDirPath The path of destination directory. | ||
| 237 | + * @param listener The replace listener. | ||
| 238 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 239 | + */ | ||
| 240 | + public static boolean copyDir(final String srcDirPath, | ||
| 241 | + final String destDirPath, | ||
| 242 | + final OnReplaceListener listener) { | ||
| 243 | + return copyDir(getFileByPath(srcDirPath), getFileByPath(destDirPath), listener); | ||
| 244 | + } | ||
| 245 | + | ||
| 246 | + /** | ||
| 247 | + * Copy the directory. | ||
| 248 | + * | ||
| 249 | + * @param srcDir The source directory. | ||
| 250 | + * @param destDir The destination directory. | ||
| 251 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 252 | + */ | ||
| 253 | + public static boolean copyDir(final File srcDir, | ||
| 254 | + final File destDir) { | ||
| 255 | + return copyOrMoveDir(srcDir, destDir, false); | ||
| 256 | + } | ||
| 257 | + | ||
| 258 | + /** | ||
| 259 | + * Copy the directory. | ||
| 260 | + * | ||
| 261 | + * @param srcDir The source directory. | ||
| 262 | + * @param destDir The destination directory. | ||
| 263 | + * @param listener The replace listener. | ||
| 264 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 265 | + */ | ||
| 266 | + public static boolean copyDir(final File srcDir, | ||
| 267 | + final File destDir, | ||
| 268 | + final OnReplaceListener listener) { | ||
| 269 | + return copyOrMoveDir(srcDir, destDir, listener, false); | ||
| 270 | + } | ||
| 271 | + | ||
| 272 | + /** | ||
| 273 | + * Copy the file. | ||
| 274 | + * | ||
| 275 | + * @param srcFilePath The path of source file. | ||
| 276 | + * @param destFilePath The path of destination file. | ||
| 277 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 278 | + */ | ||
| 279 | + public static boolean copyFile(final String srcFilePath, | ||
| 280 | + final String destFilePath) { | ||
| 281 | + return copyFile(getFileByPath(srcFilePath), getFileByPath(destFilePath)); | ||
| 282 | + } | ||
| 283 | + | ||
| 284 | + /** | ||
| 285 | + * Copy the file. | ||
| 286 | + * | ||
| 287 | + * @param srcFilePath The path of source file. | ||
| 288 | + * @param destFilePath The path of destination file. | ||
| 289 | + * @param listener The replace listener. | ||
| 290 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 291 | + */ | ||
| 292 | + public static boolean copyFile(final String srcFilePath, | ||
| 293 | + final String destFilePath, | ||
| 294 | + final OnReplaceListener listener) { | ||
| 295 | + return copyFile(getFileByPath(srcFilePath), getFileByPath(destFilePath), listener); | ||
| 296 | + } | ||
| 297 | + | ||
| 298 | + /** | ||
| 299 | + * Copy the file. | ||
| 300 | + * | ||
| 301 | + * @param srcFile The source file. | ||
| 302 | + * @param destFile The destination file. | ||
| 303 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 304 | + */ | ||
| 305 | + public static boolean copyFile(final File srcFile, | ||
| 306 | + final File destFile) { | ||
| 307 | + return copyOrMoveFile(srcFile, destFile, false); | ||
| 308 | + } | ||
| 309 | + | ||
| 310 | + | ||
| 311 | + public static File getSaveFile(Context context, String fileName) { | ||
| 312 | + File file = new File(context.getFilesDir(), fileName + ".jpg"); | ||
| 313 | + return file; | ||
| 314 | + } | ||
| 315 | + | ||
| 316 | + /** | ||
| 317 | + * Copy the file. | ||
| 318 | + * | ||
| 319 | + * @param srcFile The source file. | ||
| 320 | + * @param destFile The destination file. | ||
| 321 | + * @param listener The replace listener. | ||
| 322 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 323 | + */ | ||
| 324 | + public static boolean copyFile(final File srcFile, | ||
| 325 | + final File destFile, | ||
| 326 | + final OnReplaceListener listener) { | ||
| 327 | + return copyOrMoveFile(srcFile, destFile, listener, false); | ||
| 328 | + } | ||
| 329 | + | ||
| 330 | + /** | ||
| 331 | + * Move the directory. | ||
| 332 | + * | ||
| 333 | + * @param srcDirPath The path of source directory. | ||
| 334 | + * @param destDirPath The path of destination directory. | ||
| 335 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 336 | + */ | ||
| 337 | + public static boolean moveDir(final String srcDirPath, | ||
| 338 | + final String destDirPath) { | ||
| 339 | + return moveDir(getFileByPath(srcDirPath), getFileByPath(destDirPath)); | ||
| 340 | + } | ||
| 341 | + | ||
| 342 | + /** | ||
| 343 | + * Move the directory. | ||
| 344 | + * | ||
| 345 | + * @param srcDirPath The path of source directory. | ||
| 346 | + * @param destDirPath The path of destination directory. | ||
| 347 | + * @param listener The replace listener. | ||
| 348 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 349 | + */ | ||
| 350 | + public static boolean moveDir(final String srcDirPath, | ||
| 351 | + final String destDirPath, | ||
| 352 | + final OnReplaceListener listener) { | ||
| 353 | + return moveDir(getFileByPath(srcDirPath), getFileByPath(destDirPath), listener); | ||
| 354 | + } | ||
| 355 | + | ||
| 356 | + /** | ||
| 357 | + * Move the directory. | ||
| 358 | + * | ||
| 359 | + * @param srcDir The source directory. | ||
| 360 | + * @param destDir The destination directory. | ||
| 361 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 362 | + */ | ||
| 363 | + public static boolean moveDir(final File srcDir, | ||
| 364 | + final File destDir) { | ||
| 365 | + return copyOrMoveDir(srcDir, destDir, true); | ||
| 366 | + } | ||
| 367 | + | ||
| 368 | + /** | ||
| 369 | + * Move the directory. | ||
| 370 | + * | ||
| 371 | + * @param srcDir The source directory. | ||
| 372 | + * @param destDir The destination directory. | ||
| 373 | + * @param listener The replace listener. | ||
| 374 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 375 | + */ | ||
| 376 | + public static boolean moveDir(final File srcDir, | ||
| 377 | + final File destDir, | ||
| 378 | + final OnReplaceListener listener) { | ||
| 379 | + return copyOrMoveDir(srcDir, destDir, listener, true); | ||
| 380 | + } | ||
| 381 | + | ||
| 382 | + /** | ||
| 383 | + * Move the file. | ||
| 384 | + * | ||
| 385 | + * @param srcFilePath The path of source file. | ||
| 386 | + * @param destFilePath The path of destination file. | ||
| 387 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 388 | + */ | ||
| 389 | + public static boolean moveFile(final String srcFilePath, | ||
| 390 | + final String destFilePath) { | ||
| 391 | + return moveFile(getFileByPath(srcFilePath), getFileByPath(destFilePath)); | ||
| 392 | + } | ||
| 393 | + | ||
| 394 | + /** | ||
| 395 | + * Move the file. | ||
| 396 | + * | ||
| 397 | + * @param srcFilePath The path of source file. | ||
| 398 | + * @param destFilePath The path of destination file. | ||
| 399 | + * @param listener The replace listener. | ||
| 400 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 401 | + */ | ||
| 402 | + public static boolean moveFile(final String srcFilePath, | ||
| 403 | + final String destFilePath, | ||
| 404 | + final OnReplaceListener listener) { | ||
| 405 | + return moveFile(getFileByPath(srcFilePath), getFileByPath(destFilePath), listener); | ||
| 406 | + } | ||
| 407 | + | ||
| 408 | + /** | ||
| 409 | + * Move the file. | ||
| 410 | + * | ||
| 411 | + * @param srcFile The source file. | ||
| 412 | + * @param destFile The destination file. | ||
| 413 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 414 | + */ | ||
| 415 | + public static boolean moveFile(final File srcFile, | ||
| 416 | + final File destFile) { | ||
| 417 | + return copyOrMoveFile(srcFile, destFile, true); | ||
| 418 | + } | ||
| 419 | + | ||
| 420 | + /** | ||
| 421 | + * Move the file. | ||
| 422 | + * | ||
| 423 | + * @param srcFile The source file. | ||
| 424 | + * @param destFile The destination file. | ||
| 425 | + * @param listener The replace listener. | ||
| 426 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 427 | + */ | ||
| 428 | + public static boolean moveFile(final File srcFile, | ||
| 429 | + final File destFile, | ||
| 430 | + final OnReplaceListener listener) { | ||
| 431 | + return copyOrMoveFile(srcFile, destFile, listener, true); | ||
| 432 | + } | ||
| 433 | + | ||
| 434 | + private static boolean copyOrMoveDir(final File srcDir, | ||
| 435 | + final File destDir, | ||
| 436 | + final boolean isMove) { | ||
| 437 | + return copyOrMoveDir(srcDir, destDir, new OnReplaceListener() { | ||
| 438 | + @Override | ||
| 439 | + public boolean onReplace() { | ||
| 440 | + return true; | ||
| 441 | + } | ||
| 442 | + }, isMove); | ||
| 443 | + } | ||
| 444 | + | ||
| 445 | + private static boolean copyOrMoveDir(final File srcDir, | ||
| 446 | + final File destDir, | ||
| 447 | + final OnReplaceListener listener, | ||
| 448 | + final boolean isMove) { | ||
| 449 | + if (srcDir == null || destDir == null) return false; | ||
| 450 | + // destDir's path locate in srcDir's path then return false | ||
| 451 | + String srcPath = srcDir.getPath() + File.separator; | ||
| 452 | + String destPath = destDir.getPath() + File.separator; | ||
| 453 | + if (destPath.contains(srcPath)) return false; | ||
| 454 | + if (!srcDir.exists() || !srcDir.isDirectory()) return false; | ||
| 455 | + if (destDir.exists()) { | ||
| 456 | + if (listener == null || listener.onReplace()) {// require delete the old directory | ||
| 457 | + if (!deleteAllInDir(destDir)) {// unsuccessfully delete then return false | ||
| 458 | + return false; | ||
| 459 | + } | ||
| 460 | + } else { | ||
| 461 | + return true; | ||
| 462 | + } | ||
| 463 | + } | ||
| 464 | + if (!createOrExistsDir(destDir)) return false; | ||
| 465 | + File[] files = srcDir.listFiles(); | ||
| 466 | + for (File file : files) { | ||
| 467 | + File oneDestFile = new File(destPath + file.getName()); | ||
| 468 | + if (file.isFile()) { | ||
| 469 | + if (!copyOrMoveFile(file, oneDestFile, listener, isMove)) return false; | ||
| 470 | + } else if (file.isDirectory()) { | ||
| 471 | + if (!copyOrMoveDir(file, oneDestFile, listener, isMove)) return false; | ||
| 472 | + } | ||
| 473 | + } | ||
| 474 | + return !isMove || deleteDir(srcDir); | ||
| 475 | + } | ||
| 476 | + | ||
| 477 | + private static boolean copyOrMoveFile(final File srcFile, | ||
| 478 | + final File destFile, | ||
| 479 | + final boolean isMove) { | ||
| 480 | + return copyOrMoveFile(srcFile, destFile, new OnReplaceListener() { | ||
| 481 | + @Override | ||
| 482 | + public boolean onReplace() { | ||
| 483 | + return true; | ||
| 484 | + } | ||
| 485 | + }, isMove); | ||
| 486 | + } | ||
| 487 | + | ||
| 488 | + private static boolean copyOrMoveFile(final File srcFile, | ||
| 489 | + final File destFile, | ||
| 490 | + final OnReplaceListener listener, | ||
| 491 | + final boolean isMove) { | ||
| 492 | + if (srcFile == null || destFile == null) return false; | ||
| 493 | + // srcFile equals destFile then return false | ||
| 494 | + if (srcFile.equals(destFile)) return false; | ||
| 495 | + // srcFile doesn't exist or isn't a file then return false | ||
| 496 | + if (!srcFile.exists() || !srcFile.isFile()) return false; | ||
| 497 | + if (destFile.exists()) { | ||
| 498 | + if (listener == null || listener.onReplace()) {// require delete the old file | ||
| 499 | + if (!destFile.delete()) {// unsuccessfully delete then return false | ||
| 500 | + return false; | ||
| 501 | + } | ||
| 502 | + } else { | ||
| 503 | + return true; | ||
| 504 | + } | ||
| 505 | + } | ||
| 506 | + if (!createOrExistsDir(destFile.getParentFile())) return false; | ||
| 507 | + try { | ||
| 508 | + return writeFileFromIS(destFile, new FileInputStream(srcFile)) | ||
| 509 | + && !(isMove && !deleteFile(srcFile)); | ||
| 510 | + } catch (FileNotFoundException e) { | ||
| 511 | + e.printStackTrace(); | ||
| 512 | + return false; | ||
| 513 | + } | ||
| 514 | + } | ||
| 515 | + | ||
| 516 | + /** | ||
| 517 | + * Delete the directory. | ||
| 518 | + * | ||
| 519 | + * @param dirPath The path of directory. | ||
| 520 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 521 | + */ | ||
| 522 | + public static boolean deleteDir(final String dirPath) { | ||
| 523 | + return deleteDir(getFileByPath(dirPath)); | ||
| 524 | + } | ||
| 525 | + | ||
| 526 | + /** | ||
| 527 | + * Delete the directory. | ||
| 528 | + * | ||
| 529 | + * @param dir The directory. | ||
| 530 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 531 | + */ | ||
| 532 | + public static boolean deleteDir(final File dir) { | ||
| 533 | + if (dir == null) return false; | ||
| 534 | + // dir doesn't exist then return true | ||
| 535 | + if (!dir.exists()) return true; | ||
| 536 | + // dir isn't a directory then return false | ||
| 537 | + if (!dir.isDirectory()) return false; | ||
| 538 | + File[] files = dir.listFiles(); | ||
| 539 | + if (files != null && files.length != 0) { | ||
| 540 | + for (File file : files) { | ||
| 541 | + if (file.isFile()) { | ||
| 542 | + if (!file.delete()) return false; | ||
| 543 | + } else if (file.isDirectory()) { | ||
| 544 | + if (!deleteDir(file)) return false; | ||
| 545 | + } | ||
| 546 | + } | ||
| 547 | + } | ||
| 548 | + return dir.delete(); | ||
| 549 | + } | ||
| 550 | + | ||
| 551 | + /** | ||
| 552 | + * Delete the file. | ||
| 553 | + * | ||
| 554 | + * @param srcFilePath The path of source file. | ||
| 555 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 556 | + */ | ||
| 557 | + public static boolean deleteFile(final String srcFilePath) { | ||
| 558 | + return deleteFile(getFileByPath(srcFilePath)); | ||
| 559 | + } | ||
| 560 | + | ||
| 561 | + /** | ||
| 562 | + * Delete the file. | ||
| 563 | + * | ||
| 564 | + * @param file The file. | ||
| 565 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 566 | + */ | ||
| 567 | + public static boolean deleteFile(final File file) { | ||
| 568 | + return file != null && (!file.exists() || file.isFile() && file.delete()); | ||
| 569 | + } | ||
| 570 | + | ||
| 571 | + /** | ||
| 572 | + * Delete the all in directory. | ||
| 573 | + * | ||
| 574 | + * @param dirPath The path of directory. | ||
| 575 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 576 | + */ | ||
| 577 | + public static boolean deleteAllInDir(final String dirPath) { | ||
| 578 | + return deleteAllInDir(getFileByPath(dirPath)); | ||
| 579 | + } | ||
| 580 | + | ||
| 581 | + /** | ||
| 582 | + * Delete the all in directory. | ||
| 583 | + * | ||
| 584 | + * @param dir The directory. | ||
| 585 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 586 | + */ | ||
| 587 | + public static boolean deleteAllInDir(final File dir) { | ||
| 588 | + return deleteFilesInDirWithFilter(dir, new FileFilter() { | ||
| 589 | + @Override | ||
| 590 | + public boolean accept(File pathname) { | ||
| 591 | + return true; | ||
| 592 | + } | ||
| 593 | + }); | ||
| 594 | + } | ||
| 595 | + | ||
| 596 | + /** | ||
| 597 | + * Delete all files in directory. | ||
| 598 | + * | ||
| 599 | + * @param dirPath The path of directory. | ||
| 600 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 601 | + */ | ||
| 602 | + public static boolean deleteFilesInDir(final String dirPath) { | ||
| 603 | + return deleteFilesInDir(getFileByPath(dirPath)); | ||
| 604 | + } | ||
| 605 | + | ||
| 606 | + /** | ||
| 607 | + * Delete all files in directory. | ||
| 608 | + * | ||
| 609 | + * @param dir The directory. | ||
| 610 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 611 | + */ | ||
| 612 | + public static boolean deleteFilesInDir(final File dir) { | ||
| 613 | + return deleteFilesInDirWithFilter(dir, new FileFilter() { | ||
| 614 | + @Override | ||
| 615 | + public boolean accept(File pathname) { | ||
| 616 | + return pathname.isFile(); | ||
| 617 | + } | ||
| 618 | + }); | ||
| 619 | + } | ||
| 620 | + | ||
| 621 | + /** | ||
| 622 | + * Delete all files that satisfy the filter in directory. | ||
| 623 | + * | ||
| 624 | + * @param dirPath The path of directory. | ||
| 625 | + * @param filter The filter. | ||
| 626 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 627 | + */ | ||
| 628 | + public static boolean deleteFilesInDirWithFilter(final String dirPath, | ||
| 629 | + final FileFilter filter) { | ||
| 630 | + return deleteFilesInDirWithFilter(getFileByPath(dirPath), filter); | ||
| 631 | + } | ||
| 632 | + | ||
| 633 | + /** | ||
| 634 | + * Delete all files that satisfy the filter in directory. | ||
| 635 | + * | ||
| 636 | + * @param dir The directory. | ||
| 637 | + * @param filter The filter. | ||
| 638 | + * @return {@code true}: success<br>{@code false}: fail | ||
| 639 | + */ | ||
| 640 | + public static boolean deleteFilesInDirWithFilter(final File dir, final FileFilter filter) { | ||
| 641 | + if (dir == null) return false; | ||
| 642 | + // dir doesn't exist then return true | ||
| 643 | + if (!dir.exists()) return true; | ||
| 644 | + // dir isn't a directory then return false | ||
| 645 | + if (!dir.isDirectory()) return false; | ||
| 646 | + File[] files = dir.listFiles(); | ||
| 647 | + if (files != null && files.length != 0) { | ||
| 648 | + for (File file : files) { | ||
| 649 | + if (filter.accept(file)) { | ||
| 650 | + if (file.isFile()) { | ||
| 651 | + if (!file.delete()) return false; | ||
| 652 | + } else if (file.isDirectory()) { | ||
| 653 | + if (!deleteDir(file)) return false; | ||
| 654 | + } | ||
| 655 | + } | ||
| 656 | + } | ||
| 657 | + } | ||
| 658 | + return true; | ||
| 659 | + } | ||
| 660 | + | ||
| 661 | + /** | ||
| 662 | + * Return the files in directory. | ||
| 663 | + * <p>Doesn't traverse subdirectories</p> | ||
| 664 | + * | ||
| 665 | + * @param dirPath The path of directory. | ||
| 666 | + * @return the files in directory | ||
| 667 | + */ | ||
| 668 | + public static List<File> listFilesInDir(final String dirPath) { | ||
| 669 | + return listFilesInDir(dirPath, false); | ||
| 670 | + } | ||
| 671 | + | ||
| 672 | + /** | ||
| 673 | + * Return the files in directory. | ||
| 674 | + * <p>Doesn't traverse subdirectories</p> | ||
| 675 | + * | ||
| 676 | + * @param dir The directory. | ||
| 677 | + * @return the files in directory | ||
| 678 | + */ | ||
| 679 | + public static List<File> listFilesInDir(final File dir) { | ||
| 680 | + return listFilesInDir(dir, false); | ||
| 681 | + } | ||
| 682 | + | ||
| 683 | + /** | ||
| 684 | + * Return the files in directory. | ||
| 685 | + * | ||
| 686 | + * @param dirPath The path of directory. | ||
| 687 | + * @param isRecursive True to traverse subdirectories, false otherwise. | ||
| 688 | + * @return the files in directory | ||
| 689 | + */ | ||
| 690 | + public static List<File> listFilesInDir(final String dirPath, final boolean isRecursive) { | ||
| 691 | + return listFilesInDir(getFileByPath(dirPath), isRecursive); | ||
| 692 | + } | ||
| 693 | + | ||
| 694 | + /** | ||
| 695 | + * Return the files in directory. | ||
| 696 | + * | ||
| 697 | + * @param dir The directory. | ||
| 698 | + * @param isRecursive True to traverse subdirectories, false otherwise. | ||
| 699 | + * @return the files in directory | ||
| 700 | + */ | ||
| 701 | + public static List<File> listFilesInDir(final File dir, final boolean isRecursive) { | ||
| 702 | + return listFilesInDirWithFilter(dir, new FileFilter() { | ||
| 703 | + @Override | ||
| 704 | + public boolean accept(File pathname) { | ||
| 705 | + return true; | ||
| 706 | + } | ||
| 707 | + }, isRecursive); | ||
| 708 | + } | ||
| 709 | + | ||
| 710 | + /** | ||
| 711 | + * Return the files that satisfy the filter in directory. | ||
| 712 | + * <p>Doesn't traverse subdirectories</p> | ||
| 713 | + * | ||
| 714 | + * @param dirPath The path of directory. | ||
| 715 | + * @param filter The filter. | ||
| 716 | + * @return the files that satisfy the filter in directory | ||
| 717 | + */ | ||
| 718 | + public static List<File> listFilesInDirWithFilter(final String dirPath, | ||
| 719 | + final FileFilter filter) { | ||
| 720 | + return listFilesInDirWithFilter(getFileByPath(dirPath), filter, false); | ||
| 721 | + } | ||
| 722 | + | ||
| 723 | + /** | ||
| 724 | + * Return the files that satisfy the filter in directory. | ||
| 725 | + * <p>Doesn't traverse subdirectories</p> | ||
| 726 | + * | ||
| 727 | + * @param dir The directory. | ||
| 728 | + * @param filter The filter. | ||
| 729 | + * @return the files that satisfy the filter in directory | ||
| 730 | + */ | ||
| 731 | + public static List<File> listFilesInDirWithFilter(final File dir, | ||
| 732 | + final FileFilter filter) { | ||
| 733 | + return listFilesInDirWithFilter(dir, filter, false); | ||
| 734 | + } | ||
| 735 | + | ||
| 736 | + /** | ||
| 737 | + * Return the files that satisfy the filter in directory. | ||
| 738 | + * | ||
| 739 | + * @param dirPath The path of directory. | ||
| 740 | + * @param filter The filter. | ||
| 741 | + * @param isRecursive True to traverse subdirectories, false otherwise. | ||
| 742 | + * @return the files that satisfy the filter in directory | ||
| 743 | + */ | ||
| 744 | + public static List<File> listFilesInDirWithFilter(final String dirPath, | ||
| 745 | + final FileFilter filter, | ||
| 746 | + final boolean isRecursive) { | ||
| 747 | + return listFilesInDirWithFilter(getFileByPath(dirPath), filter, isRecursive); | ||
| 748 | + } | ||
| 749 | + | ||
| 750 | + /** | ||
| 751 | + * Return the files that satisfy the filter in directory. | ||
| 752 | + * | ||
| 753 | + * @param dir The directory. | ||
| 754 | + * @param filter The filter. | ||
| 755 | + * @param isRecursive True to traverse subdirectories, false otherwise. | ||
| 756 | + * @return the files that satisfy the filter in directory | ||
| 757 | + */ | ||
| 758 | + public static List<File> listFilesInDirWithFilter(final File dir, | ||
| 759 | + final FileFilter filter, | ||
| 760 | + final boolean isRecursive) { | ||
| 761 | + if (!isDir(dir)) return null; | ||
| 762 | + List<File> list = new ArrayList<>(); | ||
| 763 | + File[] files = dir.listFiles(); | ||
| 764 | + if (files != null && files.length != 0) { | ||
| 765 | + for (File file : files) { | ||
| 766 | + if (filter.accept(file)) { | ||
| 767 | + list.add(file); | ||
| 768 | + } | ||
| 769 | + if (isRecursive && file.isDirectory()) { | ||
| 770 | + //noinspection ConstantConditions | ||
| 771 | + list.addAll(listFilesInDirWithFilter(file, filter, true)); | ||
| 772 | + } | ||
| 773 | + } | ||
| 774 | + } | ||
| 775 | + return list; | ||
| 776 | + } | ||
| 777 | + | ||
| 778 | + /** | ||
| 779 | + * Return the time that the file was last modified. | ||
| 780 | + * | ||
| 781 | + * @param filePath The path of file. | ||
| 782 | + * @return the time that the file was last modified | ||
| 783 | + */ | ||
| 784 | + | ||
| 785 | + public static long getFileLastModified(final String filePath) { | ||
| 786 | + return getFileLastModified(getFileByPath(filePath)); | ||
| 787 | + } | ||
| 788 | + | ||
| 789 | + /** | ||
| 790 | + * Return the time that the file was last modified. | ||
| 791 | + * | ||
| 792 | + * @param file The file. | ||
| 793 | + * @return the time that the file was last modified | ||
| 794 | + */ | ||
| 795 | + public static long getFileLastModified(final File file) { | ||
| 796 | + if (file == null) return -1; | ||
| 797 | + return file.lastModified(); | ||
| 798 | + } | ||
| 799 | + | ||
| 800 | + /** | ||
| 801 | + * Return the charset of file simply. | ||
| 802 | + * | ||
| 803 | + * @param filePath The path of file. | ||
| 804 | + * @return the charset of file simply | ||
| 805 | + */ | ||
| 806 | + public static String getFileCharsetSimple(final String filePath) { | ||
| 807 | + return getFileCharsetSimple(getFileByPath(filePath)); | ||
| 808 | + } | ||
| 809 | + | ||
| 810 | + /** | ||
| 811 | + * Return the charset of file simply. | ||
| 812 | + * | ||
| 813 | + * @param file The file. | ||
| 814 | + * @return the charset of file simply | ||
| 815 | + */ | ||
| 816 | + public static String getFileCharsetSimple(final File file) { | ||
| 817 | + int p = 0; | ||
| 818 | + InputStream is = null; | ||
| 819 | + try { | ||
| 820 | + is = new BufferedInputStream(new FileInputStream(file)); | ||
| 821 | + p = (is.read() << 8) + is.read(); | ||
| 822 | + } catch (IOException e) { | ||
| 823 | + e.printStackTrace(); | ||
| 824 | + } finally { | ||
| 825 | + try { | ||
| 826 | + if (is != null) { | ||
| 827 | + is.close(); | ||
| 828 | + } | ||
| 829 | + } catch (IOException e) { | ||
| 830 | + e.printStackTrace(); | ||
| 831 | + } | ||
| 832 | + } | ||
| 833 | + switch (p) { | ||
| 834 | + case 0xefbb: | ||
| 835 | + return "UTF-8"; | ||
| 836 | + case 0xfffe: | ||
| 837 | + return "Unicode"; | ||
| 838 | + case 0xfeff: | ||
| 839 | + return "UTF-16BE"; | ||
| 840 | + default: | ||
| 841 | + return "GBK"; | ||
| 842 | + } | ||
| 843 | + } | ||
| 844 | + | ||
| 845 | + /** | ||
| 846 | + * Return the number of lines of file. | ||
| 847 | + * | ||
| 848 | + * @param filePath The path of file. | ||
| 849 | + * @return the number of lines of file | ||
| 850 | + */ | ||
| 851 | + public static int getFileLines(final String filePath) { | ||
| 852 | + return getFileLines(getFileByPath(filePath)); | ||
| 853 | + } | ||
| 854 | + | ||
| 855 | + /** | ||
| 856 | + * Return the number of lines of file. | ||
| 857 | + * | ||
| 858 | + * @param file The file. | ||
| 859 | + * @return the number of lines of file | ||
| 860 | + */ | ||
| 861 | + public static int getFileLines(final File file) { | ||
| 862 | + int count = 1; | ||
| 863 | + InputStream is = null; | ||
| 864 | + try { | ||
| 865 | + is = new BufferedInputStream(new FileInputStream(file)); | ||
| 866 | + byte[] buffer = new byte[1024]; | ||
| 867 | + int readChars; | ||
| 868 | + if (LINE_SEP.endsWith("\n")) { | ||
| 869 | + while ((readChars = is.read(buffer, 0, 1024)) != -1) { | ||
| 870 | + for (int i = 0; i < readChars; ++i) { | ||
| 871 | + if (buffer[i] == '\n') ++count; | ||
| 872 | + } | ||
| 873 | + } | ||
| 874 | + } else { | ||
| 875 | + while ((readChars = is.read(buffer, 0, 1024)) != -1) { | ||
| 876 | + for (int i = 0; i < readChars; ++i) { | ||
| 877 | + if (buffer[i] == '\r') ++count; | ||
| 878 | + } | ||
| 879 | + } | ||
| 880 | + } | ||
| 881 | + } catch (IOException e) { | ||
| 882 | + e.printStackTrace(); | ||
| 883 | + } finally { | ||
| 884 | + try { | ||
| 885 | + if (is != null) { | ||
| 886 | + is.close(); | ||
| 887 | + } | ||
| 888 | + } catch (IOException e) { | ||
| 889 | + e.printStackTrace(); | ||
| 890 | + } | ||
| 891 | + } | ||
| 892 | + return count; | ||
| 893 | + } | ||
| 894 | + | ||
| 895 | + /** | ||
| 896 | + * Return the size of directory. | ||
| 897 | + * | ||
| 898 | + * @param dirPath The path of directory. | ||
| 899 | + * @return the size of directory | ||
| 900 | + */ | ||
| 901 | + public static String getDirSize(final String dirPath) { | ||
| 902 | + return getDirSize(getFileByPath(dirPath)); | ||
| 903 | + } | ||
| 904 | + | ||
| 905 | + /** | ||
| 906 | + * Return the size of directory. | ||
| 907 | + * | ||
| 908 | + * @param dir The directory. | ||
| 909 | + * @return the size of directory | ||
| 910 | + */ | ||
| 911 | + public static String getDirSize(final File dir) { | ||
| 912 | + long len = getDirLength(dir); | ||
| 913 | + return len == -1 ? "" : byte2FitMemorySize(len); | ||
| 914 | + } | ||
| 915 | + | ||
| 916 | + /** | ||
| 917 | + * Return the length of file. | ||
| 918 | + * | ||
| 919 | + * @param filePath The path of file. | ||
| 920 | + * @return the length of file | ||
| 921 | + */ | ||
| 922 | + public static String getFileSize(final String filePath) { | ||
| 923 | + long len = getFileLength(filePath); | ||
| 924 | + return len == -1 ? "" : byte2FitMemorySize(len); | ||
| 925 | + } | ||
| 926 | + | ||
| 927 | + /** | ||
| 928 | + * Return the length of file. | ||
| 929 | + * | ||
| 930 | + * @param file The file. | ||
| 931 | + * @return the length of file | ||
| 932 | + */ | ||
| 933 | + public static String getFileSize(final File file) { | ||
| 934 | + long len = getFileLength(file); | ||
| 935 | + return len == -1 ? "" : byte2FitMemorySize(len); | ||
| 936 | + } | ||
| 937 | + | ||
| 938 | + /** | ||
| 939 | + * Return the length of directory. | ||
| 940 | + * | ||
| 941 | + * @param dirPath The path of directory. | ||
| 942 | + * @return the length of directory | ||
| 943 | + */ | ||
| 944 | + public static long getDirLength(final String dirPath) { | ||
| 945 | + return getDirLength(getFileByPath(dirPath)); | ||
| 946 | + } | ||
| 947 | + | ||
| 948 | + /** | ||
| 949 | + * Return the length of directory. | ||
| 950 | + * | ||
| 951 | + * @param dir The directory. | ||
| 952 | + * @return the length of directory | ||
| 953 | + */ | ||
| 954 | + public static long getDirLength(final File dir) { | ||
| 955 | + if (!isDir(dir)) return -1; | ||
| 956 | + long len = 0; | ||
| 957 | + File[] files = dir.listFiles(); | ||
| 958 | + if (files != null && files.length != 0) { | ||
| 959 | + for (File file : files) { | ||
| 960 | + if (file.isDirectory()) { | ||
| 961 | + len += getDirLength(file); | ||
| 962 | + } else { | ||
| 963 | + len += file.length(); | ||
| 964 | + } | ||
| 965 | + } | ||
| 966 | + } | ||
| 967 | + return len; | ||
| 968 | + } | ||
| 969 | + | ||
| 970 | + /** | ||
| 971 | + * Return the length of file. | ||
| 972 | + * | ||
| 973 | + * @param filePath The path of file. | ||
| 974 | + * @return the length of file | ||
| 975 | + */ | ||
| 976 | + public static long getFileLength(final String filePath) { | ||
| 977 | + boolean isURL = filePath.matches("[a-zA-z]+://[^\\s]*"); | ||
| 978 | + if (isURL) { | ||
| 979 | + try { | ||
| 980 | + HttpURLConnection conn = (HttpURLConnection) new URL(filePath).openConnection(); | ||
| 981 | + conn.setRequestProperty("Accept-Encoding", "identity"); | ||
| 982 | + conn.connect(); | ||
| 983 | + if (conn.getResponseCode() == 200) { | ||
| 984 | + return conn.getContentLength(); | ||
| 985 | + } | ||
| 986 | + return -1; | ||
| 987 | + } catch (IOException e) { | ||
| 988 | + e.printStackTrace(); | ||
| 989 | + } | ||
| 990 | + } | ||
| 991 | + return getFileLength(getFileByPath(filePath)); | ||
| 992 | + } | ||
| 993 | + | ||
| 994 | + /** | ||
| 995 | + * Return the length of file. | ||
| 996 | + * | ||
| 997 | + * @param file The file. | ||
| 998 | + * @return the length of file | ||
| 999 | + */ | ||
| 1000 | + public static long getFileLength(final File file) { | ||
| 1001 | + if (!isFile(file)) return -1; | ||
| 1002 | + return file.length(); | ||
| 1003 | + } | ||
| 1004 | + | ||
| 1005 | + /** | ||
| 1006 | + * Return the MD5 of file. | ||
| 1007 | + * | ||
| 1008 | + * @param filePath The path of file. | ||
| 1009 | + * @return the md5 of file | ||
| 1010 | + */ | ||
| 1011 | + public static String getFileMD5ToString(final String filePath) { | ||
| 1012 | + File file = isSpace(filePath) ? null : new File(filePath); | ||
| 1013 | + return getFileMD5ToString(file); | ||
| 1014 | + } | ||
| 1015 | + | ||
| 1016 | + /** | ||
| 1017 | + * Return the MD5 of file. | ||
| 1018 | + * | ||
| 1019 | + * @param file The file. | ||
| 1020 | + * @return the md5 of file | ||
| 1021 | + */ | ||
| 1022 | + public static String getFileMD5ToString(final File file) { | ||
| 1023 | + return bytes2HexString(getFileMD5(file)); | ||
| 1024 | + } | ||
| 1025 | + | ||
| 1026 | + /** | ||
| 1027 | + * Return the MD5 of file. | ||
| 1028 | + * | ||
| 1029 | + * @param filePath The path of file. | ||
| 1030 | + * @return the md5 of file | ||
| 1031 | + */ | ||
| 1032 | + public static byte[] getFileMD5(final String filePath) { | ||
| 1033 | + return getFileMD5(getFileByPath(filePath)); | ||
| 1034 | + } | ||
| 1035 | + | ||
| 1036 | + /** | ||
| 1037 | + * Return the MD5 of file. | ||
| 1038 | + * | ||
| 1039 | + * @param file The file. | ||
| 1040 | + * @return the md5 of file | ||
| 1041 | + */ | ||
| 1042 | + public static byte[] getFileMD5(final File file) { | ||
| 1043 | + if (file == null) return null; | ||
| 1044 | + DigestInputStream dis = null; | ||
| 1045 | + try { | ||
| 1046 | + FileInputStream fis = new FileInputStream(file); | ||
| 1047 | + MessageDigest md = MessageDigest.getInstance("MD5"); | ||
| 1048 | + dis = new DigestInputStream(fis, md); | ||
| 1049 | + byte[] buffer = new byte[1024 * 256]; | ||
| 1050 | + while (true) { | ||
| 1051 | + if (!(dis.read(buffer) > 0)) break; | ||
| 1052 | + } | ||
| 1053 | + md = dis.getMessageDigest(); | ||
| 1054 | + return md.digest(); | ||
| 1055 | + } catch (NoSuchAlgorithmException | IOException e) { | ||
| 1056 | + e.printStackTrace(); | ||
| 1057 | + } finally { | ||
| 1058 | + try { | ||
| 1059 | + if (dis != null) { | ||
| 1060 | + dis.close(); | ||
| 1061 | + } | ||
| 1062 | + } catch (IOException e) { | ||
| 1063 | + e.printStackTrace(); | ||
| 1064 | + } | ||
| 1065 | + } | ||
| 1066 | + return null; | ||
| 1067 | + } | ||
| 1068 | + | ||
| 1069 | + /** | ||
| 1070 | + * Return the file's path of directory. | ||
| 1071 | + * | ||
| 1072 | + * @param file The file. | ||
| 1073 | + * @return the file's path of directory | ||
| 1074 | + */ | ||
| 1075 | + public static String getDirName(final File file) { | ||
| 1076 | + if (file == null) return ""; | ||
| 1077 | + return getDirName(file.getAbsolutePath()); | ||
| 1078 | + } | ||
| 1079 | + | ||
| 1080 | + /** | ||
| 1081 | + * Return the file's path of directory. | ||
| 1082 | + * | ||
| 1083 | + * @param filePath The path of file. | ||
| 1084 | + * @return the file's path of directory | ||
| 1085 | + */ | ||
| 1086 | + public static String getDirName(final String filePath) { | ||
| 1087 | + if (isSpace(filePath)) return ""; | ||
| 1088 | + int lastSep = filePath.lastIndexOf(File.separator); | ||
| 1089 | + return lastSep == -1 ? "" : filePath.substring(0, lastSep + 1); | ||
| 1090 | + } | ||
| 1091 | + | ||
| 1092 | + /** | ||
| 1093 | + * Return the name of file. | ||
| 1094 | + * | ||
| 1095 | + * @param file The file. | ||
| 1096 | + * @return the name of file | ||
| 1097 | + */ | ||
| 1098 | + public static String getFileName(final File file) { | ||
| 1099 | + if (file == null) return ""; | ||
| 1100 | + return getFileName(file.getAbsolutePath()); | ||
| 1101 | + } | ||
| 1102 | + | ||
| 1103 | + /** | ||
| 1104 | + * Return the name of file. | ||
| 1105 | + * | ||
| 1106 | + * @param filePath The path of file. | ||
| 1107 | + * @return the name of file | ||
| 1108 | + */ | ||
| 1109 | + public static String getFileName(final String filePath) { | ||
| 1110 | + if (isSpace(filePath)) return ""; | ||
| 1111 | + int lastSep = filePath.lastIndexOf(File.separator); | ||
| 1112 | + return lastSep == -1 ? filePath : filePath.substring(lastSep + 1); | ||
| 1113 | + } | ||
| 1114 | + | ||
| 1115 | + /** | ||
| 1116 | + * Return the name of file without extension. | ||
| 1117 | + * | ||
| 1118 | + * @param file The file. | ||
| 1119 | + * @return the name of file without extension | ||
| 1120 | + */ | ||
| 1121 | + public static String getFileNameNoExtension(final File file) { | ||
| 1122 | + if (file == null) return ""; | ||
| 1123 | + return getFileNameNoExtension(file.getPath()); | ||
| 1124 | + } | ||
| 1125 | + | ||
| 1126 | + /** | ||
| 1127 | + * Return the name of file without extension. | ||
| 1128 | + * | ||
| 1129 | + * @param filePath The path of file. | ||
| 1130 | + * @return the name of file without extension | ||
| 1131 | + */ | ||
| 1132 | + public static String getFileNameNoExtension(final String filePath) { | ||
| 1133 | + if (isSpace(filePath)) return ""; | ||
| 1134 | + int lastPoi = filePath.lastIndexOf('.'); | ||
| 1135 | + int lastSep = filePath.lastIndexOf(File.separator); | ||
| 1136 | + if (lastSep == -1) { | ||
| 1137 | + return (lastPoi == -1 ? filePath : filePath.substring(0, lastPoi)); | ||
| 1138 | + } | ||
| 1139 | + if (lastPoi == -1 || lastSep > lastPoi) { | ||
| 1140 | + return filePath.substring(lastSep + 1); | ||
| 1141 | + } | ||
| 1142 | + return filePath.substring(lastSep + 1, lastPoi); | ||
| 1143 | + } | ||
| 1144 | + | ||
| 1145 | + /** | ||
| 1146 | + * Return the extension of file. | ||
| 1147 | + * | ||
| 1148 | + * @param file The file. | ||
| 1149 | + * @return the extension of file | ||
| 1150 | + */ | ||
| 1151 | + public static String getFileExtension(final File file) { | ||
| 1152 | + if (file == null) return ""; | ||
| 1153 | + return getFileExtension(file.getPath()); | ||
| 1154 | + } | ||
| 1155 | + | ||
| 1156 | + /** | ||
| 1157 | + * Return the extension of file. | ||
| 1158 | + * | ||
| 1159 | + * @param filePath The path of file. | ||
| 1160 | + * @return the extension of file | ||
| 1161 | + */ | ||
| 1162 | + public static String getFileExtension(final String filePath) { | ||
| 1163 | + if (isSpace(filePath)) return ""; | ||
| 1164 | + int lastPoi = filePath.lastIndexOf('.'); | ||
| 1165 | + int lastSep = filePath.lastIndexOf(File.separator); | ||
| 1166 | + if (lastPoi == -1 || lastSep >= lastPoi) return ""; | ||
| 1167 | + return filePath.substring(lastPoi + 1); | ||
| 1168 | + } | ||
| 1169 | + | ||
| 1170 | + /////////////////////////////////////////////////////////////////////////// | ||
| 1171 | + // interface | ||
| 1172 | + /////////////////////////////////////////////////////////////////////////// | ||
| 1173 | + | ||
| 1174 | + public interface OnReplaceListener { | ||
| 1175 | + boolean onReplace(); | ||
| 1176 | + } | ||
| 1177 | + | ||
| 1178 | + /////////////////////////////////////////////////////////////////////////// | ||
| 1179 | + // other utils methods | ||
| 1180 | + /////////////////////////////////////////////////////////////////////////// | ||
| 1181 | + | ||
| 1182 | + private static final char HEX_DIGITS[] = | ||
| 1183 | + {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; | ||
| 1184 | + | ||
| 1185 | + private static String bytes2HexString(final byte[] bytes) { | ||
| 1186 | + if (bytes == null) return ""; | ||
| 1187 | + int len = bytes.length; | ||
| 1188 | + if (len <= 0) return ""; | ||
| 1189 | + char[] ret = new char[len << 1]; | ||
| 1190 | + for (int i = 0, j = 0; i < len; i++) { | ||
| 1191 | + ret[j++] = HEX_DIGITS[bytes[i] >> 4 & 0x0f]; | ||
| 1192 | + ret[j++] = HEX_DIGITS[bytes[i] & 0x0f]; | ||
| 1193 | + } | ||
| 1194 | + return new String(ret); | ||
| 1195 | + } | ||
| 1196 | + | ||
| 1197 | + private static String byte2FitMemorySize(final long byteNum) { | ||
| 1198 | + if (byteNum < 0) { | ||
| 1199 | + return "shouldn't be less than zero!"; | ||
| 1200 | + } else if (byteNum < 1024) { | ||
| 1201 | + return String.format(Locale.getDefault(), "%.3fB", (double) byteNum); | ||
| 1202 | + } else if (byteNum < 1048576) { | ||
| 1203 | + return String.format(Locale.getDefault(), "%.3fKB", (double) byteNum / 1024); | ||
| 1204 | + } else if (byteNum < 1073741824) { | ||
| 1205 | + return String.format(Locale.getDefault(), "%.3fMB", (double) byteNum / 1048576); | ||
| 1206 | + } else { | ||
| 1207 | + return String.format(Locale.getDefault(), "%.3fGB", (double) byteNum / 1073741824); | ||
| 1208 | + } | ||
| 1209 | + } | ||
| 1210 | + | ||
| 1211 | + private static boolean isSpace(final String s) { | ||
| 1212 | + if (s == null) return true; | ||
| 1213 | + for (int i = 0, len = s.length(); i < len; ++i) { | ||
| 1214 | + if (!Character.isWhitespace(s.charAt(i))) { | ||
| 1215 | + return false; | ||
| 1216 | + } | ||
| 1217 | + } | ||
| 1218 | + return true; | ||
| 1219 | + } | ||
| 1220 | + | ||
| 1221 | + private static boolean writeFileFromIS(final File file, | ||
| 1222 | + final InputStream is) { | ||
| 1223 | + OutputStream os = null; | ||
| 1224 | + try { | ||
| 1225 | + os = new BufferedOutputStream(new FileOutputStream(file)); | ||
| 1226 | + byte data[] = new byte[8192]; | ||
| 1227 | + int len; | ||
| 1228 | + while ((len = is.read(data, 0, 8192)) != -1) { | ||
| 1229 | + os.write(data, 0, len); | ||
| 1230 | + } | ||
| 1231 | + return true; | ||
| 1232 | + } catch (IOException e) { | ||
| 1233 | + e.printStackTrace(); | ||
| 1234 | + return false; | ||
| 1235 | + } finally { | ||
| 1236 | + try { | ||
| 1237 | + is.close(); | ||
| 1238 | + } catch (IOException e) { | ||
| 1239 | + e.printStackTrace(); | ||
| 1240 | + } | ||
| 1241 | + try { | ||
| 1242 | + if (os != null) { | ||
| 1243 | + os.close(); | ||
| 1244 | + } | ||
| 1245 | + } catch (IOException e) { | ||
| 1246 | + e.printStackTrace(); | ||
| 1247 | + } | ||
| 1248 | + } | ||
| 1249 | + } | ||
| 1250 | + | ||
| 1251 | + public static boolean isExternalStorageWritable() { | ||
| 1252 | + String state = Environment.getExternalStorageState(); | ||
| 1253 | + if (Environment.MEDIA_MOUNTED.equals(state)) { | ||
| 1254 | + return true; | ||
| 1255 | + } | ||
| 1256 | + return false; | ||
| 1257 | + } | ||
| 1258 | + | ||
| 1259 | +} |
lib_media/src/main/java/com/cnlive/libs/base/util/StatusBarUtil2.java
0 → 100644
| 1 | +package com.cnlive.libs.base.util; | ||
| 2 | + | ||
| 3 | +import android.annotation.TargetApi; | ||
| 4 | +import android.app.Activity; | ||
| 5 | +import android.content.Context; | ||
| 6 | +import android.graphics.Color; | ||
| 7 | +import android.os.Build; | ||
| 8 | +import androidx.annotation.ColorInt; | ||
| 9 | +import androidx.annotation.IntRange; | ||
| 10 | +import androidx.annotation.NonNull; | ||
| 11 | +import androidx.coordinatorlayout.widget.CoordinatorLayout; | ||
| 12 | +import androidx.drawerlayout.widget.DrawerLayout; | ||
| 13 | +import android.view.View; | ||
| 14 | +import android.view.ViewGroup; | ||
| 15 | +import android.view.Window; | ||
| 16 | +import android.view.WindowManager; | ||
| 17 | +import android.widget.LinearLayout; | ||
| 18 | + | ||
| 19 | + | ||
| 20 | +import com.cnlive.media.R; | ||
| 21 | +import com.qiniu.pili.droid.shortvideo.PLShortVideoEnv; | ||
| 22 | + | ||
| 23 | +import java.lang.reflect.Field; | ||
| 24 | +import java.lang.reflect.Method; | ||
| 25 | + | ||
| 26 | +/** | ||
| 27 | + * Created by Jaeger on 16/2/14. | ||
| 28 | + * <p> | ||
| 29 | + * Email: chjie.jaeger@gmail.com | ||
| 30 | + * GitHub: https://github.com/laobie | ||
| 31 | + */ | ||
| 32 | +public class StatusBarUtil2 { | ||
| 33 | + | ||
| 34 | + public static final int DEFAULT_STATUS_BAR_ALPHA = 112; | ||
| 35 | + private static final int FAKE_STATUS_BAR_VIEW_ID = R.id.status_bar_util_fake_status_bar_view; | ||
| 36 | + private static final int FAKE_TRANSLUCENT_VIEW_ID = R.id.status_bar_util_translucent_view; | ||
| 37 | + private static final int TAG_KEY_HAVE_SET_OFFSET = -123; | ||
| 38 | + | ||
| 39 | + /** | ||
| 40 | + * 设置状态栏颜色 | ||
| 41 | + * | ||
| 42 | + * @param activity 需要设置的 activity | ||
| 43 | + * @param color 状态栏颜色值 | ||
| 44 | + */ | ||
| 45 | + public static void setColor(Activity activity, @ColorInt int color) { | ||
| 46 | + setColor(activity, color, DEFAULT_STATUS_BAR_ALPHA); | ||
| 47 | + PLShortVideoEnv.init() | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + /** | ||
| 51 | + * 设置状态栏颜色 | ||
| 52 | + * | ||
| 53 | + * @param activity 需要设置的activity | ||
| 54 | + * @param color 状态栏颜色值 | ||
| 55 | + * @param statusBarAlpha 状态栏透明度 | ||
| 56 | + */ | ||
| 57 | + | ||
| 58 | + public static void setColor(Activity activity, @ColorInt int color, @IntRange(from = 0, to = 255) int statusBarAlpha) { | ||
| 59 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { | ||
| 60 | + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); | ||
| 61 | + activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); | ||
| 62 | + activity.getWindow().setStatusBarColor(calculateStatusColor(color, statusBarAlpha)); | ||
| 63 | + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { | ||
| 64 | + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); | ||
| 65 | + ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView(); | ||
| 66 | + View fakeStatusBarView = decorView.findViewById(FAKE_STATUS_BAR_VIEW_ID); | ||
| 67 | + if (fakeStatusBarView != null) { | ||
| 68 | + if (fakeStatusBarView.getVisibility() == View.GONE) { | ||
| 69 | + fakeStatusBarView.setVisibility(View.VISIBLE); | ||
| 70 | + } | ||
| 71 | + fakeStatusBarView.setBackgroundColor(calculateStatusColor(color, statusBarAlpha)); | ||
| 72 | + } else { | ||
| 73 | + decorView.addView(createStatusBarView(activity, color, statusBarAlpha)); | ||
| 74 | + } | ||
| 75 | + setRootView(activity); | ||
| 76 | + } | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + /** | ||
| 80 | + * 为滑动返回界面设置状态栏颜色 | ||
| 81 | + * | ||
| 82 | + * @param activity 需要设置的activity | ||
| 83 | + * @param color 状态栏颜色值 | ||
| 84 | + */ | ||
| 85 | + public static void setColorForSwipeBack(Activity activity, int color) { | ||
| 86 | + setColorForSwipeBack(activity, color, DEFAULT_STATUS_BAR_ALPHA); | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | + /** | ||
| 90 | + * 为滑动返回界面设置状态栏颜色 | ||
| 91 | + * | ||
| 92 | + * @param activity 需要设置的activity | ||
| 93 | + * @param color 状态栏颜色值 | ||
| 94 | + * @param statusBarAlpha 状态栏透明度 | ||
| 95 | + */ | ||
| 96 | + public static void setColorForSwipeBack(Activity activity, @ColorInt int color, | ||
| 97 | + @IntRange(from = 0, to = 255) int statusBarAlpha) { | ||
| 98 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { | ||
| 99 | + | ||
| 100 | + ViewGroup contentView = ((ViewGroup) activity.findViewById(android.R.id.content)); | ||
| 101 | + View rootView = contentView.getChildAt(0); | ||
| 102 | + int statusBarHeight = getStatusBarHeight(activity); | ||
| 103 | + if (rootView != null && rootView instanceof CoordinatorLayout) { | ||
| 104 | + final CoordinatorLayout coordinatorLayout = (CoordinatorLayout) rootView; | ||
| 105 | + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { | ||
| 106 | + coordinatorLayout.setFitsSystemWindows(false); | ||
| 107 | + contentView.setBackgroundColor(calculateStatusColor(color, statusBarAlpha)); | ||
| 108 | + boolean isNeedRequestLayout = contentView.getPaddingTop() < statusBarHeight; | ||
| 109 | + if (isNeedRequestLayout) { | ||
| 110 | + contentView.setPadding(0, statusBarHeight, 0, 0); | ||
| 111 | + coordinatorLayout.post(new Runnable() { | ||
| 112 | + @Override | ||
| 113 | + public void run() { | ||
| 114 | + coordinatorLayout.requestLayout(); | ||
| 115 | + } | ||
| 116 | + }); | ||
| 117 | + } | ||
| 118 | + } else { | ||
| 119 | + coordinatorLayout.setStatusBarBackgroundColor(calculateStatusColor(color, statusBarAlpha)); | ||
| 120 | + } | ||
| 121 | + } else { | ||
| 122 | + contentView.setPadding(0, statusBarHeight, 0, 0); | ||
| 123 | + contentView.setBackgroundColor(calculateStatusColor(color, statusBarAlpha)); | ||
| 124 | + } | ||
| 125 | + setTransparentForWindow(activity); | ||
| 126 | + } | ||
| 127 | + } | ||
| 128 | + | ||
| 129 | + /** | ||
| 130 | + * 设置状态栏纯色 不加半透明效果 | ||
| 131 | + * | ||
| 132 | + * @param activity 需要设置的 activity | ||
| 133 | + * @param color 状态栏颜色值 | ||
| 134 | + */ | ||
| 135 | + public static void setColorNoTranslucent(Activity activity, @ColorInt int color) { | ||
| 136 | + setColor(activity, color, 0); | ||
| 137 | + } | ||
| 138 | + | ||
| 139 | + /** | ||
| 140 | + * 设置状态栏颜色(5.0以下无半透明效果,不建议使用) | ||
| 141 | + * | ||
| 142 | + * @param activity 需要设置的 activity | ||
| 143 | + * @param color 状态栏颜色值 | ||
| 144 | + */ | ||
| 145 | + @Deprecated | ||
| 146 | + public static void setColorDiff(Activity activity, @ColorInt int color) { | ||
| 147 | + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { | ||
| 148 | + return; | ||
| 149 | + } | ||
| 150 | + transparentStatusBar(activity); | ||
| 151 | + ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content); | ||
| 152 | + // 移除半透明矩形,以免叠加 | ||
| 153 | + View fakeStatusBarView = contentView.findViewById(FAKE_STATUS_BAR_VIEW_ID); | ||
| 154 | + if (fakeStatusBarView != null) { | ||
| 155 | + if (fakeStatusBarView.getVisibility() == View.GONE) { | ||
| 156 | + fakeStatusBarView.setVisibility(View.VISIBLE); | ||
| 157 | + } | ||
| 158 | + fakeStatusBarView.setBackgroundColor(color); | ||
| 159 | + } else { | ||
| 160 | + contentView.addView(createStatusBarView(activity, color)); | ||
| 161 | + } | ||
| 162 | + setRootView(activity); | ||
| 163 | + } | ||
| 164 | + | ||
| 165 | + /** | ||
| 166 | + * 使状态栏半透明 | ||
| 167 | + * <p> | ||
| 168 | + * 适用于图片作为背景的界面,此时需要图片填充到状态栏 | ||
| 169 | + * | ||
| 170 | + * @param activity 需要设置的activity | ||
| 171 | + */ | ||
| 172 | + public static void setTranslucent(Activity activity) { | ||
| 173 | + setTranslucent(activity, DEFAULT_STATUS_BAR_ALPHA); | ||
| 174 | + } | ||
| 175 | + | ||
| 176 | + /** | ||
| 177 | + * 使状态栏半透明 | ||
| 178 | + * <p> | ||
| 179 | + * 适用于图片作为背景的界面,此时需要图片填充到状态栏 | ||
| 180 | + * | ||
| 181 | + * @param activity 需要设置的activity | ||
| 182 | + * @param statusBarAlpha 状态栏透明度 | ||
| 183 | + */ | ||
| 184 | + public static void setTranslucent(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha) { | ||
| 185 | + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { | ||
| 186 | + return; | ||
| 187 | + } | ||
| 188 | + setTransparent(activity); | ||
| 189 | + addTranslucentView(activity, statusBarAlpha); | ||
| 190 | + } | ||
| 191 | + | ||
| 192 | + /** | ||
| 193 | + * 针对根布局是 CoordinatorLayout, 使状态栏半透明 | ||
| 194 | + * <p> | ||
| 195 | + * 适用于图片作为背景的界面,此时需要图片填充到状态栏 | ||
| 196 | + * | ||
| 197 | + * @param activity 需要设置的activity | ||
| 198 | + * @param statusBarAlpha 状态栏透明度 | ||
| 199 | + */ | ||
| 200 | + public static void setTranslucentForCoordinatorLayout(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha) { | ||
| 201 | + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { | ||
| 202 | + return; | ||
| 203 | + } | ||
| 204 | + transparentStatusBar(activity); | ||
| 205 | + addTranslucentView(activity, statusBarAlpha); | ||
| 206 | + } | ||
| 207 | + | ||
| 208 | + /** | ||
| 209 | + * 设置状态栏全透明 | ||
| 210 | + * | ||
| 211 | + * @param activity 需要设置的activity | ||
| 212 | + */ | ||
| 213 | + public static void setTransparent(Activity activity) { | ||
| 214 | + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { | ||
| 215 | + return; | ||
| 216 | + } | ||
| 217 | + transparentStatusBar(activity); | ||
| 218 | + setRootView(activity); | ||
| 219 | + } | ||
| 220 | + | ||
| 221 | + /** | ||
| 222 | + * 使状态栏透明(5.0以上半透明效果,不建议使用) | ||
| 223 | + * <p> | ||
| 224 | + * 适用于图片作为背景的界面,此时需要图片填充到状态栏 | ||
| 225 | + * | ||
| 226 | + * @param activity 需要设置的activity | ||
| 227 | + */ | ||
| 228 | + @Deprecated | ||
| 229 | + public static void setTranslucentDiff(Activity activity) { | ||
| 230 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { | ||
| 231 | + // 设置状态栏透明 | ||
| 232 | + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); | ||
| 233 | + setRootView(activity); | ||
| 234 | + } | ||
| 235 | + } | ||
| 236 | + | ||
| 237 | + /** | ||
| 238 | + * 为DrawerLayout 布局设置状态栏变色 | ||
| 239 | + * | ||
| 240 | + * @param activity 需要设置的activity | ||
| 241 | + * @param drawerLayout DrawerLayout | ||
| 242 | + * @param color 状态栏颜色值 | ||
| 243 | + */ | ||
| 244 | + public static void setColorForDrawerLayout(Activity activity, DrawerLayout drawerLayout, @ColorInt int color) { | ||
| 245 | + setColorForDrawerLayout(activity, drawerLayout, color, DEFAULT_STATUS_BAR_ALPHA); | ||
| 246 | + } | ||
| 247 | + | ||
| 248 | + /** | ||
| 249 | + * 为DrawerLayout 布局设置状态栏颜色,纯色 | ||
| 250 | + * | ||
| 251 | + * @param activity 需要设置的activity | ||
| 252 | + * @param drawerLayout DrawerLayout | ||
| 253 | + * @param color 状态栏颜色值 | ||
| 254 | + */ | ||
| 255 | + public static void setColorNoTranslucentForDrawerLayout(Activity activity, DrawerLayout drawerLayout, @ColorInt int color) { | ||
| 256 | + setColorForDrawerLayout(activity, drawerLayout, color, 0); | ||
| 257 | + } | ||
| 258 | + | ||
| 259 | + /** | ||
| 260 | + * 为DrawerLayout 布局设置状态栏变色 | ||
| 261 | + * | ||
| 262 | + * @param activity 需要设置的activity | ||
| 263 | + * @param drawerLayout DrawerLayout | ||
| 264 | + * @param color 状态栏颜色值 | ||
| 265 | + * @param statusBarAlpha 状态栏透明度 | ||
| 266 | + */ | ||
| 267 | + public static void setColorForDrawerLayout(Activity activity, DrawerLayout drawerLayout, @ColorInt int color, | ||
| 268 | + @IntRange(from = 0, to = 255) int statusBarAlpha) { | ||
| 269 | + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { | ||
| 270 | + return; | ||
| 271 | + } | ||
| 272 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { | ||
| 273 | + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); | ||
| 274 | + activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); | ||
| 275 | + activity.getWindow().setStatusBarColor(Color.TRANSPARENT); | ||
| 276 | + } else { | ||
| 277 | + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); | ||
| 278 | + } | ||
| 279 | + // 生成一个状态栏大小的矩形 | ||
| 280 | + // 添加 statusBarView 到布局中 | ||
| 281 | + ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0); | ||
| 282 | + View fakeStatusBarView = contentLayout.findViewById(FAKE_STATUS_BAR_VIEW_ID); | ||
| 283 | + if (fakeStatusBarView != null) { | ||
| 284 | + if (fakeStatusBarView.getVisibility() == View.GONE) { | ||
| 285 | + fakeStatusBarView.setVisibility(View.VISIBLE); | ||
| 286 | + } | ||
| 287 | + fakeStatusBarView.setBackgroundColor(color); | ||
| 288 | + } else { | ||
| 289 | + contentLayout.addView(createStatusBarView(activity, color), 0); | ||
| 290 | + } | ||
| 291 | + // 内容布局不是 LinearLayout 时,设置padding top | ||
| 292 | + if (!(contentLayout instanceof LinearLayout) && contentLayout.getChildAt(1) != null) { | ||
| 293 | + contentLayout.getChildAt(1) | ||
| 294 | + .setPadding(contentLayout.getPaddingLeft(), getStatusBarHeight(activity) + contentLayout.getPaddingTop(), | ||
| 295 | + contentLayout.getPaddingRight(), contentLayout.getPaddingBottom()); | ||
| 296 | + } | ||
| 297 | + // 设置属性 | ||
| 298 | + setDrawerLayoutProperty(drawerLayout, contentLayout); | ||
| 299 | + addTranslucentView(activity, statusBarAlpha); | ||
| 300 | + } | ||
| 301 | + | ||
| 302 | + /** | ||
| 303 | + * 设置 DrawerLayout 属性 | ||
| 304 | + * | ||
| 305 | + * @param drawerLayout DrawerLayout | ||
| 306 | + * @param drawerLayoutContentLayout DrawerLayout 的内容布局 | ||
| 307 | + */ | ||
| 308 | + private static void setDrawerLayoutProperty(DrawerLayout drawerLayout, ViewGroup drawerLayoutContentLayout) { | ||
| 309 | + ViewGroup drawer = (ViewGroup) drawerLayout.getChildAt(1); | ||
| 310 | + drawerLayout.setFitsSystemWindows(false); | ||
| 311 | + drawerLayoutContentLayout.setFitsSystemWindows(false); | ||
| 312 | + drawerLayoutContentLayout.setClipToPadding(true); | ||
| 313 | + drawer.setFitsSystemWindows(false); | ||
| 314 | + } | ||
| 315 | + | ||
| 316 | + /** | ||
| 317 | + * 为DrawerLayout 布局设置状态栏变色(5.0以下无半透明效果,不建议使用) | ||
| 318 | + * | ||
| 319 | + * @param activity 需要设置的activity | ||
| 320 | + * @param drawerLayout DrawerLayout | ||
| 321 | + * @param color 状态栏颜色值 | ||
| 322 | + */ | ||
| 323 | + @Deprecated | ||
| 324 | + public static void setColorForDrawerLayoutDiff(Activity activity, DrawerLayout drawerLayout, @ColorInt int color) { | ||
| 325 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { | ||
| 326 | + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); | ||
| 327 | + // 生成一个状态栏大小的矩形 | ||
| 328 | + ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0); | ||
| 329 | + View fakeStatusBarView = contentLayout.findViewById(FAKE_STATUS_BAR_VIEW_ID); | ||
| 330 | + if (fakeStatusBarView != null) { | ||
| 331 | + if (fakeStatusBarView.getVisibility() == View.GONE) { | ||
| 332 | + fakeStatusBarView.setVisibility(View.VISIBLE); | ||
| 333 | + } | ||
| 334 | + fakeStatusBarView.setBackgroundColor(calculateStatusColor(color, DEFAULT_STATUS_BAR_ALPHA)); | ||
| 335 | + } else { | ||
| 336 | + // 添加 statusBarView 到布局中 | ||
| 337 | + contentLayout.addView(createStatusBarView(activity, color), 0); | ||
| 338 | + } | ||
| 339 | + // 内容布局不是 LinearLayout 时,设置padding top | ||
| 340 | + if (!(contentLayout instanceof LinearLayout) && contentLayout.getChildAt(1) != null) { | ||
| 341 | + contentLayout.getChildAt(1).setPadding(0, getStatusBarHeight(activity), 0, 0); | ||
| 342 | + } | ||
| 343 | + // 设置属性 | ||
| 344 | + setDrawerLayoutProperty(drawerLayout, contentLayout); | ||
| 345 | + } | ||
| 346 | + } | ||
| 347 | + | ||
| 348 | + /** | ||
| 349 | + * 为 DrawerLayout 布局设置状态栏透明 | ||
| 350 | + * | ||
| 351 | + * @param activity 需要设置的activity | ||
| 352 | + * @param drawerLayout DrawerLayout | ||
| 353 | + */ | ||
| 354 | + public static void setTranslucentForDrawerLayout(Activity activity, DrawerLayout drawerLayout) { | ||
| 355 | + setTranslucentForDrawerLayout(activity, drawerLayout, DEFAULT_STATUS_BAR_ALPHA); | ||
| 356 | + } | ||
| 357 | + | ||
| 358 | + /** | ||
| 359 | + * 为 DrawerLayout 布局设置状态栏透明 | ||
| 360 | + * | ||
| 361 | + * @param activity 需要设置的activity | ||
| 362 | + * @param drawerLayout DrawerLayout | ||
| 363 | + */ | ||
| 364 | + public static void setTranslucentForDrawerLayout(Activity activity, DrawerLayout drawerLayout, | ||
| 365 | + @IntRange(from = 0, to = 255) int statusBarAlpha) { | ||
| 366 | + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { | ||
| 367 | + return; | ||
| 368 | + } | ||
| 369 | + setTransparentForDrawerLayout(activity, drawerLayout); | ||
| 370 | + addTranslucentView(activity, statusBarAlpha); | ||
| 371 | + } | ||
| 372 | + | ||
| 373 | + /** | ||
| 374 | + * 为 DrawerLayout 布局设置状态栏透明 | ||
| 375 | + * | ||
| 376 | + * @param activity 需要设置的activity | ||
| 377 | + * @param drawerLayout DrawerLayout | ||
| 378 | + */ | ||
| 379 | + public static void setTransparentForDrawerLayout(Activity activity, DrawerLayout drawerLayout) { | ||
| 380 | + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { | ||
| 381 | + return; | ||
| 382 | + } | ||
| 383 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { | ||
| 384 | + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); | ||
| 385 | + activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); | ||
| 386 | + activity.getWindow().setStatusBarColor(Color.TRANSPARENT); | ||
| 387 | + } else { | ||
| 388 | + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); | ||
| 389 | + } | ||
| 390 | + | ||
| 391 | + ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0); | ||
| 392 | + // 内容布局不是 LinearLayout 时,设置padding top | ||
| 393 | + if (!(contentLayout instanceof LinearLayout) && contentLayout.getChildAt(1) != null) { | ||
| 394 | + contentLayout.getChildAt(1).setPadding(0, getStatusBarHeight(activity), 0, 0); | ||
| 395 | + } | ||
| 396 | + | ||
| 397 | + // 设置属性 | ||
| 398 | + setDrawerLayoutProperty(drawerLayout, contentLayout); | ||
| 399 | + } | ||
| 400 | + | ||
| 401 | + /** | ||
| 402 | + * 为 DrawerLayout 布局设置状态栏透明(5.0以上半透明效果,不建议使用) | ||
| 403 | + * | ||
| 404 | + * @param activity 需要设置的activity | ||
| 405 | + * @param drawerLayout DrawerLayout | ||
| 406 | + */ | ||
| 407 | + @Deprecated | ||
| 408 | + public static void setTranslucentForDrawerLayoutDiff(Activity activity, DrawerLayout drawerLayout) { | ||
| 409 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { | ||
| 410 | + // 设置状态栏透明 | ||
| 411 | + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); | ||
| 412 | + // 设置内容布局属性 | ||
| 413 | + ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0); | ||
| 414 | + contentLayout.setFitsSystemWindows(true); | ||
| 415 | + contentLayout.setClipToPadding(true); | ||
| 416 | + // 设置抽屉布局属性 | ||
| 417 | + ViewGroup vg = (ViewGroup) drawerLayout.getChildAt(1); | ||
| 418 | + vg.setFitsSystemWindows(false); | ||
| 419 | + // 设置 DrawerLayout 属性 | ||
| 420 | + drawerLayout.setFitsSystemWindows(false); | ||
| 421 | + } | ||
| 422 | + } | ||
| 423 | + | ||
| 424 | + /** | ||
| 425 | + * 为头部是 ImageView 的界面设置状态栏全透明 | ||
| 426 | + * | ||
| 427 | + * @param activity 需要设置的activity | ||
| 428 | + * @param needOffsetView 需要向下偏移的 View | ||
| 429 | + */ | ||
| 430 | + public static void setTransparentForImageView(Activity activity, View needOffsetView) { | ||
| 431 | + setTranslucentForImageView(activity, 0, needOffsetView); | ||
| 432 | + } | ||
| 433 | + | ||
| 434 | + /** | ||
| 435 | + * 为头部是 ImageView 的界面设置状态栏透明(使用默认透明度) | ||
| 436 | + * | ||
| 437 | + * @param activity 需要设置的activity | ||
| 438 | + * @param needOffsetView 需要向下偏移的 View | ||
| 439 | + */ | ||
| 440 | + public static void setTranslucentForImageView(Activity activity, View needOffsetView) { | ||
| 441 | + setTranslucentForImageView(activity, DEFAULT_STATUS_BAR_ALPHA, needOffsetView); | ||
| 442 | + } | ||
| 443 | + | ||
| 444 | + /** | ||
| 445 | + * 为头部是 ImageView 的界面设置状态栏透明 | ||
| 446 | + * | ||
| 447 | + * @param activity 需要设置的activity | ||
| 448 | + * @param statusBarAlpha 状态栏透明度 | ||
| 449 | + * @param needOffsetView 需要向下偏移的 View | ||
| 450 | + */ | ||
| 451 | + public static void setTranslucentForImageView(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha, | ||
| 452 | + View needOffsetView) { | ||
| 453 | + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { | ||
| 454 | + return; | ||
| 455 | + } | ||
| 456 | + setTransparentForWindow(activity); | ||
| 457 | + addTranslucentView(activity, statusBarAlpha); | ||
| 458 | + if (needOffsetView != null) { | ||
| 459 | + Object haveSetOffset = needOffsetView.getTag(TAG_KEY_HAVE_SET_OFFSET); | ||
| 460 | + if (haveSetOffset != null && (Boolean) haveSetOffset) { | ||
| 461 | + return; | ||
| 462 | + } | ||
| 463 | + ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) needOffsetView.getLayoutParams(); | ||
| 464 | + layoutParams.setMargins(layoutParams.leftMargin, layoutParams.topMargin + getStatusBarHeight(activity), | ||
| 465 | + layoutParams.rightMargin, layoutParams.bottomMargin); | ||
| 466 | + needOffsetView.setTag(TAG_KEY_HAVE_SET_OFFSET, true); | ||
| 467 | + } | ||
| 468 | + } | ||
| 469 | + | ||
| 470 | + /** | ||
| 471 | + * 为 fragment 头部是 ImageView 的设置状态栏透明 | ||
| 472 | + * | ||
| 473 | + * @param activity fragment 对应的 activity | ||
| 474 | + * @param needOffsetView 需要向下偏移的 View | ||
| 475 | + */ | ||
| 476 | + public static void setTranslucentForImageViewInFragment(Activity activity, View needOffsetView) { | ||
| 477 | + setTranslucentForImageViewInFragment(activity, DEFAULT_STATUS_BAR_ALPHA, needOffsetView); | ||
| 478 | + } | ||
| 479 | + | ||
| 480 | + /** | ||
| 481 | + * 为 fragment 头部是 ImageView 的设置状态栏透明 | ||
| 482 | + * | ||
| 483 | + * @param activity fragment 对应的 activity | ||
| 484 | + * @param needOffsetView 需要向下偏移的 View | ||
| 485 | + */ | ||
| 486 | + public static void setTransparentForImageViewInFragment(Activity activity, View needOffsetView) { | ||
| 487 | + setTranslucentForImageViewInFragment(activity, 0, needOffsetView); | ||
| 488 | + } | ||
| 489 | + | ||
| 490 | + /** | ||
| 491 | + * 为 fragment 头部是 ImageView 的设置状态栏透明 | ||
| 492 | + * | ||
| 493 | + * @param activity fragment 对应的 activity | ||
| 494 | + * @param statusBarAlpha 状态栏透明度 | ||
| 495 | + * @param needOffsetView 需要向下偏移的 View | ||
| 496 | + */ | ||
| 497 | + public static void setTranslucentForImageViewInFragment(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha, | ||
| 498 | + View needOffsetView) { | ||
| 499 | + setTranslucentForImageView(activity, statusBarAlpha, needOffsetView); | ||
| 500 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { | ||
| 501 | + clearPreviousSetting(activity); | ||
| 502 | + } | ||
| 503 | + } | ||
| 504 | + | ||
| 505 | + /** | ||
| 506 | + * 隐藏伪状态栏 View | ||
| 507 | + * | ||
| 508 | + * @param activity 调用的 Activity | ||
| 509 | + */ | ||
| 510 | + public static void hideFakeStatusBarView(Activity activity) { | ||
| 511 | + ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView(); | ||
| 512 | + View fakeStatusBarView = decorView.findViewById(FAKE_STATUS_BAR_VIEW_ID); | ||
| 513 | + if (fakeStatusBarView != null) { | ||
| 514 | + fakeStatusBarView.setVisibility(View.GONE); | ||
| 515 | + } | ||
| 516 | + View fakeTranslucentView = decorView.findViewById(FAKE_TRANSLUCENT_VIEW_ID); | ||
| 517 | + if (fakeTranslucentView != null) { | ||
| 518 | + fakeTranslucentView.setVisibility(View.GONE); | ||
| 519 | + } | ||
| 520 | + } | ||
| 521 | + | ||
| 522 | + @TargetApi(Build.VERSION_CODES.M) | ||
| 523 | + public static void setLightMode(Activity activity) { | ||
| 524 | + setMIUIStatusBarDarkIcon(activity, true); | ||
| 525 | + setMeizuStatusBarDarkIcon(activity, true); | ||
| 526 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { | ||
| 527 | + activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); | ||
| 528 | + } | ||
| 529 | + } | ||
| 530 | + | ||
| 531 | + @TargetApi(Build.VERSION_CODES.M) | ||
| 532 | + public static void setDarkMode(Activity activity) { | ||
| 533 | + setMIUIStatusBarDarkIcon(activity, false); | ||
| 534 | + setMeizuStatusBarDarkIcon(activity, false); | ||
| 535 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { | ||
| 536 | + activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); | ||
| 537 | + } | ||
| 538 | + } | ||
| 539 | + | ||
| 540 | + /** | ||
| 541 | + * 修改 MIUI V6 以上状态栏颜色 | ||
| 542 | + */ | ||
| 543 | + private static void setMIUIStatusBarDarkIcon(@NonNull Activity activity, boolean darkIcon) { | ||
| 544 | + Class<? extends Window> clazz = activity.getWindow().getClass(); | ||
| 545 | + try { | ||
| 546 | + Class<?> layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams"); | ||
| 547 | + Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE"); | ||
| 548 | + int darkModeFlag = field.getInt(layoutParams); | ||
| 549 | + Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class); | ||
| 550 | + extraFlagField.invoke(activity.getWindow(), darkIcon ? darkModeFlag : 0, darkModeFlag); | ||
| 551 | + } catch (Exception e) { | ||
| 552 | + //e.printStackTrace(); | ||
| 553 | + } | ||
| 554 | + } | ||
| 555 | + | ||
| 556 | + /** | ||
| 557 | + * 修改魅族状态栏字体颜色 Flyme 4.0 | ||
| 558 | + */ | ||
| 559 | + private static void setMeizuStatusBarDarkIcon(@NonNull Activity activity, boolean darkIcon) { | ||
| 560 | + try { | ||
| 561 | + WindowManager.LayoutParams lp = activity.getWindow().getAttributes(); | ||
| 562 | + Field darkFlag = WindowManager.LayoutParams.class.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON"); | ||
| 563 | + Field meizuFlags = WindowManager.LayoutParams.class.getDeclaredField("meizuFlags"); | ||
| 564 | + darkFlag.setAccessible(true); | ||
| 565 | + meizuFlags.setAccessible(true); | ||
| 566 | + int bit = darkFlag.getInt(null); | ||
| 567 | + int value = meizuFlags.getInt(lp); | ||
| 568 | + if (darkIcon) { | ||
| 569 | + value |= bit; | ||
| 570 | + } else { | ||
| 571 | + value &= ~bit; | ||
| 572 | + } | ||
| 573 | + meizuFlags.setInt(lp, value); | ||
| 574 | + activity.getWindow().setAttributes(lp); | ||
| 575 | + } catch (Exception e) { | ||
| 576 | + //e.printStackTrace(); | ||
| 577 | + } | ||
| 578 | + } | ||
| 579 | + | ||
| 580 | + /////////////////////////////////////////////////////////////////////////////////// | ||
| 581 | + | ||
| 582 | + @TargetApi(Build.VERSION_CODES.KITKAT) | ||
| 583 | + private static void clearPreviousSetting(Activity activity) { | ||
| 584 | + ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView(); | ||
| 585 | + View fakeStatusBarView = decorView.findViewById(FAKE_STATUS_BAR_VIEW_ID); | ||
| 586 | + if (fakeStatusBarView != null) { | ||
| 587 | + decorView.removeView(fakeStatusBarView); | ||
| 588 | + ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0); | ||
| 589 | + rootView.setPadding(0, 0, 0, 0); | ||
| 590 | + } | ||
| 591 | + } | ||
| 592 | + | ||
| 593 | + /** | ||
| 594 | + * 添加半透明矩形条 | ||
| 595 | + * | ||
| 596 | + * @param activity 需要设置的 activity | ||
| 597 | + * @param statusBarAlpha 透明值 | ||
| 598 | + */ | ||
| 599 | + public static void addTranslucentView(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha) { | ||
| 600 | + ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content); | ||
| 601 | + View fakeTranslucentView = contentView.findViewById(FAKE_TRANSLUCENT_VIEW_ID); | ||
| 602 | + if (fakeTranslucentView != null) { | ||
| 603 | + if (fakeTranslucentView.getVisibility() == View.GONE) { | ||
| 604 | + fakeTranslucentView.setVisibility(View.VISIBLE); | ||
| 605 | + } | ||
| 606 | + fakeTranslucentView.setBackgroundColor(Color.argb(statusBarAlpha, 0, 0, 0)); | ||
| 607 | + } else { | ||
| 608 | + contentView.addView(createTranslucentStatusBarView(activity, statusBarAlpha)); | ||
| 609 | + } | ||
| 610 | + } | ||
| 611 | + | ||
| 612 | + /** | ||
| 613 | + * 生成一个和状态栏大小相同的彩色矩形条 | ||
| 614 | + * | ||
| 615 | + * @param activity 需要设置的 activity | ||
| 616 | + * @param color 状态栏颜色值 | ||
| 617 | + * @return 状态栏矩形条 | ||
| 618 | + */ | ||
| 619 | + private static View createStatusBarView(Activity activity, @ColorInt int color) { | ||
| 620 | + return createStatusBarView(activity, color, 0); | ||
| 621 | + } | ||
| 622 | + | ||
| 623 | + /** | ||
| 624 | + * 生成一个和状态栏大小相同的半透明矩形条 | ||
| 625 | + * | ||
| 626 | + * @param activity 需要设置的activity | ||
| 627 | + * @param color 状态栏颜色值 | ||
| 628 | + * @param alpha 透明值 | ||
| 629 | + * @return 状态栏矩形条 | ||
| 630 | + */ | ||
| 631 | + private static View createStatusBarView(Activity activity, @ColorInt int color, int alpha) { | ||
| 632 | + // 绘制一个和状态栏一样高的矩形 | ||
| 633 | + View statusBarView = new View(activity); | ||
| 634 | + LinearLayout.LayoutParams params = | ||
| 635 | + new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity)); | ||
| 636 | + statusBarView.setLayoutParams(params); | ||
| 637 | + statusBarView.setBackgroundColor(calculateStatusColor(color, alpha)); | ||
| 638 | + statusBarView.setId(FAKE_STATUS_BAR_VIEW_ID); | ||
| 639 | + return statusBarView; | ||
| 640 | + } | ||
| 641 | + | ||
| 642 | + /** | ||
| 643 | + * 设置根布局参数 | ||
| 644 | + */ | ||
| 645 | + private static void setRootView(Activity activity) { | ||
| 646 | + ViewGroup parent = (ViewGroup) activity.findViewById(android.R.id.content); | ||
| 647 | + for (int i = 0, count = parent.getChildCount(); i < count; i++) { | ||
| 648 | + View childView = parent.getChildAt(i); | ||
| 649 | + if (childView instanceof ViewGroup) { | ||
| 650 | + childView.setFitsSystemWindows(true); | ||
| 651 | + ((ViewGroup) childView).setClipToPadding(true); | ||
| 652 | + } | ||
| 653 | + } | ||
| 654 | + } | ||
| 655 | + | ||
| 656 | + /** | ||
| 657 | + * 设置透明 | ||
| 658 | + */ | ||
| 659 | + public static void setTransparentForWindow(Activity activity) { | ||
| 660 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { | ||
| 661 | + activity.getWindow().setStatusBarColor(Color.TRANSPARENT); | ||
| 662 | + activity.getWindow() | ||
| 663 | + .getDecorView() | ||
| 664 | + .setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); | ||
| 665 | + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { | ||
| 666 | + activity.getWindow() | ||
| 667 | + .setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); | ||
| 668 | + } | ||
| 669 | + } | ||
| 670 | + | ||
| 671 | + /** | ||
| 672 | + * 使状态栏透明 | ||
| 673 | + */ | ||
| 674 | + @TargetApi(Build.VERSION_CODES.KITKAT) | ||
| 675 | + private static void transparentStatusBar(Activity activity) { | ||
| 676 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { | ||
| 677 | + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); | ||
| 678 | + activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); | ||
| 679 | + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); | ||
| 680 | + activity.getWindow().setStatusBarColor(Color.TRANSPARENT); | ||
| 681 | + } else { | ||
| 682 | + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); | ||
| 683 | + } | ||
| 684 | + } | ||
| 685 | + | ||
| 686 | + /** | ||
| 687 | + * 创建半透明矩形 View | ||
| 688 | + * | ||
| 689 | + * @param alpha 透明值 | ||
| 690 | + * @return 半透明 View | ||
| 691 | + */ | ||
| 692 | + private static View createTranslucentStatusBarView(Activity activity, int alpha) { | ||
| 693 | + // 绘制一个和状态栏一样高的矩形 | ||
| 694 | + View statusBarView = new View(activity); | ||
| 695 | + LinearLayout.LayoutParams params = | ||
| 696 | + new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity)); | ||
| 697 | + statusBarView.setLayoutParams(params); | ||
| 698 | + statusBarView.setBackgroundColor(Color.argb(alpha, 0, 0, 0)); | ||
| 699 | + statusBarView.setId(FAKE_TRANSLUCENT_VIEW_ID); | ||
| 700 | + return statusBarView; | ||
| 701 | + } | ||
| 702 | + | ||
| 703 | + /** | ||
| 704 | + * 获取状态栏高度 | ||
| 705 | + * | ||
| 706 | + * @param context context | ||
| 707 | + * @return 状态栏高度 | ||
| 708 | + */ | ||
| 709 | + public static int getStatusBarHeight(Context context) { | ||
| 710 | + // 获得状态栏高度 | ||
| 711 | + int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); | ||
| 712 | + return context.getResources().getDimensionPixelSize(resourceId); | ||
| 713 | + } | ||
| 714 | + | ||
| 715 | + /** | ||
| 716 | + * 计算状态栏颜色 | ||
| 717 | + * | ||
| 718 | + * @param color color值 | ||
| 719 | + * @param alpha alpha值 | ||
| 720 | + * @return 最终的状态栏颜色 | ||
| 721 | + */ | ||
| 722 | + private static int calculateStatusColor(@ColorInt int color, int alpha) { | ||
| 723 | + if (alpha == 0) { | ||
| 724 | + return color; | ||
| 725 | + } | ||
| 726 | + float a = 1 - alpha / 255f; | ||
| 727 | + int red = color >> 16 & 0xff; | ||
| 728 | + int green = color >> 8 & 0xff; | ||
| 729 | + int blue = color & 0xff; | ||
| 730 | + red = (int) (red * a + 0.5); | ||
| 731 | + green = (int) (green * a + 0.5); | ||
| 732 | + blue = (int) (blue * a + 0.5); | ||
| 733 | + return 0xff << 24 | red << 16 | green << 8 | blue; | ||
| 734 | + } | ||
| 735 | +} |
lib_media/src/main/java/com/cnlive/libs/base/util/StringUtils.java
0 → 100644
| 1 | +package com.cnlive.libs.base.util; | ||
| 2 | + | ||
| 3 | +import android.annotation.TargetApi; | ||
| 4 | +import android.nfc.NdefRecord; | ||
| 5 | +import android.os.Build; | ||
| 6 | +import android.text.TextPaint; | ||
| 7 | +import android.util.Base64; | ||
| 8 | +import android.util.Log; | ||
| 9 | + | ||
| 10 | +import java.net.URLDecoder; | ||
| 11 | +import java.net.URLEncoder; | ||
| 12 | +import java.nio.charset.Charset; | ||
| 13 | +import java.text.DecimalFormat; | ||
| 14 | +import java.text.SimpleDateFormat; | ||
| 15 | +import java.util.ArrayList; | ||
| 16 | +import java.util.Calendar; | ||
| 17 | +import java.util.Date; | ||
| 18 | +import java.util.Iterator; | ||
| 19 | +import java.util.Locale; | ||
| 20 | +import java.util.TimeZone; | ||
| 21 | +import java.util.regex.Matcher; | ||
| 22 | +import java.util.regex.Pattern; | ||
| 23 | + | ||
| 24 | + | ||
| 25 | +/** | ||
| 26 | + * 字符串工具类 | ||
| 27 | + * | ||
| 28 | + * @author tangjun | ||
| 29 | + */ | ||
| 30 | +public class StringUtils { | ||
| 31 | + | ||
| 32 | + public static final String EMPTY = ""; | ||
| 33 | + public static final SimpleDateFormat DATE_FORMAT_PART = new SimpleDateFormat( | ||
| 34 | + "HH:mm", Locale.getDefault()); | ||
| 35 | + private static final String TAG = StringUtils.class.getSimpleName(); | ||
| 36 | + private static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd"; | ||
| 37 | + private static final String DEFAULT_DATETIME_PATTERN = "yyyy-MM-dd hh:mm:ss"; | ||
| 38 | + /** | ||
| 39 | + * 用于生成文件 | ||
| 40 | + */ | ||
| 41 | + private static final String DEFAULT_FILE_PATTERN = "yyyy-MM-dd-HH-mm-ss"; | ||
| 42 | + private static final double KB = 1024.0; | ||
| 43 | + private static final double MB = 1048576.0; | ||
| 44 | + private static final double GB = 1073741824.0; | ||
| 45 | + | ||
| 46 | + public static String currentTimeString() { | ||
| 47 | + return DATE_FORMAT_PART.format(Calendar.getInstance().getTime()); | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + public static char chatAt(String pinyin, int index) { | ||
| 51 | + if (pinyin != null && pinyin.length() > 0) | ||
| 52 | + return pinyin.charAt(index); | ||
| 53 | + return ' '; | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | + /** | ||
| 57 | + * 获取字符串宽度 | ||
| 58 | + */ | ||
| 59 | + public static float GetTextWidth(String Sentence, float Size) { | ||
| 60 | + if (isEmpty(Sentence)) | ||
| 61 | + return 0; | ||
| 62 | + TextPaint FontPaint = new TextPaint(); | ||
| 63 | + FontPaint.setTextSize(Size); | ||
| 64 | + return FontPaint.measureText(Sentence.trim()) + (int) (Size * 0.1); // 留点余地 | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + /** | ||
| 68 | + * 格式化日期字符串 | ||
| 69 | + * | ||
| 70 | + * @param date | ||
| 71 | + * @param pattern | ||
| 72 | + * @return | ||
| 73 | + */ | ||
| 74 | + public static String formatDate(Date date, String pattern) { | ||
| 75 | + SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.getDefault()); | ||
| 76 | + return format.format(date); | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + /** | ||
| 80 | + * 格式化日期字符串 | ||
| 81 | + * | ||
| 82 | + * @param date | ||
| 83 | + * @return 例如2011-3-24 | ||
| 84 | + */ | ||
| 85 | + public static String formatDate(Date date) { | ||
| 86 | + return formatDate(date, DEFAULT_DATE_PATTERN); | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | + public static String formatDate(long date) { | ||
| 90 | + return formatDate(new Date(date), DEFAULT_DATE_PATTERN); | ||
| 91 | + } | ||
| 92 | + | ||
| 93 | + /** | ||
| 94 | + * 获取当前时间 格式为yyyy-MM-dd 例如2011-07-08 | ||
| 95 | + * | ||
| 96 | + * @return | ||
| 97 | + */ | ||
| 98 | + public static String getDate() { | ||
| 99 | + return formatDate(new Date(), DEFAULT_DATE_PATTERN); | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + /** | ||
| 103 | + * 生成一个文件名,不含后缀 | ||
| 104 | + */ | ||
| 105 | + public static String createFileName() { | ||
| 106 | + Date date = new Date(System.currentTimeMillis()); | ||
| 107 | + SimpleDateFormat format = new SimpleDateFormat(DEFAULT_FILE_PATTERN, Locale.getDefault()); | ||
| 108 | + return format.format(date); | ||
| 109 | + } | ||
| 110 | + | ||
| 111 | + /** | ||
| 112 | + * 获取当前时间 | ||
| 113 | + * | ||
| 114 | + * @return | ||
| 115 | + */ | ||
| 116 | + public static String getDateTime() { | ||
| 117 | + return formatDate(new Date(), DEFAULT_DATETIME_PATTERN); | ||
| 118 | + } | ||
| 119 | + | ||
| 120 | + /** | ||
| 121 | + * 格式化日期时间字符串 | ||
| 122 | + * | ||
| 123 | + * @param date | ||
| 124 | + * @return 例如2011-11-30 16:06:54 | ||
| 125 | + */ | ||
| 126 | + public static String formatDateTime(Date date) { | ||
| 127 | + return formatDate(date, DEFAULT_DATETIME_PATTERN); | ||
| 128 | + } | ||
| 129 | + | ||
| 130 | + public static String formatDateTime(long date) { | ||
| 131 | + return formatDate(new Date(date), DEFAULT_DATETIME_PATTERN); | ||
| 132 | + } | ||
| 133 | + | ||
| 134 | + /** | ||
| 135 | + * 格林威时间转换 | ||
| 136 | + * | ||
| 137 | + * @param gmt | ||
| 138 | + * @return | ||
| 139 | + */ | ||
| 140 | + public static String formatGMTDate(String gmt) { | ||
| 141 | + TimeZone timeZoneLondon = TimeZone.getTimeZone(gmt); | ||
| 142 | + return formatDate(Calendar.getInstance(timeZoneLondon) | ||
| 143 | + .getTimeInMillis()); | ||
| 144 | + } | ||
| 145 | + | ||
| 146 | + /** | ||
| 147 | + * 拼接数组 | ||
| 148 | + * | ||
| 149 | + * @param array | ||
| 150 | + * @param separator | ||
| 151 | + * @return | ||
| 152 | + */ | ||
| 153 | + public static String join(final ArrayList<String> array, | ||
| 154 | + final String separator) { | ||
| 155 | + StringBuffer result = new StringBuffer(); | ||
| 156 | + if (array != null && array.size() > 0) { | ||
| 157 | + for (String str : array) { | ||
| 158 | + result.append(str); | ||
| 159 | + result.append(separator); | ||
| 160 | + } | ||
| 161 | + result.delete(result.length() - 1, result.length()); | ||
| 162 | + } | ||
| 163 | + return result.toString(); | ||
| 164 | + } | ||
| 165 | + | ||
| 166 | + public static String join(final Iterator<String> iter, | ||
| 167 | + final String separator) { | ||
| 168 | + StringBuffer result = new StringBuffer(); | ||
| 169 | + if (iter != null) { | ||
| 170 | + while (iter.hasNext()) { | ||
| 171 | + String key = iter.next(); | ||
| 172 | + result.append(key); | ||
| 173 | + result.append(separator); | ||
| 174 | + } | ||
| 175 | + if (result.length() > 0) | ||
| 176 | + result.delete(result.length() - 1, result.length()); | ||
| 177 | + } | ||
| 178 | + return result.toString(); | ||
| 179 | + } | ||
| 180 | + | ||
| 181 | + /** | ||
| 182 | + * 判断字符串是否为空 | ||
| 183 | + * | ||
| 184 | + * @param str | ||
| 185 | + * @return | ||
| 186 | + */ | ||
| 187 | + public static boolean isEmpty(String str) { | ||
| 188 | + return str == null || str.length() == 0 || str.equals("null"); | ||
| 189 | + } | ||
| 190 | + | ||
| 191 | + /** | ||
| 192 | + * @param str | ||
| 193 | + * @return | ||
| 194 | + */ | ||
| 195 | + public static String trim(String str) { | ||
| 196 | + return str == null ? EMPTY : str.trim(); | ||
| 197 | + } | ||
| 198 | + | ||
| 199 | + /** | ||
| 200 | + * 转换时间显示 | ||
| 201 | + * | ||
| 202 | + * @param time 毫秒 | ||
| 203 | + * @return | ||
| 204 | + */ | ||
| 205 | + public static String generateTime(long time) { | ||
| 206 | + int totalSeconds = (int) (time / 1000); | ||
| 207 | + int seconds = totalSeconds % 60; | ||
| 208 | + int minutes = (totalSeconds / 60) % 60; | ||
| 209 | + int hours = totalSeconds / 3600; | ||
| 210 | + | ||
| 211 | + return hours > 0 ? String.format(Locale.getDefault(), "%02d:%02d:%02d", hours, minutes, | ||
| 212 | + seconds) : String.format(Locale.getDefault(), "%02d:%02d", minutes, seconds); | ||
| 213 | + } | ||
| 214 | + | ||
| 215 | + /** | ||
| 216 | + * 根据秒速获取时间格式 | ||
| 217 | + */ | ||
| 218 | + public static String gennerTime(int totalSeconds) { | ||
| 219 | + int seconds = totalSeconds % 60; | ||
| 220 | + int minutes = (totalSeconds / 60) % 60; | ||
| 221 | + return String.format(Locale.getDefault(), "%02d:%02d", minutes, seconds); | ||
| 222 | + } | ||
| 223 | + | ||
| 224 | + /** | ||
| 225 | + * 转换文件大小 | ||
| 226 | + * | ||
| 227 | + * @param size | ||
| 228 | + * @return | ||
| 229 | + */ | ||
| 230 | + public static String generateFileSize(long size) { | ||
| 231 | + String fileSize; | ||
| 232 | + if (size < KB) | ||
| 233 | + fileSize = size + "B"; | ||
| 234 | + else if (size < MB) | ||
| 235 | + fileSize = String.format("%.1f", size / KB) + "KB"; | ||
| 236 | + else if (size < GB) | ||
| 237 | + fileSize = String.format("%.1f", size / MB) + "MB"; | ||
| 238 | + else | ||
| 239 | + fileSize = String.format("%.1f", size / GB) + "GB"; | ||
| 240 | + | ||
| 241 | + return fileSize; | ||
| 242 | + } | ||
| 243 | + | ||
| 244 | + public static String getTimeDiff(long time) { | ||
| 245 | + // Calendar cal = Calendar.getInstance(); | ||
| 246 | + long diff = 0; | ||
| 247 | + // Date dnow = cal.getTime(); | ||
| 248 | + String str = ""; | ||
| 249 | + diff = System.currentTimeMillis() - time; | ||
| 250 | + | ||
| 251 | + if (diff > 2592000000L) {// 30 * 24 * 60 * 60 * 1000=2592000000 毫秒 | ||
| 252 | + str = "1个月前"; | ||
| 253 | + } else if (diff > 1814400000) {// 21 * 24 * 60 * 60 * 1000=1814400000 毫秒 | ||
| 254 | + str = "3周前"; | ||
| 255 | + } else if (diff > 1209600000) {// 14 * 24 * 60 * 60 * 1000=1209600000 毫秒 | ||
| 256 | + str = "2周前"; | ||
| 257 | + } else if (diff > 604800000) {// 7 * 24 * 60 * 60 * 1000=604800000 毫秒 | ||
| 258 | + str = "1周前"; | ||
| 259 | + } else if (diff > 86400000) { // 24 * 60 * 60 * 1000=86400000 毫秒 | ||
| 260 | + // System.out.println("X天前"); | ||
| 261 | + str = (int) Math.floor(diff / 86400000f) + "天前"; | ||
| 262 | + } else if (diff > 18000000) {// 5 * 60 * 60 * 1000=18000000 毫秒 | ||
| 263 | + // System.out.println("X小时前"); | ||
| 264 | + str = (int) Math.floor(diff / 18000000f) + "小时前"; | ||
| 265 | + } else if (diff > 60000) {// 1 * 60 * 1000=60000 毫秒 | ||
| 266 | + // System.out.println("X分钟前"); | ||
| 267 | + str = (int) Math.floor(diff / 60000) + "分钟前"; | ||
| 268 | + } else { | ||
| 269 | + str = (int) Math.floor(diff / 1000) + "秒前"; | ||
| 270 | + } | ||
| 271 | + return str; | ||
| 272 | + } | ||
| 273 | + | ||
| 274 | + /** | ||
| 275 | + * 截取字符串 | ||
| 276 | + * | ||
| 277 | + * @param search 待搜索的字符串 | ||
| 278 | + * @param start 起始字符串 例如:<title> | ||
| 279 | + * @param end 结束字符串 例如:</title> | ||
| 280 | + * @param defaultValue | ||
| 281 | + * @return | ||
| 282 | + */ | ||
| 283 | + public static String substring(String search, String start, String end, | ||
| 284 | + String defaultValue) { | ||
| 285 | + int start_len = start.length(); | ||
| 286 | + int start_pos = StringUtils.isEmpty(start) ? 0 : search.indexOf(start); | ||
| 287 | + if (start_pos > -1) { | ||
| 288 | + int end_pos = StringUtils.isEmpty(end) ? -1 : search.indexOf(end, | ||
| 289 | + start_pos + start_len); | ||
| 290 | + if (end_pos > -1) | ||
| 291 | + return search.substring(start_pos + start.length(), end_pos); | ||
| 292 | + else | ||
| 293 | + return search.substring(start_pos + start.length()); | ||
| 294 | + } | ||
| 295 | + return defaultValue; | ||
| 296 | + } | ||
| 297 | + | ||
| 298 | + /** | ||
| 299 | + * 截取字符串 | ||
| 300 | + * | ||
| 301 | + * @param search 待搜索的字符串 | ||
| 302 | + * @param start 起始字符串 例如:<title> | ||
| 303 | + * @param end 结束字符串 例如:</title> | ||
| 304 | + * @return | ||
| 305 | + */ | ||
| 306 | + public static String substring(String search, String start, String end) { | ||
| 307 | + return substring(search, start, end, ""); | ||
| 308 | + } | ||
| 309 | + | ||
| 310 | + /** | ||
| 311 | + * 拼接字符串 | ||
| 312 | + * | ||
| 313 | + * @param strs | ||
| 314 | + * @return | ||
| 315 | + */ | ||
| 316 | + public static String concat(String... strs) { | ||
| 317 | + StringBuffer result = new StringBuffer(); | ||
| 318 | + if (strs != null) { | ||
| 319 | + for (String str : strs) { | ||
| 320 | + if (str != null) | ||
| 321 | + result.append(str); | ||
| 322 | + } | ||
| 323 | + } | ||
| 324 | + return result.toString(); | ||
| 325 | + } | ||
| 326 | + | ||
| 327 | + /** | ||
| 328 | + * 获取中文字符个数 | ||
| 329 | + */ | ||
| 330 | + public static int getChineseCharCount(String str) { | ||
| 331 | + String tempStr; | ||
| 332 | + int count = 0; | ||
| 333 | + for (int i = 0; i < str.length(); i++) { | ||
| 334 | + tempStr = String.valueOf(str.charAt(i)); | ||
| 335 | + if (tempStr.getBytes().length == 3) { | ||
| 336 | + count++; | ||
| 337 | + } | ||
| 338 | + } | ||
| 339 | + return count; | ||
| 340 | + } | ||
| 341 | + | ||
| 342 | + /** | ||
| 343 | + * 获取英文字符个数 | ||
| 344 | + */ | ||
| 345 | + public static int getEnglishCount(String str) { | ||
| 346 | + String tempStr; | ||
| 347 | + int count = 0; | ||
| 348 | + for (int i = 0; i < str.length(); i++) { | ||
| 349 | + tempStr = String.valueOf(str.charAt(i)); | ||
| 350 | + if (!(tempStr.getBytes().length == 3)) { | ||
| 351 | + count++; | ||
| 352 | + } | ||
| 353 | + } | ||
| 354 | + return count; | ||
| 355 | + } | ||
| 356 | + | ||
| 357 | + public static String encode(String url) { | ||
| 358 | + try { | ||
| 359 | + return URLEncoder.encode(url, "UTF-8"); | ||
| 360 | + } catch (Exception e) { | ||
| 361 | + Log.e(TAG, e.getMessage(), e); | ||
| 362 | + } | ||
| 363 | + return url; | ||
| 364 | + } | ||
| 365 | + | ||
| 366 | + public static String base64encode(String value) { | ||
| 367 | + try { | ||
| 368 | + return new String(Base64.encode(value.getBytes(), Base64.DEFAULT)); | ||
| 369 | + } catch (Exception e) { | ||
| 370 | + Log.e(TAG, e.getMessage(), e); | ||
| 371 | + } | ||
| 372 | + return value; | ||
| 373 | + } | ||
| 374 | + | ||
| 375 | + public static String decode(String url) { | ||
| 376 | + try { | ||
| 377 | + return URLDecoder.decode(url, "UTF-8"); | ||
| 378 | + } catch (Exception e) { | ||
| 379 | + Log.e(TAG, e.getMessage(), e); | ||
| 380 | + } | ||
| 381 | + return url; | ||
| 382 | + } | ||
| 383 | + | ||
| 384 | + public static String base64decode(String value) { | ||
| 385 | + try { | ||
| 386 | + | ||
| 387 | + return new String(Base64.decode(value, Base64.DEFAULT)); | ||
| 388 | + } catch (Exception e) { | ||
| 389 | + Log.e(TAG, e.getMessage(), e); | ||
| 390 | + } | ||
| 391 | + return value; | ||
| 392 | + } | ||
| 393 | + | ||
| 394 | + @TargetApi(Build.VERSION_CODES.GINGERBREAD) | ||
| 395 | + public static NdefRecord createTextRecord(String payload, Locale locale, boolean encodeInUtf8) { | ||
| 396 | + byte[] langBytes = locale.getLanguage().getBytes(Charset.forName("US-ASCII")); | ||
| 397 | + Charset utfEncoding = encodeInUtf8 ? Charset.forName("UTF-8") : Charset.forName("UTF-16"); | ||
| 398 | + byte[] textBytes = payload.getBytes(utfEncoding); | ||
| 399 | + int utfBit = encodeInUtf8 ? 0 : (1 << 7); | ||
| 400 | + char status = (char) (utfBit + langBytes.length); | ||
| 401 | + byte[] data = new byte[1 + langBytes.length + textBytes.length]; | ||
| 402 | + data[0] = (byte) status; | ||
| 403 | + System.arraycopy(langBytes, 0, data, 1, langBytes.length); | ||
| 404 | + System.arraycopy(textBytes, 0, data, 1 + langBytes.length, textBytes.length); | ||
| 405 | + NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, | ||
| 406 | + NdefRecord.RTD_TEXT, new byte[0], data); | ||
| 407 | + return record; | ||
| 408 | + } | ||
| 409 | + | ||
| 410 | + /** | ||
| 411 | + * 转换中国币文字显示 | ||
| 412 | + * | ||
| 413 | + * @param gold | ||
| 414 | + * @return | ||
| 415 | + */ | ||
| 416 | + public static String generateGoldValue(int gold) { | ||
| 417 | + String goldstr; | ||
| 418 | + if (gold < 10000) { | ||
| 419 | + goldstr = gold + "中国币"; | ||
| 420 | + } else if (gold < 100000000) { | ||
| 421 | + goldstr = String.format(Locale.getDefault(), "%.1f万中国币", gold / 10000); | ||
| 422 | + } else | ||
| 423 | + goldstr = String.format(Locale.getDefault(), "%.1f亿中国币", gold / 100000000); | ||
| 424 | + return goldstr; | ||
| 425 | + } | ||
| 426 | + | ||
| 427 | + /** | ||
| 428 | + * 数量转换为万 | ||
| 429 | + */ | ||
| 430 | + public static String getNumDiff(int count, String sub) { | ||
| 431 | + String afterNum = ""; | ||
| 432 | + if (count >= 0 && count < 10000) { | ||
| 433 | + afterNum = count + sub; | ||
| 434 | + } else if (count >= 10000 && count < 10000000) { | ||
| 435 | + if (count / 1000 % 10 != 0) { | ||
| 436 | + float num = (float) count / 10000; | ||
| 437 | + DecimalFormat decimalFormat = new DecimalFormat("0.0"); | ||
| 438 | + afterNum = decimalFormat.format(num).concat("万" + sub); | ||
| 439 | + } else { | ||
| 440 | + afterNum = (count / 10000) + "万" + sub; | ||
| 441 | + } | ||
| 442 | + } else if (count >= 10000000) { | ||
| 443 | + afterNum = "1000万" + sub; | ||
| 444 | + } | ||
| 445 | + return afterNum; | ||
| 446 | + } | ||
| 447 | + | ||
| 448 | + /** | ||
| 449 | + * 利用正则表达式判断字符串是否是数字 | ||
| 450 | + * | ||
| 451 | + * @param str | ||
| 452 | + * @return | ||
| 453 | + */ | ||
| 454 | + public static boolean isNumeric(String str) { | ||
| 455 | + if (str == null || str.trim().length() == 0) return false; | ||
| 456 | + Pattern pattern = Pattern.compile("[0-9]*"); | ||
| 457 | + Matcher isNum = pattern.matcher(str); | ||
| 458 | + if (!isNum.matches()) { | ||
| 459 | + return false; | ||
| 460 | + } | ||
| 461 | + return true; | ||
| 462 | + } | ||
| 463 | + | ||
| 464 | + | ||
| 465 | + // private static final char[] cnNumbers = {'零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'}; | ||
| 466 | + private static final char[] cnNumbers = {'零', '一', '二', '三', '四', '五', '六', '七', '八', '九'}; | ||
| 467 | + // private static final char[] series = {' ', '拾', '百', '仟', '万', '拾', '百', '仟', '亿'}; | ||
| 468 | + private static final char[] series = {' ', '十', '百', '千', '万', '十', '百', '千', '亿'}; | ||
| 469 | + | ||
| 470 | + /** | ||
| 471 | + * 取得大写形式的字符串 | ||
| 472 | + */ | ||
| 473 | + public static String getCnString(Integer value) { | ||
| 474 | + // 整数部分 | ||
| 475 | + String integerPart = ""; | ||
| 476 | + // 小数部分 | ||
| 477 | + String floatPart = ""; | ||
| 478 | + | ||
| 479 | + String original = value.toString(); | ||
| 480 | + | ||
| 481 | + if (original.contains(".")) { | ||
| 482 | + // 如果包含小数点 | ||
| 483 | + int dotIndex = original.indexOf("."); | ||
| 484 | + integerPart = original.substring(0, dotIndex); | ||
| 485 | + floatPart = original.substring(dotIndex + 1); | ||
| 486 | + } else { | ||
| 487 | + // 不包含小数点 | ||
| 488 | + integerPart = original; | ||
| 489 | + } | ||
| 490 | + // 因为是累加所以用StringBuffer | ||
| 491 | + StringBuffer sb = new StringBuffer(); | ||
| 492 | + | ||
| 493 | + // 整数部分处理 | ||
| 494 | + for (int i = 0; i < integerPart.length(); i++) { | ||
| 495 | + int number = Integer.parseInt(String.valueOf(integerPart.charAt(i))); | ||
| 496 | + | ||
| 497 | + sb.append(cnNumbers[number]); | ||
| 498 | + sb.append(series[integerPart.length() - 1 - i]); | ||
| 499 | + } | ||
| 500 | + // 小数部分处理 | ||
| 501 | + if (floatPart.length() > 0) { | ||
| 502 | + sb.append("点"); | ||
| 503 | + for (int i = 0; i < floatPart.length(); i++) { | ||
| 504 | + int number = Integer.parseInt(String.valueOf(floatPart.charAt(i))); | ||
| 505 | + | ||
| 506 | + sb.append(cnNumbers[number]); | ||
| 507 | + } | ||
| 508 | + } | ||
| 509 | + | ||
| 510 | + // 返回拼接好的字符串 | ||
| 511 | + return sb.toString().trim(); | ||
| 512 | + } | ||
| 513 | + | ||
| 514 | + | ||
| 515 | +} |
lib_media/src/main/java/com/cnlive/media/ImagePicker.java
| @@ -11,7 +11,6 @@ import com.cnlive.media.media.entity.Media; | @@ -11,7 +11,6 @@ import com.cnlive.media.media.entity.Media; | ||
| 11 | import com.cnlive.media.ui.activity.MediaActivity; | 11 | import com.cnlive.media.ui.activity.MediaActivity; |
| 12 | import com.cnlive.media.ui.activity.MediaPreviewActivity; | 12 | import com.cnlive.media.ui.activity.MediaPreviewActivity; |
| 13 | import com.cnlive.media.ui.activity.RecordActivity; | 13 | import com.cnlive.media.ui.activity.RecordActivity; |
| 14 | -import com.qiniu.pili.droid.shortvideo.PLShortVideoEnv; | ||
| 15 | 14 | ||
| 16 | import java.util.ArrayList; | 15 | import java.util.ArrayList; |
| 17 | 16 |
lib_media/src/main/java/com/cnlive/media/frame/view/ImageCropView.java
| @@ -6,8 +6,8 @@ import android.graphics.Bitmap; | @@ -6,8 +6,8 @@ import android.graphics.Bitmap; | ||
| 6 | import android.net.Uri; | 6 | import android.net.Uri; |
| 7 | import android.os.Build; | 7 | import android.os.Build; |
| 8 | import android.text.TextUtils; | 8 | import android.text.TextUtils; |
| 9 | +import android.widget.Toast; | ||
| 9 | 10 | ||
| 10 | -import com.cnlive.libs.base.util.AlertUtil; | ||
| 11 | import com.cnlive.libs.base.util.FileUtils; | 11 | import com.cnlive.libs.base.util.FileUtils; |
| 12 | import com.cnlive.media.R; | 12 | import com.cnlive.media.R; |
| 13 | import com.cnlive.media.media.entity.Media; | 13 | import com.cnlive.media.media.entity.Media; |
| @@ -126,12 +126,12 @@ public class ImageCropView implements MvpView { | @@ -126,12 +126,12 @@ public class ImageCropView implements MvpView { | ||
| 126 | 126 | ||
| 127 | public void showMessage(String message) { | 127 | public void showMessage(String message) { |
| 128 | if (TextUtils.isEmpty(message) || mActivity.isFinishing()) return; | 128 | if (TextUtils.isEmpty(message) || mActivity.isFinishing()) return; |
| 129 | - AlertUtil.showDeftToast(mActivity, message); | 129 | + Toast.makeText(mActivity,message,Toast.LENGTH_SHORT).show(); |
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | public void showSucessMessage(String message) { | 132 | public void showSucessMessage(String message) { |
| 133 | if (TextUtils.isEmpty(message) || mActivity.isFinishing()) return; | 133 | if (TextUtils.isEmpty(message) || mActivity.isFinishing()) return; |
| 134 | - AlertUtil.showSuccessToast(mActivity, message); | 134 | + Toast.makeText(mActivity,message,Toast.LENGTH_SHORT).show(); |
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | 137 |
lib_media/src/main/res/values/dimens.xml
| @@ -17,4 +17,6 @@ | @@ -17,4 +17,6 @@ | ||
| 17 | <dimen name="activity_vertical_margin">16dp</dimen> | 17 | <dimen name="activity_vertical_margin">16dp</dimen> |
| 18 | <dimen name="list_divider_height">1px</dimen> | 18 | <dimen name="list_divider_height">1px</dimen> |
| 19 | <dimen name="list_divider_height_negative">-1px</dimen> | 19 | <dimen name="list_divider_height_negative">-1px</dimen> |
| 20 | + <item name="status_bar_util_fake_status_bar_view" type="id"/> | ||
| 21 | + <item name="status_bar_util_translucent_view" type="id"/> | ||
| 20 | </resources> | 22 | </resources> |
lib_media/src/main/res/values/styles.xml
| 1 | <?xml version="1.0" encoding="utf-8"?> | 1 | <?xml version="1.0" encoding="utf-8"?> |
| 2 | <resources> | 2 | <resources> |
| 3 | - <style name="AppTheme" parent="QMUI.Compat.NoActionBar"> | ||
| 4 | - <!-- 配置Android提供的theme --> | ||
| 5 | - <item name="android:listPreferredItemHeight">?attr/qmui_list_item_height_higher</item> | ||
| 6 | - <item name="android:listPreferredItemHeightSmall">?attr/qmui_list_item_height</item> | ||
| 7 | - <item name="colorPrimaryDark">@color/transparent</item> | ||
| 8 | - <!-- 配置qmui提供的theme --> | ||
| 9 | - <item name="qmui_config_color_blue">#FFFFFF</item> | ||
| 10 | - <item name="qmui_content_spacing_horizontal">20dp</item> | ||
| 11 | - <item name="qmui_content_padding_horizontal">@dimen/qmui_content_spacing_horizontal</item> | ||
| 12 | - <item name="windowActionBar">false</item> | ||
| 13 | - <item name="windowNoTitle">true</item> | ||
| 14 | - | ||
| 15 | - <!-- 配置app自己的theme --> | ||
| 16 | - <!--<item name="app_primary_color">@color/qmui_config_color_white</item>--> | ||
| 17 | - <!--<item name="app_content_bg_color">@color/qmui_config_color_white</item>--> | ||
| 18 | - | ||
| 19 | - <item name="qmui_bottom_sheet_grid_item_mini_width">96dp</item> | ||
| 20 | - </style> | ||
| 21 | - | ||
| 22 | - <style name="BtnOkStyle"> | ||
| 23 | - <item name="android:layout_width">wrap_content</item> | ||
| 24 | - <item name="android:layout_height">40dp</item> | ||
| 25 | - <item name="android:enabled">false</item> | ||
| 26 | - <item name="android:paddingLeft">@dimen/imagepicker_padding</item> | ||
| 27 | - <item name="android:paddingRight">@dimen/imagepicker_padding</item> | ||
| 28 | - <item name="android:text">@string/btn_imagepicker_ok</item> | ||
| 29 | - <item name="android:textColor">@drawable/imagepicker_btn_ok_tv_selector</item> | ||
| 30 | - <item name="android:background">@drawable/imagepicker_btn_ok_bg_selector</item> | ||
| 31 | - </style> | ||
| 32 | - | ||
| 33 | - <!--图片文件夹pop动画--> | ||
| 34 | - <style name="FloderPopAnimStyle"> | ||
| 35 | - <item name="android:windowEnterAnimation">@anim/imagepicker_pop_slide_in</item> | ||
| 36 | - <item name="android:windowExitAnimation">@anim/imagepicker_pop_slide_out</item> | ||
| 37 | - </style> | ||
| 38 | 3 | ||
| 39 | 4 | ||
| 40 | <style name="FullActivityThemeStyle" parent="QMUI.NoActionBar" > | 5 | <style name="FullActivityThemeStyle" parent="QMUI.NoActionBar" > |