parent
adf990b519
commit
a5dabad141
@ -0,0 +1,199 @@
|
||||
package xyz.wbsite.dbtool.javafx.manger.callable;
|
||||
|
||||
import xyz.wbsite.dbtool.javafx.manger.FreeMarkerManager;
|
||||
import xyz.wbsite.dbtool.javafx.manger.ManagerFactory;
|
||||
import xyz.wbsite.dbtool.javafx.manger.ProjectManager;
|
||||
import xyz.wbsite.dbtool.javafx.po.AbstractDBmapper;
|
||||
import xyz.wbsite.dbtool.javafx.po.AndroidOption;
|
||||
import xyz.wbsite.dbtool.javafx.tool.Tool;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
import static xyz.wbsite.dbtool.javafx.tool.Tool.clear;
|
||||
|
||||
public class AndroidCallable implements Callable {
|
||||
|
||||
private Tool tool = new Tool();
|
||||
private String path;
|
||||
private AndroidOption option;
|
||||
|
||||
private FreeMarkerManager freeMarkerManager;
|
||||
|
||||
public AndroidCallable(@NotNull String path, AndroidOption option) {
|
||||
this.path = path;
|
||||
this.option = option;
|
||||
this.freeMarkerManager = ManagerFactory.getFreeMarkerManager();
|
||||
}
|
||||
|
||||
private AbstractDBmapper dBmapper;
|
||||
|
||||
public Boolean call() throws Exception {
|
||||
File project = new File(path, option.projectName);
|
||||
if (!project.exists()) {
|
||||
project.mkdirs();
|
||||
} else {
|
||||
clear(project);
|
||||
}
|
||||
|
||||
dBmapper = ProjectManager.dBmapper;
|
||||
|
||||
// 目录生成
|
||||
File app = new File(project, "app");
|
||||
app.mkdirs();
|
||||
File src = new File(app, "src");
|
||||
src.mkdirs();
|
||||
File main = new File(src, "main");
|
||||
main.mkdirs();
|
||||
File java = new File(main, "java");
|
||||
java.mkdirs();
|
||||
File res = new File(src, "res");
|
||||
res.mkdirs();
|
||||
File domain = new File(java.getAbsolutePath() + File.separator + option.domain.replaceAll("\\.", Matcher.quoteReplacement(File.separator)));
|
||||
domain.mkdirs();
|
||||
File base = new File(domain, "base");
|
||||
base.mkdirs();
|
||||
File activity = new File(base, "activity");
|
||||
activity.mkdirs();
|
||||
File service = new File(base, "service");
|
||||
service.mkdirs();
|
||||
File util = new File(base, "util");
|
||||
util.mkdirs();
|
||||
File fragment = new File(domain, "fragment");
|
||||
fragment.mkdirs();
|
||||
|
||||
{
|
||||
Tool.outputResource("Android/.gitignore", new File(project, ".gitignore"));
|
||||
Tool.outputResource("Android/build.gradles", new File(project, "build.gradle"));
|
||||
Tool.outputResource("Android/settings.gradles", new File(project, "settings.gradle"));
|
||||
}
|
||||
|
||||
{
|
||||
HashMap<String, Object> ctx = new HashMap<String, Object>();
|
||||
ctx.put("package", option.packages);
|
||||
freeMarkerManager.outputTemp(new File(app, "build.gradle"), "Android/app/build.gradles", ctx);
|
||||
Tool.outputResource("Android/app/proguard-rules.pro", new File(app, "build.gradle"));
|
||||
}
|
||||
|
||||
{
|
||||
HashMap<String, Object> ctx = new HashMap<String, Object>();
|
||||
ctx.put("package", option.packages);
|
||||
ctx.put("domain", option.domain);
|
||||
freeMarkerManager.outputTemp(new File(main, "AndroidManifest.xml"), "Android/app/src/main/AndroidManifest.xml", ctx);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
HashMap<String, Object> ctx = new HashMap<String, Object>();
|
||||
ctx.put("package", option.packages);
|
||||
ctx.put("domain", option.domain);
|
||||
freeMarkerManager.outputTemp(new File(base, "BaseActivity.java"), "Android/app/src/main/java/base/BaseActivity.java", ctx);
|
||||
freeMarkerManager.outputTemp(new File(base, "BaseFragment.java"), "Android/app/src/main/java/base/BaseFragment.java", ctx);
|
||||
freeMarkerManager.outputTemp(new File(base, "BaseSPAActivity.java"), "Android/app/src/main/java/base/BaseSPAActivity.java", ctx);
|
||||
freeMarkerManager.outputTemp(new File(base, "BaseSPAFragment.java"), "Android/app/src/main/java/base/BaseSPAFragment.java", ctx);
|
||||
freeMarkerManager.outputTemp(new File(base, "BaseSPATakePhotoFragment.java"), "Android/app/src/main/java/base/BaseSPATakePhotoFragment.java", ctx);
|
||||
freeMarkerManager.outputTemp(new File(base, "IActivityResult.java"), "Android/app/src/main/java/base/IActivityResult.java", ctx);
|
||||
|
||||
freeMarkerManager.outputTemp(new File(activity, "FilePickerActivity.java"), "Android/app/src/main/java/base/activity/FilePickerActivity.java", ctx);
|
||||
freeMarkerManager.outputTemp(new File(activity, "QRcodeActivity.java"), "Android/app/src/main/java/base/activity/QRcodeActivity.java", ctx);
|
||||
|
||||
|
||||
freeMarkerManager.outputTemp(new File(service, "RestartService.java"), "Android/app/src/main/java/base/service/RestartService.java", ctx);
|
||||
|
||||
freeMarkerManager.outputTemp(new File(util, "AnimationUtil.java"), "Android/app/src/main/java/base/util/AnimationUtil.java", ctx);
|
||||
freeMarkerManager.outputTemp(new File(util, "ApkUtil.java"), "Android/app/src/main/java/base/util/ApkUtil.java", ctx);
|
||||
freeMarkerManager.outputTemp(new File(util, "Base64Util.java"), "Android/app/src/main/java/base/util/Base64Util.java", ctx);
|
||||
freeMarkerManager.outputTemp(new File(util, "BitmapUtil.java"), "Android/app/src/main/java/base/util/BitmapUtil.java", ctx);
|
||||
freeMarkerManager.outputTemp(new File(util, "BluetoothUtil.java"), "Android/app/src/main/java/base/util/BluetoothUtil.java", ctx);
|
||||
freeMarkerManager.outputTemp(new File(util, "Consant.java"), "Android/app/src/main/java/base/util/Consant.java", ctx);
|
||||
freeMarkerManager.outputTemp(new File(util, "DataBaseUtil.java"), "Android/app/src/main/java/base/util/DataBaseUtil.java", ctx);
|
||||
freeMarkerManager.outputTemp(new File(util, "DensityUtil.java"), "Android/app/src/main/java/base/util/DensityUtil.java", ctx);
|
||||
freeMarkerManager.outputTemp(new File(util, "DESUtil.java"), "Android/app/src/main/java/base/util/DESUtil.java", ctx);
|
||||
freeMarkerManager.outputTemp(new File(util, "DialogUtil.java"), "Android/app/src/main/java/base/util/DialogUtil.java", ctx);
|
||||
freeMarkerManager.outputTemp(new File(util, "FastBlur.java"), "Android/app/src/main/java/base/util/FastBlur.java", ctx);
|
||||
freeMarkerManager.outputTemp(new File(util, "FileUtil.java"), "Android/app/src/main/java/base/util/FileUtil.java", ctx);
|
||||
freeMarkerManager.outputTemp(new File(util, "GPSUtil.java"), "Android/app/src/main/java/base/util/GPSUtil.java", ctx);
|
||||
freeMarkerManager.outputTemp(new File(util, "IdCardUtil.java"), "Android/app/src/main/java/base/util/IdCardUtil.java", ctx);
|
||||
freeMarkerManager.outputTemp(new File(util, "Logger.java"), "Android/app/src/main/java/base/util/Logger.java", ctx);
|
||||
freeMarkerManager.outputTemp(new File(util, "NetUtil.java"), "Android/app/src/main/java/base/util/NetUtil.java", ctx);
|
||||
freeMarkerManager.outputTemp(new File(util, "RSAUtil.java"), "Android/app/src/main/java/base/util/RSAUtil.java", ctx);
|
||||
freeMarkerManager.outputTemp(new File(util, "SizeUtil.java"), "Android/app/src/main/java/base/util/SizeUtil.java", ctx);
|
||||
freeMarkerManager.outputTemp(new File(util, "SPUtil.java"), "Android/app/src/main/java/base/util/SPUtil.java", ctx);
|
||||
freeMarkerManager.outputTemp(new File(util, "StorageUtil.java"), "Android/app/src/main/java/base/util/StorageUtil.java", ctx);
|
||||
freeMarkerManager.outputTemp(new File(util, "Tasker.java"), "Android/app/src/main/java/base/util/Tasker.java", ctx);
|
||||
freeMarkerManager.outputTemp(new File(util, "Toaster.java"), "Android/app/src/main/java/base/util/Toaster.java", ctx);
|
||||
}
|
||||
|
||||
{
|
||||
HashMap<String, Object> ctx = new HashMap<String, Object>();
|
||||
ctx.put("package", option.packages);
|
||||
ctx.put("domain", option.domain);
|
||||
freeMarkerManager.outputTemp(new File(domain, "WBUIApplication.java"), "Android/app/src/main/java/WBUIApplication.java", ctx);
|
||||
freeMarkerManager.outputTemp(new File(domain, "WBUIMainActivity.java"), "Android/app/src/main/java/WBUIMainActivity.java", ctx);
|
||||
}
|
||||
|
||||
{
|
||||
HashMap<String, Object> ctx = new HashMap<String, Object>();
|
||||
ctx.put("package", option.packages);
|
||||
ctx.put("domain", option.domain);
|
||||
freeMarkerManager.outputTemp(new File(fragment, "LoginFragment.java"), "Android/app/src/main/java/fragment/LoginFragment.java", ctx);
|
||||
freeMarkerManager.outputTemp(new File(fragment, "MainFragment.java"), "Android/app/src/main/java/fragment/MainFragment.java", ctx);
|
||||
}
|
||||
|
||||
|
||||
System.out.println("finish");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public class Method {
|
||||
private String request;
|
||||
private String stringMethod;
|
||||
private String manager;
|
||||
private String method;
|
||||
private String target;
|
||||
|
||||
public String getRequest() {
|
||||
return request;
|
||||
}
|
||||
|
||||
public void setRequest(String request) {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
public String getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
public void setTarget(String target) {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public String getStringMethod() {
|
||||
return stringMethod;
|
||||
}
|
||||
|
||||
public void setStringMethod(String stringMethod) {
|
||||
this.stringMethod = stringMethod;
|
||||
}
|
||||
|
||||
public String getManager() {
|
||||
return manager;
|
||||
}
|
||||
|
||||
public void setManager(String manager) {
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
public String getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public void setMethod(String method) {
|
||||
this.method = method;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
# Built application files
|
||||
*.apk
|
||||
*.ap_
|
||||
|
||||
# Files for the Dalvik VM
|
||||
*.dex
|
||||
|
||||
# Java class files
|
||||
*.class
|
||||
|
||||
# Generated files
|
||||
bin/
|
||||
gen/
|
||||
|
||||
# Gradle files
|
||||
.gradle/
|
||||
build/
|
||||
|
||||
# Local configuration file (sdk path, etc)
|
||||
local.properties
|
||||
|
||||
# Proguard folder generated by Eclipse
|
||||
proguard/
|
||||
|
||||
#Log Files
|
||||
*.log
|
||||
|
||||
*.iml
|
||||
|
@ -0,0 +1,46 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 26
|
||||
defaultConfig {
|
||||
applicationId "${package}"
|
||||
minSdkVersion 23
|
||||
targetSdkVersion 26
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation 'com.android.support:appcompat-v7:26.1.0'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
||||
|
||||
//QMUI
|
||||
implementation 'com.qmuiteam:qmui:1.1.3'
|
||||
implementation "com.qmuiteam:arch:0.1.4"
|
||||
//依赖注入框架
|
||||
implementation 'com.jakewharton:butterknife:8.8.1'
|
||||
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
|
||||
//拍照,相册
|
||||
implementation 'com.jph.takephoto:takephoto_library:4.0.3'
|
||||
//图片查看
|
||||
implementation 'com.github.chrisbanes:PhotoView:1.2.6'
|
||||
//权限申请框架
|
||||
implementation 'com.yanzhenjie:permission:2.0.0-rc12'
|
||||
//二维码
|
||||
implementation 'com.google.zxing:core:3.3.2'
|
||||
implementation'com.journeyapps:zxing-android-embedded:3.6.0'
|
||||
//文件选择
|
||||
implementation 'com.leon:lfilepickerlibrary:1.7.0'
|
||||
//Picker
|
||||
implementation 'com.github.gzu-liyujiang.AndroidPicker:WheelPicker:1.5.6'
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
@ -0,0 +1,33 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="${package}">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name_cn"
|
||||
tools:replace="android:label"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme" >
|
||||
<activity
|
||||
android:name="${domain}.WBUIMainActivity"
|
||||
android:label="@string/app_name"
|
||||
android:windowSoftInputMode="stateAlwaysHidden">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<!--文件选择器-->
|
||||
<activity android:name="${domain}.base.activity.FilePickerActivity" />
|
||||
<!--二维码Activity-->
|
||||
<activity android:name="${domain}.base.activity.QRcodeActivity" />
|
||||
<!--重启服务-->
|
||||
<service android:name="${domain}.base.services.RestartService" />
|
||||
</application>
|
||||
|
||||
|
||||
</manifest>
|
@ -0,0 +1,201 @@
|
||||
package xyz.wbsite.webclient;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Color;
|
||||
import android.location.Location;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.view.Gravity;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.qmuiteam.qmui.util.QMUIDisplayHelper;
|
||||
import com.qmuiteam.qmui.widget.dialog.QMUIDialog;
|
||||
import com.qmuiteam.qmui.widget.dialog.QMUIDialogAction;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import xyz.wbsite.wbui.base.utils.DataBaseUtil;
|
||||
|
||||
|
||||
/**
|
||||
* Application 入口。
|
||||
*/
|
||||
public class WBUIApplication extends Application implements Thread.UncaughtExceptionHandler {
|
||||
|
||||
private static WBUIApplication instance;
|
||||
private WeakReference<Activity> currentActivity;
|
||||
|
||||
private DataBaseUtil db;
|
||||
private Map<String, Object> map;
|
||||
private Location mLocation;
|
||||
|
||||
private Toast toast;
|
||||
protected Handler handler = new Handler();
|
||||
|
||||
public Location getLocation() {
|
||||
return mLocation;
|
||||
}
|
||||
|
||||
public Handler getHandler() {
|
||||
return handler;
|
||||
}
|
||||
|
||||
public static WBUIApplication getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static Map getMap() {
|
||||
return instance.map;
|
||||
}
|
||||
|
||||
public DataBaseUtil getDb() {
|
||||
return db;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
// if (LeakCanary.isInAnalyzerProcess(this)) {
|
||||
// return;
|
||||
// }
|
||||
// LeakCanary.install(this);
|
||||
instance = this;
|
||||
initExceptionHandler();
|
||||
initMap();
|
||||
initLife();
|
||||
}
|
||||
|
||||
public void lozyInit() {
|
||||
initDB();
|
||||
}
|
||||
|
||||
private void initDB() {
|
||||
db = new DataBaseUtil(this, new DataBaseUtil.Register() {
|
||||
@Override
|
||||
public List<Class> run() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void initMap() {
|
||||
map = new HashMap();
|
||||
}
|
||||
|
||||
private void initLife() {
|
||||
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
|
||||
@Override
|
||||
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityStarted(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResumed(Activity activity) {
|
||||
currentActivity = new WeakReference<Activity>(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityPaused(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityStopped(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityDestroyed(Activity activity) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void initExceptionHandler() {
|
||||
// 程序的默认处理器
|
||||
Thread.setDefaultUncaughtExceptionHandler(this);
|
||||
}
|
||||
|
||||
// 判断是否安装插件
|
||||
public boolean hasInstallPlugin(String packageName) {
|
||||
try {
|
||||
PackageInfo info = getPackageManager().getPackageInfo(packageName, 0);
|
||||
return (info != null);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 展示Toast消息。
|
||||
*
|
||||
* @param message 消息内容
|
||||
*/
|
||||
public synchronized void showToast(final String message) {
|
||||
if (toast == null) {
|
||||
toast = new Toast(this);
|
||||
toast.setGravity(Gravity.CENTER, 0, 0);
|
||||
TextView textView = new TextView(this);
|
||||
textView.setTextColor(Color.parseColor("#ffffff"));
|
||||
int padding = QMUIDisplayHelper.dp2px(this, 20);
|
||||
textView.setPadding(padding, padding, padding, padding);
|
||||
textView.setBackgroundColor(Color.parseColor("#aa131313"));
|
||||
toast.setView(textView);
|
||||
}
|
||||
((TextView) toast.getView()).setText(message);
|
||||
toast.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uncaughtException(Thread thread, Throwable throwable) {
|
||||
Log.e("error--->", "error : ", throwable);
|
||||
exit();
|
||||
}
|
||||
|
||||
public void confirm(String message, QMUIDialogAction.ActionListener actionListener) {
|
||||
if (currentActivity != null) {
|
||||
Activity activity = currentActivity.get();
|
||||
QMUIDialog qmuiDialog = new QMUIDialog.MessageDialogBuilder(activity)
|
||||
.setMessage(message)
|
||||
.addAction("取消", new QMUIDialogAction.ActionListener() {
|
||||
@Override
|
||||
public void onClick(QMUIDialog dialog, int index) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
})
|
||||
.addAction("确定", actionListener)
|
||||
.create(com.qmuiteam.qmui.R.style.QMUI_Dialog);
|
||||
qmuiDialog.show();
|
||||
}
|
||||
}
|
||||
|
||||
public void exit() {
|
||||
confirm("确认退出?", new QMUIDialogAction.ActionListener() {
|
||||
@Override
|
||||
public void onClick(QMUIDialog dialog, int index) {
|
||||
dialog.dismiss();
|
||||
android.os.Process.killProcess(android.os.Process.myPid());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
package xyz.wbsite.webclient;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.zxing.integration.android.IntentIntegrator;
|
||||
import com.google.zxing.integration.android.IntentResult;
|
||||
import com.yanzhenjie.permission.Action;
|
||||
import com.yanzhenjie.permission.AndPermission;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import xyz.wbsite.wbui.base.BaseSPAActivity;
|
||||
import xyz.wbsite.wbui.base.Consant;
|
||||
import xyz.wbsite.webclient.fragment.LoginFragment;
|
||||
|
||||
public class WBUIMainActivity extends BaseSPAActivity {
|
||||
private static final String KEY_FRAGMENT = "key_fragment";
|
||||
private static final int VALUE_FRAGMENT_HOME = 0;
|
||||
private static final int VALUE_FRAGMENT_NOTCH_HELPER = 1;
|
||||
|
||||
@Override
|
||||
protected int getContextViewId() {
|
||||
return R.id.main_id;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
AndPermission.with(this).runtime().permission(Manifest.permission.READ_EXTERNAL_STORAGE).onGranted(new Action<List<String>>() {
|
||||
@Override
|
||||
public void onAction(List<String> data) {
|
||||
startFirstFragment(new LoginFragment());
|
||||
}
|
||||
}).onDenied(new Action<List<String>>() {
|
||||
@Override
|
||||
public void onAction(List<String> data) {
|
||||
startFirstFragment(new LoginFragment());
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (requestCode == Consant.REQUESTCODE_FROM_FRAGMENT) {
|
||||
Toast.makeText(getApplicationContext(), "选中了个文件", Toast.LENGTH_SHORT).show();
|
||||
}else {
|
||||
IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
|
||||
if (result != null) {
|
||||
if (result.getContents() == null) {
|
||||
Toast.makeText(this, "Cancelled", Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
Toast.makeText(this, "Scanned: " + result.getContents(), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
} else {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,28 @@
|
||||
package xyz.wbsite.wbui.base;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
public abstract class BaseActivity extends Activity {
|
||||
private Hashtable<Integer, IActivityResult> resultHashtable = new Hashtable<>();
|
||||
private int mRequestCode = 1;
|
||||
|
||||
public void startForResult(Intent intent, IActivityResult activityResult) {
|
||||
int requestCode = mRequestCode++;
|
||||
resultHashtable.put(requestCode, activityResult);
|
||||
startActivityForResult(intent, requestCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (resultHashtable.containsKey(requestCode)) {
|
||||
IActivityResult i = resultHashtable.remove(requestCode);
|
||||
if (i != null) {
|
||||
i.onResult(resultCode, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package xyz.wbsite.wbui.base;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.Unbinder;
|
||||
|
||||
public abstract class BaseFragment extends Fragment {
|
||||
private Unbinder unbinder;
|
||||
protected Handler handler = new Handler();
|
||||
|
||||
protected abstract void initView();
|
||||
|
||||
protected abstract int getFragmnetLayout();
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View inflate = LayoutInflater.from(getActivity()).inflate(getFragmnetLayout(), null);
|
||||
unbinder = ButterKnife.bind(this, inflate);
|
||||
initView();
|
||||
return inflate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
unbinder.unbind();
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package xyz.wbsite.wbui.base;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
|
||||
import com.qmuiteam.qmui.arch.QMUIFragmentActivity;
|
||||
import com.qmuiteam.qmui.widget.dialog.QMUIDialog;
|
||||
import com.qmuiteam.qmui.widget.dialog.QMUIDialogAction;
|
||||
import com.qmuiteam.qmui.widget.dialog.QMUITipDialog;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
import xyz.wbsite.webclient.fragment.LoginFragment;
|
||||
|
||||
|
||||
public abstract class BaseSPAActivity extends QMUIFragmentActivity {
|
||||
|
||||
protected QMUITipDialog loading;
|
||||
|
||||
private Hashtable<Integer, IActivityResult> resultHashtable = new Hashtable<>();
|
||||
private int mRequestCode = 1;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
loading = new QMUITipDialog.Builder(this).setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING).setTipWord("加载中...").create();
|
||||
}
|
||||
|
||||
public void showLoading() {
|
||||
loading.show();
|
||||
}
|
||||
|
||||
public void dismissLoading() {
|
||||
loading.dismiss();
|
||||
}
|
||||
|
||||
public synchronized void confirmDialog(String messgae, QMUIDialogAction.ActionListener actionListener) {
|
||||
new QMUIDialog.MessageDialogBuilder(this)
|
||||
.setTitle("消息")
|
||||
.setMessage(messgae)
|
||||
.addAction("确定", actionListener)
|
||||
.setCanceledOnTouchOutside(false)
|
||||
.create(com.qmuiteam.qmui.R.style.QMUI_Dialog).show();
|
||||
}
|
||||
|
||||
public void startForResult(Intent intent, IActivityResult activityResult) {
|
||||
int requestCode = mRequestCode++;
|
||||
resultHashtable.put(requestCode, activityResult);
|
||||
startActivityForResult(intent, requestCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (resultHashtable.containsKey(requestCode)) {
|
||||
IActivityResult i = resultHashtable.remove(requestCode);
|
||||
if (i != null) {
|
||||
i.onResult(resultCode, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void startFirstFragment(BaseSPAFragment fragment) {
|
||||
getSupportFragmentManager()
|
||||
.beginTransaction()
|
||||
.add(getContextViewId(), fragment, fragment.getClass().getSimpleName())
|
||||
.addToBackStack(fragment.getClass().getSimpleName())
|
||||
.commit();
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package xyz.wbsite.wbui.base;
|
||||
|
||||
|
||||
import android.content.Intent;
|
||||
|
||||
public interface IActivityResult {
|
||||
void onResult(int resultCode, Intent data);
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package xyz.wbsite.wbui.base.activity;
|
||||
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.leon.lfilepickerlibrary.LFilePicker;
|
||||
import com.leon.lfilepickerlibrary.utils.Constant;
|
||||
|
||||
import xyz.wbsite.wbui.base.BaseSPAActivity;
|
||||
|
||||
public class FilePickerActivity extends BaseSPAActivity {
|
||||
|
||||
private static final int REQUESTCODE_FROM_ACTIVITY = 0;
|
||||
|
||||
|
||||
@Override
|
||||
protected int getContextViewId() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
new LFilePicker()
|
||||
.withActivity(this)
|
||||
.withTitle("选择附件")
|
||||
.withBackIcon(Constant.BACKICON_STYLETHREE)
|
||||
.withRequestCode(REQUESTCODE_FROM_ACTIVITY)
|
||||
.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
setResult(resultCode,data);
|
||||
finish();
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package xyz.wbsite.wbui.base.activity;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.os.PersistableBundle;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import com.journeyapps.barcodescanner.CaptureManager;
|
||||
import com.journeyapps.barcodescanner.DecoratedBarcodeView;
|
||||
|
||||
import xyz.wbsite.webclient.R;
|
||||
|
||||
|
||||
public class QRcodeActivity extends Activity implements DecoratedBarcodeView.TorchListener {
|
||||
|
||||
private CaptureManager captureManager;
|
||||
private DecoratedBarcodeView mDBV;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_custom_capture);
|
||||
|
||||
mDBV = (DecoratedBarcodeView) findViewById(R.id.dbv_custom);
|
||||
mDBV.setTorchListener(this);
|
||||
|
||||
//重要代码,初始化捕获
|
||||
captureManager = new CaptureManager(this, mDBV);
|
||||
captureManager.initializeFromIntent(getIntent(), savedInstanceState);
|
||||
captureManager.decode();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
captureManager.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
captureManager.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
captureManager.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
|
||||
super.onSaveInstanceState(outState, outPersistentState);
|
||||
captureManager.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
return mDBV.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTorchOn() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTorchOff() {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
package xyz.wbsite.wbui.base.services;
|
||||
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
|
||||
public class RestartService extends Service {
|
||||
|
||||
/**
|
||||
* 重启整个APP
|
||||
*
|
||||
* @param context
|
||||
* @param Delayed 延迟多少毫秒
|
||||
*/
|
||||
public static void restartAPP(Context context, long Delayed) {
|
||||
|
||||
// 开启服务,用来重启
|
||||
Intent intent1 = new Intent(context, RestartService.class);
|
||||
intent1.putExtra("PackageName", context.getPackageName());
|
||||
intent1.putExtra("Delayed", Delayed);
|
||||
context.startService(intent1);
|
||||
|
||||
// 杀死进程
|
||||
android.os.Process.killProcess(android.os.Process.myPid());
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用关闭重启时间
|
||||
*/
|
||||
private static long stopDelayed = 1000;
|
||||
|
||||
private Handler handler;
|
||||
|
||||
private String PackageName;
|
||||
|
||||
public RestartService() {
|
||||
handler = new Handler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(final Intent intent, int flags, int startId) {
|
||||
stopDelayed = intent.getLongExtra("Delayed", 1000);
|
||||
PackageName = intent.getStringExtra("PackageName");
|
||||
handler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Intent LaunchIntent = getPackageManager().getLaunchIntentForPackage(PackageName);
|
||||
startActivity(LaunchIntent);
|
||||
RestartService.this.stopSelf();
|
||||
}
|
||||
}, stopDelayed);
|
||||
return super.onStartCommand(intent, flags, startId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,123 @@
|
||||
package xyz.wbsite.wbui.base.ui;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
||||
public class WBUICustomDialog extends Dialog {
|
||||
public WBUICustomDialog(Context context) {
|
||||
super(context);
|
||||
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
this.getWindow().getDecorView().setPadding(0, 0, 0, 0);
|
||||
this.getWindow().getDecorView().setBackground(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentView(View view, ViewGroup.LayoutParams params) {
|
||||
if (params.width == ViewGroup.LayoutParams.MATCH_PARENT) {
|
||||
params.width = this.getWindow().getContext().getResources().getDisplayMetrics().widthPixels;
|
||||
}
|
||||
if (params.height == ViewGroup.LayoutParams.MATCH_PARENT) {
|
||||
params.height = this.getWindow().getContext().getResources().getDisplayMetrics().heightPixels;
|
||||
}
|
||||
|
||||
super.setContentView(view, params);
|
||||
}
|
||||
|
||||
public void setContentView(View view, ViewGroup.LayoutParams params, double widthScale, double heightScale) {
|
||||
if (widthScale < 0) {
|
||||
widthScale = 0;
|
||||
}
|
||||
if (heightScale > 1) {
|
||||
heightScale = 1;
|
||||
}
|
||||
if (params.width == ViewGroup.LayoutParams.MATCH_PARENT) {
|
||||
params.width = (int) (widthScale * this.getWindow().getContext().getResources().getDisplayMetrics().widthPixels);
|
||||
}
|
||||
if (params.height == ViewGroup.LayoutParams.MATCH_PARENT) {
|
||||
params.height = (int) (heightScale * this.getWindow().getContext().getResources().getDisplayMetrics().heightPixels);
|
||||
}
|
||||
super.setContentView(view, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentView(int layoutResID) {
|
||||
LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
View inflate = inflater.inflate(layoutResID, null);
|
||||
if (inflater == null) {
|
||||
throw new AssertionError("layout not find");
|
||||
}
|
||||
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
this.setContentView(inflate, layoutParams);
|
||||
}
|
||||
|
||||
public void setContentView(int layoutResID, double widthScale, double heightScale) {
|
||||
LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
View inflate = inflater.inflate(layoutResID, null);
|
||||
if (inflater == null) {
|
||||
throw new AssertionError("layout not find");
|
||||
}
|
||||
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
this.setContentView(inflate, layoutParams, widthScale, heightScale);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对齐方式
|
||||
*
|
||||
* @param gravity
|
||||
*/
|
||||
public void setGravity(int gravity) {
|
||||
WindowManager.LayoutParams attributes = getWindow().getAttributes();
|
||||
attributes.gravity = gravity;
|
||||
getWindow().setAttributes(attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置背景屏幕透明度
|
||||
*/
|
||||
public void setDimAmount(float amount) {
|
||||
this.getWindow().setDimAmount(amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义按钮点击事件
|
||||
*
|
||||
* @param viewId 自定义Dialog viewId
|
||||
* @param clickListener 点击事件监听器
|
||||
* @param dismiss 是否消失
|
||||
*/
|
||||
public void addOnclickListener(int viewId, final View.OnClickListener clickListener, final boolean dismiss) {
|
||||
this.findViewById(viewId).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
clickListener.onClick(v);
|
||||
if (dismiss) {
|
||||
dismiss();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义按钮点击事件
|
||||
*
|
||||
* @param view 自定义Dialog view
|
||||
* @param clickListener 点击事件监听器
|
||||
* @param dismiss 是否消失
|
||||
*/
|
||||
public void addOnclickListener(View view, final View.OnClickListener clickListener, final boolean dismiss) {
|
||||
view.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
clickListener.onClick(v);
|
||||
if (dismiss) {
|
||||
dismiss();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package xyz.wbsite.wbui.base.ui;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.LinearGradient;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Shader;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.GridView;
|
||||
|
||||
import xyz.wbsite.webclient.R;
|
||||
|
||||
public class WBUIGridView extends GridView {
|
||||
public WBUIGridView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public WBUIGridView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public WBUIGridView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
int cols = getNumColumns(); //获取列数
|
||||
|
||||
Paint localPaint; //设置画笔
|
||||
localPaint = new Paint();
|
||||
localPaint.setStyle(Paint.Style.FILL); //画笔实心
|
||||
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
View childAt = getChildAt(i);
|
||||
localPaint.setShader(new LinearGradient(childAt.getLeft(), childAt.getBottom(), childAt.getRight(), childAt.getBottom(), new int[]{
|
||||
getResources().getColor(R.color.colorGray_09), getResources().getColor(R.color.colorGray_09), getResources().getColor(R.color.colorGray_09)}, null, Shader.TileMode.REPEAT));
|
||||
canvas.drawLine(childAt.getLeft(), childAt.getBottom() - 1, childAt.getRight(), childAt.getBottom() - 1, localPaint);
|
||||
|
||||
if ((i + 1) % cols != 0) {
|
||||
localPaint.setShader(new LinearGradient(childAt.getRight(), childAt.getTop(), childAt.getRight(), childAt.getBottom(), new int[]{
|
||||
getResources().getColor(R.color.colorGray_09), getResources().getColor(R.color.colorGray_09), getResources().getColor(R.color.colorGray_09)}, null, Shader.TileMode.MIRROR));
|
||||
canvas.drawLine(childAt.getRight() - 1, childAt.getTop(), childAt.getRight() - 1, childAt.getBottom(), localPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
package xyz.wbsite.wbui.base.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
public class WBUITextView extends android.support.v7.widget.AppCompatTextView {
|
||||
private int mOffsetY = 0;
|
||||
public Bitmap lastBitmap;
|
||||
|
||||
public WBUITextView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public WBUITextView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (lastBitmap != null) {
|
||||
canvas.drawBitmap(lastBitmap, 0, mOffsetY - getHeight(), null);
|
||||
canvas.translate(0, mOffsetY);
|
||||
}
|
||||
super.onDraw(canvas);
|
||||
|
||||
if (mOffsetY == 0) {
|
||||
lastBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
|
||||
super.onDraw(new Canvas(lastBitmap));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(CharSequence text, BufferType type) {
|
||||
mOffsetY = getHeight();
|
||||
post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mOffsetY > 0) {
|
||||
mOffsetY -= 5;
|
||||
if (mOffsetY < 0) mOffsetY = 0;
|
||||
postDelayed(this, 10);
|
||||
} else {
|
||||
mOffsetY = 0;
|
||||
}
|
||||
System.out.println(mOffsetY);
|
||||
invalidate();
|
||||
}
|
||||
});
|
||||
super.setText(text, type);
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package xyz.wbsite.wbui.base.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
public class WBUITipTextView extends android.support.v7.widget.AppCompatTextView {
|
||||
private long time = 3000;
|
||||
private String lastValue = "";
|
||||
private Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
time-=1000;
|
||||
if (time <= 0){
|
||||
WBUITipTextView.this.setText("");
|
||||
}else {
|
||||
postDelayed(runnable,1000);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public WBUITipTextView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public WBUITipTextView(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public WBUITipTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(CharSequence text, BufferType type) {
|
||||
this.time = 3000;
|
||||
postDelayed(runnable,1000);
|
||||
|
||||
super.setText(text, type);
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
package xyz.wbsite.wbui.base.ui.button;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.ShapeDrawable;
|
||||
import android.graphics.drawable.StateListDrawable;
|
||||
import android.graphics.drawable.shapes.RoundRectShape;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.Button;
|
||||
|
||||
public class WbButton extends Button {
|
||||
private int mColor;
|
||||
private float mScale;
|
||||
|
||||
public WbButton(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public WbButton(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
mScale = getResources().getDisplayMetrics().density;
|
||||
ColorStateList textColors = this.getTextColors();
|
||||
mColor = textColors.getDefaultColor();
|
||||
|
||||
StateListDrawable stateListDrawable = new StateListDrawable();
|
||||
stateListDrawable.setEnterFadeDuration(200);
|
||||
stateListDrawable.setExitFadeDuration(200);
|
||||
int radius = (int) (5 * mScale);
|
||||
int width = (int) (1 * mScale);
|
||||
|
||||
//不可按时的drawable
|
||||
{
|
||||
RoundRectShape roundRectShape = new RoundRectShape(
|
||||
new float[]{radius, radius, radius, radius, radius, radius, radius, radius},
|
||||
new RectF(width, width, width, width),
|
||||
new float[]{radius - width, radius - width, radius - width, radius - width, radius - width, radius - width, radius - width, radius - width}
|
||||
);
|
||||
ShapeDrawable shapeDrawable = new ShapeDrawable(roundRectShape);
|
||||
shapeDrawable.getPaint().setColor(Color.parseColor("#aaaaaa"));
|
||||
stateListDrawable.addState(new int[]{-android.R.attr.state_enabled}, shapeDrawable);
|
||||
}
|
||||
//正常的drawable
|
||||
{
|
||||
RoundRectShape roundRectShape = new RoundRectShape(
|
||||
new float[]{radius, radius, radius, radius, radius, radius, radius, radius},
|
||||
new RectF(width, width, width, width),
|
||||
new float[]{radius - width, radius - width, radius - width, radius - width, radius - width, radius - width, radius - width, radius - width}
|
||||
);
|
||||
ShapeDrawable shapeDrawable = new ShapeDrawable(roundRectShape);
|
||||
shapeDrawable.getPaint().setColor(mColor);
|
||||
|
||||
stateListDrawable.addState(new int[]{-android.R.attr.state_pressed}, shapeDrawable);
|
||||
}
|
||||
//按下去的drawable
|
||||
{
|
||||
RoundRectShape roundRectShape = new RoundRectShape(
|
||||
new float[]{radius, radius, radius, radius, radius, radius, radius, radius},
|
||||
null,
|
||||
null
|
||||
);
|
||||
ShapeDrawable shapeDrawable = new ShapeDrawable(roundRectShape);
|
||||
shapeDrawable.getPaint().setColor(mColor);
|
||||
stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, shapeDrawable);
|
||||
}
|
||||
this.setBackground(stateListDrawable);
|
||||
|
||||
//各状态对应的字体颜色
|
||||
int[][] satate = {
|
||||
{-android.R.attr.state_enabled},
|
||||
{-android.R.attr.state_pressed},
|
||||
{android.R.attr.state_pressed}
|
||||
};
|
||||
int[] colors = {Color.parseColor("#aaaaaa"), mColor, Color.WHITE,};
|
||||
|
||||
ColorStateList colorStateList = new ColorStateList(satate, colors);
|
||||
this.setTextColor(colorStateList);
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package xyz.wbsite.wbui.base.ui.button;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ImageButton;
|
||||
|
||||
public class WbImageButton extends ImageButton {
|
||||
private int mSrcWitdh;
|
||||
private int mSrcHeight;
|
||||
private int mExactlyWidth;
|
||||
private int mEactlyHeight;
|
||||
|
||||
public WbImageButton(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public WbImageButton(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
|
||||
Drawable drawable = getDrawable();
|
||||
Rect bounds = drawable.getBounds();
|
||||
mSrcWitdh = bounds.width();
|
||||
mSrcHeight = bounds.height();
|
||||
|
||||
System.out.println(mSrcWitdh);
|
||||
System.out.println(mSrcHeight);
|
||||
if (mSrcWitdh != 0 && mSrcHeight != 0) {
|
||||
if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY && MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY) {
|
||||
//宽度确定,高度自适应
|
||||
mExactlyWidth = MeasureSpec.getSize(widthMeasureSpec);
|
||||
mEactlyHeight = mExactlyWidth * mSrcHeight / mSrcWitdh;
|
||||
setMeasuredDimension(mExactlyWidth, mEactlyHeight);
|
||||
} else if (MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) {
|
||||
//高度确定,宽度自适应
|
||||
mEactlyHeight = MeasureSpec.getSize(heightMeasureSpec);
|
||||
mExactlyWidth = mEactlyHeight * mSrcWitdh / mSrcHeight;
|
||||
setMeasuredDimension(mExactlyWidth, mEactlyHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
package xyz.wbsite.wbui.base.ui.button;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ShapeDrawable;
|
||||
import android.graphics.drawable.StateListDrawable;
|
||||
import android.graphics.drawable.shapes.RoundRectShape;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class WbMultiToggleButton extends LinearLayout implements View.OnClickListener {
|
||||
private Button b1;
|
||||
private Button b2;
|
||||
|
||||
|
||||
public WbMultiToggleButton(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public WbMultiToggleButton(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
this.setOrientation(HORIZONTAL);
|
||||
float density = this.getResources().getDisplayMetrics().density;
|
||||
LayoutParams layoutParams = new LayoutParams(0, LayoutParams.MATCH_PARENT);
|
||||
layoutParams.weight = 1;
|
||||
|
||||
{
|
||||
// 边框
|
||||
ShapeDrawable shapeDrawable = new ShapeDrawable(new RoundRectShape(new float[]{density * 5, density * 5, density * 5, density * 5, density * 5, density * 5, density * 5, density * 5}, null, null));
|
||||
shapeDrawable.getPaint().setColor(Color.parseColor("#aaaaaa"));
|
||||
this.setPadding((int) (density * 1), (int) (density * 1), (int) (density * 1), (int) (density * 1));
|
||||
this.setBackground(shapeDrawable);
|
||||
}
|
||||
|
||||
{
|
||||
b1 = new Button(getContext());
|
||||
b1.setText("aa");
|
||||
b1.setTag("b1");
|
||||
b1.setOnClickListener(this);
|
||||
int[][] satate = {
|
||||
{-android.R.attr.state_selected},
|
||||
{android.R.attr.state_selected}
|
||||
};
|
||||
int[] colors = {Color.BLACK, Color.WHITE};
|
||||
ColorStateList colorStateList = new ColorStateList(satate, colors);
|
||||
b1.setTextColor(colorStateList);
|
||||
|
||||
ShapeDrawable unselected = new ShapeDrawable(new RoundRectShape(new float[]{density * 4, density * 4, 0, 0, 0, 0, density * 4, density * 4}, null, null));
|
||||
unselected.getPaint().setColor(Color.WHITE);
|
||||
ShapeDrawable selected = new ShapeDrawable(new RoundRectShape(new float[]{density * 4, density * 4, 0, 0, 0, 0, density * 4, density * 4}, null, null));
|
||||
selected.getPaint().setColor(Color.parseColor("#66b3ff"));
|
||||
StateListDrawable listDrawable = new StateListDrawable();
|
||||
listDrawable.addState(new int[]{-android.R.attr.state_selected}, unselected);
|
||||
listDrawable.addState(new int[]{android.R.attr.state_selected}, selected);
|
||||
b1.setBackground(listDrawable);
|
||||
this.addView(b1, layoutParams);
|
||||
}
|
||||
|
||||
{
|
||||
b2 = new Button(getContext());
|
||||
b2.setText("bb");
|
||||
b2.setTag("b2");
|
||||
b2.setOnClickListener(this);
|
||||
int[][] satate = {
|
||||
{-android.R.attr.state_selected},
|
||||
{android.R.attr.state_selected}
|
||||
};
|
||||
int[] colors = {Color.BLACK, Color.WHITE};
|
||||
ColorStateList colorStateList = new ColorStateList(satate, colors);
|
||||
b2.setTextColor(colorStateList);
|
||||
ShapeDrawable unselected = new ShapeDrawable(new RoundRectShape(new float[]{0, 0, density * 4, density * 4, density * 4, density * 4, 0, 0}, null, null));
|
||||
unselected.getPaint().setColor(Color.WHITE);
|
||||
ShapeDrawable selected = new ShapeDrawable(new RoundRectShape(new float[]{0, 0, density * 4, density * 4, density * 4, density * 4, 0, 0}, null, null));
|
||||
selected.getPaint().setColor(Color.parseColor("#66b3ff"));
|
||||
StateListDrawable listDrawable = new StateListDrawable();
|
||||
listDrawable.addState(new int[]{-android.R.attr.state_selected}, unselected);
|
||||
listDrawable.addState(new int[]{android.R.attr.state_selected}, selected);
|
||||
b2.setBackground(listDrawable);
|
||||
this.addView(b2, layoutParams);
|
||||
}
|
||||
|
||||
b1.setSelected(true);
|
||||
b2.setSelected(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Object tag = v.getTag();
|
||||
if (tag instanceof String) {
|
||||
String t = (String) tag;
|
||||
switch (t) {
|
||||
case "b1":
|
||||
b1.setSelected(true);
|
||||
b2.setSelected(false);
|
||||
break;
|
||||
case "b2":
|
||||
b1.setSelected(false);
|
||||
b2.setSelected(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
package xyz.wbsite.wbui.base.ui.button;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.StateListDrawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.RadioButton;
|
||||
|
||||
|
||||
/**
|
||||
* Created by bingwang on 2016/7/17.
|
||||
*/
|
||||
public class WbRadioButton extends RadioButton {
|
||||
|
||||
public WbRadioButton(Context context) {
|
||||
super(context);
|
||||
initial();
|
||||
}
|
||||
|
||||
public WbRadioButton(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
initial();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造自定义radio
|
||||
*/
|
||||
public void initial() {
|
||||
float density = getResources().getDisplayMetrics().density;
|
||||
StateListDrawable stateListDrawable = new StateListDrawable();
|
||||
|
||||
Bitmap unchecked = Bitmap.createBitmap((int) (30 * density), (int) (30 * density), Bitmap.Config.ARGB_8888);
|
||||
Bitmap checked = Bitmap.createBitmap((int) (30 * density), (int) (30 * density), Bitmap.Config.ARGB_8888);
|
||||
|
||||
{//未选中状态
|
||||
Canvas canvas = new Canvas(unchecked);
|
||||
Paint paint = new Paint();
|
||||
paint.setColor(Color.DKGRAY);
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeWidth(5 * density);
|
||||
canvas.drawRect(4.5f * density, 4.5f * density, 25.5f * density, 25.5f * density, paint);
|
||||
}
|
||||
|
||||
{//选中状态
|
||||
Canvas canvas = new Canvas(checked);
|
||||
Paint paint = new Paint();
|
||||
paint.setColor(Color.DKGRAY);
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeWidth(5 * density);
|
||||
canvas.drawRect(4.5f * density, 4.5f * density, 25.5f * density, 25.5f * density, paint);
|
||||
paint.setColor(Color.argb(255, 00, 94, 00));
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
canvas.drawRect(9 * density, 9 * density, 21 * density, 21 * density, paint);
|
||||
}
|
||||
|
||||
stateListDrawable.addState(new int[]{-android.R.attr.state_checked}, new BitmapDrawable(getResources(), unchecked));
|
||||
stateListDrawable.addState(new int[]{android.R.attr.state_checked}, new BitmapDrawable(getResources(), checked));
|
||||
this.setButtonDrawable(stateListDrawable);
|
||||
}
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
package xyz.wbsite.wbui.base.ui.button;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ShapeDrawable;
|
||||
import android.graphics.drawable.StateListDrawable;
|
||||
import android.graphics.drawable.shapes.RoundRectShape;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class WbToggleButton extends LinearLayout implements View.OnClickListener {
|
||||
private Button b1;
|
||||
private Button b2;
|
||||
|
||||
|
||||
public WbToggleButton(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public WbToggleButton(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
this.setOrientation(HORIZONTAL);
|
||||
float density = this.getResources().getDisplayMetrics().density;
|
||||
LayoutParams layoutParams = new LayoutParams(0, LayoutParams.MATCH_PARENT);
|
||||
layoutParams.weight = 1;
|
||||
|
||||
{
|
||||
// 边框
|
||||
ShapeDrawable shapeDrawable = new ShapeDrawable(new RoundRectShape(new float[]{density * 5, density * 5, density * 5, density * 5, density * 5, density * 5, density * 5, density * 5}, null, null));
|
||||
shapeDrawable.getPaint().setColor(Color.parseColor("#aaaaaa"));
|
||||
this.setPadding((int) (density * 1), (int) (density * 1), (int) (density * 1), (int) (density * 1));
|
||||
this.setBackground(shapeDrawable);
|
||||
}
|
||||
|
||||
{
|
||||
b1 = new Button(getContext());
|
||||
b1.setText("aa");
|
||||
b1.setTag("b1");
|
||||
b1.setOnClickListener(this);
|
||||
int[][] satate = {
|
||||
{-android.R.attr.state_selected},
|
||||
{android.R.attr.state_selected}
|
||||
};
|
||||
int[] colors = {Color.BLACK, Color.WHITE};
|
||||
ColorStateList colorStateList = new ColorStateList(satate, colors);
|
||||
b1.setTextColor(colorStateList);
|
||||
|
||||
ShapeDrawable unselected = new ShapeDrawable(new RoundRectShape(new float[]{density * 4, density * 4, 0, 0, 0, 0, density * 4, density * 4}, null, null));
|
||||
unselected.getPaint().setColor(Color.WHITE);
|
||||
ShapeDrawable selected = new ShapeDrawable(new RoundRectShape(new float[]{density * 4, density * 4, 0, 0, 0, 0, density * 4, density * 4}, null, null));
|
||||
selected.getPaint().setColor(Color.parseColor("#66b3ff"));
|
||||
StateListDrawable listDrawable = new StateListDrawable();
|
||||
listDrawable.addState(new int[]{-android.R.attr.state_selected}, unselected);
|
||||
listDrawable.addState(new int[]{android.R.attr.state_selected}, selected);
|
||||
b1.setBackground(listDrawable);
|
||||
this.addView(b1, layoutParams);
|
||||
}
|
||||
|
||||
{
|
||||
b2 = new Button(getContext());
|
||||
b2.setText("bb");
|
||||
b2.setTag("b2");
|
||||
b2.setOnClickListener(this);
|
||||
int[][] satate = {
|
||||
{-android.R.attr.state_selected},
|
||||
{android.R.attr.state_selected}
|
||||
};
|
||||
int[] colors = {Color.BLACK, Color.WHITE};
|
||||
ColorStateList colorStateList = new ColorStateList(satate, colors);
|
||||
b2.setTextColor(colorStateList);
|
||||
ShapeDrawable unselected = new ShapeDrawable(new RoundRectShape(new float[]{0, 0, density * 4, density * 4, density * 4, density * 4, 0, 0}, null, null));
|
||||
unselected.getPaint().setColor(Color.WHITE);
|
||||
ShapeDrawable selected = new ShapeDrawable(new RoundRectShape(new float[]{0, 0, density * 4, density * 4, density * 4, density * 4, 0, 0}, null, null));
|
||||
selected.getPaint().setColor(Color.parseColor("#66b3ff"));
|
||||
StateListDrawable listDrawable = new StateListDrawable();
|
||||
listDrawable.addState(new int[]{-android.R.attr.state_selected}, unselected);
|
||||
listDrawable.addState(new int[]{android.R.attr.state_selected}, selected);
|
||||
b2.setBackground(listDrawable);
|
||||
this.addView(b2, layoutParams);
|
||||
}
|
||||
|
||||
b1.setSelected(true);
|
||||
b2.setSelected(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Object tag = v.getTag();
|
||||
if (tag instanceof String) {
|
||||
String t = (String) tag;
|
||||
switch (t) {
|
||||
case "b1":
|
||||
b1.setSelected(true);
|
||||
b2.setSelected(false);
|
||||
break;
|
||||
case "b2":
|
||||
b1.setSelected(false);
|
||||
b2.setSelected(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
package xyz.wbsite.wbui.base.ui.dialog;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.Gravity;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.widget.Button;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class ConfirmDialog extends Dialog {
|
||||
private LinearLayout mLinearLayout;
|
||||
|
||||
public ConfirmDialog(@NonNull Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public ConfirmDialog(@NonNull Context context, int themeResId) {
|
||||
super(context, themeResId);
|
||||
}
|
||||
|
||||
public ConfirmDialog(Context context, String message) {
|
||||
super(context);
|
||||
//px与dp比例
|
||||
float mScale = getContext().getResources().getDisplayMetrics().density;
|
||||
|
||||
//设置基本参数
|
||||
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
// this.getWindow().setBackgroundDrawable(new ColorDrawable(Color.argb(0, 0, 0, 0)));
|
||||
// this.getWindow().setDimAmount(0);
|
||||
this.setCanceledOnTouchOutside(false);
|
||||
|
||||
//父容器
|
||||
{
|
||||
mLinearLayout = new LinearLayout(getContext());
|
||||
mLinearLayout.setGravity(Gravity.CENTER);
|
||||
mLinearLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
mLinearLayout.setPadding(10, 10, 10, 10);
|
||||
mLinearLayout.setBackground(new ColorDrawable(Color.WHITE));
|
||||
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, (int) (mScale * 50));
|
||||
this.setContentView(mLinearLayout, layoutParams);
|
||||
}
|
||||
|
||||
|
||||
//消息显示框
|
||||
TextView mTextView = new TextView(context);
|
||||
mTextView.setText(message);
|
||||
mTextView.setGravity(Gravity.CENTER);
|
||||
mTextView.setTextColor(Color.BLACK);
|
||||
mTextView.setMinWidth((int) (mScale * 150));
|
||||
mLinearLayout.addView(mTextView);
|
||||
|
||||
{
|
||||
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, (int) (mScale * 50));
|
||||
|
||||
Button button = new Button(getContext());
|
||||
button.setText("确认");
|
||||
button.setTextColor(Color.parseColor("#7AECC4"));
|
||||
button.setBackground(null);
|
||||
button.setGravity(Gravity.RIGHT);
|
||||
mLinearLayout.addView(button, layoutParams);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,123 @@
|
||||
package xyz.wbsite.wbui.base.ui.dialog;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
||||
public class CustomDialog extends Dialog {
|
||||
public CustomDialog(Context context) {
|
||||
super(context);
|
||||
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
this.getWindow().getDecorView().setPadding(0, 0, 0, 0);
|
||||
// this.getWindow().setBackgroundDrawable(new ColorDrawable(Color.argb(0, 0, 0, 0)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentView(View view, ViewGroup.LayoutParams params) {
|
||||
if (params.width == ViewGroup.LayoutParams.MATCH_PARENT) {
|
||||
params.width = this.getWindow().getContext().getResources().getDisplayMetrics().widthPixels;
|
||||
}
|
||||
if (params.height == ViewGroup.LayoutParams.MATCH_PARENT) {
|
||||
params.height = this.getWindow().getContext().getResources().getDisplayMetrics().heightPixels;
|
||||
}
|
||||
|
||||
super.setContentView(view, params);
|
||||
}
|
||||
|
||||
public void setContentView(View view, ViewGroup.LayoutParams params, double widthScale, double heightScale) {
|
||||
if (widthScale < 0) {
|
||||
widthScale = 0;
|
||||
}
|
||||
if (heightScale > 1) {
|
||||
heightScale = 1;
|
||||
}
|
||||
if (params.width == ViewGroup.LayoutParams.MATCH_PARENT) {
|
||||
params.width = (int) (widthScale * this.getWindow().getContext().getResources().getDisplayMetrics().widthPixels);
|
||||
}
|
||||
if (params.height == ViewGroup.LayoutParams.MATCH_PARENT) {
|
||||
params.height = (int) (heightScale * this.getWindow().getContext().getResources().getDisplayMetrics().heightPixels);
|
||||
}
|
||||
super.setContentView(view, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentView(int layoutResID) {
|
||||
LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
View inflate = inflater.inflate(layoutResID, null);
|
||||
if (inflater == null) {
|
||||
throw new AssertionError("layout not find");
|
||||
}
|
||||
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
this.setContentView(inflate, layoutParams);
|
||||
}
|
||||
|
||||
public void setContentView(int layoutResID, double widthScale, double heightScale) {
|
||||
LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
View inflate = inflater.inflate(layoutResID, null);
|
||||
if (inflater == null) {
|
||||
throw new AssertionError("layout not find");
|
||||
}
|
||||
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
this.setContentView(inflate, layoutParams, widthScale, heightScale);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对齐方式
|
||||
*
|
||||
* @param gravity
|
||||
*/
|
||||
public void setGravity(int gravity) {
|
||||
WindowManager.LayoutParams attributes = getWindow().getAttributes();
|
||||
attributes.gravity = gravity;
|
||||
getWindow().setAttributes(attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置背景屏幕透明度
|
||||
*/
|
||||
public void setDimAmount(float amount) {
|
||||
this.getWindow().setDimAmount(amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义按钮点击事件
|
||||
*
|
||||
* @param viewId 自定义Dialog viewId
|
||||
* @param clickListener 点击事件监听器
|
||||
* @param dismiss 是否消失
|
||||
*/
|
||||
public void addOnclickListener(int viewId, final View.OnClickListener clickListener, final boolean dismiss) {
|
||||
this.findViewById(viewId).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
clickListener.onClick(v);
|
||||
if (dismiss) {
|
||||
dismiss();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义按钮点击事件
|
||||
*
|
||||
* @param view 自定义Dialog view
|
||||
* @param clickListener 点击事件监听器
|
||||
* @param dismiss 是否消失
|
||||
*/
|
||||
public void addOnclickListener(View view, final View.OnClickListener clickListener, final boolean dismiss) {
|
||||
view.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
clickListener.onClick(v);
|
||||
if (dismiss) {
|
||||
dismiss();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package xyz.wbsite.wbui.base.ui.dialog;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
public class WBUIDialog extends Dialog {
|
||||
public WBUIDialog(@NonNull Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public void show() {
|
||||
super.show();
|
||||
// FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) mContentView
|
||||
// .getLayoutParams();
|
||||
// layoutParams.width = display.getWidth();
|
||||
// layoutParams.height = display.getHeight();
|
||||
// mContentView.setLayoutParams(layoutParams);
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,155 @@
|
||||
package xyz.wbsite.wbui.base.ui.dialog;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.ShapeDrawable;
|
||||
import android.graphics.drawable.StateListDrawable;
|
||||
import android.graphics.drawable.shapes.RoundRectShape;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.TranslateAnimation;
|
||||
import android.widget.Button;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
|
||||
/**
|
||||
* Created by bingwang on 2016/5/17.
|
||||
*/
|
||||
public class WbConfirmDialog extends Dialog {
|
||||
LinearLayout mLinearLayout;
|
||||
private float demsity = 1;
|
||||
private Button mPositiveButton;
|
||||
private Button mNegativeButton;
|
||||
private OnPostiveListener mOnPostiveListener = null;
|
||||
private OnNegativeListener mOnNegativeListener = null;
|
||||
|
||||
public WbConfirmDialog(Context context) {
|
||||
super(context);
|
||||
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
this.getWindow().setGravity(Gravity.FILL_HORIZONTAL | Gravity.BOTTOM);
|
||||
this.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||
this.getWindow().setDimAmount(0.2f);
|
||||
this.getWindow().setWindowAnimations(-1);
|
||||
this.demsity = context.getResources().getDisplayMetrics().density;
|
||||
|
||||
mLinearLayout = new LinearLayout(context);
|
||||
mLinearLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
mLinearLayout.setPadding((int) (5 * demsity), 0, (int) (5 * demsity), (int) (5 * demsity));
|
||||
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);
|
||||
lp.width = context.getResources().getDisplayMetrics().widthPixels;
|
||||
this.setContentView(mLinearLayout, lp);
|
||||
|
||||
{
|
||||
mNegativeButton = new Button(context);
|
||||
mNegativeButton.setText("取消");
|
||||
mNegativeButton.setGravity(Gravity.CENTER);
|
||||
mNegativeButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
onNegative();
|
||||
}
|
||||
});
|
||||
|
||||
float[] out = {5 * demsity, 5 * demsity, 5 * demsity, 5 * demsity, 5 * demsity, 5 * demsity, 5 * demsity, 5 * demsity};
|
||||
RoundRectShape roundRectShape = new RoundRectShape(out, null, null);
|
||||
ShapeDrawable shapeDrawable = new ShapeDrawable(roundRectShape);
|
||||
shapeDrawable.getPaint().setColor(Color.argb(255, 255, 255, 255));
|
||||
|
||||
StateListDrawable stateListDrawable = new StateListDrawable();
|
||||
stateListDrawable.addState(new int[]{-android.R.attr.state_pressed}, shapeDrawable);
|
||||
|
||||
ShapeDrawable shapeDrawable1 = new ShapeDrawable(roundRectShape);
|
||||
shapeDrawable1.getPaint().setColor(Color.argb(255, 240, 240, 240));
|
||||
stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, shapeDrawable1);
|
||||
|
||||
mNegativeButton.setBackground(stateListDrawable);
|
||||
|
||||
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, (int) (45 * demsity));
|
||||
layoutParams.setMargins(0, (int) (5 * demsity), 0, 0);
|
||||
mLinearLayout.addView(mNegativeButton, layoutParams);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
mPositiveButton = new Button(context);
|
||||
mPositiveButton.setText("确认");
|
||||
mPositiveButton.setGravity(Gravity.CENTER);
|
||||
float[] out = {5 * demsity, 5 * demsity, 5 * demsity, 5 * demsity, 5 * demsity, 5 * demsity, 5 * demsity, 5 * demsity};
|
||||
RoundRectShape roundRectShape = new RoundRectShape(out, null, null);
|
||||
ShapeDrawable shapeDrawable = new ShapeDrawable(roundRectShape);
|
||||
shapeDrawable.getPaint().setColor(Color.argb(255, 255, 255, 255));
|
||||
|
||||
StateListDrawable stateListDrawable = new StateListDrawable();
|
||||
stateListDrawable.addState(new int[]{-android.R.attr.state_pressed}, shapeDrawable);
|
||||
|
||||
ShapeDrawable shapeDrawable1 = new ShapeDrawable(roundRectShape);
|
||||
shapeDrawable1.getPaint().setColor(Color.argb(255, 240, 240, 240));
|
||||
stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, shapeDrawable1);
|
||||
mPositiveButton.setBackground(stateListDrawable);
|
||||
|
||||
mPositiveButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
onPositive();
|
||||
}
|
||||
});
|
||||
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, (int) (45 * demsity));
|
||||
mLinearLayout.addView(mPositiveButton, 0, layoutParams);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
super.show();
|
||||
TranslateAnimation translateAnimation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0,
|
||||
Animation.RELATIVE_TO_SELF, 1.0f, Animation.RELATIVE_TO_SELF, 0);
|
||||
translateAnimation.setDuration(200);
|
||||
|
||||
mLinearLayout.startAnimation(translateAnimation);
|
||||
}
|
||||
|
||||
public void onPositive() {
|
||||
dismiss();
|
||||
if (mOnPostiveListener != null) {
|
||||
mOnPostiveListener.onPostive();
|
||||
}
|
||||
}
|
||||
|
||||
public void onNegative() {
|
||||
dismiss();
|
||||
if (mOnNegativeListener != null) {
|
||||
mOnNegativeListener.onNegative();
|
||||
}
|
||||
}
|
||||
|
||||
public OnNegativeListener getOnNegativeListener() {
|
||||
return mOnNegativeListener;
|
||||
}
|
||||
|
||||
public void setOnNegativeListener(OnNegativeListener mOnNegativeListener) {
|
||||
this.mOnNegativeListener = mOnNegativeListener;
|
||||
}
|
||||
|
||||
public OnPostiveListener getOnPostiveListener() {
|
||||
return mOnPostiveListener;
|
||||
}
|
||||
|
||||
public void setOnPostiveListener(OnPostiveListener mOnPostiveListener) {
|
||||
this.mOnPostiveListener = mOnPostiveListener;
|
||||
}
|
||||
|
||||
public interface OnPostiveListener {
|
||||
void onPostive();
|
||||
}
|
||||
|
||||
public interface OnNegativeListener {
|
||||
void onNegative();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,168 @@
|
||||
package xyz.wbsite.wbui.base.ui.image;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.LinearGradient;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.RadialGradient;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Shader;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||
import android.view.animation.AccelerateInterpolator;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.CycleInterpolator;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.RotateAnimation;
|
||||
|
||||
|
||||
public class AnimationView extends View {
|
||||
|
||||
private int fullDegrees = 300;
|
||||
|
||||
private float progress = 0;
|
||||
|
||||
private int offset = 0;
|
||||
private int indicatorRadius;
|
||||
private int indicatorWidth;
|
||||
|
||||
private int arrowWidth;
|
||||
|
||||
private int shadowRadius;
|
||||
|
||||
private int shadowWidth;
|
||||
|
||||
private Animation rotateAnimation;
|
||||
|
||||
public AnimationView(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public AnimationView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
indicatorWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3, getContext().getResources().getDisplayMetrics());
|
||||
shadowWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3, getContext().getResources().getDisplayMetrics());
|
||||
rotateAnimation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
|
||||
rotateAnimation.setDuration(1000);
|
||||
rotateAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
|
||||
rotateAnimation.setRepeatCount(Animation.INFINITE);
|
||||
arrowWidth = indicatorWidth * 3;
|
||||
}
|
||||
|
||||
private int getOffset() {
|
||||
int o = 0;
|
||||
if (getPaddingTop() > o) {
|
||||
o = getPaddingTop();
|
||||
}
|
||||
|
||||
if (getPaddingRight() > o) {
|
||||
o = getPaddingRight();
|
||||
}
|
||||
|
||||
if (getPaddingBottom() > o) {
|
||||
o = getPaddingBottom();
|
||||
}
|
||||
|
||||
if (getPaddingLeft() > o) {
|
||||
o = getPaddingLeft();
|
||||
}
|
||||
|
||||
if (getPaddingStart() > o) {
|
||||
o = getPaddingStart();
|
||||
}
|
||||
|
||||
if (getPaddingEnd() > o) {
|
||||
o = getPaddingEnd();
|
||||
}
|
||||
|
||||
if (o == 0) {
|
||||
o = shadowWidth + 10;
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
|
||||
{//阴影部分
|
||||
shadowRadius = Math.min(width, height) / 2;
|
||||
Paint paint = new Paint();
|
||||
paint.setColor(Color.RED);
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeWidth(shadowWidth);
|
||||
RadialGradient radialGradient = new RadialGradient(
|
||||
width / 2,
|
||||
height / 2,
|
||||
shadowRadius,
|
||||
Color.parseColor("#888888"),
|
||||
Color.TRANSPARENT,
|
||||
Shader.TileMode.REPEAT);
|
||||
paint.setShader(radialGradient);
|
||||
canvas.drawCircle(getWidth() / 2, getHeight() / 2, shadowRadius - shadowWidth / 2 - 1, paint);
|
||||
}
|
||||
|
||||
{//指示器部分
|
||||
offset = getOffset();
|
||||
indicatorRadius = shadowRadius - offset - shadowWidth;
|
||||
int currentDegress = (int) (fullDegrees * progress);
|
||||
int currentArrowWidth = (int) (arrowWidth * progress);
|
||||
|
||||
Path path = new Path();
|
||||
path.moveTo(width / 2, height / 2 - indicatorRadius);
|
||||
RectF outer = new RectF(
|
||||
width / 2 - indicatorRadius,
|
||||
height / 2 - indicatorRadius,
|
||||
width / 2 + indicatorRadius,
|
||||
height / 2 + indicatorRadius
|
||||
);
|
||||
path.addArc(outer, -90, currentDegress);
|
||||
Paint paint1 = new Paint();
|
||||
paint1.setStyle(Paint.Style.STROKE);
|
||||
paint1.setStrokeWidth(indicatorWidth);
|
||||
paint1.setAntiAlias(true);
|
||||
canvas.drawPath(path, paint1);
|
||||
|
||||
Path arrowPath = new Path();
|
||||
arrowPath.moveTo(width / 2, height / 2 - indicatorRadius - currentArrowWidth / 2);
|
||||
arrowPath.lineTo(width / 2, height / 2 - indicatorRadius + currentArrowWidth / 2);
|
||||
arrowPath.lineTo(width / 2 + currentArrowWidth, height / 2 - indicatorRadius);
|
||||
arrowPath.close();
|
||||
paint1.setStyle(Paint.Style.FILL);
|
||||
canvas.rotate(currentDegress, width / 2, height / 2);
|
||||
canvas.drawPath(arrowPath, paint1);
|
||||
}
|
||||
}
|
||||
|
||||
public void startAnimation() {
|
||||
progress = 1;
|
||||
this.startAnimation(rotateAnimation);
|
||||
}
|
||||
|
||||
public void stopAnimation() {
|
||||
this.clearAnimation();
|
||||
}
|
||||
|
||||
|
||||
public float getProgress() {
|
||||
return progress;
|
||||
}
|
||||
|
||||
public void setProgress(float progress) {
|
||||
this.progress = progress;
|
||||
invalidate();
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package xyz.wbsite.wbui.base.ui.image;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import xyz.wbsite.wbui.base.utils.FastBlur;
|
||||
|
||||
|
||||
public class BlurImage extends android.support.v7.widget.AppCompatImageView {
|
||||
public BlurImage(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public BlurImage(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
//获取当前显示的位图
|
||||
Bitmap bitMap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
|
||||
super.onDraw(new Canvas(bitMap));
|
||||
//模糊处理
|
||||
FastBlur.doBlur(bitMap, 10, true);
|
||||
//绘图
|
||||
canvas.drawBitmap(bitMap, 0, 0, new Paint());
|
||||
}
|
||||
}
|
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package xyz.wbsite.wbui.base.ui.image;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RadialGradient;
|
||||
import android.graphics.Shader;
|
||||
import android.graphics.drawable.ShapeDrawable;
|
||||
import android.graphics.drawable.shapes.OvalShape;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.view.ViewCompat;
|
||||
import android.view.View;
|
||||
import android.view.animation.Animation;
|
||||
import android.widget.ImageView;
|
||||
|
||||
/**
|
||||
* Private class created to work around issues with AnimationListeners being
|
||||
* called before the animation is actually complete and support shadows on older
|
||||
* platforms.
|
||||
*/
|
||||
public class CircleImageView extends ImageView {
|
||||
|
||||
private static final int KEY_SHADOW_COLOR = 0x1E000000;
|
||||
private static final int FILL_SHADOW_COLOR = 0x3D000000;
|
||||
// PX
|
||||
private static final float X_OFFSET = 0f;
|
||||
private static final float Y_OFFSET = 1.75f;
|
||||
private static final float SHADOW_RADIUS = 3.5f;
|
||||
private static final int SHADOW_ELEVATION = 4;
|
||||
|
||||
private Animation.AnimationListener mListener;
|
||||
int mShadowRadius;
|
||||
|
||||
public CircleImageView(Context context, int color) {
|
||||
super(context);
|
||||
final float density = getContext().getResources().getDisplayMetrics().density;
|
||||
final int shadowYOffset = (int) (density * Y_OFFSET);
|
||||
final int shadowXOffset = (int) (density * X_OFFSET);
|
||||
|
||||
mShadowRadius = (int) (density * SHADOW_RADIUS);
|
||||
|
||||
ShapeDrawable circle;
|
||||
if (elevationSupported()) {
|
||||
circle = new ShapeDrawable(new OvalShape());
|
||||
ViewCompat.setElevation(this, SHADOW_ELEVATION * density);
|
||||
} else {
|
||||
OvalShape oval = new OvalShadow(mShadowRadius);
|
||||
circle = new ShapeDrawable(oval);
|
||||
setLayerType(View.LAYER_TYPE_SOFTWARE, circle.getPaint());
|
||||
circle.getPaint().setShadowLayer(mShadowRadius, shadowXOffset, shadowYOffset,
|
||||
KEY_SHADOW_COLOR);
|
||||
final int padding = mShadowRadius;
|
||||
// set padding so the inner image sits correctly within the shadow.
|
||||
setPadding(padding, padding, padding, padding);
|
||||
}
|
||||
circle.getPaint().setColor(color);
|
||||
ViewCompat.setBackground(this, circle);
|
||||
}
|
||||
|
||||
private boolean elevationSupported() {
|
||||
return android.os.Build.VERSION.SDK_INT >= 21;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
if (!elevationSupported()) {
|
||||
setMeasuredDimension(getMeasuredWidth() + mShadowRadius * 2, getMeasuredHeight()
|
||||
+ mShadowRadius * 2);
|
||||
}
|
||||
}
|
||||
|
||||
public void setAnimationListener(Animation.AnimationListener listener) {
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationStart() {
|
||||
super.onAnimationStart();
|
||||
if (mListener != null) {
|
||||
mListener.onAnimationStart(getAnimation());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd() {
|
||||
super.onAnimationEnd();
|
||||
if (mListener != null) {
|
||||
mListener.onAnimationEnd(getAnimation());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the background color of the circle image view.
|
||||
*
|
||||
* @param colorRes Id of a color resource.
|
||||
*/
|
||||
public void setBackgroundColorRes(int colorRes) {
|
||||
setBackgroundColor(ContextCompat.getColor(getContext(), colorRes));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundColor(int color) {
|
||||
if (getBackground() instanceof ShapeDrawable) {
|
||||
((ShapeDrawable) getBackground()).getPaint().setColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
private class OvalShadow extends OvalShape {
|
||||
private RadialGradient mRadialGradient;
|
||||
private Paint mShadowPaint;
|
||||
|
||||
OvalShadow(int shadowRadius) {
|
||||
super();
|
||||
mShadowPaint = new Paint();
|
||||
mShadowRadius = shadowRadius;
|
||||
updateRadialGradient((int) rect().width());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResize(float width, float height) {
|
||||
super.onResize(width, height);
|
||||
updateRadialGradient((int) width);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas, Paint paint) {
|
||||
final int viewWidth = CircleImageView.this.getWidth();
|
||||
final int viewHeight = CircleImageView.this.getHeight();
|
||||
canvas.drawCircle(viewWidth / 2, viewHeight / 2, viewWidth / 2, mShadowPaint);
|
||||
canvas.drawCircle(viewWidth / 2, viewHeight / 2, viewWidth / 2 - mShadowRadius, paint);
|
||||
}
|
||||
|
||||
private void updateRadialGradient(int diameter) {
|
||||
mRadialGradient = new RadialGradient(diameter / 2, diameter / 2,
|
||||
mShadowRadius, new int[] { FILL_SHADOW_COLOR, Color.TRANSPARENT },
|
||||
null, Shader.TileMode.CLAMP);
|
||||
mShadowPaint.setShader(mRadialGradient);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package xyz.wbsite.wbui.base.ui.image;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ImageView;
|
||||
|
||||
public class RoundImageView extends ImageView {
|
||||
public RoundImageView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public RoundImageView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
|
||||
//获取原图
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
Bitmap srcBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||
super.onDraw(new Canvas(srcBitmap));
|
||||
|
||||
//绘制原图
|
||||
{
|
||||
Bitmap shapeBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||
Canvas shapeCanvas = new Canvas(shapeBitmap);
|
||||
shapeCanvas.drawCircle(width / 2, height / 2, Math.min(width, height) / 2 - 4, new Paint());
|
||||
|
||||
Paint paint = new Paint();
|
||||
paint.setAntiAlias(true);
|
||||
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
|
||||
shapeCanvas.drawBitmap(srcBitmap, 0, 0, paint);
|
||||
|
||||
canvas.drawBitmap(shapeBitmap, 0, 0, new Paint());
|
||||
}
|
||||
|
||||
//绘制边框
|
||||
{
|
||||
Paint paint = new Paint();
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setColor(Color.GREEN);
|
||||
paint.setStrokeWidth(4);
|
||||
paint.setAntiAlias(true);
|
||||
canvas.drawCircle(width / 2, height / 2, Math.min(width, height) / 2 - 4, paint);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package xyz.wbsite.wbui.base.ui.image;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import xyz.wbsite.webclient.R;
|
||||
|
||||
public class WBUISquareImageView extends android.support.v7.widget.AppCompatImageView {
|
||||
|
||||
private int weight_width = 1;
|
||||
private int weight_height = 1;
|
||||
|
||||
public WBUISquareImageView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public WBUISquareImageView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.uiSquare);
|
||||
weight_width = typedArray.getInt(R.styleable.uiSquare_weight_width,1);
|
||||
weight_height = typedArray.getInt(R.styleable.uiSquare_weight_height,1);
|
||||
}
|
||||
|
||||
public WBUISquareImageView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
setMeasuredDimension(getDefaultSize(0, widthMeasureSpec), getDefaultSize(0, heightMeasureSpec));
|
||||
int width = getMeasuredWidth();
|
||||
int height = getMeasuredHeight();
|
||||
|
||||
int expectWidth = height * weight_width / weight_height;
|
||||
int expectHeght = width * weight_height / weight_width;
|
||||
|
||||
if (expectWidth == 0){
|
||||
expectWidth = expectHeght;
|
||||
}else if (expectHeght == 0){
|
||||
expectHeght = expectWidth;
|
||||
}else {
|
||||
if ((double) expectWidth / width <= (double) expectHeght / height) {
|
||||
expectHeght = expectWidth * weight_height / weight_width;
|
||||
} else {
|
||||
expectWidth = expectHeght * weight_width / weight_height;
|
||||
}
|
||||
}
|
||||
|
||||
widthMeasureSpec = MeasureSpec.makeMeasureSpec(expectWidth, MeasureSpec.EXACTLY);
|
||||
heightMeasureSpec = MeasureSpec.makeMeasureSpec(expectHeght, MeasureSpec.EXACTLY);
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package xyz.wbsite.wbui.base.ui.image;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import xyz.wbsite.wbui.base.utils.FastBlur;
|
||||
|
||||
|
||||
public class WbRoundImageView extends android.support.v7.widget.AppCompatImageView {
|
||||
public WbRoundImageView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public WbRoundImageView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
|
||||
//获取原图
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
Bitmap srcBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||
super.onDraw(new Canvas(srcBitmap));
|
||||
|
||||
canvas.drawBitmap(FastBlur.doBlur(srcBitmap, 20, false), 0, 0, new Paint());
|
||||
|
||||
//绘制原图
|
||||
{
|
||||
Bitmap shapeBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||
Canvas shapeCanvas = new Canvas(shapeBitmap);
|
||||
shapeCanvas.drawCircle(width / 2, height / 2, Math.min(width, height) / 2 - 4, new Paint());
|
||||
|
||||
Paint paint = new Paint();
|
||||
paint.setAntiAlias(true);
|
||||
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
|
||||
shapeCanvas.drawBitmap(srcBitmap, 0, 0, paint);
|
||||
|
||||
canvas.drawBitmap(shapeBitmap, 0, 0, new Paint());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
package xyz.wbsite.wbui.base.ui.layout;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import xyz.wbsite.webclient.R;
|
||||
|
||||
public class WBUISquareLayout extends RelativeLayout {
|
||||
|
||||
private int weight_width = 1;
|
||||
private int weight_height = 1;
|
||||
private int mWidth;
|
||||
private int mHeight;
|
||||
|
||||
private View targetView;
|
||||
|
||||
public WBUISquareLayout(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public WBUISquareLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setWillNotDraw(false);
|
||||
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.uiSquare);
|
||||
weight_width = typedArray.getInt(R.styleable.uiSquare_weight_width, weight_width);
|
||||
weight_height = typedArray.getInt(R.styleable.uiSquare_weight_height, weight_height);
|
||||
}
|
||||
|
||||
public WBUISquareLayout(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
private void ensureView() {
|
||||
int childCount = getChildCount();
|
||||
if (childCount > 1) {
|
||||
throw new IllegalStateException("WBUISquareLayout can host only one child");
|
||||
} else if (childCount == 1) {
|
||||
targetView = getChildAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
|
||||
int wMode = MeasureSpec.getMode(widthMeasureSpec);
|
||||
int wSize = MeasureSpec.getSize(widthMeasureSpec);
|
||||
int hMode = MeasureSpec.getMode(heightMeasureSpec);
|
||||
int hSize = MeasureSpec.getSize(heightMeasureSpec);
|
||||
|
||||
if (wMode == MeasureSpec.EXACTLY && hMode == MeasureSpec.EXACTLY) {
|
||||
mWidth = wSize;
|
||||
mHeight = hSize;
|
||||
} else if (wMode == MeasureSpec.EXACTLY && hMode != MeasureSpec.EXACTLY) {
|
||||
mWidth = wSize;
|
||||
mHeight = wSize * weight_height / weight_width;
|
||||
} else if (wMode != MeasureSpec.EXACTLY && hMode == MeasureSpec.EXACTLY) {
|
||||
mWidth = hSize * weight_width / weight_height;
|
||||
mHeight = hSize;
|
||||
} else if (wMode != MeasureSpec.EXACTLY && hMode != MeasureSpec.EXACTLY) {
|
||||
measureChildren(widthMeasureSpec, heightMeasureSpec);
|
||||
ensureView();
|
||||
if (targetView != null) {
|
||||
int measuredWidth = targetView.getMeasuredWidth();
|
||||
int measuredHeight = targetView.getMeasuredHeight();
|
||||
mWidth = mHeight = Math.max(measuredWidth, measuredHeight);
|
||||
}
|
||||
}
|
||||
measureChildren(MeasureSpec.makeMeasureSpec(mWidth,MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(mHeight,MeasureSpec.AT_MOST));
|
||||
setMeasuredDimension(mWidth, mHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
ensureView();
|
||||
if (targetView != null) {
|
||||
int measuredWidth = targetView.getMeasuredWidth();
|
||||
int measuredHeight = targetView.getMeasuredHeight();
|
||||
if (measuredWidth > measuredHeight) {
|
||||
int dy = measuredWidth - measuredHeight;
|
||||
targetView.layout(0, dy / 2, measuredWidth, measuredHeight + dy / 2);
|
||||
} else {
|
||||
int dx = measuredHeight - measuredWidth;
|
||||
targetView.layout(dx / 2, 0, measuredWidth + dx / 2, measuredHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
package xyz.wbsite.wbui.base.ui.layout;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.support.v4.view.PagerAdapter;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
/**
|
||||
* Created by bingwang on 2016/5/16.
|
||||
*/
|
||||
public class WbViewPager extends RelativeLayout {
|
||||
|
||||
private LinearLayout mIndexView;
|
||||
private ViewPager mViewPager;
|
||||
|
||||
public WbViewPager(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public WbViewPager(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
mViewPager = new ViewPager(context);
|
||||
this.addView(mViewPager, new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
|
||||
mIndexView = new LinearLayout(context);
|
||||
mIndexView.setGravity(Gravity.CENTER);
|
||||
mIndexView.setOrientation(LinearLayout.HORIZONTAL);
|
||||
LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 50);
|
||||
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
|
||||
layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
|
||||
layoutParams.setMargins(0, 0, 0, 10);
|
||||
this.addView(mIndexView, layoutParams);
|
||||
}
|
||||
|
||||
public void setAdapter(PagerAdapter adapter) {
|
||||
mViewPager.setAdapter(adapter);
|
||||
|
||||
for (int i = 0; i < adapter.getCount(); i++) {
|
||||
Circle circle = new Circle(getContext());
|
||||
if (i == 0) {
|
||||
circle.setColor(Color.argb(255, 100, 100, 100));
|
||||
}
|
||||
mIndexView.addView(circle, new ViewGroup.LayoutParams(40, 20));
|
||||
}
|
||||
|
||||
|
||||
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
for (int i = 0; i < mIndexView.getChildCount(); i++) {
|
||||
Circle circle = (Circle) mIndexView.getChildAt(i);
|
||||
circle.setColor(Color.argb(255, 200, 200, 200));
|
||||
circle.invalidate();
|
||||
}
|
||||
Circle circle = (Circle) mIndexView.getChildAt(position);
|
||||
circle.setColor(Color.argb(255, 100, 100, 100));
|
||||
circle.invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private class Circle extends View {
|
||||
private int mColor = Color.argb(255, 200, 200, 200);
|
||||
private Paint mPaint = new Paint();
|
||||
|
||||
public Circle(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
mPaint.setColor(mColor);
|
||||
canvas.drawCircle(getWidth() / 2, getHeight() / 2, Math.min(getWidth() / 2, getHeight() / 2), mPaint);
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return mColor;
|
||||
}
|
||||
|
||||
public void setColor(int mColor) {
|
||||
this.mColor = mColor;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,144 @@
|
||||
package xyz.wbsite.wbui.base.ui.list;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.ListView;
|
||||
|
||||
public class BoundListView extends ListView {
|
||||
public static int OVERSCROLL_STATE_NORMAL = 0;//正常
|
||||
public static int OVERSCROLL_STATE_PULL = -1;//拉
|
||||
public static int OVERSCROLL_STATE_PUSH = 1;//推
|
||||
|
||||
private int mOverScrollState = OVERSCROLL_STATE_NORMAL;
|
||||
private float lastY = -1;//最近一次Y轴位置
|
||||
|
||||
/**
|
||||
* 小于0-->pull,大于0-->push
|
||||
*/
|
||||
private int mOverY = 0;
|
||||
|
||||
public BoundListView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public BoundListView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOverScrollMode(int mode) {
|
||||
//去掉边缘发光效果
|
||||
super.setOverScrollMode(OVER_SCROLL_NEVER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
switch (ev.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
if (mOverY < 0) {
|
||||
mOverScrollState = OVERSCROLL_STATE_PULL;
|
||||
} else if (mOverY > 0) {
|
||||
mOverScrollState = OVERSCROLL_STATE_PUSH;
|
||||
}
|
||||
}
|
||||
if (mOverScrollState != OVERSCROLL_STATE_NORMAL) {
|
||||
switch (ev.getAction()) {
|
||||
case MotionEvent.ACTION_UP:
|
||||
mOverScrollState = OVERSCROLL_STATE_NORMAL;
|
||||
onBound();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (lastY < 0) {
|
||||
lastY = ev.getY();
|
||||
} else {
|
||||
if (Math.abs(ev.getY() - lastY) > 30) {
|
||||
lastY = ev.getY();
|
||||
return true;
|
||||
}
|
||||
if (ev.getY() - lastY != 0) {
|
||||
if (mOverScrollState == OVERSCROLL_STATE_PULL) {
|
||||
mOverY -= (ev.getY() - lastY);
|
||||
if (mOverY > 0) {
|
||||
mOverY = 0;
|
||||
mOverScrollState = OVERSCROLL_STATE_NORMAL;
|
||||
ev.setAction(MotionEvent.ACTION_DOWN);
|
||||
super.onTouchEvent(ev);
|
||||
}
|
||||
} else if (mOverScrollState == OVERSCROLL_STATE_PUSH) {
|
||||
mOverY -= (ev.getY() - lastY);
|
||||
if (mOverY < 0) {
|
||||
mOverY = 0;
|
||||
mOverScrollState = OVERSCROLL_STATE_NORMAL;
|
||||
ev.setAction(MotionEvent.ACTION_DOWN);
|
||||
super.onTouchEvent(ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
lastY = ev.getY();
|
||||
invalidate();
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return super.onTouchEvent(ev);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
|
||||
// if (isTouchEvent) {
|
||||
// if (deltaY < 0) {
|
||||
// mOverScrollState = OVERSCROLL_STATE_PULL;
|
||||
// } else {
|
||||
// mOverScrollState = OVERSCROLL_STATE_PUSH;
|
||||
// }
|
||||
// mOverY += deltaY;
|
||||
// invalidate();
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
canvas.translate(0, -mOverY / 2);
|
||||
super.draw(canvas);
|
||||
}
|
||||
|
||||
/**
|
||||
* 回弹归位
|
||||
*/
|
||||
private void onBound() {
|
||||
final int during = 1000;
|
||||
final int d = 10;
|
||||
if (mOverY != 0) {
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
int flag = 1;
|
||||
if (mOverY < 0) {
|
||||
flag = -1;
|
||||
mOverY = -mOverY;
|
||||
}
|
||||
int temp = mOverY;
|
||||
|
||||
int i = 0;
|
||||
while (i < during && Math.abs(temp) >= 5 && mOverScrollState == OVERSCROLL_STATE_NORMAL) {
|
||||
try {
|
||||
Thread.sleep(d);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
i += d;
|
||||
temp = (int) (Math.pow((double) i / during - 1, 2) * temp);
|
||||
mOverY = flag * temp;
|
||||
postInvalidate();
|
||||
}
|
||||
mOverY = 0;
|
||||
postInvalidate();
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package xyz.wbsite.wbui.base.ui.list;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ListView;
|
||||
|
||||
public class NoScrollListView extends ListView {
|
||||
|
||||
public NoScrollListView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public NoScrollListView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public NoScrollListView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置listView不可滑动
|
||||
*
|
||||
* @param widthMeasureSpec
|
||||
* @param heightMeasureSpec
|
||||
*/
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
|
||||
MeasureSpec.AT_MOST);
|
||||
super.onMeasure(widthMeasureSpec, expandSpec);
|
||||
}
|
||||
}
|
@ -0,0 +1,178 @@
|
||||
package xyz.wbsite.wbui.base.ui.list;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ScrollView;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public class OverScrollView extends ScrollView {
|
||||
LinearLayout mLinearLayout;
|
||||
LinearLayout mHeader;
|
||||
LinearLayout mFooter;
|
||||
private int mLastScrollY = -1;
|
||||
private int mOverY = 0;
|
||||
private int mLastMotionY = 0;
|
||||
|
||||
public static int OVERSCROLL_STATE_NORMAL = 0;//正常
|
||||
public static int OVERSCROLL_STATE_PULL = 1;//拉
|
||||
public static int OVERSCROLL_STATE_PUSH = -1;//推
|
||||
|
||||
private int mOverScrollState = OVERSCROLL_STATE_NORMAL;
|
||||
|
||||
public OverScrollView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public OverScrollView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOverScrollMode(int mode) {
|
||||
//去掉边缘发光效果
|
||||
super.setOverScrollMode(OVER_SCROLL_NEVER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addView(View child, int index, ViewGroup.LayoutParams params) {
|
||||
Log.i("--->", "addView");
|
||||
|
||||
mLinearLayout = new LinearLayout(getContext());
|
||||
mLinearLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
|
||||
mHeader = new LinearLayout(getContext());
|
||||
mFooter = new LinearLayout(getContext());
|
||||
mLinearLayout.addView(mHeader, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
mLinearLayout.addView(child, params);
|
||||
mLinearLayout.addView(mFooter, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
super.addView(mLinearLayout, index, layoutParams);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
switch (ev.getAction()) {
|
||||
case MotionEvent.ACTION_UP:
|
||||
mOverScrollState = OVERSCROLL_STATE_NORMAL;
|
||||
onBound();
|
||||
}
|
||||
|
||||
if (mOverScrollState == OVERSCROLL_STATE_PULL) {
|
||||
if (ev.getY() > mLastMotionY) {
|
||||
mOverY = (int) (ev.getY() - mLastMotionY);
|
||||
this.fullScroll(ScrollView.FOCUS_UP);
|
||||
mHeader.setMinimumHeight(mOverY);
|
||||
Log.i("-->", "mOverY=" + mOverY);
|
||||
} else {
|
||||
mOverScrollState = OVERSCROLL_STATE_NORMAL;
|
||||
}
|
||||
return true;
|
||||
} else if (mOverScrollState == OVERSCROLL_STATE_PUSH) {
|
||||
if (mLastMotionY > ev.getY()) {
|
||||
mOverY = (int) (ev.getY() - mLastMotionY);
|
||||
mFooter.setMinimumHeight(-mOverY);
|
||||
this.fullScroll(ScrollView.FOCUS_DOWN);
|
||||
Log.i("-->", "mOverY=" + mOverY);
|
||||
} else {
|
||||
mOverScrollState = OVERSCROLL_STATE_NORMAL;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return super.onTouchEvent(ev);
|
||||
}
|
||||
|
||||
/**
|
||||
* 回弹归位
|
||||
*/
|
||||
private void onBound() {
|
||||
final Handler handler = new Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
if (mOverY > 0) {
|
||||
OverScrollView.this.fullScroll(ScrollView.FOCUS_UP);
|
||||
mHeader.setMinimumHeight(mOverY);
|
||||
} else if (mOverY < 0) {
|
||||
OverScrollView.this.fullScroll(ScrollView.FOCUS_DOWN);
|
||||
mFooter.setMinimumHeight(-mOverY);
|
||||
} else {
|
||||
mHeader.setMinimumHeight(0);
|
||||
mFooter.setMinimumHeight(0);
|
||||
}
|
||||
}
|
||||
};
|
||||
new Thread() {
|
||||
int during = 1000;
|
||||
int d = 10;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
int flag = 1;
|
||||
if (mOverY < 0) {
|
||||
flag = -1;
|
||||
mOverY = -mOverY;
|
||||
}
|
||||
int temp = mOverY;
|
||||
|
||||
int i = 0;
|
||||
while (i < during && Math.abs(temp) >= 5 && mOverScrollState == OVERSCROLL_STATE_NORMAL) {
|
||||
try {
|
||||
Thread.sleep(d);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
i += d;
|
||||
temp = (int) (Math.pow((double) i / during - 1, 2) * temp);
|
||||
mOverY = flag * temp;
|
||||
handler.sendEmptyMessage(1);
|
||||
}
|
||||
mOverY = 0;
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
|
||||
|
||||
//只捕捉边界值
|
||||
if (mOverScrollState == OVERSCROLL_STATE_NORMAL && (scrollY == 0 || scrollY == scrollRangeY)) {
|
||||
if (scrollY == 0) {
|
||||
mOverScrollState = OVERSCROLL_STATE_PULL;
|
||||
} else {
|
||||
mOverScrollState = OVERSCROLL_STATE_PUSH;
|
||||
}
|
||||
try {
|
||||
Class aClass = this.getClass().getSuperclass();
|
||||
Field mLastMotionYField = aClass.getDeclaredField("mLastMotionY");
|
||||
mLastMotionYField.setAccessible(true);
|
||||
mLastMotionY = (int) mLastMotionYField.get(this);
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
// switch (mOverScrollState){
|
||||
// case -1:
|
||||
// Log.i("-->","PUSH");
|
||||
// break;
|
||||
// case 1:
|
||||
// Log.i("-->","PULL");
|
||||
// break;
|
||||
// case 0:
|
||||
// Log.i("-->","NORMAL");
|
||||
// break;
|
||||
// }
|
||||
|
||||
// Log.i("-->-->","deltaY-->"+getScaleY()+"/"+scrollY+"---"+scrollRangeY);
|
||||
return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package xyz.wbsite.wbui.base.ui.list;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
/**
|
||||
* Created by wangbing on 2016/4/17.
|
||||
*/
|
||||
public class OverView extends LinearLayout {
|
||||
private int mOverY = 0;
|
||||
private int mLastY = -1;
|
||||
|
||||
public OverView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public OverView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
Log.i("-->", "Y" + event.getY());
|
||||
Log.i("-->", "mLastY" + mLastY);
|
||||
if (mLastY == -1) {
|
||||
mLastY = (int) event.getY();
|
||||
} else {
|
||||
mOverY = (int) (event.getY() - mLastY);
|
||||
invalidate();
|
||||
}
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_UP:
|
||||
mLastY = -1;
|
||||
onBound();
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void onBound() {
|
||||
final int during = 1000;
|
||||
final int d = 10;
|
||||
if (mOverY != 0) {
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
int flag = 1;
|
||||
if (mOverY < 0) {
|
||||
flag = -1;
|
||||
mOverY = -mOverY;
|
||||
}
|
||||
int temp = mOverY;
|
||||
|
||||
int i = 0;
|
||||
while (i < during && Math.abs(temp) >= 5) {
|
||||
try {
|
||||
Thread.sleep(d);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
i += d;
|
||||
temp = (int) (Math.pow((double) i / during - 1, 2) * temp);
|
||||
mOverY = flag * temp;
|
||||
postInvalidate();
|
||||
}
|
||||
mOverY = 0;
|
||||
postInvalidate();
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
canvas.translate(0, mOverY / 2);
|
||||
super.draw(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
||||
if (ev.getAction() == MotionEvent.ACTION_MOVE) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,142 @@
|
||||
package xyz.wbsite.wbui.base.ui.other;
|
||||
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RadialGradient;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Shader;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
|
||||
import xyz.wbsite.wbui.base.utils.DensityUtil;
|
||||
|
||||
public class LoadingProgressBar extends View {
|
||||
private ValueAnimator mAnimator;
|
||||
|
||||
private Paint mShadowPaint = new Paint();
|
||||
private Paint mPaint = new Paint();
|
||||
private int shadowWidth = DensityUtil.dp2px(getContext(), 4);
|
||||
private int backgroundWidth = DensityUtil.dp2px(getContext(), 4);
|
||||
private int indicatorWidth = DensityUtil.dp2px(getContext(), 3);
|
||||
|
||||
private int startAngle = -90;
|
||||
private int sweepAngle = 100;
|
||||
private int mDuration = 1000;
|
||||
|
||||
private int defaultSize = DensityUtil.dp2px(getContext(), 50);
|
||||
|
||||
private boolean isAnimating = false;
|
||||
|
||||
public LoadingProgressBar(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public LoadingProgressBar(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
int wMode = MeasureSpec.getMode(widthMeasureSpec);
|
||||
int hMode = MeasureSpec.getMode(heightMeasureSpec);
|
||||
|
||||
if (wMode == MeasureSpec.AT_MOST) {
|
||||
setMeasuredDimension(defaultSize, MeasureSpec.getSize(heightMeasureSpec));
|
||||
return;
|
||||
} else if (hMode == MeasureSpec.AT_MOST) {
|
||||
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), defaultSize);
|
||||
return;
|
||||
} else if (wMode == MeasureSpec.AT_MOST && hMode == MeasureSpec.AT_MOST) {
|
||||
setMeasuredDimension(defaultSize, defaultSize);
|
||||
return;
|
||||
}
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
int radius = Math.min(width, height) / 2;
|
||||
if (radius >= shadowWidth + backgroundWidth) {
|
||||
RadialGradient radialGradient = new RadialGradient(width / 2, height / 2, radius, new int[]{Color.GRAY, Color.TRANSPARENT}, null, Shader.TileMode.CLAMP);
|
||||
mShadowPaint.setShader(radialGradient);
|
||||
canvas.drawCircle(width / 2, height / 2, radius, mShadowPaint);
|
||||
|
||||
mPaint.setColor(Color.WHITE);
|
||||
mPaint.setStyle(Paint.Style.FILL);
|
||||
mPaint.setAntiAlias(true);
|
||||
canvas.drawCircle(width / 2, height / 2, radius - shadowWidth, mPaint);
|
||||
}
|
||||
|
||||
|
||||
if (radius >= shadowWidth + backgroundWidth + indicatorWidth) {
|
||||
mPaint.setColor(Color.RED);
|
||||
mPaint.setStyle(Paint.Style.STROKE);
|
||||
mPaint.setStrokeWidth(indicatorWidth);
|
||||
|
||||
RectF rectF = new RectF(
|
||||
width / 2 - radius + shadowWidth + backgroundWidth + indicatorWidth / 2,
|
||||
height / 2 - radius + shadowWidth + backgroundWidth + indicatorWidth / 2,
|
||||
width / 2 + radius - shadowWidth - backgroundWidth - indicatorWidth / 2,
|
||||
height / 2 + radius - shadowWidth - backgroundWidth - indicatorWidth / 2);
|
||||
canvas.drawArc(rectF, startAngle, sweepAngle, false, mPaint);
|
||||
}
|
||||
}
|
||||
|
||||
public void setProgress(float process) {
|
||||
startAngle = (int) (process * 360 - 90);
|
||||
sweepAngle = (int) (Math.abs(startAngle + 90 - 180) * 1.0f / 180 * 120 + 45);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void startAnimation() {
|
||||
mAnimator = ValueAnimator.ofInt(-90, 270);
|
||||
mAnimator.setDuration(mDuration);
|
||||
mAnimator.setRepeatCount(ValueAnimator.INFINITE);
|
||||
mAnimator.setRepeatMode(ValueAnimator.RESTART);
|
||||
mAnimator.setInterpolator(new LinearInterpolator());
|
||||
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
startAngle = (int) animation.getAnimatedValue();
|
||||
sweepAngle = (int) (Math.abs(startAngle + 90 - 180) * 1.0f / 180 * 120 + 45);
|
||||
invalidate();
|
||||
}
|
||||
});
|
||||
mAnimator.addListener(new Animator.AnimatorListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
isAnimating = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
isAnimating = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animator animation) {
|
||||
}
|
||||
});
|
||||
mAnimator.start();
|
||||
}
|
||||
|
||||
public void stopAnimation() {
|
||||
if (isAnimating) {
|
||||
mAnimator.cancel();
|
||||
startAngle = -90;
|
||||
sweepAngle = 100;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
package xyz.wbsite.wbui.base.ui.other;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.SweepGradient;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
|
||||
/**
|
||||
* Created by bingwang on 2016/5/14.
|
||||
*/
|
||||
public class LoadingView extends View {
|
||||
/**
|
||||
* 周期
|
||||
*/
|
||||
private int mDuring = 1000;
|
||||
/**
|
||||
* 旋转步长
|
||||
*/
|
||||
private int mStep = 10;
|
||||
/**
|
||||
* 当前旋转角度
|
||||
*/
|
||||
private int mSweep = 0;
|
||||
/**
|
||||
* 前景色
|
||||
*/
|
||||
private int mColor = Color.BLACK;
|
||||
|
||||
public LoadingView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public LoadingView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
||||
DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||
WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
|
||||
wm.getDefaultDisplay().getMetrics(displayMetrics);
|
||||
|
||||
int widhtMode = MeasureSpec.getMode(widthMeasureSpec);
|
||||
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
|
||||
if (widhtMode == MeasureSpec.EXACTLY) {
|
||||
width = widthSize;
|
||||
} else {
|
||||
width = (int) (50 * displayMetrics.density);
|
||||
}
|
||||
|
||||
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
|
||||
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
|
||||
if (heightMode == MeasureSpec.EXACTLY) {
|
||||
height = heightSize;
|
||||
} else {
|
||||
height = (int) (50 * displayMetrics.density);
|
||||
}
|
||||
setMeasuredDimension(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDraw(Canvas canvas) {
|
||||
int scale = 0;
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
if (width > height) {
|
||||
scale = height;
|
||||
} else {
|
||||
scale = width;
|
||||
}
|
||||
//画圈
|
||||
Paint paint = new Paint();
|
||||
//设置画笔
|
||||
paint.setColor(Color.BLUE);
|
||||
paint.setAntiAlias(true);
|
||||
//设置角度渐变
|
||||
SweepGradient radialGradient = new SweepGradient(width / 2, height / 2, mColor, Color.argb(0, 0, 0, 255));
|
||||
paint.setShader(radialGradient);
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeWidth(10);
|
||||
|
||||
canvas.rotate(mSweep, width / 2, height / 2);
|
||||
canvas.drawCircle(width / 2, height / 2, scale / 2 - 10, paint);
|
||||
mSweep += mStep;
|
||||
if (mSweep >= 360) {
|
||||
mSweep = 0;
|
||||
}
|
||||
postInvalidateDelayed(360 / mStep);
|
||||
}
|
||||
|
||||
public int getDuring() {
|
||||
return mDuring;
|
||||
}
|
||||
|
||||
public void setDuring(int mDuring) {
|
||||
this.mDuring = mDuring;
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return mColor;
|
||||
}
|
||||
|
||||
public void setColor(int mColor) {
|
||||
this.mColor = mColor;
|
||||
}
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
package xyz.wbsite.wbui.base.ui.other;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RectF;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
|
||||
/**
|
||||
* Created by bingwang on 2016/5/14.
|
||||
*/
|
||||
public class LoadingView1 extends View {
|
||||
/**
|
||||
* 周期
|
||||
*/
|
||||
private int mDuring = 1000;
|
||||
|
||||
private int firstFlag;
|
||||
/**
|
||||
* 前景色
|
||||
*/
|
||||
private int mColor = Color.BLACK;
|
||||
|
||||
public LoadingView1(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public LoadingView1(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
||||
DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||
WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
|
||||
wm.getDefaultDisplay().getMetrics(displayMetrics);
|
||||
|
||||
int widhtMode = MeasureSpec.getMode(widthMeasureSpec);
|
||||
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
|
||||
if (widhtMode == MeasureSpec.EXACTLY) {
|
||||
width = widthSize;
|
||||
} else {
|
||||
width = (int) (50 * displayMetrics.density);
|
||||
}
|
||||
|
||||
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
|
||||
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
|
||||
if (heightMode == MeasureSpec.EXACTLY) {
|
||||
height = heightSize;
|
||||
} else {
|
||||
height = (int) (50 * displayMetrics.density);
|
||||
}
|
||||
setMeasuredDimension(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
int scale = 0;
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
if (width > height) {
|
||||
scale = height;
|
||||
} else {
|
||||
scale = width;
|
||||
}
|
||||
|
||||
Paint p = new Paint();
|
||||
p.setAntiAlias(true);
|
||||
p.setColor(mColor);
|
||||
|
||||
int centerX = getWidth() / 2;
|
||||
int centerY = getHeight() / 2;
|
||||
int blockWidth = scale / 20;
|
||||
int blockHeight = scale / 4;
|
||||
int radiou = blockWidth / 2;
|
||||
RectF rect = new RectF(centerX - blockWidth / 2, centerY - 3 * blockHeight / 2, centerX + blockWidth / 2, centerY - blockHeight / 2);
|
||||
canvas.rotate(firstFlag, centerX, centerY);
|
||||
firstFlag += 30;
|
||||
if (firstFlag == 360) firstFlag = 0;
|
||||
canvas.drawRoundRect(rect, radiou, radiou, p);
|
||||
|
||||
for (int i = 0; i < 11; i++) {
|
||||
canvas.rotate(30, centerX, centerY);
|
||||
p.setAlpha(i * (255 / 12));
|
||||
canvas.drawRoundRect(rect, radiou, radiou, p);
|
||||
}
|
||||
postInvalidateDelayed(mDuring / 12);
|
||||
}
|
||||
|
||||
public int getDuring() {
|
||||
return mDuring;
|
||||
}
|
||||
|
||||
public void setDuring(int mDuring) {
|
||||
this.mDuring = mDuring;
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return mColor;
|
||||
}
|
||||
|
||||
public void setColor(int mColor) {
|
||||
this.mColor = mColor;
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package xyz.wbsite.wbui.base.ui.other;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||
|
||||
/**
|
||||
* Created by bingwang on 2016/5/14.
|
||||
*/
|
||||
public class LoadingView2 extends View {
|
||||
/**
|
||||
* 周期
|
||||
*/
|
||||
private int mDuring = 600;
|
||||
private int timeStamp = 0;
|
||||
private int currentAngle = 0;
|
||||
|
||||
public LoadingView2(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public LoadingView2(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
|
||||
AccelerateDecelerateInterpolator interpolator = new AccelerateDecelerateInterpolator();
|
||||
currentAngle = (int) (360 * interpolator.getInterpolation(((float) (timeStamp % mDuring) / (mDuring + 1))));
|
||||
canvas.rotate(currentAngle, width / 2, height / 2);
|
||||
|
||||
Paint paint = new Paint();
|
||||
paint.setAntiAlias(true);
|
||||
canvas.drawCircle(width / 2, height / 2, 3, paint);
|
||||
|
||||
int abs = Math.abs((currentAngle % 360) % 180 - 180 * ((currentAngle % 360) / 180));
|
||||
for (int i = 0; i < 5; i++) {
|
||||
canvas.rotate(-abs * 30 / 180, width / 2, height / 2);
|
||||
paint.setAlpha(255 - 255 * i / 5);
|
||||
canvas.drawCircle(width / 2, height / 2 - 50, 10, paint);
|
||||
}
|
||||
|
||||
// for (int i = 0; i < 200; i++) {
|
||||
// float interpolation = interpolator.getInterpolation(i / 100f);
|
||||
//
|
||||
// StringBuffer stringBuffer = new StringBuffer();
|
||||
// stringBuffer.append(i/100f);
|
||||
// for (int j = 0; j < interpolation*100; j++) {
|
||||
// stringBuffer.append(".");
|
||||
// }
|
||||
// System.out.println(stringBuffer.toString());
|
||||
// }
|
||||
|
||||
timeStamp += 10;
|
||||
postInvalidateDelayed(30);
|
||||
}
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
package xyz.wbsite.wbui.base.witget.other;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.inputmethodservice.Keyboard.Key;
|
||||
import android.inputmethodservice.KeyboardView;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import xyz.wbsite.webclient.R;
|
||||
|
||||
public class WBUIKeyboardView extends KeyboardView {
|
||||
|
||||
private Drawable mKeybgDrawable;
|
||||
private Resources res;
|
||||
|
||||
public WBUIKeyboardView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
initResources(context);
|
||||
}
|
||||
|
||||
public WBUIKeyboardView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
initResources(context);
|
||||
}
|
||||
|
||||
private void initResources(Context context) {
|
||||
res = context.getResources();
|
||||
mKeybgDrawable = res.getDrawable(R.drawable.ui_keyboard_key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDraw(Canvas canvas) {
|
||||
List<Key> keys = getKeyboard().getKeys();
|
||||
for (Key key : keys) {
|
||||
canvas.save();
|
||||
|
||||
int offsety = 0;
|
||||
if (key.y == 0) {
|
||||
offsety = 1;
|
||||
}
|
||||
|
||||
int initdrawy = key.y + offsety;
|
||||
|
||||
Rect rect = new Rect(key.x, initdrawy, key.x + key.width, key.y
|
||||
+ key.height);
|
||||
|
||||
canvas.clipRect(rect);
|
||||
|
||||
int primaryCode = -1;
|
||||
if (null != key.codes && key.codes.length != 0) {
|
||||
primaryCode = key.codes[0];
|
||||
}
|
||||
|
||||
Drawable dr = mKeybgDrawable;
|
||||
|
||||
if (null != dr) {
|
||||
int[] state = key.getCurrentDrawableState();
|
||||
|
||||
dr.setState(state);
|
||||
dr.setBounds(rect);
|
||||
dr.draw(canvas);
|
||||
}
|
||||
|
||||
Paint paint = new Paint();
|
||||
paint.setAntiAlias(true);
|
||||
paint.setTextAlign(Paint.Align.CENTER);
|
||||
paint.setTextSize(50);
|
||||
paint.setColor(Color.BLACK);
|
||||
|
||||
if (key.label != null) {
|
||||
canvas.drawText(
|
||||
key.label.toString(),
|
||||
key.x + (key.width / 2),
|
||||
initdrawy + (key.height + paint.getTextSize() - paint.descent()) / 2,
|
||||
paint);
|
||||
} else if (key.icon != null) {
|
||||
int intriWidth = key.icon.getIntrinsicWidth();
|
||||
int intriHeight = key.icon.getIntrinsicHeight();
|
||||
|
||||
final int drawableX = key.x + (key.width - intriWidth) / 2;
|
||||
final int drawableY = initdrawy + (key.height - intriHeight) / 2;
|
||||
|
||||
key.icon.setBounds(
|
||||
drawableX, drawableY, drawableX + intriWidth,
|
||||
drawableY + intriHeight);
|
||||
|
||||
key.icon.draw(canvas);
|
||||
}
|
||||
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
package xyz.wbsite.wbui.base.ui.spinner;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.LayerDrawable;
|
||||
import android.graphics.drawable.ShapeDrawable;
|
||||
import android.graphics.drawable.shapes.RoundRectShape;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.PopupWindow;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class WbSpinner extends TextView {
|
||||
private String[] arrs = {
|
||||
"AAAAAAAAAAAA", "BBBBBBBBBBB", "CCCCCCCCCCC", "DDDDDDDDDDD"
|
||||
};
|
||||
private float scale;
|
||||
private ListView optionList;
|
||||
private Context context;
|
||||
private int width;
|
||||
private boolean isShow = false;
|
||||
private PopupWindow popupWindow;
|
||||
private TextView itemTxtView;
|
||||
|
||||
public WbSpinner(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public WbSpinner(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
width = getWidth();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
context = getContext();
|
||||
scale = getResources().getDisplayMetrics().density;
|
||||
this.setTextColor(Color.BLACK);
|
||||
|
||||
this.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (isShow) {
|
||||
popupWindow.dismiss();
|
||||
isShow = false;
|
||||
return;
|
||||
}
|
||||
isShow = true;
|
||||
optionList = new ListView(context);
|
||||
optionList.setDivider(new ColorDrawable(Color.parseColor("#efefef")));
|
||||
optionList.setDividerHeight(1);
|
||||
optionList.setFadingEdgeLength(0);
|
||||
|
||||
ShapeDrawable shapeDrawable = new ShapeDrawable(new RoundRectShape(new float[]{0, 0, 0, 0, 5, 5, 5, 5}, new RectF((int) (1 * scale), (int) (1 * scale), (int) (1 * scale), (int) (1 * scale)), new float[]{0, 0, 0, 0, 5, 5, 5, 5}));
|
||||
shapeDrawable.getPaint().setColor(Color.parseColor("#efefef"));
|
||||
shapeDrawable.setPadding((int) (1 * scale), 0, (int) (1 * scale), (int) (1 * scale));
|
||||
|
||||
ColorDrawable colorDrawable = new ColorDrawable(Color.WHITE);
|
||||
LayerDrawable layerDrawable = new LayerDrawable(new Drawable[]{colorDrawable, shapeDrawable});
|
||||
optionList.setBackground(layerDrawable);
|
||||
|
||||
itemTxtView = new TextView(getContext());
|
||||
itemTxtView.setBackgroundColor(Color.BLUE);
|
||||
int id = (int) (new Date().getTime());
|
||||
itemTxtView.setId(id);
|
||||
|
||||
optionList.setAdapter(new ArrayAdapter<String>(context, id, arrs));
|
||||
optionList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
WbSpinner.this.setText(arrs[position]);
|
||||
popupWindow.dismiss();
|
||||
isShow = false;
|
||||
}
|
||||
});
|
||||
|
||||
popupWindow = new PopupWindow(width, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
popupWindow.setContentView(optionList);
|
||||
popupWindow.showAsDropDown(WbSpinner.this, 0, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package xyz.wbsite.wbui.base.ui.textview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextPaint;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
public class AverageTextView extends android.support.v7.widget.AppCompatTextView {
|
||||
|
||||
public AverageTextView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public AverageTextView(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
TextPaint paint = getPaint();
|
||||
paint.setTextAlign(Paint.Align.CENTER);
|
||||
paint.setColor(getCurrentTextColor());
|
||||
|
||||
String mText = getText().toString();
|
||||
int width = getWidth() - getPaddingLeft() - getPaddingRight();
|
||||
int height = getHeight() - getPaddingTop() - getPaddingBottom();
|
||||
int x_offset = getPaddingLeft();
|
||||
int y_offset = getPaddingTop();
|
||||
|
||||
Paint.FontMetrics fontMetrics = paint.getFontMetrics();
|
||||
float offset = (Math.abs(fontMetrics.top) - fontMetrics.bottom) / 2;
|
||||
|
||||
if (mText.length() >= 2) {
|
||||
String firstF = String.valueOf(mText.charAt(0));
|
||||
String lastF = String.valueOf(mText.charAt(mText.length() - 1));
|
||||
|
||||
float firstF_W = paint.measureText(firstF);
|
||||
float lastF_W = paint.measureText(lastF);
|
||||
|
||||
{// 绘制首位字符
|
||||
canvas.drawText(firstF, firstF_W / 2 + x_offset, height / 2 + offset + y_offset, paint);
|
||||
canvas.drawText(lastF, width - lastF_W / 2 + x_offset, height / 2 + offset + y_offset, paint);
|
||||
}
|
||||
|
||||
// 如果大于2个才均分
|
||||
if (mText.length() > 2) {
|
||||
float remainingWidth = width - firstF_W / 2 - lastF_W / 2;//剩余宽度
|
||||
float averageW = remainingWidth / (mText.length() - 2 + 1);//等分距离
|
||||
|
||||
for (int i = 1; i < mText.length() - 1; i++) {//循环绘文字
|
||||
String f = String.valueOf(mText.charAt(i));
|
||||
canvas.drawText(f, firstF_W/2 + i * averageW + x_offset, height / 2 + offset + y_offset, paint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package xyz.wbsite.wbui.base.ui.textview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.TextView;
|
||||
|
||||
/**
|
||||
* Created by wangbing on 2018/4/7.
|
||||
*/
|
||||
|
||||
public class TipTextView extends TextView {
|
||||
private long time = 3000;
|
||||
private String lastValue = "";
|
||||
private Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
time -= 1000;
|
||||
if (time <= 0) {
|
||||
TipTextView.this.setText("");
|
||||
} else {
|
||||
postDelayed(runnable, 1000);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public TipTextView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public TipTextView(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public TipTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(CharSequence text, BufferType type) {
|
||||
this.time = 3000;
|
||||
postDelayed(runnable, 1000);
|
||||
|
||||
super.setText(text, type);
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package xyz.wbsite.wbui.base.ui.textview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.StateListDrawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.Gravity;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.EditText;
|
||||
|
||||
public class WbEditText extends EditText {
|
||||
private float density;
|
||||
private Paint paint;
|
||||
|
||||
public WbEditText(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public WbEditText(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
density = getResources().getDisplayMetrics().density;
|
||||
|
||||
StateListDrawable stateListDrawable = new StateListDrawable();
|
||||
|
||||
{
|
||||
Bitmap bitmap = Bitmap.createBitmap((int) (density * 20), (int) (density * 20), Bitmap.Config.ARGB_4444);
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
paint = new Paint();
|
||||
canvas.drawCircle(density * 20 / 2, density * 20 / 2, density * 20 / 2, paint);
|
||||
|
||||
BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), bitmap);
|
||||
bitmapDrawable.setBounds((int) (density * 20), (int) (density * 20), (int) (density * 20), (int) (density * 20));
|
||||
bitmapDrawable.setGravity(Gravity.RIGHT);
|
||||
|
||||
stateListDrawable.addState(new int[]{android.R.attr.state_focused}, bitmapDrawable);
|
||||
}
|
||||
|
||||
|
||||
this.setBackground(stateListDrawable);
|
||||
this.setPadding(20, 20, 50, 20);
|
||||
this.setMinimumWidth(200);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
float x = event.getX();
|
||||
float y = event.getY();
|
||||
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
|
||||
if (x > (width - density * 20) && y > height / 2 - density * 10 && y < (height / 2 + density * 10)) {
|
||||
paint.setColor(Color.BLUE);
|
||||
invalidate();
|
||||
return true;
|
||||
}
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package xyz.wbsite.wbui.base.ui.textview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.TextView;
|
||||
|
||||
/**
|
||||
* Created by wangbing on 16/6/2.
|
||||
*/
|
||||
public class WbTextView extends TextView {
|
||||
private int mOffsetY = 0;
|
||||
public Bitmap lastBitmap;
|
||||
|
||||
public WbTextView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public WbTextView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (lastBitmap != null) {
|
||||
canvas.drawBitmap(lastBitmap, 0, mOffsetY - getHeight(), null);
|
||||
canvas.translate(0, mOffsetY);
|
||||
}
|
||||
super.onDraw(canvas);
|
||||
|
||||
if (mOffsetY == 0) {
|
||||
lastBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
|
||||
super.onDraw(new Canvas(lastBitmap));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(CharSequence text, BufferType type) {
|
||||
mOffsetY = getHeight();
|
||||
post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mOffsetY > 0) {
|
||||
mOffsetY -= 5;
|
||||
if (mOffsetY < 0) mOffsetY = 0;
|
||||
postDelayed(this, 10);
|
||||
} else {
|
||||
mOffsetY = 0;
|
||||
}
|
||||
System.out.println(mOffsetY);
|
||||
invalidate();
|
||||
}
|
||||
});
|
||||
super.setText(text, type);
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
package xyz.wbsite.wbui.base.ui.textview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.TextView;
|
||||
|
||||
/**
|
||||
* Created by bingwang on 2016/6/4.
|
||||
*/
|
||||
public class WbTextView1 extends TextView {
|
||||
private int r = 250;
|
||||
|
||||
public void setR(int r) {
|
||||
this.r = r;
|
||||
}
|
||||
|
||||
public WbTextView1(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public WbTextView1(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
int meshWidth = 5;
|
||||
int meshHeight = 5;
|
||||
|
||||
//获得原始位图
|
||||
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||
super.onDraw(new Canvas(bitmap));
|
||||
|
||||
//初始化网格坐标
|
||||
float[] vers = new float[(meshWidth + 1) * (meshHeight + 1) * 2];
|
||||
for (int y = 0; y <= meshHeight; y++) {
|
||||
for (int x = 0; x <= meshWidth; x++) {
|
||||
vers[2 * x + y * (2 * (meshWidth + 1))] = (float) width * x / meshWidth;
|
||||
vers[2 * x + y * (2 * (meshWidth + 1)) + 1] = (float) height * y / meshWidth;
|
||||
}
|
||||
}
|
||||
|
||||
//扭曲坐标
|
||||
for (int i = 0; i < vers.length; i += 2) {
|
||||
if (vers[i] != width / 2) {
|
||||
//获取周长
|
||||
float l = Math.abs(vers[i] - width / 2);
|
||||
//获取角度
|
||||
double v = Math.toRadians((l / (2 * Math.PI * r)) * 360);
|
||||
//转换后的长度
|
||||
double v1 = Math.sin(v) * r;
|
||||
//转成实际坐标
|
||||
vers[i] = (float) ((Math.abs(vers[i] - width / 2) / (vers[i] - width / 2)) * v1 + width / 2);
|
||||
}
|
||||
}
|
||||
|
||||
canvas.drawBitmapMesh(bitmap, meshWidth, meshHeight, vers, 0, null, 0, null);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package xyz.wbsite.wbui.base.ui.textview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.Gravity;
|
||||
import android.widget.TextView;
|
||||
|
||||
/**
|
||||
* TextView 自带右箭头
|
||||
*/
|
||||
public class WbTextView2 extends TextView {
|
||||
public WbTextView2(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public WbTextView2(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
int drawableWidth = 20;
|
||||
int drawableColor = Color.parseColor("#aaaaaa");
|
||||
|
||||
float density = getResources().getDisplayMetrics().density;
|
||||
Bitmap bitmap = Bitmap.createBitmap((int) (1 * drawableWidth * density), (int) (1 * drawableWidth * density), Bitmap.Config.ARGB_4444);
|
||||
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
Path path = new Path();
|
||||
path.moveTo(0.775f * drawableWidth * density, 0.5f * drawableWidth * density);
|
||||
path.lineTo(0.4f * drawableWidth * density, 0.875f * drawableWidth * density);
|
||||
path.arcTo(new RectF(0.35f * drawableWidth * density, 0.725f * drawableWidth * density, 0.45f * drawableWidth * density, 0.875f * drawableWidth * density), 90, 90, false);
|
||||
path.lineTo(0.65f * drawableWidth * density, 0.5f * drawableWidth * density);
|
||||
path.lineTo(0.35f * drawableWidth * density, 0.2f * drawableWidth * density);
|
||||
path.arcTo(new RectF(0.35f * drawableWidth * density, 0.125f * drawableWidth * density, 0.45f * drawableWidth * density, 0.275f * drawableWidth * density), 180, 90, false);
|
||||
path.lineTo(0.775f * drawableWidth * density, 0.5f * drawableWidth * density);
|
||||
|
||||
Paint paint = new Paint();
|
||||
paint.setColor(drawableColor);
|
||||
canvas.drawPath(path, paint);
|
||||
|
||||
BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), bitmap);
|
||||
bitmapDrawable.setGravity(Gravity.RIGHT);
|
||||
this.setPadding(this.getPaddingLeft(), this.getPaddingTop(), (int) (drawableWidth * density + this.getPaddingRight()), this.getPaddingBottom());
|
||||
this.setBackground(bitmapDrawable);
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package xyz.wbsite.wbui.base.ui.toast;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.Gravity;
|
||||
import android.view.WindowManager;
|
||||
import android.view.animation.TranslateAnimation;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class MessageToast extends Toast {
|
||||
private Context mContext;
|
||||
private FrameLayout mRootView;
|
||||
private String message;
|
||||
|
||||
private MessageToast(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public MessageToast(Context context, String message) {
|
||||
super(context);
|
||||
this.mContext = context;
|
||||
this.message = message;
|
||||
this.mRootView = new FrameLayout(context);
|
||||
this.setView(mRootView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
//加入控件
|
||||
TextView tvMessage = new TextView(mContext);
|
||||
tvMessage.setText(message);
|
||||
tvMessage.setGravity(Gravity.CENTER);
|
||||
tvMessage.setBackgroundColor(Color.argb(100, 100, 100, 100));
|
||||
mRootView.addView(tvMessage);
|
||||
|
||||
//高度
|
||||
WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
|
||||
DisplayMetrics metrics = new DisplayMetrics();
|
||||
wm.getDefaultDisplay().getMetrics(metrics);
|
||||
tvMessage.setHeight((int) (45 * metrics.density));
|
||||
|
||||
//动画
|
||||
TranslateAnimation translateAnimation = new TranslateAnimation(0f, 0f, 45 * metrics.density, 0.0f);
|
||||
translateAnimation.setDuration(400);
|
||||
tvMessage.startAnimation(translateAnimation);
|
||||
|
||||
//位置
|
||||
this.setGravity(Gravity.BOTTOM | Gravity.FILL_HORIZONTAL, 0, 0);
|
||||
|
||||
super.show();
|
||||
}
|
||||
}
|
@ -0,0 +1,134 @@
|
||||
package xyz.wbsite.wbui.base.utils;
|
||||
|
||||
|
||||
import android.view.View;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.CycleInterpolator;
|
||||
import android.view.animation.TranslateAnimation;
|
||||
|
||||
public class AnimationUtil {
|
||||
|
||||
public static void shake(View view, int counts, Animation.AnimationListener listener) {
|
||||
Animation translateAnimation = new TranslateAnimation(0, 10, 0, 0);
|
||||
translateAnimation.setInterpolator(new CycleInterpolator(counts));
|
||||
translateAnimation.setDuration(500);
|
||||
translateAnimation.setAnimationListener(listener);
|
||||
view.startAnimation(translateAnimation);
|
||||
}
|
||||
|
||||
public static void shake(View view, int counts) {
|
||||
shake(view, counts, null);
|
||||
}
|
||||
|
||||
public static void toBottom(final View view, long duration, Animation.AnimationListener listener) {
|
||||
TranslateAnimation animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.0f,
|
||||
Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF,
|
||||
0.0f, Animation.RELATIVE_TO_SELF, 1.0f);
|
||||
animation.setDuration(duration);
|
||||
animation.setAnimationListener(listener);
|
||||
view.clearAnimation();
|
||||
view.startAnimation(animation);
|
||||
}
|
||||
|
||||
public static void toBottom(View view, long duration) {
|
||||
toBottom(view, duration, null);
|
||||
}
|
||||
|
||||
public static void toTop(View view, long duration, Animation.AnimationListener listener) {
|
||||
TranslateAnimation animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.0f,
|
||||
Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF,
|
||||
0.0f, Animation.RELATIVE_TO_SELF, -1.0f);
|
||||
animation.setDuration(duration);
|
||||
animation.setAnimationListener(listener);
|
||||
view.clearAnimation();
|
||||
view.startAnimation(animation);
|
||||
}
|
||||
|
||||
public static void toTop(View view, long duration) {
|
||||
toTop(view, duration, null);
|
||||
}
|
||||
|
||||
public static void toLeft(View view, long duration, Animation.AnimationListener listener) {
|
||||
TranslateAnimation animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.0f,
|
||||
Animation.RELATIVE_TO_SELF, -1.0f, Animation.RELATIVE_TO_SELF,
|
||||
0.0f, Animation.RELATIVE_TO_SELF, 0.0f);
|
||||
animation.setDuration(duration);
|
||||
animation.setAnimationListener(listener);
|
||||
view.clearAnimation();
|
||||
view.startAnimation(animation);
|
||||
}
|
||||
|
||||
public static void toLeft(View view, long duration) {
|
||||
toLeft(view, duration, null);
|
||||
}
|
||||
|
||||
public static void toRight(final View view, long duration, Animation.AnimationListener listener) {
|
||||
TranslateAnimation animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.0f,
|
||||
Animation.RELATIVE_TO_SELF, 1.0f, Animation.RELATIVE_TO_SELF,
|
||||
0.0f, Animation.RELATIVE_TO_SELF, 0.0f);
|
||||
animation.setDuration(duration);
|
||||
animation.setAnimationListener(listener);
|
||||
view.clearAnimation();
|
||||
view.startAnimation(animation);
|
||||
}
|
||||
|
||||
public static void toRight(final View view, long duration) {
|
||||
toRight(view, duration, null);
|
||||
}
|
||||
|
||||
public static void fromBottom(View view, long duration, Animation.AnimationListener listener) {
|
||||
TranslateAnimation animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.0f,
|
||||
Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF,
|
||||
1.0f, Animation.RELATIVE_TO_SELF, 0.0f);
|
||||
animation.setDuration(duration);
|
||||
animation.setAnimationListener(listener);
|
||||
view.clearAnimation();
|
||||
view.startAnimation(animation);
|
||||
}
|
||||
|
||||
public static void fromBottom(View view, long duration) {
|
||||
fromBottom(view, duration, null);
|
||||
}
|
||||
|
||||
public static void fromTop(View view, long duration, Animation.AnimationListener listener) {
|
||||
TranslateAnimation animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.0f,
|
||||
Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF,
|
||||
-1.0f, Animation.RELATIVE_TO_SELF, 0.0f);
|
||||
animation.setDuration(duration);
|
||||
animation.setAnimationListener(listener);
|
||||
view.clearAnimation();
|
||||
view.startAnimation(animation);
|
||||
}
|
||||
|
||||
public static void fromTop(View view, long duration) {
|
||||
fromTop(view, duration, null);
|
||||
}
|
||||
|
||||
public static void fromLeft(View view, long duration, Animation.AnimationListener listener) {
|
||||
TranslateAnimation animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, -1.0f,
|
||||
Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF,
|
||||
0.0f, Animation.RELATIVE_TO_SELF, 0.0f);
|
||||
animation.setDuration(duration);
|
||||
animation.setAnimationListener(listener);
|
||||
view.clearAnimation();
|
||||
view.startAnimation(animation);
|
||||
}
|
||||
|
||||
public static void fromLeft(View view, long duration) {
|
||||
fromLeft(view, duration, null);
|
||||
}
|
||||
|
||||
public static void fromRight(View view, long duration, Animation.AnimationListener listener) {
|
||||
TranslateAnimation animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 1.0f,
|
||||
Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF,
|
||||
0.0f, Animation.RELATIVE_TO_SELF, 0.0f);
|
||||
animation.setDuration(duration);
|
||||
animation.setAnimationListener(listener);
|
||||
view.clearAnimation();
|
||||
view.startAnimation(animation);
|
||||
}
|
||||
|
||||
public static void fromRight(View view, long duration) {
|
||||
fromRight(view, duration, null);
|
||||
}
|
||||
}
|
@ -0,0 +1,507 @@
|
||||
package xyz.wbsite.wbui.base.utils;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Base64Util
|
||||
*
|
||||
* @author wangbing
|
||||
* @version 0.0.1
|
||||
* @since 2017-01-01
|
||||
*/
|
||||
public class Base64Util {
|
||||
private static final char[] CA = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();
|
||||
private static final int[] IA = new int[256];
|
||||
|
||||
static {
|
||||
Arrays.fill(IA, -1);
|
||||
for(int i = 0, iS = CA.length; i < iS; i++)
|
||||
IA[CA[i]] = i;
|
||||
IA['='] = 0;
|
||||
}
|
||||
|
||||
public final static char[] encodeToChar(byte[] sArr, boolean lineSep) {
|
||||
// Check special case
|
||||
int sLen = sArr != null ? sArr.length : 0;
|
||||
if(sLen == 0)
|
||||
return new char[0];
|
||||
|
||||
int eLen = (sLen / 3) * 3; // Length of even 24-bits.
|
||||
int cCnt = ((sLen - 1) / 3 + 1) << 2; // Returned character count
|
||||
int dLen = cCnt + (lineSep ? (cCnt - 1) / 76 << 1 : 0); // Length of returned array
|
||||
char[] dArr = new char[dLen];
|
||||
|
||||
// Encode even 24-bits
|
||||
for(int s = 0, d = 0, cc = 0; s < eLen; ) {
|
||||
// Copy next three bytes into lower 24 bits of int, paying attension to sign.
|
||||
int i = (sArr[s++] & 0xff) << 16 | (sArr[s++] & 0xff) << 8 | (sArr[s++] & 0xff);
|
||||
|
||||
// Encode the int into four chars
|
||||
dArr[d++] = CA[(i >>> 18) & 0x3f];
|
||||
dArr[d++] = CA[(i >>> 12) & 0x3f];
|
||||
dArr[d++] = CA[(i >>> 6) & 0x3f];
|
||||
dArr[d++] = CA[i & 0x3f];
|
||||
|
||||
// Add optional line separator
|
||||
if(lineSep && ++cc == 19 && d < dLen - 2) {
|
||||
dArr[d++] = '\r';
|
||||
dArr[d++] = '\n';
|
||||
cc = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Pad and encode last bits if source isn't even 24 bits.
|
||||
int left = sLen - eLen; // 0 - 2.
|
||||
if(left > 0) {
|
||||
// Prepare the int
|
||||
int i = ((sArr[eLen] & 0xff) << 10) | (left == 2 ? ((sArr[sLen - 1] & 0xff) << 2) : 0);
|
||||
|
||||
// Set last four chars
|
||||
dArr[dLen - 4] = CA[i >> 12];
|
||||
dArr[dLen - 3] = CA[(i >>> 6) & 0x3f];
|
||||
dArr[dLen - 2] = left == 2 ? CA[i & 0x3f] : '=';
|
||||
dArr[dLen - 1] = '=';
|
||||
}
|
||||
return dArr;
|
||||
}
|
||||
|
||||
public final static byte[] decode(char[] sArr) {
|
||||
// Check special case
|
||||
int sLen = sArr != null ? sArr.length : 0;
|
||||
if(sLen == 0)
|
||||
return new byte[0];
|
||||
|
||||
// Count illegal characters (including '\r', '\n') to know what size the returned array will be,
|
||||
// so we don't have to reallocate & copy it later.
|
||||
int sepCnt = 0; // Number of separator characters. (Actually illegal characters, but that's a bonus...)
|
||||
for(int i = 0; i < sLen; i++) // If input is "pure" (I.e. no line separators or illegal chars) base64 this loop can be commented out.
|
||||
if(IA[sArr[i]] < 0)
|
||||
sepCnt++;
|
||||
|
||||
// Check so that legal chars (including '=') are evenly divideable by 4 as specified in RFC 2045.
|
||||
if((sLen - sepCnt) % 4 != 0)
|
||||
return null;
|
||||
|
||||
int pad = 0;
|
||||
for(int i = sLen; i > 1 && IA[sArr[--i]] <= 0; )
|
||||
if(sArr[i] == '=')
|
||||
pad++;
|
||||
|
||||
int len = ((sLen - sepCnt) * 6 >> 3) - pad;
|
||||
|
||||
byte[] dArr = new byte[len]; // Preallocate byte[] of exact length
|
||||
|
||||
for(int s = 0, d = 0; d < len; ) {
|
||||
// Assemble three bytes into an int from four "valid" characters.
|
||||
int i = 0;
|
||||
for(int j = 0; j < 4; j++) { // j only increased if a valid char was found.
|
||||
int c = IA[sArr[s++]];
|
||||
if(c >= 0)
|
||||
i |= c << (18 - j * 6);
|
||||
else
|
||||
j--;
|
||||
}
|
||||
// Add the bytes
|
||||
dArr[d++] = (byte) (i >> 16);
|
||||
if(d < len) {
|
||||
dArr[d++] = (byte) (i >> 8);
|
||||
if(d < len)
|
||||
dArr[d++] = (byte) i;
|
||||
}
|
||||
}
|
||||
return dArr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a BASE64 encoded char array that is known to be resonably well formatted. The method is about twice as
|
||||
* fast as {@link =#=decode(char[])}. The preconditions are:<br>
|
||||
* + The array must have a line length of 76 chars OR no line separators at all (one line).<br>
|
||||
* + Line separator must be "\r\n", as specified in RFC 2045
|
||||
* + The array must not contain illegal characters within the encoded string<br>
|
||||
* + The array CAN have illegal characters at the beginning and end, those will be dealt with appropriately.<br>
|
||||
*
|
||||
* @param sArr The source array. Length 0 will return an empty array. <code>null</code> will throw an exception.
|
||||
* @return The decoded array of bytes. May be of length 0.
|
||||
*/
|
||||
public final static byte[] decodeFast(char[] sArr) {
|
||||
// Check special case
|
||||
int sLen = sArr.length;
|
||||
if(sLen == 0)
|
||||
return new byte[0];
|
||||
|
||||
int sIx = 0, eIx = sLen - 1; // Start and end index after trimming.
|
||||
|
||||
// Trim illegal chars from start
|
||||
while(sIx < eIx && IA[sArr[sIx]] < 0)
|
||||
sIx++;
|
||||
|
||||
// Trim illegal chars from end
|
||||
while(eIx > 0 && IA[sArr[eIx]] < 0)
|
||||
eIx--;
|
||||
|
||||
// get the padding count (=) (0, 1 or 2)
|
||||
int pad = sArr[eIx] == '=' ? (sArr[eIx - 1] == '=' ? 2 : 1) : 0; // Count '=' at end.
|
||||
int cCnt = eIx - sIx + 1; // Content count including possible separators
|
||||
int sepCnt = sLen > 76 ? (sArr[76] == '\r' ? cCnt / 78 : 0) << 1 : 0;
|
||||
|
||||
int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes
|
||||
byte[] dArr = new byte[len]; // Preallocate byte[] of exact length
|
||||
|
||||
// Decode all but the last 0 - 2 bytes.
|
||||
int d = 0;
|
||||
for(int cc = 0, eLen = (len / 3) * 3; d < eLen; ) {
|
||||
// Assemble three bytes into an int from four "valid" characters.
|
||||
int i = IA[sArr[sIx++]] << 18 | IA[sArr[sIx++]] << 12 | IA[sArr[sIx++]] << 6 | IA[sArr[sIx++]];
|
||||
|
||||
// Add the bytes
|
||||
dArr[d++] = (byte) (i >> 16);
|
||||
dArr[d++] = (byte) (i >> 8);
|
||||
dArr[d++] = (byte) i;
|
||||
|
||||
// If line separator, jump over it.
|
||||
if(sepCnt > 0 && ++cc == 19) {
|
||||
sIx += 2;
|
||||
cc = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(d < len) {
|
||||
// Decode last 1-3 bytes (incl '=') into 1-3 bytes
|
||||
int i = 0;
|
||||
for(int j = 0; sIx <= eIx - pad; j++)
|
||||
i |= IA[sArr[sIx++]] << (18 - j * 6);
|
||||
|
||||
for(int r = 16; d < len; r -= 8)
|
||||
dArr[d++] = (byte) (i >> r);
|
||||
}
|
||||
|
||||
return dArr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a raw byte array into a BASE64 <code>byte[]</code> representation i accordance with RFC 2045.
|
||||
*
|
||||
* @param sArr The bytes to convert. If <code>null</code> or length 0 an empty array will be returned.
|
||||
* @param lineSep Optional "\r\n" after 76 characters, unless end of file.<br>
|
||||
* No line separator will be in breach of RFC 2045 which specifies max 76 per line but will be a
|
||||
* little faster.
|
||||
* @return A BASE64 encoded array. Never <code>null</code>.
|
||||
*/
|
||||
public final static byte[] encodeToByte(byte[] sArr, boolean lineSep) {
|
||||
// Check special case
|
||||
int sLen = sArr != null ? sArr.length : 0;
|
||||
if(sLen == 0)
|
||||
return new byte[0];
|
||||
|
||||
int eLen = (sLen / 3) * 3; // Length of even 24-bits.
|
||||
int cCnt = ((sLen - 1) / 3 + 1) << 2; // Returned character count
|
||||
int dLen = cCnt + (lineSep ? (cCnt - 1) / 76 << 1 : 0); // Length of returned array
|
||||
byte[] dArr = new byte[dLen];
|
||||
|
||||
// Encode even 24-bits
|
||||
for(int s = 0, d = 0, cc = 0; s < eLen; ) {
|
||||
// Copy next three bytes into lower 24 bits of int, paying attension to sign.
|
||||
int i = (sArr[s++] & 0xff) << 16 | (sArr[s++] & 0xff) << 8 | (sArr[s++] & 0xff);
|
||||
|
||||
// Encode the int into four chars
|
||||
dArr[d++] = (byte) CA[(i >>> 18) & 0x3f];
|
||||
dArr[d++] = (byte) CA[(i >>> 12) & 0x3f];
|
||||
dArr[d++] = (byte) CA[(i >>> 6) & 0x3f];
|
||||
dArr[d++] = (byte) CA[i & 0x3f];
|
||||
|
||||
// Add optional line separator
|
||||
if(lineSep && ++cc == 19 && d < dLen - 2) {
|
||||
dArr[d++] = '\r';
|
||||
dArr[d++] = '\n';
|
||||
cc = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Pad and encode last bits if source isn't an even 24 bits.
|
||||
int left = sLen - eLen; // 0 - 2.
|
||||
if(left > 0) {
|
||||
// Prepare the int
|
||||
int i = ((sArr[eLen] & 0xff) << 10) | (left == 2 ? ((sArr[sLen - 1] & 0xff) << 2) : 0);
|
||||
|
||||
// Set last four chars
|
||||
dArr[dLen - 4] = (byte) CA[i >> 12];
|
||||
dArr[dLen - 3] = (byte) CA[(i >>> 6) & 0x3f];
|
||||
dArr[dLen - 2] = left == 2 ? (byte) CA[i & 0x3f] : (byte) '=';
|
||||
dArr[dLen - 1] = '=';
|
||||
}
|
||||
return dArr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a BASE64 encoded byte array. All illegal characters will be ignored and can handle both arrays with
|
||||
* and without line separators.
|
||||
*
|
||||
* @param sArr The source array. Length 0 will return an empty array. <code>null</code> will throw an exception.
|
||||
* @return The decoded array of bytes. May be of length 0. Will be <code>null</code> if the legal characters
|
||||
* (including '=') isn't divideable by 4. (I.e. definitely corrupted).
|
||||
*/
|
||||
public final static byte[] decode(byte[] sArr) {
|
||||
// Check special case
|
||||
int sLen = sArr.length;
|
||||
|
||||
// Count illegal characters (including '\r', '\n') to know what size the returned array will be,
|
||||
// so we don't have to reallocate & copy it later.
|
||||
int sepCnt = 0; // Number of separator characters. (Actually illegal characters, but that's a bonus...)
|
||||
for(int i = 0; i < sLen; i++) // If input is "pure" (I.e. no line separators or illegal chars) base64 this loop can be commented out.
|
||||
if(IA[sArr[i] & 0xff] < 0)
|
||||
sepCnt++;
|
||||
|
||||
// Check so that legal chars (including '=') are evenly divideable by 4 as specified in RFC 2045.
|
||||
if((sLen - sepCnt) % 4 != 0)
|
||||
return null;
|
||||
|
||||
int pad = 0;
|
||||
for(int i = sLen; i > 1 && IA[sArr[--i] & 0xff] <= 0; )
|
||||
if(sArr[i] == '=')
|
||||
pad++;
|
||||
|
||||
int len = ((sLen - sepCnt) * 6 >> 3) - pad;
|
||||
|
||||
byte[] dArr = new byte[len]; // Preallocate byte[] of exact length
|
||||
|
||||
for(int s = 0, d = 0; d < len; ) {
|
||||
// Assemble three bytes into an int from four "valid" characters.
|
||||
int i = 0;
|
||||
for(int j = 0; j < 4; j++) { // j only increased if a valid char was found.
|
||||
int c = IA[sArr[s++] & 0xff];
|
||||
if(c >= 0)
|
||||
i |= c << (18 - j * 6);
|
||||
else
|
||||
j--;
|
||||
}
|
||||
|
||||
// Add the bytes
|
||||
dArr[d++] = (byte) (i >> 16);
|
||||
if(d < len) {
|
||||
dArr[d++] = (byte) (i >> 8);
|
||||
if(d < len)
|
||||
dArr[d++] = (byte) i;
|
||||
}
|
||||
}
|
||||
|
||||
return dArr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decodes a BASE64 encoded byte array that is known to be resonably well formatted. The method is about twice as
|
||||
* fast as {@link =#=decode(byte[])}. The preconditions are:<br>
|
||||
* + The array must have a line length of 76 chars OR no line separators at all (one line).<br>
|
||||
* + Line separator must be "\r\n", as specified in RFC 2045
|
||||
* + The array must not contain illegal characters within the encoded string<br>
|
||||
* + The array CAN have illegal characters at the beginning and end, those will be dealt with appropriately.<br>
|
||||
*
|
||||
* @param sArr The source array. Length 0 will return an empty array. <code>null</code> will throw an exception.
|
||||
* @return The decoded array of bytes. May be of length 0.
|
||||
*/
|
||||
public final static byte[] decodeFast(byte[] sArr) {
|
||||
// Check special case
|
||||
int sLen = sArr.length;
|
||||
if(sLen == 0)
|
||||
return new byte[0];
|
||||
|
||||
int sIx = 0, eIx = sLen - 1; // Start and end index after trimming.
|
||||
|
||||
// Trim illegal chars from start
|
||||
while(sIx < eIx && IA[sArr[sIx] & 0xff] < 0)
|
||||
sIx++;
|
||||
|
||||
// Trim illegal chars from end
|
||||
while(eIx > 0 && IA[sArr[eIx] & 0xff] < 0)
|
||||
eIx--;
|
||||
|
||||
// get the padding count (=) (0, 1 or 2)
|
||||
int pad = sArr[eIx] == '=' ? (sArr[eIx - 1] == '=' ? 2 : 1) : 0; // Count '=' at end.
|
||||
int cCnt = eIx - sIx + 1; // Content count including possible separators
|
||||
int sepCnt = sLen > 76 ? (sArr[76] == '\r' ? cCnt / 78 : 0) << 1 : 0;
|
||||
|
||||
int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes
|
||||
byte[] dArr = new byte[len]; // Preallocate byte[] of exact length
|
||||
|
||||
// Decode all but the last 0 - 2 bytes.
|
||||
int d = 0;
|
||||
for(int cc = 0, eLen = (len / 3) * 3; d < eLen; ) {
|
||||
// Assemble three bytes into an int from four "valid" characters.
|
||||
int i = IA[sArr[sIx++]] << 18 | IA[sArr[sIx++]] << 12 | IA[sArr[sIx++]] << 6 | IA[sArr[sIx++]];
|
||||
|
||||
// Add the bytes
|
||||
dArr[d++] = (byte) (i >> 16);
|
||||
dArr[d++] = (byte) (i >> 8);
|
||||
dArr[d++] = (byte) i;
|
||||
|
||||
// If line separator, jump over it.
|
||||
if(sepCnt > 0 && ++cc == 19) {
|
||||
sIx += 2;
|
||||
cc = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(d < len) {
|
||||
// Decode last 1-3 bytes (incl '=') into 1-3 bytes
|
||||
int i = 0;
|
||||
for(int j = 0; sIx <= eIx - pad; j++)
|
||||
i |= IA[sArr[sIx++]] << (18 - j * 6);
|
||||
|
||||
for(int r = 16; d < len; r -= 8)
|
||||
dArr[d++] = (byte) (i >> r);
|
||||
}
|
||||
|
||||
return dArr;
|
||||
}
|
||||
|
||||
// ****************************************************************************************
|
||||
// * String version
|
||||
// ****************************************************************************************
|
||||
|
||||
/**
|
||||
* Encodes a raw byte array into a BASE64 <code>String</code> representation i accordance with RFC 2045.
|
||||
*
|
||||
* @param sArr The bytes to convert. If <code>null</code> or length 0 an empty array will be returned.
|
||||
* @param lineSep Optional "\r\n" after 76 characters, unless end of file.<br>
|
||||
* No line separator will be in breach of RFC 2045 which specifies max 76 per line but will be a
|
||||
* little faster.
|
||||
* @return A BASE64 encoded array. Never <code>null</code>.
|
||||
*/
|
||||
public final static String encodeToString(byte[] sArr, boolean lineSep) {
|
||||
// Reuse char[] since we can't create a String incrementally anyway and StringBuffer/Builder would be slower.
|
||||
return new String(encodeToChar(sArr, lineSep));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a BASE64 encoded <code>String</code>. All illegal characters will be ignored and can handle both strings with
|
||||
* and without line separators.<br>
|
||||
* <b>Note!</b> It can be up to about 2x the speed to call <code>decode(str.toCharArray())</code> instead. That
|
||||
* will create a temporary array though. This version will use <code>str.charAt(i)</code> to iterate the string.
|
||||
*
|
||||
* @param str The source string. <code>null</code> or length 0 will return an empty array.
|
||||
* @return The decoded array of bytes. May be of length 0. Will be <code>null</code> if the legal characters
|
||||
* (including '=') isn't divideable by 4. (I.e. definitely corrupted).
|
||||
*/
|
||||
public final static byte[] decode(String str) {
|
||||
// Check special case
|
||||
int sLen = str != null ? str.length() : 0;
|
||||
if(sLen == 0)
|
||||
return new byte[0];
|
||||
|
||||
// Count illegal characters (including '\r', '\n') to know what size the returned array will be,
|
||||
// so we don't have to reallocate & copy it later.
|
||||
int sepCnt = 0; // Number of separator characters. (Actually illegal characters, but that's a bonus...)
|
||||
for(int i = 0; i < sLen; i++) // If input is "pure" (I.e. no line separators or illegal chars) base64 this loop can be commented out.
|
||||
if(IA[str.charAt(i)] < 0)
|
||||
sepCnt++;
|
||||
|
||||
// Check so that legal chars (including '=') are evenly divideable by 4 as specified in RFC 2045.
|
||||
if((sLen - sepCnt) % 4 != 0)
|
||||
return null;
|
||||
|
||||
// Count '=' at end
|
||||
int pad = 0;
|
||||
for(int i = sLen; i > 1 && IA[str.charAt(--i)] <= 0; )
|
||||
if(str.charAt(i) == '=')
|
||||
pad++;
|
||||
|
||||
int len = ((sLen - sepCnt) * 6 >> 3) - pad;
|
||||
|
||||
byte[] dArr = new byte[len]; // Preallocate byte[] of exact length
|
||||
|
||||
for(int s = 0, d = 0; d < len; ) {
|
||||
// Assemble three bytes into an int from four "valid" characters.
|
||||
int i = 0;
|
||||
for(int j = 0; j < 4; j++) { // j only increased if a valid char was found.
|
||||
int c = IA[str.charAt(s++)];
|
||||
if(c >= 0)
|
||||
i |= c << (18 - j * 6);
|
||||
else
|
||||
j--;
|
||||
}
|
||||
// Add the bytes
|
||||
dArr[d++] = (byte) (i >> 16);
|
||||
if(d < len) {
|
||||
dArr[d++] = (byte) (i >> 8);
|
||||
if(d < len)
|
||||
dArr[d++] = (byte) i;
|
||||
}
|
||||
}
|
||||
return dArr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a BASE64 encoded string that is known to be resonably well formatted. The method is about twice as
|
||||
* fast as {@link =#=decode(String)}. The preconditions are:<br>
|
||||
* + The array must have a line length of 76 chars OR no line separators at all (one line).<br>
|
||||
* + Line separator must be "\r\n", as specified in RFC 2045
|
||||
* + The array must not contain illegal characters within the encoded string<br>
|
||||
* + The array CAN have illegal characters at the beginning and end, those will be dealt with appropriately.<br>
|
||||
*
|
||||
* @param s The source string. Length 0 will return an empty array. <code>null</code> will throw an exception.
|
||||
* @return The decoded array of bytes. May be of length 0.
|
||||
*/
|
||||
public final static byte[] decodeFast(String s) {
|
||||
// Check special case
|
||||
int sLen = s.length();
|
||||
if(sLen == 0)
|
||||
return new byte[0];
|
||||
|
||||
int sIx = 0, eIx = sLen - 1; // Start and end index after trimming.
|
||||
|
||||
// Trim illegal chars from start
|
||||
while(sIx < eIx && IA[s.charAt(sIx) & 0xff] < 0)
|
||||
sIx++;
|
||||
|
||||
// Trim illegal chars from end
|
||||
while(eIx > 0 && IA[s.charAt(eIx) & 0xff] < 0)
|
||||
eIx--;
|
||||
|
||||
// get the padding count (=) (0, 1 or 2)
|
||||
int pad = s.charAt(eIx) == '=' ? (s.charAt(eIx - 1) == '=' ? 2 : 1) : 0; // Count '=' at end.
|
||||
int cCnt = eIx - sIx + 1; // Content count including possible separators
|
||||
int sepCnt = sLen > 76 ? (s.charAt(76) == '\r' ? cCnt / 78 : 0) << 1 : 0;
|
||||
|
||||
int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes
|
||||
byte[] dArr = new byte[len]; // Preallocate byte[] of exact length
|
||||
|
||||
// Decode all but the last 0 - 2 bytes.
|
||||
int d = 0;
|
||||
for(int cc = 0, eLen = (len / 3) * 3; d < eLen; ) {
|
||||
// Assemble three bytes into an int from four "valid" characters.
|
||||
int i = IA[s.charAt(sIx++)] << 18 | IA[s.charAt(sIx++)] << 12 | IA[s.charAt(sIx++)] << 6 | IA[s.charAt(sIx++)];
|
||||
|
||||
// Add the bytes
|
||||
dArr[d++] = (byte) (i >> 16);
|
||||
dArr[d++] = (byte) (i >> 8);
|
||||
dArr[d++] = (byte) i;
|
||||
|
||||
// If line separator, jump over it.
|
||||
if(sepCnt > 0 && ++cc == 19) {
|
||||
sIx += 2;
|
||||
cc = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(d < len) {
|
||||
// Decode last 1-3 bytes (incl '=') into 1-3 bytes
|
||||
int i = 0;
|
||||
for(int j = 0; sIx <= eIx - pad; j++)
|
||||
i |= IA[s.charAt(sIx++)] << (18 - j * 6);
|
||||
|
||||
for(int r = 16; d < len; r -= 8)
|
||||
dArr[d++] = (byte) (i >> r);
|
||||
}
|
||||
|
||||
return dArr;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String s = Base64Util.encodeToString("我搜搜1我搜搜1我搜搜1我搜搜1我搜搜1我搜搜1我搜搜1我搜搜1我搜搜1我搜搜1我搜搜1我搜搜1我搜搜1我搜搜1我搜搜1我搜搜1我搜搜1我搜搜1我搜搜1我搜搜1我搜搜1我搜搜1我搜搜1我搜搜1我搜搜1我搜搜1我搜搜1我搜搜1我搜搜1我搜搜1".getBytes(), false);
|
||||
System.out.println(s);
|
||||
|
||||
byte[] decode = Base64Util.decode(s);
|
||||
System.out.println(new String(decode));
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,135 @@
|
||||
|
||||
package xyz.wbsite.wbui.base.utils;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.BitmapFactory.Options;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.TypedValue;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public final class BitmapUtil {
|
||||
|
||||
|
||||
public static Bitmap scaleBitmap(Bitmap src, int destWidth, int destHeigth) {
|
||||
if (src == null) return null;
|
||||
|
||||
int width = src.getWidth();
|
||||
int height = src.getHeight();
|
||||
|
||||
float scaleWidth = ((float) destWidth) / width;
|
||||
float scaleHeight = ((float) destHeigth) / height;
|
||||
|
||||
Matrix matrix = new Matrix();
|
||||
matrix.postScale(scaleWidth, scaleHeight);
|
||||
return Bitmap.createBitmap(src, 0, 0, width, height, matrix, true);
|
||||
}
|
||||
|
||||
public static Bitmap scaleBitmap(Bitmap src, float scale) {
|
||||
if (src == null) return null;
|
||||
|
||||
int width = src.getWidth();
|
||||
int height = src.getHeight();
|
||||
|
||||
Matrix matrix = new Matrix();
|
||||
matrix.postScale(scale, scale);
|
||||
return Bitmap.createBitmap(src, 0, 0, width, height, matrix, true);
|
||||
}
|
||||
|
||||
public static Drawable getDrawableFromAssetFile(Resources res, String fileName) {
|
||||
InputStream is = null;
|
||||
Drawable icon = null;
|
||||
try {
|
||||
is = res.getAssets().open(fileName);
|
||||
TypedValue typedValue = new TypedValue();
|
||||
typedValue.density = TypedValue.DENSITY_DEFAULT;
|
||||
icon = Drawable.createFromResourceStream(res, typedValue, is, null);
|
||||
} catch (Exception e) {
|
||||
} finally {
|
||||
try {
|
||||
if (is != null) {
|
||||
is.close();
|
||||
is = null;
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
}
|
||||
}
|
||||
return icon;
|
||||
}
|
||||
|
||||
public static Bitmap getBitmapFromAssetFile(Resources res, String fileName) {
|
||||
InputStream is = null;
|
||||
Bitmap bmp = null;
|
||||
try {
|
||||
is = res.getAssets().open(fileName);
|
||||
|
||||
DisplayMetrics metrics = res.getDisplayMetrics();
|
||||
Options opts = new Options();
|
||||
opts.inDensity = (int) (metrics.densityDpi / metrics.scaledDensity);
|
||||
bmp = BitmapFactory.decodeStream(is, null, opts);
|
||||
is.close();
|
||||
is = null;
|
||||
} catch (Exception e) {
|
||||
} finally {
|
||||
try {
|
||||
if (is != null) is.close();
|
||||
} catch (final IOException e) {
|
||||
}
|
||||
}
|
||||
return bmp;
|
||||
}
|
||||
|
||||
public static Drawable getDrawableFromFile(Resources res, String fileName) {
|
||||
FileInputStream fis = null;
|
||||
Drawable icon = null;
|
||||
try {
|
||||
fis = new FileInputStream(fileName);
|
||||
DisplayMetrics metrics = res.getDisplayMetrics();
|
||||
Options opts = new Options();
|
||||
opts.inDensity = (int) (metrics.densityDpi / metrics.scaledDensity);
|
||||
Bitmap bmp = BitmapFactory.decodeStream(fis, null, opts);
|
||||
|
||||
fis.close();
|
||||
fis = null;
|
||||
if (bmp != null) {
|
||||
icon = new BitmapDrawable(bmp);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
} finally {
|
||||
try {
|
||||
if (fis != null) fis.close();
|
||||
} catch (final IOException e) {
|
||||
}
|
||||
}
|
||||
return icon;
|
||||
}
|
||||
|
||||
public static Bitmap getBitmapFromFile(Resources res, String fileName) {
|
||||
FileInputStream fis = null;
|
||||
Bitmap bmp = null;
|
||||
try {
|
||||
fis = new FileInputStream(fileName);
|
||||
|
||||
DisplayMetrics metrics = res.getDisplayMetrics();
|
||||
Options opts = new Options();
|
||||
opts.inDensity = (int) (metrics.densityDpi / metrics.scaledDensity);
|
||||
bmp = BitmapFactory.decodeStream(fis, null, opts);
|
||||
fis.close();
|
||||
fis = null;
|
||||
} catch (Exception e) {
|
||||
} finally {
|
||||
try {
|
||||
if (fis != null) fis.close();
|
||||
} catch (final IOException e) {
|
||||
}
|
||||
}
|
||||
return bmp;
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package xyz.wbsite.wbui.base;
|
||||
|
||||
/**
|
||||
* 内容辅助类
|
||||
*/
|
||||
public class Consant {
|
||||
|
||||
//是否记住密码
|
||||
public static String REMEMBER_PASSWORD = "remember_password";
|
||||
|
||||
//是否自动登录
|
||||
public static String AUTO_LOGIN = "auto_login";
|
||||
|
||||
//文件存储目录
|
||||
public static String DIR = "WBUI";
|
||||
|
||||
//图片存储目录
|
||||
public static String DIR_IMG = "WBUI/temp";
|
||||
|
||||
public static int REQUESTCODE_FROM_FRAGMENT = 1;
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package xyz.wbsite.wbui.base.utils;
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.Key;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
public class DESUtil {
|
||||
|
||||
public static final String ALGORITHM_DES = "DES";
|
||||
|
||||
public static Key generateKey(String algorithm) throws NoSuchAlgorithmException {
|
||||
KeyGenerator generator = KeyGenerator.getInstance(algorithm);
|
||||
return generator.generateKey();
|
||||
}
|
||||
|
||||
public static Key getKey(byte[] key, String algorithm) throws NoSuchAlgorithmException {
|
||||
return new SecretKeySpec(key, algorithm);
|
||||
}
|
||||
|
||||
public static byte[] encrypt(String transformation, Key key, String content)
|
||||
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
|
||||
IllegalBlockSizeException, BadPaddingException {
|
||||
Cipher cipher = Cipher.getInstance(transformation);
|
||||
// 加密模式
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key);
|
||||
return cipher.doFinal(content.getBytes());
|
||||
}
|
||||
|
||||
public static byte[] decrypt(String transformation, Key key, byte[] content)
|
||||
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
|
||||
IllegalBlockSizeException, BadPaddingException {
|
||||
Cipher cipher = Cipher.getInstance(transformation);
|
||||
// 解密模式
|
||||
cipher.init(Cipher.DECRYPT_MODE, key);
|
||||
return cipher.doFinal(content);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,435 @@
|
||||
package xyz.wbsite.wbui.base.utils;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.database.Cursor;
|
||||
import android.database.DatabaseErrorHandler;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteException;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import xyz.wbsite.webclient.WBUIApplication;
|
||||
import xyz.wbsite.wbui.base.Consant;
|
||||
|
||||
public class DataBaseUtil {
|
||||
private String defaultPath = "";
|
||||
private String defaultDBName = "data.db";
|
||||
private SQLiteOpenHelper sqLiteOpenHelper;
|
||||
private SQLiteDatabase writableDatabase;
|
||||
private List<Class> entityList;
|
||||
|
||||
private DataBaseUtil() {
|
||||
}
|
||||
|
||||
public DataBaseUtil(Context context, Register register) {
|
||||
entityList = register.run();
|
||||
File ownCacheDirectory = StorageUtil.getOwnCacheDirectory(context, Consant.DIR);
|
||||
defaultPath = ownCacheDirectory.getAbsolutePath();
|
||||
sqLiteOpenHelper = new SQLiteOpenHelperImpl(context, defaultDBName, null, 1);
|
||||
writableDatabase = sqLiteOpenHelper.getWritableDatabase();
|
||||
}
|
||||
|
||||
public <T> List<T> query(T t) {
|
||||
return query(t, 0, 0);
|
||||
}
|
||||
|
||||
public <T> List<T> query(T t, int start, int size) {
|
||||
ArrayList<T> list = new ArrayList<>();
|
||||
try {
|
||||
Class a = findEntity(t);
|
||||
//1、获取表名
|
||||
String table = a.getSimpleName();
|
||||
//2、获取字段列表
|
||||
List<Field> fs = new ArrayList<>();
|
||||
for (Field f : a.getDeclaredFields()) {
|
||||
if (f.isAnnotationPresent(DBField.class)) {
|
||||
fs.add(f);
|
||||
}
|
||||
}
|
||||
String[] columns = new String[fs.size()];
|
||||
int where = 0;
|
||||
for (int i = 0; i < columns.length; i++) {
|
||||
fs.get(i).setAccessible(true);
|
||||
columns[i] = fs.get(i).getName().toUpperCase();
|
||||
try {
|
||||
Object o = fs.get(i).get(t);
|
||||
if (o != null) {
|
||||
where++;
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
//3、获取where条件
|
||||
StringBuilder selectionSB = new StringBuilder("");
|
||||
String[] selectionArgs = null;
|
||||
if (where > 0) {
|
||||
selectionArgs = new String[where];
|
||||
where = 0;
|
||||
for (int i = 0; i < columns.length; i++) {
|
||||
columns[i] = fs.get(i).getName().toUpperCase();
|
||||
try {
|
||||
Object o = fs.get(i).get(t);
|
||||
if (o != null) {
|
||||
if ("".equals(selectionSB.toString())) {
|
||||
selectionSB.append(" ");
|
||||
} else {
|
||||
selectionSB.append(" and ");
|
||||
}
|
||||
selectionSB.append(columns[i]).append(" like ?");
|
||||
selectionArgs[where] = o.toString();
|
||||
where++;
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
//4、分页
|
||||
String limit = size != 0 ? (start + "," + size) : "";
|
||||
|
||||
//5、其他暂未支持
|
||||
|
||||
Cursor query = null;
|
||||
try {
|
||||
query = writableDatabase.query(table, columns, selectionSB.toString(), selectionArgs, null, null, "", limit);
|
||||
} catch (SQLiteException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
while (query.moveToNext()) {
|
||||
try {
|
||||
T o = (T) a.newInstance();
|
||||
for (int i = 0; i < fs.size(); i++) {
|
||||
Field field = fs.get(i);
|
||||
String string = query.getString(i);
|
||||
field.set(o, string);
|
||||
}
|
||||
list.add(o);
|
||||
} catch (InstantiationException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public <T> void delete(T t) {
|
||||
try {
|
||||
Class aClass = findEntity(t);
|
||||
//1、获取表名
|
||||
String table = aClass.getSimpleName();
|
||||
//2、获取字段列表
|
||||
List<Field> fs = new ArrayList<>();
|
||||
for (Field f : aClass.getDeclaredFields()) {
|
||||
if (f.isAnnotationPresent(DBField.class)) {
|
||||
fs.add(f);
|
||||
}
|
||||
}
|
||||
String[] columns = new String[fs.size()];
|
||||
int where = 0;
|
||||
for (int i = 0; i < columns.length; i++) {
|
||||
columns[i] = fs.get(i).getName().toUpperCase();
|
||||
try {
|
||||
fs.get(i).setAccessible(true);
|
||||
Object o = fs.get(i).get(t);
|
||||
if (o != null) {
|
||||
where++;
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
//3、获取where条件
|
||||
StringBuilder selectionSB = new StringBuilder("");
|
||||
String[] selectionArgs = null;
|
||||
if (where > 0) {
|
||||
selectionArgs = new String[where];
|
||||
where = 0;
|
||||
for (int i = 0; i < columns.length; i++) {
|
||||
columns[i] = fs.get(i).getName().toUpperCase();
|
||||
try {
|
||||
fs.get(i).setAccessible(true);
|
||||
Object o = fs.get(i).get(t);
|
||||
if (o != null) {
|
||||
if ("".equals(selectionSB.toString())) {
|
||||
selectionSB.append(" ");
|
||||
} else {
|
||||
selectionSB.append(" and ");
|
||||
}
|
||||
selectionSB.append(columns[i]).append(" = ?");
|
||||
selectionArgs[where] = o.toString();
|
||||
where++;
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
writableDatabase.delete(table, selectionSB.toString(), selectionArgs);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public <T> void insert(T t) {
|
||||
try {
|
||||
Class aClass = findEntity(t);
|
||||
StringBuffer sql = new StringBuffer();
|
||||
String tableName = aClass.getSimpleName();
|
||||
sql.append("INSERT INTO ");
|
||||
sql.append(tableName.toUpperCase());
|
||||
sql.append("(");
|
||||
|
||||
ContentValues contentValues = new ContentValues();
|
||||
StringBuffer fieldsSql = new StringBuffer();
|
||||
StringBuffer valueSql = new StringBuffer();
|
||||
for (Field f : aClass.getDeclaredFields()) {
|
||||
if (f.isAnnotationPresent(DBField.class)) {
|
||||
|
||||
f.setAccessible(true);
|
||||
try {
|
||||
String value = "";
|
||||
Object o = f.get(t);
|
||||
if (o instanceof String) {
|
||||
value = (String) o;
|
||||
valueSql.append(value);
|
||||
} else {
|
||||
valueSql.append("null");
|
||||
}
|
||||
valueSql.append(",");
|
||||
contentValues.put(f.getName().toUpperCase(), value);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
valueSql.append("null,");
|
||||
}
|
||||
|
||||
fieldsSql.append(f.getName().toUpperCase());
|
||||
fieldsSql.append(",");
|
||||
}
|
||||
}
|
||||
|
||||
if (",".equals(fieldsSql.substring(fieldsSql.length() - 1, fieldsSql.length()))) {
|
||||
fieldsSql.replace(fieldsSql.length() - 1, fieldsSql.length(), "");
|
||||
}
|
||||
if (",".equals(valueSql.substring(valueSql.length() - 1, valueSql.length()))) {
|
||||
valueSql.replace(valueSql.length() - 1, valueSql.length(), "");
|
||||
}
|
||||
sql.append(fieldsSql);
|
||||
sql.append(") VALUES (");
|
||||
sql.append(valueSql);
|
||||
sql.append(")");
|
||||
|
||||
writableDatabase.insert(tableName, null, contentValues);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public <T> void insertBitch(List<T> data) {
|
||||
if (data == null || data.size() == 0) {
|
||||
return;
|
||||
}
|
||||
writableDatabase.beginTransaction();
|
||||
for (Object datum : data) {
|
||||
insert(datum);
|
||||
}
|
||||
writableDatabase.setTransactionSuccessful();
|
||||
writableDatabase.endTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找注册的实体
|
||||
*
|
||||
* @param t
|
||||
* @param <T>
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
private <T> Class findEntity(T t) throws Exception {
|
||||
for (Class aClass : entityList) {
|
||||
if (t.getClass() == aClass) {
|
||||
return aClass;
|
||||
}
|
||||
}
|
||||
throw new Exception("can not find Entity:" + t.getClass().getName() + ", make sure it is registered");
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据库字段注解
|
||||
*/
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface DBField {
|
||||
String value() default "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 利用字段注解拼接sql
|
||||
*
|
||||
* @param mClass
|
||||
* @param sql
|
||||
*/
|
||||
private void fillSql(Class mClass, StringBuffer sql) {
|
||||
Field[] fields = mClass.getDeclaredFields();
|
||||
for (Field f : fields) {
|
||||
if (f.isAnnotationPresent(DBField.class)) {
|
||||
DBField bind = f.getAnnotation(DBField.class);
|
||||
String type = bind.value();
|
||||
sql.append(f.getName().toUpperCase());
|
||||
sql.append(" ");
|
||||
sql.append(type);
|
||||
sql.append(",");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class SQLiteOpenHelperImpl extends SQLiteOpenHelper {
|
||||
|
||||
public SQLiteOpenHelperImpl(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
|
||||
super(new DatabaseContext(context), name, factory, version);
|
||||
}
|
||||
|
||||
public SQLiteOpenHelperImpl(Context context, String name, SQLiteDatabase.CursorFactory factory, int version, DatabaseErrorHandler errorHandler) {
|
||||
super(context, name, factory, version, errorHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase sqLiteDatabase) {
|
||||
for (Class object : entityList) {
|
||||
StringBuffer sql = new StringBuffer();
|
||||
String name = object.getSimpleName();
|
||||
|
||||
sql.append("CREATE TABLE ");
|
||||
sql.append(name);
|
||||
sql.append(" (");
|
||||
fillSql(object, sql);
|
||||
|
||||
sql.replace(sql.length() - 1, sql.length(), "");
|
||||
sql.append(")");
|
||||
sqLiteDatabase.execSQL(sql.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建数据库辅助类,可以自定义数据库存放路径
|
||||
*/
|
||||
class DatabaseContext extends ContextWrapper {
|
||||
|
||||
public DatabaseContext(Context base) {
|
||||
super(base);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDatabasePath(String name) {
|
||||
if ("".equals(defaultPath)) {//defaultPath如果为""则放在程序默认位置
|
||||
defaultPath = getApplicationContext().getDatabasePath("database").getAbsolutePath();
|
||||
}
|
||||
|
||||
File path = new File(defaultPath);
|
||||
if (!path.exists()) {
|
||||
path.mkdirs();
|
||||
}
|
||||
|
||||
File dbfile = new File(path, defaultDBName);
|
||||
|
||||
if (!dbfile.exists()) {
|
||||
try {
|
||||
dbfile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return dbfile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLiteDatabase openOrCreateDatabase(String name, int mode,
|
||||
SQLiteDatabase.CursorFactory factory,
|
||||
DatabaseErrorHandler errorHandler) {
|
||||
return openOrCreateDatabase(name, mode, factory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLiteDatabase openOrCreateDatabase(String name, int mode,
|
||||
SQLiteDatabase.CursorFactory factory) {
|
||||
SQLiteDatabase result = SQLiteDatabase.openOrCreateDatabase(
|
||||
getDatabasePath(name), null);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public interface Register {
|
||||
List<Class> run();
|
||||
}
|
||||
|
||||
/**
|
||||
* 以下为Demo
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
//Demo
|
||||
DataBaseUtil db = new DataBaseUtil(WBUIApplication.getInstance(), new Register() {
|
||||
@Override
|
||||
public List<Class> run() {
|
||||
List<Class> objects = new ArrayList<>();
|
||||
objects.add(User.class);
|
||||
return objects;
|
||||
}
|
||||
});
|
||||
//插入数据
|
||||
db.insert(new User("Test"));
|
||||
//删除数据
|
||||
db.delete(new User("Test"));
|
||||
//查询数据(不分页)
|
||||
db.query(new User("Test"));
|
||||
//查询数据(分页)
|
||||
db.query(new User("Test"),0,10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Demo Entity
|
||||
*/
|
||||
public static class User {
|
||||
@DataBaseUtil.DBField("VARCHAR(20)")
|
||||
private String name;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public User(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package xyz.wbsite.wbui.base.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.TypedValue;
|
||||
|
||||
public class DensityUtil {
|
||||
private DensityUtil() {
|
||||
/* cannot be instantiated */
|
||||
throw new UnsupportedOperationException("cannot be instantiated");
|
||||
}
|
||||
|
||||
/**
|
||||
* dp转px
|
||||
*
|
||||
* @param context
|
||||
* @param dpVal
|
||||
* @return
|
||||
*/
|
||||
public static int dp2px(Context context, float dpVal) {
|
||||
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
|
||||
dpVal, context.getResources().getDisplayMetrics());
|
||||
}
|
||||
|
||||
/**
|
||||
* sp转px
|
||||
*
|
||||
* @param context
|
||||
* @param spVal
|
||||
* @return
|
||||
*/
|
||||
public static int sp2px(Context context, float spVal) {
|
||||
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
|
||||
spVal, context.getResources().getDisplayMetrics());
|
||||
}
|
||||
|
||||
/**
|
||||
* px转dp
|
||||
*
|
||||
* @param context
|
||||
* @param pxVal
|
||||
* @return
|
||||
*/
|
||||
public static float px2dp(Context context, float pxVal) {
|
||||
final float scale = context.getResources().getDisplayMetrics().density;
|
||||
return (pxVal / scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* px转sp
|
||||
*
|
||||
* @param context
|
||||
* @param pxVal
|
||||
* @return
|
||||
*/
|
||||
public static float px2sp(Context context, float pxVal) {
|
||||
return (pxVal / context.getResources().getDisplayMetrics().scaledDensity);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package xyz.wbsite.wbui.base.utils;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.qmuiteam.qmui.widget.dialog.QMUIDialog;
|
||||
import com.qmuiteam.qmui.widget.dialog.QMUIDialogAction;
|
||||
|
||||
|
||||
public class DialogUtil {
|
||||
|
||||
/**
|
||||
* 展示一个需要确认的消息提示
|
||||
*
|
||||
* @param context
|
||||
* @param title 标题
|
||||
* @param message 消息内容
|
||||
*/
|
||||
public static void showConfirmMessage(Context context, String title, String message) {
|
||||
QMUIDialog qmuiDialog = new QMUIDialog.MessageDialogBuilder(context)
|
||||
.setMessage(message)
|
||||
.addAction("确定", new QMUIDialogAction.ActionListener() {
|
||||
@Override
|
||||
public void onClick(QMUIDialog dialog, int index) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
})
|
||||
.create(com.qmuiteam.qmui.R.style.QMUI_Dialog);
|
||||
qmuiDialog.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* 展示一个需要确认的消息提示(带回调)
|
||||
*
|
||||
* @param context
|
||||
* @param title 标题
|
||||
* @param message 消息内容
|
||||
*/
|
||||
public static void showConfirmMessage(Context context, String title, String message, QMUIDialogAction.ActionListener actionListener) {
|
||||
QMUIDialog qmuiDialog = new QMUIDialog.MessageDialogBuilder(context)
|
||||
.setMessage(message)
|
||||
.addAction("取消", new QMUIDialogAction.ActionListener() {
|
||||
@Override
|
||||
public void onClick(QMUIDialog dialog, int index) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
})
|
||||
.addAction("确定", actionListener)
|
||||
.create(com.qmuiteam.qmui.R.style.QMUI_Dialog);
|
||||
qmuiDialog.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* 展示一个信息弹窗
|
||||
*
|
||||
* @param context
|
||||
* @param title 标题
|
||||
* @param message 消息内容
|
||||
*/
|
||||
public static void showMessage(Context context, String title, String message) {
|
||||
new QMUIDialog.MessageDialogBuilder(context)
|
||||
.setTitle(title)
|
||||
.setMessage(message)
|
||||
.addAction("确认", new QMUIDialogAction.ActionListener() {
|
||||
@Override
|
||||
public void onClick(QMUIDialog dialog, int index) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
})
|
||||
.create(com.qmuiteam.qmui.R.style.QMUI_Dialog).show();
|
||||
}
|
||||
}
|
@ -0,0 +1,217 @@
|
||||
package xyz.wbsite.wbui.base.utils;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
/**
|
||||
* Created by wangbing on 16/6/7.
|
||||
*/
|
||||
public class FastBlur {
|
||||
|
||||
public static Bitmap doBlur(Bitmap sentBitmap, int radius,
|
||||
boolean canReuseInBitmap) {
|
||||
Bitmap bitmap;
|
||||
if (canReuseInBitmap) {
|
||||
bitmap = sentBitmap;
|
||||
} else {
|
||||
bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);
|
||||
}
|
||||
|
||||
if (radius < 1) {
|
||||
return (null);
|
||||
}
|
||||
|
||||
int w = bitmap.getWidth();
|
||||
int h = bitmap.getHeight();
|
||||
|
||||
int[] pix = new int[w * h];
|
||||
bitmap.getPixels(pix, 0, w, 0, 0, w, h);
|
||||
|
||||
int wm = w - 1;
|
||||
int hm = h - 1;
|
||||
int wh = w * h;
|
||||
int div = radius + radius + 1;
|
||||
|
||||
int r[] = new int[wh];
|
||||
int g[] = new int[wh];
|
||||
int b[] = new int[wh];
|
||||
int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
|
||||
int vmin[] = new int[Math.max(w, h)];
|
||||
|
||||
int divsum = (div + 1) >> 1;
|
||||
divsum *= divsum;
|
||||
int dv[] = new int[256 * divsum];
|
||||
for (i = 0; i < 256 * divsum; i++) {
|
||||
dv[i] = (i / divsum);
|
||||
}
|
||||
|
||||
yw = yi = 0;
|
||||
|
||||
int[][] stack = new int[div][3];
|
||||
int stackpointer;
|
||||
int stackstart;
|
||||
int[] sir;
|
||||
int rbs;
|
||||
int r1 = radius + 1;
|
||||
int routsum, goutsum, boutsum;
|
||||
int rinsum, ginsum, binsum;
|
||||
|
||||
for (y = 0; y < h; y++) {
|
||||
rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
|
||||
for (i = -radius; i <= radius; i++) {
|
||||
p = pix[yi + Math.min(wm, Math.max(i, 0))];
|
||||
sir = stack[i + radius];
|
||||
sir[0] = (p & 0xff0000) >> 16;
|
||||
sir[1] = (p & 0x00ff00) >> 8;
|
||||
sir[2] = (p & 0x0000ff);
|
||||
rbs = r1 - Math.abs(i);
|
||||
rsum += sir[0] * rbs;
|
||||
gsum += sir[1] * rbs;
|
||||
bsum += sir[2] * rbs;
|
||||
if (i > 0) {
|
||||
rinsum += sir[0];
|
||||
ginsum += sir[1];
|
||||
binsum += sir[2];
|
||||
} else {
|
||||
routsum += sir[0];
|
||||
goutsum += sir[1];
|
||||
boutsum += sir[2];
|
||||
}
|
||||
}
|
||||
stackpointer = radius;
|
||||
|
||||
for (x = 0; x < w; x++) {
|
||||
|
||||
r[yi] = dv[rsum];
|
||||
g[yi] = dv[gsum];
|
||||
b[yi] = dv[bsum];
|
||||
|
||||
rsum -= routsum;
|
||||
gsum -= goutsum;
|
||||
bsum -= boutsum;
|
||||
|
||||
stackstart = stackpointer - radius + div;
|
||||
sir = stack[stackstart % div];
|
||||
|
||||
routsum -= sir[0];
|
||||
goutsum -= sir[1];
|
||||
boutsum -= sir[2];
|
||||
|
||||
if (y == 0) {
|
||||
vmin[x] = Math.min(x + radius + 1, wm);
|
||||
}
|
||||
p = pix[yw + vmin[x]];
|
||||
|
||||
sir[0] = (p & 0xff0000) >> 16;
|
||||
sir[1] = (p & 0x00ff00) >> 8;
|
||||
sir[2] = (p & 0x0000ff);
|
||||
|
||||
rinsum += sir[0];
|
||||
ginsum += sir[1];
|
||||
binsum += sir[2];
|
||||
|
||||
rsum += rinsum;
|
||||
gsum += ginsum;
|
||||
bsum += binsum;
|
||||
|
||||
stackpointer = (stackpointer + 1) % div;
|
||||
sir = stack[(stackpointer) % div];
|
||||
|
||||
routsum += sir[0];
|
||||
goutsum += sir[1];
|
||||
boutsum += sir[2];
|
||||
|
||||
rinsum -= sir[0];
|
||||
ginsum -= sir[1];
|
||||
binsum -= sir[2];
|
||||
|
||||
yi++;
|
||||
}
|
||||
yw += w;
|
||||
}
|
||||
for (x = 0; x < w; x++) {
|
||||
rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
|
||||
yp = -radius * w;
|
||||
for (i = -radius; i <= radius; i++) {
|
||||
yi = Math.max(0, yp) + x;
|
||||
|
||||
sir = stack[i + radius];
|
||||
|
||||
sir[0] = r[yi];
|
||||
sir[1] = g[yi];
|
||||
sir[2] = b[yi];
|
||||
|
||||
rbs = r1 - Math.abs(i);
|
||||
|
||||
rsum += r[yi] * rbs;
|
||||
gsum += g[yi] * rbs;
|
||||
bsum += b[yi] * rbs;
|
||||
|
||||
if (i > 0) {
|
||||
rinsum += sir[0];
|
||||
ginsum += sir[1];
|
||||
binsum += sir[2];
|
||||
} else {
|
||||
routsum += sir[0];
|
||||
goutsum += sir[1];
|
||||
boutsum += sir[2];
|
||||
}
|
||||
|
||||
if (i < hm) {
|
||||
yp += w;
|
||||
}
|
||||
}
|
||||
yi = x;
|
||||
stackpointer = radius;
|
||||
for (y = 0; y < h; y++) {
|
||||
// Preserve alpha channel: ( 0xff000000 & pix[yi] )
|
||||
pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16)
|
||||
| (dv[gsum] << 8) | dv[bsum];
|
||||
|
||||
rsum -= routsum;
|
||||
gsum -= goutsum;
|
||||
bsum -= boutsum;
|
||||
|
||||
stackstart = stackpointer - radius + div;
|
||||
sir = stack[stackstart % div];
|
||||
|
||||
routsum -= sir[0];
|
||||
goutsum -= sir[1];
|
||||
boutsum -= sir[2];
|
||||
|
||||
if (x == 0) {
|
||||
vmin[y] = Math.min(y + r1, hm) * w;
|
||||
}
|
||||
p = x + vmin[y];
|
||||
|
||||
sir[0] = r[p];
|
||||
sir[1] = g[p];
|
||||
sir[2] = b[p];
|
||||
|
||||
rinsum += sir[0];
|
||||
ginsum += sir[1];
|
||||
binsum += sir[2];
|
||||
|
||||
rsum += rinsum;
|
||||
gsum += ginsum;
|
||||
bsum += binsum;
|
||||
|
||||
stackpointer = (stackpointer + 1) % div;
|
||||
sir = stack[stackpointer];
|
||||
|
||||
routsum += sir[0];
|
||||
goutsum += sir[1];
|
||||
boutsum += sir[2];
|
||||
|
||||
rinsum -= sir[0];
|
||||
ginsum -= sir[1];
|
||||
binsum -= sir[2];
|
||||
|
||||
yi += w;
|
||||
}
|
||||
}
|
||||
|
||||
bitmap.setPixels(pix, 0, w, 0, 0, w, h);
|
||||
|
||||
return (bitmap);
|
||||
}
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
package xyz.wbsite.wbui.base.utils;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 文件及文件夹工具类
|
||||
*/
|
||||
public class FileUtil {
|
||||
|
||||
public static byte[] File2byte(File file) {
|
||||
byte[] buffer = null;
|
||||
try {
|
||||
FileInputStream fis = new FileInputStream(file);
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
byte[] b = new byte[1024];
|
||||
int n;
|
||||
while ((n = fis.read(b)) != -1) {
|
||||
bos.write(b, 0, n);
|
||||
}
|
||||
fis.close();
|
||||
bos.close();
|
||||
buffer = bos.toByteArray();
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public static void byte2File(byte[] buf, File file) {
|
||||
BufferedOutputStream bos = null;
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
file.getParentFile().mkdirs();
|
||||
file.createNewFile();
|
||||
fos = new FileOutputStream(file);
|
||||
bos = new BufferedOutputStream(fos);
|
||||
bos.write(buf);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (bos != null) {
|
||||
try {
|
||||
bos.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (fos != null) {
|
||||
try {
|
||||
fos.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static long sizeOf(File file) {
|
||||
|
||||
if (!file.exists()) {
|
||||
String message = file + " does not exist";
|
||||
throw new IllegalArgumentException(message);
|
||||
}
|
||||
|
||||
if (file.isDirectory()) {
|
||||
return sizeOfDirectory(file);
|
||||
} else {
|
||||
return file.length();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static long sizeOfDirectory(File directory) {
|
||||
checkDirectory(directory);
|
||||
|
||||
final File[] files = directory.listFiles();
|
||||
if (files == null) { // null if security restricted
|
||||
return 0L;
|
||||
}
|
||||
long size = 0;
|
||||
|
||||
for (final File file : files) {
|
||||
|
||||
size += sizeOf(file);
|
||||
if (size < 0) {
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
private static void checkDirectory(File directory) {
|
||||
if (!directory.exists()) {
|
||||
throw new IllegalArgumentException(directory + " does not exist");
|
||||
}
|
||||
if (!directory.isDirectory()) {
|
||||
throw new IllegalArgumentException(directory
|
||||
+ " is not a directory");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,156 @@
|
||||
package xyz.wbsite.wbui.base.utils;
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
|
||||
public class RSAUtil {
|
||||
|
||||
public static final String PUBLIC_KEY = "RSAPublicKey";
|
||||
public static final String PRIVATE_KEY = "RSAPrivateKey";
|
||||
private static final String KEY_ALGORITHM = "RSA";
|
||||
private static int KEY_SIZE = 512;
|
||||
|
||||
private static PublicKey MOBILE_PUBLIC_KEY = null;
|
||||
private static PrivateKey MOBILE_PRIVATE_KEY = null;
|
||||
|
||||
static {
|
||||
try {
|
||||
|
||||
// 初始化公钥
|
||||
X509EncodedKeySpec spec = new X509EncodedKeySpec(Base64Util.decode("MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJChCOcEFsKdG9Ibwi23b3UreERc1D5+GhEjvByxmFZ2Q+mqco8V9CDsIZUfpb6pLQA8x32G17YHEyj34etpmBUCAwEAAQ=="));
|
||||
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
|
||||
MOBILE_PUBLIC_KEY = keyFactory.generatePublic(spec);
|
||||
|
||||
// 初始化私钥
|
||||
PKCS8EncodedKeySpec specPri = new PKCS8EncodedKeySpec(Base64Util.decode("MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEAkKEI5wQWwp0b0hvCLbdvdSt4RFzUPn4aESO8HLGYVnZD6apyjxX0IOwhlR+lvqktADzHfYbXtgcTKPfh62mYFQIDAQABAkBhuZ4lUxr592TEDOOhNnCGkI/cSYlUjKqaaDYEgW/5Azom4VLya/JXFQVMVeMKQoiwH8aXn8od6+l5O7m+mYVlAiEA5yPFXhM4GXY0Oxe7l0uHKRlLkHIz44kvnd4Fj2xNfK8CIQCgL0SljzvL+iilHb+5PKk1wmpLPaDKajZqInSOhkhQewIgFpGAkOnxfVL0UJzFnUUrolCs9yKffGUFuDVYd6OMgVMCICh2CBbxqR8K3z1l2EnH4s3rf8HlnTnDvl7suRhPHvEFAiAxvjwQl6yHoDH6IGB6jeE9+hYK/xvuGT2TAyztZhfVRA=="));
|
||||
|
||||
keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
|
||||
MOBILE_PRIVATE_KEY = keyFactory.generatePrivate(specPri);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidKeySpecException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static Map<String, Object> generateKeys() throws Exception {
|
||||
KeyPairGenerator generator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
|
||||
generator.initialize(KEY_SIZE);
|
||||
KeyPair keyPair = generator.generateKeyPair();
|
||||
PublicKey publicKey = keyPair.getPublic();
|
||||
PrivateKey privateKey = keyPair.getPrivate();
|
||||
|
||||
Map<String, Object> keys = new HashMap<String, Object>();
|
||||
keys.put(PUBLIC_KEY, publicKey);
|
||||
keys.put(PRIVATE_KEY, privateKey);
|
||||
return keys;
|
||||
}
|
||||
|
||||
public static PublicKey getPublicKey(byte[] content) throws Exception {
|
||||
PublicKey publicKey = null;
|
||||
try {
|
||||
X509EncodedKeySpec spec = new X509EncodedKeySpec(content);
|
||||
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
|
||||
publicKey = keyFactory.generatePublic(spec);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
} catch (InvalidKeySpecException e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
|
||||
return publicKey;
|
||||
}
|
||||
|
||||
public static PrivateKey getPrivateKey(byte[] content) throws Exception {
|
||||
PrivateKey privateKey = null;
|
||||
try {
|
||||
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(content);
|
||||
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
|
||||
privateKey = keyFactory.generatePrivate(spec);
|
||||
} catch (InvalidKeySpecException e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
public static byte[] encryptWithPublicKey(byte[] data, PublicKey key) throws Exception {
|
||||
Cipher cipher;
|
||||
try {
|
||||
cipher = Cipher.getInstance(KEY_ALGORITHM);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key);
|
||||
return cipher.doFinal(data);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
} catch (NoSuchPaddingException e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
} catch (InvalidKeyException e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
} catch (IllegalBlockSizeException e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
} catch (BadPaddingException e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static byte[] decryptWithPrivateKey(byte[] data, PrivateKey key) throws Exception {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
|
||||
cipher.init(Cipher.DECRYPT_MODE, key);
|
||||
|
||||
return cipher.doFinal(data);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
} catch (NoSuchPaddingException e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
} catch (InvalidKeyException e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
} catch (IllegalBlockSizeException e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
} catch (BadPaddingException e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] encryptMobile(byte[] data) throws Exception {
|
||||
return encryptWithPublicKey(data, MOBILE_PUBLIC_KEY);
|
||||
}
|
||||
|
||||
public static byte[] decryptMobile(byte[] data) throws Exception {
|
||||
return decryptWithPrivateKey(data, MOBILE_PRIVATE_KEY);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,166 @@
|
||||
package xyz.wbsite.wbui.base.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import xyz.wbsite.webclient.WBUIApplication;
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2018/3/11 0011.
|
||||
*/
|
||||
|
||||
public class SPUtil {
|
||||
|
||||
public static final String FILE_DEFAULT = "default";
|
||||
|
||||
public static int getInt(String key) {
|
||||
SharedPreferences sharedPreferences = getSharePreferences(FILE_DEFAULT);
|
||||
return sharedPreferences.getInt(key, 0);
|
||||
}
|
||||
|
||||
public static boolean getBoolean(String key) {
|
||||
SharedPreferences sharedPreferences = getSharePreferences(FILE_DEFAULT);
|
||||
return sharedPreferences.getBoolean(key, false);
|
||||
}
|
||||
|
||||
public static float getFloat(String key) {
|
||||
SharedPreferences sharedPreferences = getSharePreferences(FILE_DEFAULT);
|
||||
return sharedPreferences.getFloat(key, 0);
|
||||
}
|
||||
|
||||
public static boolean getBoolean(String key, boolean defValue) {
|
||||
SharedPreferences sharedPreferences = getSharePreferences(FILE_DEFAULT);
|
||||
return sharedPreferences.getBoolean(key, defValue);
|
||||
}
|
||||
|
||||
public static String getString(String key) {
|
||||
SharedPreferences sharedPreferences = getSharePreferences(FILE_DEFAULT);
|
||||
return sharedPreferences.getString(key, "");
|
||||
}
|
||||
|
||||
public static String getStringWithDefault(String key, String defStr) {
|
||||
SharedPreferences sharedPreferences = getSharePreferences(FILE_DEFAULT);
|
||||
return sharedPreferences.getString(key, defStr);
|
||||
}
|
||||
|
||||
public static void putInt(String key, int value) {
|
||||
SharedPreferences.Editor editor = getEditor(getSharePreferences(FILE_DEFAULT));
|
||||
editor.putInt(key, value);
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
public static void putBoolean(String key, boolean value) {
|
||||
SharedPreferences.Editor editor = getEditor(getSharePreferences(FILE_DEFAULT));
|
||||
editor.putBoolean(key, value);
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
public static void putString(String key, String value) {
|
||||
SharedPreferences.Editor editor = getEditor(getSharePreferences(FILE_DEFAULT));
|
||||
editor.putString(key, value);
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
public static void putFloat(String key, float value) {
|
||||
SharedPreferences.Editor editor = getEditor(getSharePreferences(FILE_DEFAULT));
|
||||
|
||||
editor.putFloat(key, value);
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
public static void putLong(String key, long value) {
|
||||
SharedPreferences.Editor editor = getEditor(getSharePreferences(FILE_DEFAULT));
|
||||
|
||||
editor.putLong(key, value);
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
|
||||
public static long getLong(String key) {
|
||||
SharedPreferences sharedPreferences = getSharePreferences(FILE_DEFAULT);
|
||||
return sharedPreferences.getLong(key, 0);
|
||||
}
|
||||
|
||||
public static int getInt(String key, int defValue) {
|
||||
SharedPreferences sharedPreferences = getSharePreferences(FILE_DEFAULT);
|
||||
return sharedPreferences.getInt(key, defValue);
|
||||
}
|
||||
|
||||
public static int getInt(String key, String fileName) {
|
||||
|
||||
SharedPreferences sharedPreferences = getSharePreferences(getFileName(fileName));
|
||||
return sharedPreferences.getInt(key, 0);
|
||||
}
|
||||
|
||||
public static boolean getBoolean(String key, String fileName) {
|
||||
SharedPreferences sharedPreferences = getSharePreferences(getFileName(fileName));
|
||||
return sharedPreferences.getBoolean(key, false);
|
||||
}
|
||||
|
||||
public static String getString(String key, String fileName) {
|
||||
SharedPreferences sharedPreferences = getSharePreferences(getFileName(fileName));
|
||||
return sharedPreferences.getString(key, null);
|
||||
}
|
||||
|
||||
public static float getFloat(String key, String fileName) {
|
||||
SharedPreferences sharedPreferences = getSharePreferences(getFileName(fileName));
|
||||
return sharedPreferences.getFloat(key, 0);
|
||||
}
|
||||
|
||||
public static long getLong(String key, String fileName) {
|
||||
SharedPreferences sharedPreferences = getSharePreferences(getFileName(fileName));
|
||||
return sharedPreferences.getLong(key, 0);
|
||||
}
|
||||
|
||||
public static void putInt(String key, int value, String fileName) {
|
||||
SharedPreferences.Editor editor = getEditor(getSharePreferences(getFileName(fileName)));
|
||||
editor.putInt(key, value);
|
||||
editor.commit();
|
||||
|
||||
}
|
||||
|
||||
public static void putBoolean(String key, boolean value, String fileName) {
|
||||
SharedPreferences.Editor editor = getEditor(getSharePreferences(getFileName(fileName)));
|
||||
|
||||
editor.putBoolean(key, value);
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
public static void putString(String key, String value, String fileName) {
|
||||
SharedPreferences.Editor editor = getEditor(getSharePreferences(getFileName(fileName)));
|
||||
|
||||
editor.putString(key, value);
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
public static void putFloat(String key, float value, String fileName) {
|
||||
SharedPreferences.Editor editor = getEditor(getSharePreferences(getFileName(fileName)));
|
||||
|
||||
editor.putFloat(key, value);
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
public static void putLong(String key, long value, String fileName) {
|
||||
SharedPreferences.Editor editor = getEditor(getSharePreferences(getFileName(fileName)));
|
||||
|
||||
editor.putLong(key, value);
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
private static SharedPreferences getSharePreferences(String fileName) {
|
||||
return WBUIApplication.getInstance().getSharedPreferences(fileName, Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
private static SharedPreferences.Editor getEditor(SharedPreferences sharedPreferences) {
|
||||
return sharedPreferences.edit();
|
||||
}
|
||||
|
||||
public static String getFileName(String fileName) {
|
||||
if (!TextUtils.isEmpty(fileName)) {
|
||||
return fileName;
|
||||
} else {
|
||||
return FILE_DEFAULT;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package xyz.wbsite.wbui.base.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.TypedValue;
|
||||
|
||||
/**
|
||||
* 尺寸单位转换
|
||||
*/
|
||||
public class SizeUtil {
|
||||
|
||||
/**
|
||||
* dp转px
|
||||
*
|
||||
* @param context
|
||||
* @param dpVal
|
||||
* @return
|
||||
*/
|
||||
public static int dp2px(Context context, float dpVal) {
|
||||
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
|
||||
dpVal, context.getResources().getDisplayMetrics());
|
||||
}
|
||||
|
||||
/**
|
||||
* sp转px
|
||||
*
|
||||
* @param context
|
||||
* @param spVal
|
||||
* @return
|
||||
*/
|
||||
public static int sp2px(Context context, float spVal) {
|
||||
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
|
||||
spVal, context.getResources().getDisplayMetrics());
|
||||
}
|
||||
|
||||
/**
|
||||
* px转dp
|
||||
*
|
||||
* @param context
|
||||
* @param pxVal
|
||||
* @return
|
||||
*/
|
||||
public static float px2dp(Context context, float pxVal) {
|
||||
final float scale = context.getResources().getDisplayMetrics().density;
|
||||
return (pxVal / scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* px转sp
|
||||
*
|
||||
* @param context
|
||||
* @param pxVal
|
||||
* @return
|
||||
*/
|
||||
public static float px2sp(Context context, float pxVal) {
|
||||
return (pxVal / context.getResources().getDisplayMetrics().scaledDensity);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package xyz.wbsite.wbui.base.utils;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import xyz.wbsite.webclient.WBUIApplication;
|
||||
|
||||
/**
|
||||
* 消息发生器
|
||||
*/
|
||||
public class Toaster {
|
||||
/**
|
||||
* 展示Toast消息。
|
||||
*
|
||||
* @param message 消息内容
|
||||
*/
|
||||
public static void showToast(String message) {
|
||||
WBUIApplication.getInstance().showToast(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 引起注意或聚焦的消息提示
|
||||
*
|
||||
* @param message
|
||||
* @param view
|
||||
*/
|
||||
public static void showError(String message, View view) {
|
||||
showToast(message);
|
||||
if (view != null) {
|
||||
view.requestFocus();
|
||||
AnimationUtil.shake(view, 3);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package xyz.wbsite.webclient.fragment;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import butterknife.BindView;
|
||||
import xyz.wbsite.wbui.base.BaseSPAFragment;
|
||||
import xyz.wbsite.webclient.R;
|
||||
|
||||
public class LoginFragment extends BaseSPAFragment {
|
||||
|
||||
@BindView(R.id.edtUsername)
|
||||
EditText edtUsername;
|
||||
@BindView(R.id.llyUsername)
|
||||
LinearLayout llyUsername;
|
||||
@BindView(R.id.edtPassword)
|
||||
EditText edtPassword;
|
||||
@BindView(R.id.llyPassword)
|
||||
LinearLayout llyPassword;
|
||||
@BindView(R.id.btnLogin)
|
||||
Button btnLogin;
|
||||
@BindView(R.id.chkPwd)
|
||||
CheckBox chkPwd;
|
||||
@BindView(R.id.chkAuto)
|
||||
CheckBox chkAuto;
|
||||
|
||||
@Override
|
||||
protected int getFragmnetLayout() {
|
||||
return R.layout.fragment_login;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewInit() {
|
||||
btnLogin.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
showLoading();
|
||||
handler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
closeLoading();
|
||||
startFragment(new MainFragment());
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canDragBack() {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package xyz.wbsite.webclient.fragment;
|
||||
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.view.ViewPager;
|
||||
|
||||
import com.qmuiteam.qmui.widget.QMUITabSegment;
|
||||
import butterknife.BindView;
|
||||
import xyz.wbsite.wbui.base.BaseSPAFragment;
|
||||
import xyz.wbsite.webclient.R;
|
||||
|
||||
public class MainFragment extends BaseSPAFragment {
|
||||
|
||||
@BindView(R.id.pager)
|
||||
ViewPager pager;
|
||||
@BindView(R.id.tabs)
|
||||
QMUITabSegment tabs;
|
||||
|
||||
@Override
|
||||
protected int getFragmnetLayout() {
|
||||
return R.layout.fragment_main;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewInit() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canDragBack() {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,170 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillColor="#26A69A"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
</vector>
|
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/colorBackground"></solid>
|
||||
</shape>
|
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_pressed="true">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/colorFromInputActive"></solid>
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:state_focused="true">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/colorFromInputActive"></solid>
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/colorFromInput"></solid>
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<corners android:radius="5dp"></corners>
|
||||
<solid android:color="@color/colorTranslucent"></solid>
|
||||
</shape>
|
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_pressed="true">
|
||||
<shape>
|
||||
<corners android:radius="5dp"></corners>
|
||||
<solid android:color="@color/colorPrimaryDark"></solid>
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<shape>
|
||||
<corners android:radius="5dp"></corners>
|
||||
<solid android:color="@color/colorPrimary"></solid>
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<shape>
|
||||
<solid android:color="#eeeeee"></solid>
|
||||
</shape>
|
||||
</item>
|
||||
<item android:bottom="1dp">
|
||||
<shape>
|
||||
<solid android:color="#ffffff"></solid>
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
</layer-list>
|
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||
<item android:state_pressed="true">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="#83ececec"></solid>
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
After Width: | Height: | Size: 1002 B |
After Width: | Height: | Size: 973 B |
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/key_selected_color" android:state_pressed="true" />
|
||||
<item android:drawable="@drawable/key_normal_color" />
|
||||
</selector>
|
@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" >
|
||||
|
||||
<com.journeyapps.barcodescanner.DecoratedBarcodeView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/dbv_custom">
|
||||
</com.journeyapps.barcodescanner.DecoratedBarcodeView>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#202020"
|
||||
android:id="@+id/action_bar_id"
|
||||
android:layout_weight="0">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center"
|
||||
android:layout_centerVertical="true"
|
||||
android:id="@+id/back_btn_id">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/main_person_id"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:paddingLeft="12dp"
|
||||
android:paddingTop="14dp"
|
||||
android:paddingBottom="14dp"
|
||||
android:paddingRight="4dp"
|
||||
android:src="@mipmap/icon_logo" />
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@android:color/white"
|
||||
android:text="返回"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:id="@+id/main_title_id"
|
||||
android:text="扫描二维码"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="18sp"/>
|
||||
|
||||
</RelativeLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
</FrameLayout>
|
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.qmuiteam.qmui.widget.QMUIWindowInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/ui_background">
|
||||
|
||||
<com.qmuiteam.qmui.widget.QMUITopBarLayout
|
||||
android:id="@+id/topbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fitsSystemWindows="true"
|
||||
app:qmui_topbar_separator_color="@color/colorGray_10"
|
||||
app:qmui_topbar_separator_height="0dp" />
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="?attr/qmui_topbar_height"
|
||||
android:fitsSystemWindows="true">
|
||||
|
||||
</FrameLayout>
|
||||
</com.qmuiteam.qmui.widget.QMUIWindowInsetLayout>
|
@ -0,0 +1,144 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.qmuiteam.qmui.widget.QMUIWindowInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/ui_background">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fitsSystemWindows="true"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="40"
|
||||
android:gravity="center_horizontal|bottom"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:src="@mipmap/icon_logo" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginLeft="@dimen/margin_50"
|
||||
android:layout_marginRight="@dimen/margin_50"
|
||||
android:layout_weight="60"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/llyUsername"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/form_size"
|
||||
android:layout_marginBottom="@dimen/padding_10"
|
||||
android:background="@drawable/ui_background_login"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<xyz.wbsite.wbui.base.ui.image.WBUISquareImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/padding_10"
|
||||
android:src="@mipmap/icon_username"
|
||||
app:weight_height="1"
|
||||
app:weight_width="1" />
|
||||
|
||||
<View
|
||||
android:layout_width="2dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="@dimen/margin_15"
|
||||
android:layout_marginTop="@dimen/margin_15"
|
||||
android:background="@color/colorPrimaryText"></View>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/edtUsername"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/form_size"
|
||||
android:background="@null"
|
||||
android:inputType="number"
|
||||
android:paddingLeft="@dimen/padding_20"
|
||||
android:textColor="@color/colorPrimaryText" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/llyPassword"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/form_size"
|
||||
android:layout_marginBottom="@dimen/padding_10"
|
||||
android:background="@drawable/ui_background_login"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<xyz.wbsite.wbui.base.ui.image.WBUISquareImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/padding_10"
|
||||
android:src="@mipmap/icon_password"
|
||||
app:weight_height="1"
|
||||
app:weight_width="1" />
|
||||
|
||||
<View
|
||||
android:layout_width="2dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="@dimen/margin_15"
|
||||
android:layout_marginTop="@dimen/margin_15"
|
||||
android:background="@color/colorPrimaryText"></View>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/edtPassword"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/form_size"
|
||||
android:background="@null"
|
||||
android:inputType="numberPassword"
|
||||
android:paddingLeft="@dimen/padding_20"
|
||||
android:textColor="@color/colorPrimaryText" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnLogin"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/form_size"
|
||||
android:layout_marginTop="@dimen/margin_30"
|
||||
android:background="@drawable/ui_background_login_button"
|
||||
android:text="登 录"
|
||||
android:textColor="@color/colorPrimaryText"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/padding_10">
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/chkPwd"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:buttonTint="@color/colorPrimaryText"
|
||||
android:text="记住密码"
|
||||
android:textColor="@color/colorPrimaryText" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/chkAuto"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:buttonTint="@color/colorPrimaryText"
|
||||
android:text="自动登录"
|
||||
android:textColor="@color/colorPrimaryText" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</com.qmuiteam.qmui.widget.QMUIWindowInsetLayout>
|
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.qmuiteam.qmui.widget.QMUIWindowInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:background="@drawable/ui_background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.qmuiteam.qmui.widget.QMUIViewPager
|
||||
android:id="@+id/pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="?attr/qmui_topbar_height"
|
||||
android:fitsSystemWindows="true"/>
|
||||
|
||||
<com.qmuiteam.qmui.widget.QMUITabSegment
|
||||
android:id="@+id/tabs"
|
||||
android:background="@android:color/white"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/qmui_topbar_height"
|
||||
android:layout_gravity="bottom"
|
||||
android:fitsSystemWindows="true"
|
||||
android:textSize="12sp"
|
||||
app:qmui_tab_icon_position="top" />
|
||||
|
||||
</com.qmuiteam.qmui.widget.QMUIWindowInsetLayout>
|
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 4.9 KiB |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue