@ -1,7 +1,6 @@ |
|||||||
<?xml version="1.0" encoding="UTF-8"?> |
<?xml version="1.0" encoding="UTF-8"?> |
||||||
<project version="4"> |
<project version="4"> |
||||||
<component name="SqlDialectMappings"> |
<component name="SqlDialectMappings"> |
||||||
<file url="file://$PROJECT_DIR$/app/src/main/java/xyz/fycz/myreader/model/backup/UserService.java" dialect="GenericSQL" /> |
|
||||||
<file url="PROJECT" dialect="MySQL" /> |
<file url="PROJECT" dialect="MySQL" /> |
||||||
</component> |
</component> |
||||||
</project> |
</project> |
@ -0,0 +1,3 @@ |
|||||||
|
1、 正确填写WebDAV 服务器地址、WebDAV 账号、WebDAV 密码;(要获得这三项的信息,需要注册一个坚果云账号,如果直接在手机上注册,坚果云会让你下载app,过程比较麻烦,为了一步到位,最好是在电脑上打开这个注册链接:https://www.jianguoyun.com/d/signup;注册后,进入坚果云;点击右上角账户名处选择 “账户信息”,然后选择“安全选项”;在“安全选项” 中找到“第三方应用管理”,并选择“添加应用”,输入名称如“阅读”后,会生成密码,选择完成;其中https://dav.jianguoyun.com/dav/就是填入“WebDAV 服务器地址”的内容,“使用情况”后面的邮箱地址就是你的“WebDAV 账号”,点击显示密码后得到的密码就是你的“WebDAV 密码”。) |
||||||
|
|
||||||
|
2、 无需操作,APP默认每天自动云备份一次。 |
@ -1,244 +0,0 @@ |
|||||||
package xyz.fycz.myreader.base; |
|
||||||
|
|
||||||
import android.annotation.SuppressLint; |
|
||||||
import android.content.Intent; |
|
||||||
import android.graphics.PorterDuff; |
|
||||||
import android.graphics.drawable.Drawable; |
|
||||||
import android.os.Bundle; |
|
||||||
|
|
||||||
import android.view.Menu; |
|
||||||
import android.view.MenuItem; |
|
||||||
import androidx.annotation.LayoutRes; |
|
||||||
import androidx.annotation.Nullable; |
|
||||||
import androidx.appcompat.app.ActionBar; |
|
||||||
import androidx.appcompat.app.AppCompatActivity; |
|
||||||
import androidx.appcompat.app.AppCompatDelegate; |
|
||||||
import androidx.appcompat.widget.Toolbar; |
|
||||||
import butterknife.ButterKnife; |
|
||||||
import butterknife.Unbinder; |
|
||||||
|
|
||||||
import io.reactivex.disposables.CompositeDisposable; |
|
||||||
import io.reactivex.disposables.Disposable; |
|
||||||
import xyz.fycz.myreader.ActivityManage; |
|
||||||
import xyz.fycz.myreader.R; |
|
||||||
import xyz.fycz.myreader.application.MyApplication; |
|
||||||
import xyz.fycz.myreader.application.SysManager; |
|
||||||
import xyz.fycz.myreader.entity.Setting; |
|
||||||
import xyz.fycz.myreader.util.StatusBarUtil; |
|
||||||
|
|
||||||
import java.lang.reflect.Method; |
|
||||||
import java.util.ArrayList; |
|
||||||
|
|
||||||
/** |
|
||||||
* @author fengyue |
|
||||||
* @date 2020/8/12 20:02 |
|
||||||
*/ |
|
||||||
public abstract class BaseActivity2 extends AppCompatActivity { |
|
||||||
private static final int INVALID_VAL = -1; |
|
||||||
|
|
||||||
protected CompositeDisposable mDisposable; |
|
||||||
//ButterKnife
|
|
||||||
private Toolbar mToolbar; |
|
||||||
|
|
||||||
private Unbinder unbinder; |
|
||||||
|
|
||||||
private int curNightMode; |
|
||||||
/****************************abstract area*************************************/ |
|
||||||
|
|
||||||
@LayoutRes |
|
||||||
protected abstract int getContentId(); |
|
||||||
|
|
||||||
/************************init area************************************/ |
|
||||||
protected void addDisposable(Disposable d){ |
|
||||||
if (mDisposable == null){ |
|
||||||
mDisposable = new CompositeDisposable(); |
|
||||||
} |
|
||||||
mDisposable.add(d); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 配置Toolbar |
|
||||||
* @param toolbar |
|
||||||
*/ |
|
||||||
protected void setUpToolbar(Toolbar toolbar){ |
|
||||||
} |
|
||||||
|
|
||||||
protected void initData(Bundle savedInstanceState){ |
|
||||||
} |
|
||||||
/** |
|
||||||
* 初始化零件 |
|
||||||
*/ |
|
||||||
protected void initWidget() { |
|
||||||
|
|
||||||
} |
|
||||||
/** |
|
||||||
* 初始化点击事件 |
|
||||||
*/ |
|
||||||
protected void initClick(){ |
|
||||||
} |
|
||||||
/** |
|
||||||
* 逻辑使用区 |
|
||||||
*/ |
|
||||||
protected void processLogic(){ |
|
||||||
} |
|
||||||
/** |
|
||||||
* @return 是否夜间模式 |
|
||||||
*/ |
|
||||||
protected boolean isNightTheme() { |
|
||||||
return !SysManager.getSetting().isDayStyle(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 设置夜间模式 |
|
||||||
* @param isNightMode |
|
||||||
*/ |
|
||||||
protected void setNightTheme(boolean isNightMode) { |
|
||||||
Setting setting = SysManager.getSetting(); |
|
||||||
setting.setDayStyle(!isNightMode); |
|
||||||
MyApplication.getApplication().initNightTheme(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************lifecycle area*****************************************************/ |
|
||||||
|
|
||||||
@Override |
|
||||||
protected void onCreate(@Nullable Bundle savedInstanceState) { |
|
||||||
super.onCreate(savedInstanceState); |
|
||||||
initTheme(); |
|
||||||
ActivityManage.addActivity(this); |
|
||||||
setContentView(getContentId()); |
|
||||||
initData(savedInstanceState); |
|
||||||
unbinder = ButterKnife.bind(this); |
|
||||||
initToolbar(); |
|
||||||
initWidget(); |
|
||||||
initClick(); |
|
||||||
processLogic(); |
|
||||||
} |
|
||||||
|
|
||||||
private void initToolbar(){ |
|
||||||
//更严谨是通过反射判断是否存在Toolbar
|
|
||||||
mToolbar = findViewById(R.id.toolbar); |
|
||||||
if (mToolbar != null){ |
|
||||||
supportActionBar(mToolbar); |
|
||||||
setUpToolbar(mToolbar); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
protected void onResume() { |
|
||||||
super.onResume(); |
|
||||||
if (isThemeChange()){ |
|
||||||
recreate(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
protected void onDestroy() { |
|
||||||
super.onDestroy(); |
|
||||||
ActivityManage.removeActivity(this); |
|
||||||
unbinder.unbind(); |
|
||||||
if (mDisposable != null){ |
|
||||||
mDisposable.dispose(); |
|
||||||
} |
|
||||||
} |
|
||||||
/** |
|
||||||
* 初始化主题 |
|
||||||
*/ |
|
||||||
public void initTheme() { |
|
||||||
//if (isNightTheme()) {
|
|
||||||
//setTheme(R.style.AppNightTheme);
|
|
||||||
curNightMode = AppCompatDelegate.getDefaultNightMode(); |
|
||||||
/*} else { |
|
||||||
//curNightMode = false;
|
|
||||||
//setTheme(R.style.AppDayTheme);
|
|
||||||
}*/ |
|
||||||
} |
|
||||||
|
|
||||||
protected boolean isThemeChange(){ |
|
||||||
return curNightMode != AppCompatDelegate.getDefaultNightMode(); |
|
||||||
} |
|
||||||
/**************************used method area*******************************************/ |
|
||||||
|
|
||||||
protected void startActivity(Class<? extends AppCompatActivity> activity){ |
|
||||||
Intent intent = new Intent(this, activity); |
|
||||||
startActivity(intent); |
|
||||||
} |
|
||||||
|
|
||||||
protected ActionBar supportActionBar(Toolbar toolbar){ |
|
||||||
setSupportActionBar(toolbar); |
|
||||||
ActionBar actionBar = getSupportActionBar(); |
|
||||||
if (actionBar != null){ |
|
||||||
actionBar.setDisplayHomeAsUpEnabled(true); |
|
||||||
actionBar.setDisplayShowHomeEnabled(true); |
|
||||||
} |
|
||||||
mToolbar.setNavigationOnClickListener( |
|
||||||
(v) -> finish() |
|
||||||
); |
|
||||||
return actionBar; |
|
||||||
} |
|
||||||
|
|
||||||
protected void setStatusBarColor(int statusColor, boolean dark){ |
|
||||||
//沉浸式代码配置
|
|
||||||
//当FitsSystemWindows设置 true 时,会在屏幕最上方预留出状态栏高度的 padding
|
|
||||||
StatusBarUtil.setRootViewFitsSystemWindows(this, true); |
|
||||||
//设置状态栏透明
|
|
||||||
StatusBarUtil.setTranslucentStatus(this); |
|
||||||
StatusBarUtil.setStatusBarColor(this, getResources().getColor(statusColor)); |
|
||||||
|
|
||||||
//一般的手机的状态栏文字和图标都是白色的, 可如果你的应用也是纯白色的, 或导致状态栏文字看不清
|
|
||||||
//所以如果你是这种情况,请使用以下代码, 设置状态使用深色文字图标风格, 否则你可以选择性注释掉这个if内容
|
|
||||||
if (!dark) { |
|
||||||
if (!StatusBarUtil.setStatusBarDarkTheme(this, true)) { |
|
||||||
//如果不支持设置深色风格 为了兼容总不能让状态栏白白的看不清, 于是设置一个状态栏颜色为半透明,
|
|
||||||
//这样半透明+白=灰, 状态栏的文字能看得清
|
|
||||||
StatusBarUtil.setStatusBarColor(this, 0x55000000); |
|
||||||
} |
|
||||||
} |
|
||||||
} /** |
|
||||||
* 设置MENU图标颜色 |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
public boolean onCreateOptionsMenu(Menu menu) { |
|
||||||
for (int i = 0; i < menu.size(); i++) { |
|
||||||
Drawable drawable = menu.getItem(i).getIcon(); |
|
||||||
if (drawable != null) { |
|
||||||
drawable.mutate(); |
|
||||||
drawable.setColorFilter(getColor(R.color.textPrimary), PorterDuff.Mode.SRC_ATOP); |
|
||||||
} |
|
||||||
} |
|
||||||
return super.onCreateOptionsMenu(menu); |
|
||||||
} |
|
||||||
|
|
||||||
@SuppressLint("PrivateApi") |
|
||||||
@SuppressWarnings("unchecked") |
|
||||||
@Override |
|
||||||
public boolean onMenuOpened(int featureId, Menu menu) { |
|
||||||
if (menu != null) { |
|
||||||
//展开菜单显示图标
|
|
||||||
if (menu.getClass().getSimpleName().equalsIgnoreCase("MenuBuilder")) { |
|
||||||
try { |
|
||||||
Method method = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE); |
|
||||||
method.setAccessible(true); |
|
||||||
method.invoke(menu, true); |
|
||||||
method = menu.getClass().getDeclaredMethod("getNonActionItems"); |
|
||||||
ArrayList<MenuItem> menuItems = (ArrayList<MenuItem>) method.invoke(menu); |
|
||||||
if (!menuItems.isEmpty()) { |
|
||||||
for (MenuItem menuItem : menuItems) { |
|
||||||
Drawable drawable = menuItem.getIcon(); |
|
||||||
if (drawable != null) { |
|
||||||
drawable.mutate(); |
|
||||||
drawable.setColorFilter(getResources().getColor(R.color.textPrimary), PorterDuff.Mode.SRC_ATOP); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} catch (Exception ignored) { |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
return super.onMenuOpened(featureId, menu); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,129 +0,0 @@ |
|||||||
package xyz.fycz.myreader.model.backup; |
|
||||||
|
|
||||||
import xyz.fycz.myreader.application.SysManager; |
|
||||||
import xyz.fycz.myreader.common.APPCONST; |
|
||||||
import xyz.fycz.myreader.entity.Setting; |
|
||||||
import xyz.fycz.myreader.greendao.entity.Book; |
|
||||||
import xyz.fycz.myreader.greendao.service.BookService; |
|
||||||
import xyz.fycz.myreader.util.IOUtils; |
|
||||||
import xyz.fycz.myreader.util.utils.FileUtils; |
|
||||||
import java.io.*; |
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.List; |
|
||||||
|
|
||||||
/** |
|
||||||
* @author fengyue |
|
||||||
* @date 2020/4/25 9:07 |
|
||||||
*/ |
|
||||||
|
|
||||||
public class BackupAndRestore { |
|
||||||
|
|
||||||
BookService mBookService = BookService.getInstance(); |
|
||||||
|
|
||||||
/** |
|
||||||
* 备份书架 |
|
||||||
* @return 是否备份成功 |
|
||||||
*/ |
|
||||||
public boolean backup(String backupName){ |
|
||||||
List<Book> books = mBookService.getAllBooks(); |
|
||||||
StringBuilder s = new StringBuilder(); |
|
||||||
for (Book book : books) { |
|
||||||
s.append(book); |
|
||||||
s.append(",\n"); |
|
||||||
} |
|
||||||
s.deleteCharAt(s.lastIndexOf(",")); |
|
||||||
File booksFile = FileUtils.getFile(APPCONST.FILE_DIR + backupName + "/books" + FileUtils.SUFFIX_FY); |
|
||||||
File settingFile = FileUtils.getFile(APPCONST.FILE_DIR + backupName + "/setting" + FileUtils.SUFFIX_FY); |
|
||||||
BufferedWriter bw = null; |
|
||||||
ObjectOutputStream oos = null; |
|
||||||
try { |
|
||||||
bw = new BufferedWriter(new FileWriter(booksFile)); |
|
||||||
bw.write(s.toString()); |
|
||||||
bw.flush(); |
|
||||||
oos = new ObjectOutputStream(new FileOutputStream(settingFile)); |
|
||||||
oos.writeObject(SysManager.getSetting()); |
|
||||||
oos.flush(); |
|
||||||
return true; |
|
||||||
} catch (IOException e) { |
|
||||||
e.printStackTrace(); |
|
||||||
return false; |
|
||||||
} finally { |
|
||||||
IOUtils.close(bw, oos); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 恢复书架 |
|
||||||
* @return 是否恢复成功 |
|
||||||
*/ |
|
||||||
public boolean restore(String backupName) { |
|
||||||
File booksFile = FileUtils.getFile(APPCONST.FILE_DIR + backupName + "/books" + FileUtils.SUFFIX_FY); |
|
||||||
File settingFile = FileUtils.getFile(APPCONST.FILE_DIR + backupName + "/setting" + FileUtils.SUFFIX_FY); |
|
||||||
if (!booksFile.exists() || !settingFile.exists()){ |
|
||||||
return false; |
|
||||||
} |
|
||||||
BufferedReader br = null; |
|
||||||
ObjectInputStream ois = null; |
|
||||||
try { |
|
||||||
br = new BufferedReader(new FileReader(booksFile)); |
|
||||||
String tem = ""; |
|
||||||
StringBuilder s = new StringBuilder(); |
|
||||||
while ((tem = br.readLine()) != null){ |
|
||||||
s.append(tem).append("\n"); |
|
||||||
} |
|
||||||
String[] sBooks = s.toString().split("\\},"); |
|
||||||
List<Book> books = new ArrayList<>(); |
|
||||||
for (String sBook : sBooks){ |
|
||||||
sBook.replace("{", ""); |
|
||||||
sBook.replace("}", ""); |
|
||||||
String[] sBookFields = sBook.split(",\n"); |
|
||||||
for (int i = 0; i < sBookFields.length; i++) { |
|
||||||
sBookFields[i] = sBookFields[i].substring(sBookFields[i].indexOf("'") + 1, sBookFields[i].lastIndexOf("'")); |
|
||||||
} |
|
||||||
String source = "null"; |
|
||||||
boolean isCloseUpdate = false; |
|
||||||
boolean isDownloadAll = true; |
|
||||||
String group = "allBook"; |
|
||||||
String infoUrl = ""; |
|
||||||
if(!sBookFields[2].contains("novel.fycz.xyz")){ |
|
||||||
source = sBookFields[17]; |
|
||||||
} |
|
||||||
if ("本地书籍".equals(sBookFields[4])){ |
|
||||||
sBookFields[15] = "0"; |
|
||||||
} |
|
||||||
if (sBookFields.length >= 19){ |
|
||||||
isCloseUpdate = Boolean.parseBoolean(sBookFields[18]); |
|
||||||
} |
|
||||||
if (sBookFields.length >= 20){ |
|
||||||
isDownloadAll = Boolean.parseBoolean(sBookFields[19]); |
|
||||||
} |
|
||||||
if (sBookFields.length >= 21){ |
|
||||||
group = sBookFields[20]; |
|
||||||
} |
|
||||||
if (sBookFields.length >= 22){ |
|
||||||
infoUrl = sBookFields[21]; |
|
||||||
} |
|
||||||
Book book = new Book(sBookFields[0], sBookFields[1], sBookFields[2], infoUrl, sBookFields[3], sBookFields[4], |
|
||||||
sBookFields[5], sBookFields[6], sBookFields[7], sBookFields[8], sBookFields[9], sBookFields[10], |
|
||||||
sBookFields[11], Integer.parseInt(sBookFields[12]), Integer.parseInt(sBookFields[13]), |
|
||||||
Integer.parseInt(sBookFields[14]), Integer.parseInt(sBookFields[15]), Integer.parseInt(sBookFields[16]) |
|
||||||
, source, isCloseUpdate, isDownloadAll, group, 0); |
|
||||||
books.add(book); |
|
||||||
} |
|
||||||
mBookService.deleteAllBooks(); |
|
||||||
mBookService.addBooks(books); |
|
||||||
ois = new ObjectInputStream(new FileInputStream(settingFile)); |
|
||||||
Object obj = ois.readObject(); |
|
||||||
if (obj instanceof Setting){ |
|
||||||
Setting setting = (Setting) obj; |
|
||||||
SysManager.saveSetting(setting); |
|
||||||
} |
|
||||||
return true; |
|
||||||
} catch (IOException | ClassNotFoundException e) { |
|
||||||
e.printStackTrace(); |
|
||||||
return false; |
|
||||||
} finally { |
|
||||||
IOUtils.close(br, ois); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,333 +0,0 @@ |
|||||||
package xyz.fycz.myreader.model.backup; |
|
||||||
|
|
||||||
import io.reactivex.annotations.NonNull; |
|
||||||
import xyz.fycz.myreader.application.MyApplication; |
|
||||||
import xyz.fycz.myreader.model.storage.Backup; |
|
||||||
import xyz.fycz.myreader.model.storage.Restore; |
|
||||||
import xyz.fycz.myreader.webapi.callback.ResultCallback; |
|
||||||
import xyz.fycz.myreader.common.APPCONST; |
|
||||||
import xyz.fycz.myreader.common.URLCONST; |
|
||||||
import xyz.fycz.myreader.util.*; |
|
||||||
import xyz.fycz.myreader.util.utils.FileUtils; |
|
||||||
|
|
||||||
import java.io.*; |
|
||||||
import java.net.HttpURLConnection; |
|
||||||
import java.net.URL; |
|
||||||
import java.util.HashMap; |
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
/** |
|
||||||
* @author fengyue |
|
||||||
* @date 2020/4/26 11:03 |
|
||||||
*/ |
|
||||||
public class UserService { |
|
||||||
/** |
|
||||||
* 登录 |
|
||||||
* @param userLoginInfo 用户名输入的用户名和密码等登录信息 |
|
||||||
* @return 是否成功登录 |
|
||||||
*/ |
|
||||||
public static void login(final Map<String, String> userLoginInfo, final ResultCallback resultCallback) { |
|
||||||
MyApplication.getApplication().newThread(() -> { |
|
||||||
HttpURLConnection conn = null; |
|
||||||
try { |
|
||||||
URL url = new URL(URLCONST.APP_WEB_URL + "login"); |
|
||||||
conn = (HttpURLConnection) url.openConnection(); |
|
||||||
conn.setRequestMethod("POST"); |
|
||||||
conn.setConnectTimeout(60 * 1000); |
|
||||||
conn.setReadTimeout(60 * 1000); |
|
||||||
conn.setDoInput(true); |
|
||||||
conn.setDoOutput(true); |
|
||||||
String params = "username=" + userLoginInfo.get("loginName") + |
|
||||||
"&password=" + userLoginInfo.get("loginPwd") + makeSignalParam(); |
|
||||||
// 获取URLConnection对象对应的输出流
|
|
||||||
PrintWriter out = new PrintWriter(conn.getOutputStream()); |
|
||||||
// 发送请求参数
|
|
||||||
out.print(params); |
|
||||||
// flush输出流的缓冲
|
|
||||||
out.flush(); |
|
||||||
InputStream in = conn.getInputStream(); |
|
||||||
BufferedReader bw = new BufferedReader(new InputStreamReader(in, "utf-8")); |
|
||||||
StringBuilder sb = new StringBuilder(); |
|
||||||
String line = bw.readLine(); |
|
||||||
while (line != null) { |
|
||||||
sb.append(line); |
|
||||||
line = bw.readLine(); |
|
||||||
} |
|
||||||
resultCallback.onFinish(sb.toString(), 1); |
|
||||||
} catch (IOException e) { |
|
||||||
e.printStackTrace(); |
|
||||||
resultCallback.onError(e); |
|
||||||
}finally { |
|
||||||
if (conn != null) { |
|
||||||
conn.disconnect(); |
|
||||||
} |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
public static void register(final Map<String, String> userRegisterInfo, final ResultCallback resultCallback) { |
|
||||||
MyApplication.getApplication().newThread(() -> { |
|
||||||
HttpURLConnection conn = null; |
|
||||||
try { |
|
||||||
URL url = new URL(URLCONST.APP_WEB_URL + "reg"); |
|
||||||
conn = (HttpURLConnection) url.openConnection(); |
|
||||||
conn.setRequestMethod("POST"); |
|
||||||
conn.setDoInput(true); |
|
||||||
conn.setDoOutput(true); |
|
||||||
String params = "username=" + userRegisterInfo.get("username") + "&password=" + |
|
||||||
CyptoUtils.encode(APPCONST.KEY, userRegisterInfo.get("password")) + "&key=" + |
|
||||||
CyptoUtils.encode(APPCONST.KEY, APPCONST.publicKey) + makeSignalParam(); |
|
||||||
// 获取URLConnection对象对应的输出流
|
|
||||||
PrintWriter out = new PrintWriter(conn.getOutputStream()); |
|
||||||
// 发送请求参数
|
|
||||||
out.print(params); |
|
||||||
// flush输出流的缓冲
|
|
||||||
out.flush(); |
|
||||||
BufferedReader bw = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8")); |
|
||||||
StringBuilder sb = new StringBuilder(); |
|
||||||
String line = bw.readLine(); |
|
||||||
while (line != null) { |
|
||||||
sb.append(line); |
|
||||||
line = bw.readLine(); |
|
||||||
} |
|
||||||
resultCallback.onFinish(sb.toString(), 1); |
|
||||||
} catch (IOException e) { |
|
||||||
e.printStackTrace(); |
|
||||||
resultCallback.onError(e); |
|
||||||
} finally { |
|
||||||
if (conn != null) { |
|
||||||
conn.disconnect(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 写配置 |
|
||||||
* @param userLoginInfo |
|
||||||
* @return |
|
||||||
*/ |
|
||||||
public static boolean writeConfig(Map<String,String> userLoginInfo){ |
|
||||||
FileOutputStream fos = null; |
|
||||||
try { |
|
||||||
fos = MyApplication.getApplication().openFileOutput("userConfig.fy", MyApplication.getApplication().MODE_PRIVATE); |
|
||||||
String userInfo = "username='" + userLoginInfo.get("loginName") + "',\npassword='" + userLoginInfo.get("loginPwd") + "'"; |
|
||||||
byte[] bs = userInfo.getBytes(); |
|
||||||
fos.write(bs); |
|
||||||
//写完后一定要刷新
|
|
||||||
fos.flush(); |
|
||||||
return true; |
|
||||||
} catch (IOException e) { |
|
||||||
e.printStackTrace(); |
|
||||||
return false; |
|
||||||
} finally { |
|
||||||
IOUtils.close(fos); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 读配置 |
|
||||||
* @return |
|
||||||
*/ |
|
||||||
public static Map<String,String> readConfig(){ |
|
||||||
File file = MyApplication.getApplication().getFileStreamPath("userConfig.fy"); |
|
||||||
if (!file.exists()){ |
|
||||||
return null; |
|
||||||
} |
|
||||||
BufferedReader br = null; |
|
||||||
try { |
|
||||||
br = new BufferedReader(new FileReader(file)); |
|
||||||
String tem; |
|
||||||
StringBuilder config = new StringBuilder(); |
|
||||||
while ((tem = br.readLine()) != null){ |
|
||||||
config.append(tem); |
|
||||||
} |
|
||||||
String[] user = config.toString().split(","); |
|
||||||
String userName = user[0].substring(user[0].indexOf("'") + 1, user[0].lastIndexOf("'")); |
|
||||||
String password = user[1].substring(user[1].indexOf("'") + 1, user[1].lastIndexOf("'")); |
|
||||||
Map<String,String> userInfo = new HashMap<>(); |
|
||||||
userInfo.put("userName", userName); |
|
||||||
userInfo.put("password", password); |
|
||||||
return userInfo; |
|
||||||
} catch (IOException e) { |
|
||||||
e.printStackTrace(); |
|
||||||
}finally { |
|
||||||
IOUtils.close(br); |
|
||||||
} |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
public static void writeUsername(String username){ |
|
||||||
File file = FileUtils.getFile(APPCONST.QQ_DATA_DIR + "user"); |
|
||||||
BufferedWriter bw = null; |
|
||||||
try { |
|
||||||
bw = new BufferedWriter(new FileWriter(file)); |
|
||||||
bw.write(username); |
|
||||||
bw.flush(); |
|
||||||
} catch (IOException e) { |
|
||||||
e.printStackTrace(); |
|
||||||
}finally { |
|
||||||
IOUtils.close(bw); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public static String readUsername(){ |
|
||||||
File file = new File(APPCONST.QQ_DATA_DIR + "user"); |
|
||||||
if (!file.exists()){ |
|
||||||
return ""; |
|
||||||
} |
|
||||||
BufferedReader br = null; |
|
||||||
try { |
|
||||||
br = new BufferedReader(new FileReader(file)); |
|
||||||
return br.readLine(); |
|
||||||
} catch (IOException e) { |
|
||||||
e.printStackTrace(); |
|
||||||
return ""; |
|
||||||
} finally { |
|
||||||
IOUtils.close(br); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 网络备份 |
|
||||||
* @return |
|
||||||
*/ |
|
||||||
public static void webBackup(ResultCallback rc){ |
|
||||||
Map<String,String> userInfo = readConfig(); |
|
||||||
if (userInfo == null){ |
|
||||||
rc.onFinish(false, 0); |
|
||||||
} |
|
||||||
Backup.INSTANCE.backup(MyApplication.getmContext(), APPCONST.FILE_DIR + "webBackup/", new Backup.CallBack() { |
|
||||||
@Override |
|
||||||
public void backupSuccess() { |
|
||||||
MyApplication.getApplication().newThread(() ->{ |
|
||||||
File inputFile = FileUtils.getFile(APPCONST.FILE_DIR + "webBackup"); |
|
||||||
if (!inputFile.exists()) { |
|
||||||
rc.onFinish(false, 0); |
|
||||||
} |
|
||||||
File zipFile = FileUtils.getFile(APPCONST.FILE_DIR + "webBackup.zip"); |
|
||||||
FileInputStream fis = null; |
|
||||||
HttpURLConnection conn = null; |
|
||||||
try { |
|
||||||
//压缩文件
|
|
||||||
ZipUtils.zipFile(inputFile, zipFile); |
|
||||||
fis = new FileInputStream(zipFile); |
|
||||||
URL url = new URL(URLCONST.APP_WEB_URL + "bak?username=" + userInfo.get("userName") + |
|
||||||
makeSignalParam()); |
|
||||||
conn = (HttpURLConnection) url.openConnection(); |
|
||||||
conn.setRequestMethod("POST"); |
|
||||||
conn.setRequestProperty("Content-type", "multipart/form-data"); |
|
||||||
conn.setDoInput(true); |
|
||||||
conn.setDoOutput(true); |
|
||||||
OutputStream out = conn.getOutputStream(); |
|
||||||
byte[] bytes = new byte[1024]; |
|
||||||
int len = -1; |
|
||||||
while ((len = fis.read(bytes)) != -1){ |
|
||||||
out.write(bytes, 0, len); |
|
||||||
} |
|
||||||
out.flush(); |
|
||||||
zipFile.delete(); |
|
||||||
BufferedReader bw = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8")); |
|
||||||
StringBuilder sb = new StringBuilder(); |
|
||||||
String line = bw.readLine(); |
|
||||||
while (line != null) { |
|
||||||
sb.append(line); |
|
||||||
line = bw.readLine(); |
|
||||||
} |
|
||||||
String[] info = sb.toString().split(":"); |
|
||||||
int code = Integer.parseInt(info[0].trim()); |
|
||||||
rc.onFinish(code == 104, 0); |
|
||||||
} catch (Exception e) { |
|
||||||
e.printStackTrace(); |
|
||||||
rc.onError(e); |
|
||||||
} finally { |
|
||||||
IOUtils.close(fis); |
|
||||||
if (conn != null) { |
|
||||||
conn.disconnect(); |
|
||||||
} |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void backupError(@NonNull String msg) { |
|
||||||
ToastUtils.showError(msg); |
|
||||||
rc.onFinish(false, 0); |
|
||||||
} |
|
||||||
}, false); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 网络恢复 |
|
||||||
* @return |
|
||||||
*/ |
|
||||||
public static void webRestore(ResultCallback rc){ |
|
||||||
Map<String,String> userInfo = readConfig(); |
|
||||||
if (userInfo == null){ |
|
||||||
rc.onFinish(false, 0); |
|
||||||
} |
|
||||||
FileOutputStream fos = null; |
|
||||||
File zipFile = FileUtils.getFile(APPCONST.FILE_DIR + "webBackup.zip"); |
|
||||||
HttpURLConnection conn = null; |
|
||||||
try { |
|
||||||
URL url = new URL(URLCONST.APP_WEB_URL + "ret?username=" + userInfo.get("userName") + |
|
||||||
makeSignalParam()); |
|
||||||
conn = (HttpURLConnection) url.openConnection(); |
|
||||||
conn.setRequestMethod("POST"); |
|
||||||
conn.setDoInput(true); |
|
||||||
InputStream is = conn.getInputStream(); |
|
||||||
fos = new FileOutputStream(zipFile); |
|
||||||
//一边读,一边写
|
|
||||||
byte[] bytes = new byte[512]; |
|
||||||
int readCount = 0; |
|
||||||
while ((readCount = is.read(bytes)) != -1) { |
|
||||||
fos.write(bytes,0, readCount); |
|
||||||
} |
|
||||||
//刷新,输出流一定要刷新
|
|
||||||
fos.flush(); |
|
||||||
if (zipFile.length() == 0){ |
|
||||||
zipFile.delete(); |
|
||||||
rc.onFinish(false, 0); |
|
||||||
} |
|
||||||
ZipUtils.unzipFile(zipFile.getAbsolutePath(), APPCONST.FILE_DIR); |
|
||||||
Restore.INSTANCE.restore(APPCONST.FILE_DIR + "webBackup/", new Restore.CallBack() { |
|
||||||
@Override |
|
||||||
public void restoreSuccess() { |
|
||||||
zipFile.delete(); |
|
||||||
rc.onFinish(true, 0); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void restoreError(@NonNull String msg) { |
|
||||||
ToastUtils.showError(msg); |
|
||||||
rc.onFinish(false, 0); |
|
||||||
} |
|
||||||
}); |
|
||||||
} catch (Exception e) { |
|
||||||
e.printStackTrace(); |
|
||||||
rc.onError(e); |
|
||||||
}finally { |
|
||||||
IOUtils.close(fos); |
|
||||||
if (conn != null) { |
|
||||||
conn.disconnect(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
private static String makeSignalParam(){ |
|
||||||
return "&signal=" + AppInfoUtils.getSingInfo(MyApplication.getmContext(), |
|
||||||
MyApplication.getApplication().getPackageName(), AppInfoUtils.SHA1); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 判断是否登录 |
|
||||||
* @return |
|
||||||
*/ |
|
||||||
public static boolean isLogin(){ |
|
||||||
File file = MyApplication.getApplication().getFileStreamPath("userConfig.fy"); |
|
||||||
return file.exists(); |
|
||||||
} |
|
||||||
} |
|
@ -1,231 +0,0 @@ |
|||||||
package xyz.fycz.myreader.ui.activity; |
|
||||||
|
|
||||||
import android.annotation.SuppressLint; |
|
||||||
import android.app.Activity; |
|
||||||
import android.app.ProgressDialog; |
|
||||||
import android.content.Intent; |
|
||||||
import android.graphics.Bitmap; |
|
||||||
import android.os.Bundle; |
|
||||||
import android.os.Handler; |
|
||||||
import android.os.Message; |
|
||||||
import android.text.Editable; |
|
||||||
import android.text.TextWatcher; |
|
||||||
import android.view.MotionEvent; |
|
||||||
import android.view.View; |
|
||||||
import android.view.inputmethod.InputMethodManager; |
|
||||||
import android.widget.Button; |
|
||||||
import android.widget.ImageView; |
|
||||||
import android.widget.TextView; |
|
||||||
import androidx.appcompat.widget.Toolbar; |
|
||||||
import butterknife.BindView; |
|
||||||
import com.google.android.material.textfield.TextInputLayout; |
|
||||||
import xyz.fycz.myreader.R; |
|
||||||
import xyz.fycz.myreader.model.backup.UserService; |
|
||||||
import xyz.fycz.myreader.base.BaseActivity2; |
|
||||||
import xyz.fycz.myreader.webapi.callback.ResultCallback; |
|
||||||
import xyz.fycz.myreader.common.APPCONST; |
|
||||||
import xyz.fycz.myreader.ui.dialog.DialogCreator; |
|
||||||
import xyz.fycz.myreader.util.CodeUtil; |
|
||||||
import xyz.fycz.myreader.util.CyptoUtils; |
|
||||||
import xyz.fycz.myreader.util.ToastUtils; |
|
||||||
import xyz.fycz.myreader.util.utils.NetworkUtils; |
|
||||||
import xyz.fycz.myreader.util.utils.StringUtils; |
|
||||||
|
|
||||||
import java.util.HashMap; |
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
/** |
|
||||||
* @author fengyue |
|
||||||
* @date 2020/9/18 22:27 |
|
||||||
*/ |
|
||||||
public class LoginActivity extends BaseActivity2 implements TextWatcher { |
|
||||||
@BindView(R.id.et_user) |
|
||||||
TextInputLayout user; |
|
||||||
@BindView(R.id.et_password) |
|
||||||
TextInputLayout password; |
|
||||||
@BindView(R.id.bt_login) |
|
||||||
Button loginBtn; |
|
||||||
@BindView(R.id.tv_register) |
|
||||||
TextView tvRegister; |
|
||||||
@BindView(R.id.et_captcha) |
|
||||||
TextInputLayout etCaptcha; |
|
||||||
@BindView(R.id.iv_captcha) |
|
||||||
ImageView ivCaptcha; |
|
||||||
|
|
||||||
private String code; |
|
||||||
|
|
||||||
@SuppressLint("HandlerLeak") |
|
||||||
private Handler mHandler = new Handler() { |
|
||||||
@SuppressLint("HandlerLeak") |
|
||||||
@Override |
|
||||||
public void handleMessage(Message msg) { |
|
||||||
switch (msg.what) { |
|
||||||
case 1: |
|
||||||
loginBtn.setEnabled(true); |
|
||||||
break; |
|
||||||
case 2: |
|
||||||
createCaptcha(); |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
@Override |
|
||||||
protected int getContentId() { |
|
||||||
return R.layout.activity_login; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
protected void setUpToolbar(Toolbar toolbar) { |
|
||||||
super.setUpToolbar(toolbar); |
|
||||||
setStatusBarColor(R.color.colorPrimary, true); |
|
||||||
getSupportActionBar().setTitle("登录"); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
protected void initData(Bundle savedInstanceState) { |
|
||||||
super.initData(savedInstanceState); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
protected void initWidget() { |
|
||||||
super.initWidget(); |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(2)); |
|
||||||
String username = UserService.readUsername(); |
|
||||||
user.getEditText().setText(username); |
|
||||||
user.getEditText().requestFocus(username.length()); |
|
||||||
//监听内容改变 -> 控制按钮的点击状态
|
|
||||||
user.getEditText().addTextChangedListener(this); |
|
||||||
password.getEditText().addTextChangedListener(this); |
|
||||||
etCaptcha.getEditText().addTextChangedListener(this); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
protected void initClick() { |
|
||||||
super.initClick(); |
|
||||||
ivCaptcha.setOnClickListener(v -> mHandler.sendMessage(mHandler.obtainMessage(2))); |
|
||||||
|
|
||||||
loginBtn.setOnClickListener(v -> { |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(2)); |
|
||||||
if (!code.toLowerCase().equals(etCaptcha.getEditText().getText().toString().toLowerCase())){ |
|
||||||
DialogCreator.createTipDialog(this, "验证码错误!"); |
|
||||||
return; |
|
||||||
} |
|
||||||
if (!NetworkUtils.isNetWorkAvailable()) { |
|
||||||
ToastUtils.showError("无网络连接!"); |
|
||||||
return; |
|
||||||
} |
|
||||||
ProgressDialog dialog = DialogCreator.createProgressDialog(this, null, "正在登陆..."); |
|
||||||
loginBtn.setEnabled(false); |
|
||||||
final String loginName = user.getEditText().getText().toString().trim(); |
|
||||||
String loginPwd = password.getEditText().getText().toString(); |
|
||||||
final Map<String, String> userLoginInfo = new HashMap<>(); |
|
||||||
userLoginInfo.put("loginName", loginName); |
|
||||||
userLoginInfo.put("loginPwd", CyptoUtils.encode(APPCONST.KEY, loginPwd)); |
|
||||||
//验证用户名和密码
|
|
||||||
UserService.login(userLoginInfo, new ResultCallback() { |
|
||||||
@Override |
|
||||||
public void onFinish(Object o, int code) { |
|
||||||
String result = (String) o; |
|
||||||
String[] info = result.split(":"); |
|
||||||
int resultCode = Integer.parseInt(info[0].trim()); |
|
||||||
String resultName = info[1].trim(); |
|
||||||
//最后输出结果
|
|
||||||
if (resultCode == 102) { |
|
||||||
UserService.writeConfig(userLoginInfo); |
|
||||||
UserService.writeUsername(loginName); |
|
||||||
Intent intent = new Intent(); |
|
||||||
intent.putExtra("isLogin", true); |
|
||||||
setResult(Activity.RESULT_OK, intent); |
|
||||||
finish(); |
|
||||||
ToastUtils.showSuccess(resultName); |
|
||||||
} else { |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(1)); |
|
||||||
dialog.dismiss(); |
|
||||||
ToastUtils.showWarring(resultName); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onError(Exception e) { |
|
||||||
ToastUtils.showError("登录失败\n" + e.getLocalizedMessage()); |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(1)); |
|
||||||
dialog.dismiss(); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
}); |
|
||||||
|
|
||||||
tvRegister.setOnClickListener(v -> { |
|
||||||
Intent intent = new Intent(LoginActivity.this, RegisterActivity.class); |
|
||||||
startActivity(intent); |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
public void createCaptcha() { |
|
||||||
code = CodeUtil.getInstance().createCode(); |
|
||||||
Bitmap codeBitmap = CodeUtil.getInstance().createBitmap(code); |
|
||||||
ivCaptcha.setImageBitmap(codeBitmap); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* 当有控件获得焦点focus 自动弹出键盘 |
|
||||||
* 1. 点击软键盘的enter键 自动收回键盘 |
|
||||||
* 2. 代码控制 InputMethodManager |
|
||||||
* requestFocus |
|
||||||
* showSoftInput:显示键盘 必须先让这个view成为焦点requestFocus |
|
||||||
* |
|
||||||
* hideSoftInputFromWindow 隐藏键盘 |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
public boolean onTouchEvent(MotionEvent event) { |
|
||||||
if (event.getAction() == MotionEvent.ACTION_DOWN){ |
|
||||||
//隐藏键盘
|
|
||||||
//1.获取系统输入的管理器
|
|
||||||
InputMethodManager inputManager = |
|
||||||
(InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); |
|
||||||
|
|
||||||
//2.隐藏键盘
|
|
||||||
inputManager.hideSoftInputFromWindow(user.getWindowToken(),0); |
|
||||||
|
|
||||||
//3.取消焦点
|
|
||||||
View focusView = getCurrentFocus(); |
|
||||||
if (focusView != null) { |
|
||||||
focusView.clearFocus(); //取消焦点
|
|
||||||
} |
|
||||||
|
|
||||||
//getCurrentFocus().clearFocus();
|
|
||||||
|
|
||||||
//focusView.requestFocus();//请求焦点
|
|
||||||
} |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onTextChanged(CharSequence s, int start, int before, int count) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void afterTextChanged(Editable s) { |
|
||||||
//禁止输入中文
|
|
||||||
StringUtils.isNotChinese(s); |
|
||||||
//判断两个输入框是否有内容
|
|
||||||
if (user.getEditText().getText().toString().length() > 0 && |
|
||||||
password.getEditText().getText().toString().length() > 0 && |
|
||||||
etCaptcha.getEditText().getText().toString().length() > 0){ |
|
||||||
//按钮可以点击
|
|
||||||
loginBtn.setEnabled(true); |
|
||||||
}else{ |
|
||||||
//按钮不能点击
|
|
||||||
loginBtn.setEnabled(false); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,271 +0,0 @@ |
|||||||
package xyz.fycz.myreader.ui.activity; |
|
||||||
|
|
||||||
import android.annotation.SuppressLint; |
|
||||||
import android.app.ProgressDialog; |
|
||||||
import android.graphics.Bitmap; |
|
||||||
import android.os.Handler; |
|
||||||
import android.os.Message; |
|
||||||
import android.text.Editable; |
|
||||||
import android.text.TextWatcher; |
|
||||||
import android.text.method.LinkMovementMethod; |
|
||||||
import android.view.View; |
|
||||||
import android.widget.Button; |
|
||||||
import android.widget.CheckBox; |
|
||||||
import android.widget.ImageView; |
|
||||||
import android.widget.TextView; |
|
||||||
import androidx.appcompat.widget.Toolbar; |
|
||||||
import butterknife.BindView; |
|
||||||
import com.google.android.material.textfield.TextInputLayout; |
|
||||||
import xyz.fycz.myreader.R; |
|
||||||
import xyz.fycz.myreader.model.backup.UserService; |
|
||||||
import xyz.fycz.myreader.base.BaseActivity2; |
|
||||||
import xyz.fycz.myreader.webapi.callback.ResultCallback; |
|
||||||
import xyz.fycz.myreader.ui.dialog.DialogCreator; |
|
||||||
import xyz.fycz.myreader.util.CodeUtil; |
|
||||||
import xyz.fycz.myreader.util.ToastUtils; |
|
||||||
import xyz.fycz.myreader.util.utils.StringUtils; |
|
||||||
|
|
||||||
import java.util.HashMap; |
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
/** |
|
||||||
* @author fengyue |
|
||||||
* @date 2020/9/18 22:37 |
|
||||||
*/ |
|
||||||
public class RegisterActivity extends BaseActivity2 { |
|
||||||
@BindView(R.id.et_username) |
|
||||||
TextInputLayout etUsername; |
|
||||||
@BindView(R.id.et_password) |
|
||||||
TextInputLayout etPassword; |
|
||||||
@BindView(R.id.et_rp_password) |
|
||||||
TextInputLayout etRpPassword; |
|
||||||
@BindView(R.id.et_captcha) |
|
||||||
TextInputLayout etCaptcha; |
|
||||||
@BindView(R.id.iv_captcha) |
|
||||||
ImageView ivCaptcha; |
|
||||||
@BindView(R.id.bt_register) |
|
||||||
Button btRegister; |
|
||||||
@BindView(R.id.tv_register_tip) |
|
||||||
TextView tvRegisterTip; |
|
||||||
@BindView(R.id.cb_agreement) |
|
||||||
CheckBox cbAgreement; |
|
||||||
@BindView(R.id.tv_agreement) |
|
||||||
TextView tvAgreement; |
|
||||||
private String code; |
|
||||||
private String username = ""; |
|
||||||
private String password = ""; |
|
||||||
private String rpPassword = ""; |
|
||||||
private String inputCode = ""; |
|
||||||
|
|
||||||
@SuppressLint("HandlerLeak") |
|
||||||
private Handler mHandler = new Handler() { |
|
||||||
@SuppressLint("HandlerLeak") |
|
||||||
@Override |
|
||||||
public void handleMessage(Message msg) { |
|
||||||
switch (msg.what) { |
|
||||||
case 1: |
|
||||||
createCaptcha(); |
|
||||||
break; |
|
||||||
case 2: |
|
||||||
showTip((String) msg.obj); |
|
||||||
break; |
|
||||||
case 3: |
|
||||||
tvRegisterTip.setVisibility(View.GONE); |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
protected int getContentId() { |
|
||||||
return R.layout.activity_register; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
protected void setUpToolbar(Toolbar toolbar) { |
|
||||||
super.setUpToolbar(toolbar); |
|
||||||
setStatusBarColor(R.color.colorPrimary, true); |
|
||||||
getSupportActionBar().setTitle("注册"); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
protected void initWidget() { |
|
||||||
super.initWidget(); |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(1)); |
|
||||||
etUsername.requestFocus(); |
|
||||||
etUsername.getEditText().addTextChangedListener(new TextWatcher() { |
|
||||||
@Override |
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onTextChanged(CharSequence s, int start, int before, int count) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void afterTextChanged(Editable s) { |
|
||||||
StringUtils.isNotChinese(s); |
|
||||||
username = s.toString(); |
|
||||||
if (username.length() < 6 || username.length() >14){ |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(2, "用户名必须在6-14位之间")); |
|
||||||
} else if(!username.substring(0, 1).matches("^[A-Za-z]$")){ |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(2, |
|
||||||
"用户名只能以字母开头")); |
|
||||||
}else if(!username.matches("^[A-Za-z0-9-_]+$")){ |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(2, |
|
||||||
"用户名只能由数字、字母、下划线、减号组成")); |
|
||||||
}else { |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(3)); |
|
||||||
} |
|
||||||
checkNotNone(); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
etPassword.getEditText().addTextChangedListener(new TextWatcher() { |
|
||||||
@Override |
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onTextChanged(CharSequence s, int start, int before, int count) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void afterTextChanged(Editable s) { |
|
||||||
password = s.toString(); |
|
||||||
if (password.length() < 8 || password.length() > 16){ |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(2, "密码必须在8-16位之间")); |
|
||||||
} else if(password.matches("^\\d+$")){ |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(2, "密码不能是纯数字")); |
|
||||||
} else { |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(3)); |
|
||||||
} |
|
||||||
checkNotNone(); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
etRpPassword.getEditText().addTextChangedListener(new TextWatcher() { |
|
||||||
@Override |
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onTextChanged(CharSequence s, int start, int before, int count) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void afterTextChanged(Editable s) { |
|
||||||
rpPassword = s.toString(); |
|
||||||
if (!rpPassword.equals(password)){ |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(2, "两次输入的密码不一致")); |
|
||||||
} else { |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(3)); |
|
||||||
} |
|
||||||
checkNotNone(); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
etCaptcha.getEditText().addTextChangedListener(new TextWatcher() { |
|
||||||
@Override |
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onTextChanged(CharSequence s, int start, int before, int count) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void afterTextChanged(Editable s) { |
|
||||||
inputCode = s.toString().trim().toLowerCase(); |
|
||||||
if (!inputCode.equals(code.toLowerCase())){ |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(2, "验证码错误")); |
|
||||||
} else { |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(3)); |
|
||||||
} |
|
||||||
checkNotNone(); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
tvAgreement.setMovementMethod(LinkMovementMethod.getInstance()); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
protected void initClick() { |
|
||||||
super.initClick(); |
|
||||||
ivCaptcha.setOnClickListener(v -> mHandler.sendMessage(mHandler.obtainMessage(1))); |
|
||||||
|
|
||||||
btRegister.setOnClickListener(v -> { |
|
||||||
if (!username.matches("^[A-Za-z][A-Za-z0-9]{5,13}$")){ |
|
||||||
DialogCreator.createTipDialog(this, "用户名格式错误", |
|
||||||
"用户名必须在6-14位之间\n用户名只能以字母开头\n用户名只能由数字、字母、下划线、减号组成"); |
|
||||||
}else if(password.matches("^\\d+$") || !password.matches("^.{8,16}$")){ |
|
||||||
DialogCreator.createTipDialog(this, "密码格式错误", |
|
||||||
"密码必须在8-16位之间\n密码不能是纯数字"); |
|
||||||
}else if(!password.equals(rpPassword)){ |
|
||||||
DialogCreator.createTipDialog(this, "重复密码错误", |
|
||||||
"两次输入的密码不一致"); |
|
||||||
}else if(!inputCode.trim().toLowerCase().equals(code.toLowerCase())){ |
|
||||||
DialogCreator.createTipDialog(this, "验证码错误"); |
|
||||||
}else if(!cbAgreement.isChecked()){ |
|
||||||
DialogCreator.createTipDialog(this, "请勾选同意《用户服务协议》"); |
|
||||||
}else { |
|
||||||
ProgressDialog dialog = DialogCreator.createProgressDialog(this, null, "正在注册..."); |
|
||||||
Map<String, String> userRegisterInfo = new HashMap<>(); |
|
||||||
userRegisterInfo.put("username", username); |
|
||||||
userRegisterInfo.put("password", password); |
|
||||||
UserService.register(userRegisterInfo, new ResultCallback() { |
|
||||||
@Override |
|
||||||
public void onFinish(Object o, int code) { |
|
||||||
String[] info = ((String) o).split(":"); |
|
||||||
int result = Integer.parseInt(info[0].trim()); |
|
||||||
if (result == 101){ |
|
||||||
UserService.writeUsername(username); |
|
||||||
ToastUtils.showSuccess(info[1]); |
|
||||||
finish(); |
|
||||||
}else { |
|
||||||
ToastUtils.showWarring(info[1]); |
|
||||||
} |
|
||||||
dialog.dismiss(); |
|
||||||
} |
|
||||||
@Override |
|
||||||
public void onError(Exception e) { |
|
||||||
ToastUtils.showError("注册失败:\n" + e.getLocalizedMessage()); |
|
||||||
dialog.dismiss(); |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(1)); |
|
||||||
}); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
public void createCaptcha() { |
|
||||||
code = CodeUtil.getInstance().createCode(); |
|
||||||
Bitmap codeBitmap = CodeUtil.getInstance().createBitmap(code); |
|
||||||
ivCaptcha.setImageBitmap(codeBitmap); |
|
||||||
} |
|
||||||
|
|
||||||
public void showTip(String tip) { |
|
||||||
tvRegisterTip.setVisibility(View.VISIBLE); |
|
||||||
tvRegisterTip.setText(tip); |
|
||||||
} |
|
||||||
|
|
||||||
public void checkNotNone(){ |
|
||||||
if ("".equals(username) || "".equals(password) || "".equals(rpPassword) || "".equals(inputCode)){ |
|
||||||
btRegister.setEnabled(false); |
|
||||||
}else { |
|
||||||
btRegister.setEnabled(true); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -0,0 +1,62 @@ |
|||||||
|
package xyz.fycz.myreader.ui.dialog; |
||||||
|
|
||||||
|
import android.app.Dialog; |
||||||
|
import android.content.Context; |
||||||
|
import android.os.Bundle; |
||||||
|
import android.view.Gravity; |
||||||
|
import android.view.Window; |
||||||
|
import android.view.WindowManager; |
||||||
|
import android.widget.TextView; |
||||||
|
import androidx.annotation.NonNull; |
||||||
|
import butterknife.BindView; |
||||||
|
import butterknife.ButterKnife; |
||||||
|
import xyz.fycz.myreader.R; |
||||||
|
|
||||||
|
/** |
||||||
|
* Created by Zhouas666 on 2019-04-14 |
||||||
|
* Github: https://github.com/zas023
|
||||||
|
* <p> |
||||||
|
* 自由复制dialog |
||||||
|
*/ |
||||||
|
|
||||||
|
public class CopyContentDialog extends Dialog { |
||||||
|
|
||||||
|
private static final String TAG = "CopyContentDialog"; |
||||||
|
|
||||||
|
@BindView(R.id.dialog_tv_content) |
||||||
|
TextView dialogTvContent; |
||||||
|
|
||||||
|
private String content; |
||||||
|
|
||||||
|
/***************************************************************************/ |
||||||
|
|
||||||
|
public CopyContentDialog(@NonNull Context context, String content) { |
||||||
|
super(context); |
||||||
|
this.content = content; |
||||||
|
} |
||||||
|
|
||||||
|
/*****************************Initialization********************************/ |
||||||
|
@Override |
||||||
|
protected void onCreate(Bundle savedInstanceState) { |
||||||
|
super.onCreate(savedInstanceState); |
||||||
|
setContentView(R.layout.dialog_copy_content); |
||||||
|
ButterKnife.bind(this); |
||||||
|
|
||||||
|
setUpWindow(); |
||||||
|
|
||||||
|
dialogTvContent.setText(content); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 设置Dialog显示的位置 |
||||||
|
*/ |
||||||
|
private void setUpWindow() { |
||||||
|
Window window = getWindow(); |
||||||
|
WindowManager.LayoutParams lp = window.getAttributes(); |
||||||
|
lp.width = WindowManager.LayoutParams.MATCH_PARENT; |
||||||
|
lp.height = WindowManager.LayoutParams.WRAP_CONTENT; |
||||||
|
lp.gravity = Gravity.CENTER; |
||||||
|
window.setAttributes(lp); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -1,72 +0,0 @@ |
|||||||
package xyz.fycz.myreader.util; |
|
||||||
|
|
||||||
import android.app.AlarmManager; |
|
||||||
import android.app.PendingIntent; |
|
||||||
import android.content.Context; |
|
||||||
import android.content.Intent; |
|
||||||
import android.os.Build; |
|
||||||
|
|
||||||
import xyz.fycz.myreader.common.APPCONST; |
|
||||||
|
|
||||||
import java.util.Date; |
|
||||||
|
|
||||||
import static android.content.Context.ALARM_SERVICE; |
|
||||||
import static android.content.Intent.FLAG_INCLUDE_STOPPED_PACKAGES; |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public class AlarmHelper { |
|
||||||
|
|
||||||
private static String alarmActicon = "xyz.fycz.kl.gxdw"; |
|
||||||
private static String AntiHijackingActicon = "xyz.fycz.kl.gxdw.AntiHijacking"; |
|
||||||
|
|
||||||
public static void addOneShotAlarm(Context context, long time, String msg, int id){ |
|
||||||
Date date = new Date(); |
|
||||||
if(time <= date.getTime()){ |
|
||||||
return; |
|
||||||
} |
|
||||||
Intent intent = new Intent(alarmActicon); |
|
||||||
intent.putExtra(APPCONST.ALARM_SCHEDULE_MSG,msg); |
|
||||||
intent.setFlags(FLAG_INCLUDE_STOPPED_PACKAGES); |
|
||||||
PendingIntent pi = PendingIntent.getBroadcast(context, id, intent, PendingIntent.FLAG_CANCEL_CURRENT); |
|
||||||
AlarmManager alarmManager = (AlarmManager)context.getSystemService(ALARM_SERVICE); |
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { |
|
||||||
alarmManager.setExact(AlarmManager.RTC_WAKEUP,time,pi); |
|
||||||
}else { |
|
||||||
alarmManager.set(AlarmManager.RTC_WAKEUP,time,pi); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public static void removeOneShotAlarm(Context context, int id){ |
|
||||||
Intent intent = new Intent(alarmActicon); |
|
||||||
intent.setFlags(FLAG_INCLUDE_STOPPED_PACKAGES); |
|
||||||
PendingIntent pi = PendingIntent.getBroadcast(context, id, intent, PendingIntent.FLAG_CANCEL_CURRENT); |
|
||||||
AlarmManager alarmManager = (AlarmManager)context.getSystemService(ALARM_SERVICE); |
|
||||||
alarmManager.cancel(pi); |
|
||||||
} |
|
||||||
|
|
||||||
public static void addAlarm(Context context, long time, int id){ |
|
||||||
// Date date = new Date();
|
|
||||||
/* if(time <= date.getTime()){ |
|
||||||
return; |
|
||||||
}*/ |
|
||||||
Intent intent = new Intent(AntiHijackingActicon); |
|
||||||
|
|
||||||
intent.setFlags(FLAG_INCLUDE_STOPPED_PACKAGES); |
|
||||||
PendingIntent pi = PendingIntent.getBroadcast(context, id, intent, PendingIntent.FLAG_CANCEL_CURRENT); |
|
||||||
AlarmManager alarmManager = (AlarmManager)context.getSystemService(ALARM_SERVICE); |
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { |
|
||||||
alarmManager.setExact(AlarmManager.RTC_WAKEUP,new Date().getTime() + time,pi); |
|
||||||
}else { |
|
||||||
alarmManager.set(AlarmManager.RTC_WAKEUP,new Date().getTime() + time,pi); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public static void removeAlarm(Context context, int id){ |
|
||||||
Intent intent = new Intent(AntiHijackingActicon); |
|
||||||
intent.setFlags(FLAG_INCLUDE_STOPPED_PACKAGES); |
|
||||||
PendingIntent pi = PendingIntent.getBroadcast(context, id, intent, PendingIntent.FLAG_CANCEL_CURRENT); |
|
||||||
AlarmManager alarmManager = (AlarmManager)context.getSystemService(ALARM_SERVICE); |
|
||||||
alarmManager.cancel(pi); |
|
||||||
} |
|
||||||
} |
|
@ -1,125 +0,0 @@ |
|||||||
package xyz.fycz.myreader.util; |
|
||||||
|
|
||||||
import android.widget.Toast; |
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity; |
|
||||||
|
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.List; |
|
||||||
import java.util.Timer; |
|
||||||
import java.util.TimerTask; |
|
||||||
|
|
||||||
import xyz.fycz.myreader.R; |
|
||||||
|
|
||||||
/** |
|
||||||
* 防界面劫持提示 |
|
||||||
*/ |
|
||||||
public class Anti_hijackingUtils { |
|
||||||
|
|
||||||
// private int id = 12345678;//记录定时ID
|
|
||||||
|
|
||||||
private static boolean home; |
|
||||||
private static boolean back; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* 用于执行定时任务 |
|
||||||
*/ |
|
||||||
private Timer timer = null; |
|
||||||
|
|
||||||
/** |
|
||||||
* 用于保存当前任务 |
|
||||||
*/ |
|
||||||
private List<MyTimerTask> tasks = null; |
|
||||||
|
|
||||||
/** |
|
||||||
* 唯一实例 |
|
||||||
*/ |
|
||||||
private static Anti_hijackingUtils anti_hijackingUtils; |
|
||||||
|
|
||||||
private Anti_hijackingUtils() { |
|
||||||
// 初始化
|
|
||||||
tasks = new ArrayList<MyTimerTask>(); |
|
||||||
timer = new Timer(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 获取唯一实例 |
|
||||||
* |
|
||||||
* @return 唯一实例 |
|
||||||
*/ |
|
||||||
public static Anti_hijackingUtils getinstance() { |
|
||||||
if (anti_hijackingUtils == null) { |
|
||||||
anti_hijackingUtils = new Anti_hijackingUtils(); |
|
||||||
} |
|
||||||
return anti_hijackingUtils; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 在activity的onPause()方法中调用 |
|
||||||
* |
|
||||||
* @param activity |
|
||||||
*/ |
|
||||||
public void onPause(final AppCompatActivity activity) { |
|
||||||
MyTimerTask task = new MyTimerTask(activity); |
|
||||||
tasks.add(task); |
|
||||||
timer.schedule(task, 2000); |
|
||||||
// AlarmHelper.addAlarm(activity,2000,id);
|
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 在activity的onResume()方法中调用 |
|
||||||
*/ |
|
||||||
public void onResume(final AppCompatActivity activity) { |
|
||||||
if (tasks.size() > 0) { |
|
||||||
tasks.get(tasks.size() - 1).setCanRun(false); |
|
||||||
tasks.remove(tasks.size() - 1); |
|
||||||
} |
|
||||||
// AlarmHelper.removeAlarm(activity,id);
|
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 自定义TimerTask类 |
|
||||||
*/ |
|
||||||
class MyTimerTask extends TimerTask { |
|
||||||
/** |
|
||||||
* 任务是否有效 |
|
||||||
*/ |
|
||||||
private boolean canRun = true; |
|
||||||
private AppCompatActivity activity; |
|
||||||
|
|
||||||
private void setCanRun(boolean canRun) { |
|
||||||
this.canRun = canRun; |
|
||||||
} |
|
||||||
|
|
||||||
public MyTimerTask(AppCompatActivity activity) { |
|
||||||
this.activity = activity; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void run() { |
|
||||||
activity.runOnUiThread(new Runnable() { |
|
||||||
@Override |
|
||||||
public void run() { |
|
||||||
if (canRun) { |
|
||||||
// 程序退到后台,进行风险警告
|
|
||||||
if (home || back){ |
|
||||||
Toast.makeText(activity, activity.getString(R.string.anti_hijacking_tips_home), Toast.LENGTH_LONG).show(); |
|
||||||
|
|
||||||
tasks.remove(MyTimerTask.this); |
|
||||||
home = false; |
|
||||||
}else { |
|
||||||
Toast.makeText(activity, activity.getString(R.string.anti_hijacking_tips), Toast.LENGTH_LONG).show(); |
|
||||||
// TextHelper.showLongText(MyApplication.getApplication().getString(R.string.anti_hijacking_tips));
|
|
||||||
tasks.remove(MyTimerTask.this); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
} |
|
||||||
|
|
@ -1,125 +0,0 @@ |
|||||||
package xyz.fycz.myreader.util; |
|
||||||
import java.lang.reflect.Method; |
|
||||||
import java.util.Arrays; |
|
||||||
import java.util.Collection; |
|
||||||
import java.util.List; |
|
||||||
|
|
||||||
/** |
|
||||||
* Created by Kodulf |
|
||||||
*/ |
|
||||||
public class BeanPropertiesUtil { |
|
||||||
/** |
|
||||||
* 利用反射实现对象之间属性复制 |
|
||||||
* @param from |
|
||||||
* @param to |
|
||||||
*/ |
|
||||||
public static void copyProperties(Object from, Object to) throws Exception { |
|
||||||
copyPropertiesExclude(from, to, null); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 复制对象属性 |
|
||||||
* @param from |
|
||||||
* @param to |
|
||||||
* @param excludsArray 排除属性列表 |
|
||||||
* @throws Exception |
|
||||||
*/ |
|
||||||
@SuppressWarnings("unchecked") |
|
||||||
public static void copyPropertiesExclude(Object from, Object to, String[] excludsArray) throws Exception { |
|
||||||
List<String> excludesList = null; |
|
||||||
if(excludsArray != null && excludsArray.length > 0) { |
|
||||||
excludesList = Arrays.asList(excludsArray); //构造列表对象
|
|
||||||
} |
|
||||||
Method[] fromMethods = from.getClass().getDeclaredMethods(); |
|
||||||
Method[] toMethods = to.getClass().getDeclaredMethods(); |
|
||||||
Method fromMethod = null, toMethod = null; |
|
||||||
String fromMethodName = null, toMethodName = null; |
|
||||||
for (int i = 0; i < fromMethods.length; i++) { |
|
||||||
fromMethod = fromMethods[i]; |
|
||||||
fromMethodName = fromMethod.getName(); |
|
||||||
if (!fromMethodName.contains("get") || fromMethodName.contains("getId")) |
|
||||||
continue; |
|
||||||
//排除列表检测
|
|
||||||
if(excludesList != null && excludesList.contains(fromMethodName.substring(3).toLowerCase())) { |
|
||||||
continue; |
|
||||||
} |
|
||||||
toMethodName = "set" + fromMethodName.substring(3); |
|
||||||
toMethod = findMethodByName(toMethods, toMethodName); |
|
||||||
if (toMethod == null) |
|
||||||
continue; |
|
||||||
Object value = fromMethod.invoke(from); |
|
||||||
if(value == null) |
|
||||||
continue; |
|
||||||
//集合类判空处理
|
|
||||||
if(value instanceof Collection) { |
|
||||||
Collection newValue = (Collection)value; |
|
||||||
if(newValue.size() <= 0) |
|
||||||
continue; |
|
||||||
} |
|
||||||
toMethod.invoke(to, value); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 对象属性值复制,仅复制指定名称的属性值 |
|
||||||
* @param from |
|
||||||
* @param to |
|
||||||
* @param includsArray |
|
||||||
* @throws Exception |
|
||||||
*/ |
|
||||||
@SuppressWarnings("unchecked") |
|
||||||
public static void copyPropertiesInclude(Object from, Object to, String[] includsArray) throws Exception { |
|
||||||
List<String> includesList = null; |
|
||||||
if(includsArray != null && includsArray.length > 0) { |
|
||||||
includesList = Arrays.asList(includsArray); //构造列表对象
|
|
||||||
} else { |
|
||||||
return; |
|
||||||
} |
|
||||||
Method[] fromMethods = from.getClass().getDeclaredMethods(); |
|
||||||
Method[] toMethods = to.getClass().getDeclaredMethods(); |
|
||||||
Method fromMethod = null, toMethod = null; |
|
||||||
String fromMethodName = null, toMethodName = null; |
|
||||||
for (int i = 0; i < fromMethods.length; i++) { |
|
||||||
fromMethod = fromMethods[i]; |
|
||||||
fromMethodName = fromMethod.getName(); |
|
||||||
if (!fromMethodName.contains("get")) |
|
||||||
continue; |
|
||||||
//排除列表检测
|
|
||||||
String str = fromMethodName.substring(3); |
|
||||||
if(!includesList.contains(str.substring(0,1).toLowerCase() + str.substring(1))) { |
|
||||||
continue; |
|
||||||
} |
|
||||||
toMethodName = "set" + fromMethodName.substring(3); |
|
||||||
toMethod = findMethodByName(toMethods, toMethodName); |
|
||||||
if (toMethod == null) |
|
||||||
continue; |
|
||||||
Object value = fromMethod.invoke(from); |
|
||||||
if(value == null) |
|
||||||
continue; |
|
||||||
//集合类判空处理
|
|
||||||
if(value instanceof Collection) { |
|
||||||
Collection newValue = (Collection)value; |
|
||||||
if(newValue.size() <= 0) |
|
||||||
continue; |
|
||||||
} |
|
||||||
toMethod.invoke(to, value); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* 从方法数组中获取指定名称的方法 |
|
||||||
* |
|
||||||
* @param methods |
|
||||||
* @param name |
|
||||||
* @return |
|
||||||
*/ |
|
||||||
public static Method findMethodByName(Method[] methods, String name) { |
|
||||||
for (int j = 0; j < methods.length; j++) { |
|
||||||
if (methods[j].getName().equals(name)) |
|
||||||
return methods[j]; |
|
||||||
} |
|
||||||
return null; |
|
||||||
} |
|
||||||
} |
|
@ -1,431 +0,0 @@ |
|||||||
package xyz.fycz.myreader.util; |
|
||||||
|
|
||||||
import android.Manifest; |
|
||||||
import android.app.DownloadManager; |
|
||||||
import android.content.BroadcastReceiver; |
|
||||||
import android.content.Context; |
|
||||||
import android.content.DialogInterface; |
|
||||||
import android.content.Intent; |
|
||||||
import android.content.IntentFilter; |
|
||||||
import android.content.pm.PackageManager; |
|
||||||
import android.net.Uri; |
|
||||||
import android.os.Build; |
|
||||||
import android.os.Environment; |
|
||||||
import android.util.Log; |
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity; |
|
||||||
import androidx.core.app.ActivityCompat; |
|
||||||
import androidx.core.content.ContextCompat; |
|
||||||
|
|
||||||
import java.util.HashMap; |
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
import xyz.fycz.myreader.common.APPCONST; |
|
||||||
import xyz.fycz.myreader.ui.dialog.DialogCreator; |
|
||||||
|
|
||||||
import static android.app.DownloadManager.Request.VISIBILITY_HIDDEN; |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public class DownloadMangerUtils { |
|
||||||
|
|
||||||
public static final String FILE_DIR = "gxdw"; |
|
||||||
private static Map<Long, BroadcastReceiver> mBroadcastReceiverMap = new HashMap<>(); |
|
||||||
|
|
||||||
/** |
|
||||||
* 文件下载 |
|
||||||
* |
|
||||||
* @param context |
|
||||||
* @param fileDir |
|
||||||
* @param url |
|
||||||
* @param fileName |
|
||||||
*/ |
|
||||||
public static void downloadFile(Context context, String fileDir, String url, String fileName) { |
|
||||||
|
|
||||||
try { |
|
||||||
Log.d("http download:", url); |
|
||||||
//String Url = "10.10.123.16:8080/gxqdw_ubap/mEmailController.thumb?getAttachmentStream&fileId=1&fileName=自我探索——我是谁.ppt&emailId=36&token=d1828248-cc71-4719-8218-adc31ffc9cca&type=inbox&fileSize=14696446";
|
|
||||||
|
|
||||||
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)); |
|
||||||
// DownloadManager.Request.setDestinationInExternalPublicDir();
|
|
||||||
|
|
||||||
request.setDescription(fileName); |
|
||||||
request.setTitle("附件"); |
|
||||||
// in order for this if to run, you must use the android 3.2 to compile your app
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { |
|
||||||
request.allowScanningByMediaScanner(); |
|
||||||
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); |
|
||||||
// request.setNotificationVisibility(VISIBILITY_HIDDEN);
|
|
||||||
} |
|
||||||
// int i = Build.VERSION.SDK_INT;
|
|
||||||
if (Build.VERSION.SDK_INT > 17) { |
|
||||||
request.setDestinationInExternalPublicDir(fileDir, fileName); |
|
||||||
} else { |
|
||||||
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { |
|
||||||
request.setDestinationInExternalPublicDir(fileDir, fileName); |
|
||||||
} else { |
|
||||||
Log.d("download", "android版本过低,不存在外部存储,下载路径无法指定,默认路径:/data/data/com.android.providers.downloads/cache/"); |
|
||||||
DialogCreator.createCommonDialog(context, "文件下载", "android版本过低或系统兼容性问题,不存在外部存储,无法指定下载路径,文件下载到系统默认路径,请到文件管理搜索文件名", true, |
|
||||||
"关闭", new DialogInterface.OnClickListener() { |
|
||||||
@Override |
|
||||||
public void onClick(DialogInterface dialog, int which) { |
|
||||||
dialog.dismiss(); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
// get download service and enqueue file
|
|
||||||
DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); |
|
||||||
manager.enqueue(request); |
|
||||||
} catch (Exception e) { |
|
||||||
e.printStackTrace(); |
|
||||||
lowVersionNoSDDownload(context, url, fileName); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 低版本无外置存储下载 |
|
||||||
* |
|
||||||
* @param context |
|
||||||
* @param url |
|
||||||
* @param fileName |
|
||||||
*/ |
|
||||||
private static void lowVersionNoSDDownload(Context context, String url, String fileName) { |
|
||||||
try { |
|
||||||
Log.d("http download:", url); |
|
||||||
//String Url = "10.10.123.16:8080/gxqdw_ubap/mEmailController.thumb?getAttachmentStream&fileId=1&fileName=自我探索——我是谁.ppt&emailId=36&token=d1828248-cc71-4719-8218-adc31ffc9cca&type=inbox&fileSize=14696446";
|
|
||||||
|
|
||||||
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)); |
|
||||||
// DownloadManager.Request.setDestinationInExternalPublicDir();
|
|
||||||
|
|
||||||
request.setDescription(fileName); |
|
||||||
request.setTitle("附件"); |
|
||||||
// in order for this if to run, you must use the android 3.2 to compile your app
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { |
|
||||||
request.allowScanningByMediaScanner(); |
|
||||||
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); |
|
||||||
// request.setNotificationVisibility(VISIBILITY_HIDDEN);
|
|
||||||
} |
|
||||||
// int i = Build.VERSION.SDK_INT;
|
|
||||||
|
|
||||||
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { |
|
||||||
request.setDestinationInExternalPublicDir(APPCONST.FILE_DIR, fileName); |
|
||||||
} else { |
|
||||||
Log.d("download", "android版本过低,不存在外部存储,下载路径无法指定,默认路径:/data/data/com.android.providers.downloads/cache/"); |
|
||||||
DialogCreator.createCommonDialog(context, "文件下载", "android版本过低或系统兼容性问题,不存在外部存储,无法指定下载路径,文件下载到系统默认路径,请到文件管理搜索文件名", true, |
|
||||||
"关闭", new DialogInterface.OnClickListener() { |
|
||||||
@Override |
|
||||||
public void onClick(DialogInterface dialog, int which) { |
|
||||||
dialog.dismiss(); |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
// get download service and enqueue file
|
|
||||||
DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); |
|
||||||
manager.enqueue(request); |
|
||||||
} catch (Exception e) { |
|
||||||
e.printStackTrace(); |
|
||||||
ToastUtils.showError("下载错误:" + e.getLocalizedMessage()); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* 文件下载(有回调,无通知) |
|
||||||
* |
|
||||||
* @param context |
|
||||||
* @param fileDir |
|
||||||
* @param fileName |
|
||||||
* @param url |
|
||||||
* @param listener |
|
||||||
*/ |
|
||||||
public static void downloadFileByFinishListener(Context context, String fileDir, String fileName, String url, |
|
||||||
final DownloadCompleteListener listener) { |
|
||||||
try { |
|
||||||
if (isPermission(context)) { |
|
||||||
Log.d("http download:", url); |
|
||||||
// String Url = "10.10.123.16:8080/gxqdw_ubap/mEmailController.thumb?getAttachmentStream&fileId=1&fileName=自我探索——我是谁.ppt&emailId=36&token=d1828248-cc71-4719-8218-adc31ffc9cca&type=inbox&fileSize=14696446";
|
|
||||||
|
|
||||||
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)); |
|
||||||
// DownloadManager.Request.setDestinationInExternalPublicDir();
|
|
||||||
|
|
||||||
/* request.setDescription(fileName); |
|
||||||
request.setTitle("附件");*/ |
|
||||||
// in order for this if to run, you must use the android 3.2 to compile your app
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { |
|
||||||
request.allowScanningByMediaScanner(); |
|
||||||
// request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
|
|
||||||
request.setNotificationVisibility(VISIBILITY_HIDDEN); |
|
||||||
} |
|
||||||
// int i = Build.VERSION.SDK_INT;
|
|
||||||
if (Build.VERSION.SDK_INT > 17) { |
|
||||||
request.setDestinationInExternalPublicDir(fileDir, fileName); |
|
||||||
} else { |
|
||||||
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { |
|
||||||
request.setDestinationInExternalPublicDir(fileDir, fileName); |
|
||||||
} else { |
|
||||||
Log.i("download", "android版本过低,不存在外部存储,下载路径无法指定,默认路径:/data/data/com.android.providers.downloads/cache/"); |
|
||||||
} |
|
||||||
} |
|
||||||
// get download service and enqueue file
|
|
||||||
final DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); |
|
||||||
|
|
||||||
final long id = manager.enqueue(request); |
|
||||||
// 注册广播监听系统的下载完成事件。
|
|
||||||
IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE); |
|
||||||
|
|
||||||
final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { |
|
||||||
@Override |
|
||||||
public void onReceive(Context context, Intent intent) { |
|
||||||
long ID = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); |
|
||||||
if (ID == id) { |
|
||||||
listener.onFinish(manager.getUriForDownloadedFile(id)); |
|
||||||
context.unregisterReceiver(mBroadcastReceiverMap.get(id)); |
|
||||||
mBroadcastReceiverMap.remove(id); |
|
||||||
/* Toast.makeText(getApplicationContext(), "任务:" + Id + " 下载完成!", Toast.LENGTH_LONG).show();*/ |
|
||||||
} |
|
||||||
} |
|
||||||
}; |
|
||||||
context.registerReceiver(broadcastReceiver, intentFilter); |
|
||||||
mBroadcastReceiverMap.put(id, broadcastReceiver); |
|
||||||
} |
|
||||||
} catch (Exception e) { |
|
||||||
lowVersionNoSDDownloadFileByFinishListener(context, fileDir, fileName, url, listener); |
|
||||||
// listener.onError(e.toString());
|
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 低版本无外置存储文件下载(有回调,无通知) |
|
||||||
* |
|
||||||
* @param context |
|
||||||
* @param fileDir |
|
||||||
* @param fileName |
|
||||||
* @param url |
|
||||||
* @param listener |
|
||||||
*/ |
|
||||||
private static void lowVersionNoSDDownloadFileByFinishListener(Context context, String fileDir, String fileName, String url, |
|
||||||
final DownloadCompleteListener listener) { |
|
||||||
try { |
|
||||||
|
|
||||||
Log.d("http download:", url); |
|
||||||
// String Url = "10.10.123.16:8080/gxqdw_ubap/mEmailController.thumb?getAttachmentStream&fileId=1&fileName=自我探索——我是谁.ppt&emailId=36&token=d1828248-cc71-4719-8218-adc31ffc9cca&type=inbox&fileSize=14696446";
|
|
||||||
|
|
||||||
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)); |
|
||||||
// DownloadManager.Request.setDestinationInExternalPublicDir();
|
|
||||||
|
|
||||||
/* request.setDescription(fileName); |
|
||||||
request.setTitle("附件");*/ |
|
||||||
// in order for this if to run, you must use the android 3.2 to compile your app
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { |
|
||||||
request.allowScanningByMediaScanner(); |
|
||||||
// request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
|
|
||||||
request.setNotificationVisibility(VISIBILITY_HIDDEN); |
|
||||||
} |
|
||||||
// int i = Build.VERSION.SDK_INT;
|
|
||||||
|
|
||||||
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { |
|
||||||
request.setDestinationInExternalPublicDir(APPCONST.FILE_DIR, fileName); |
|
||||||
} else { |
|
||||||
Log.d("download", "android版本过低,不存在外部存储,下载路径无法指定,默认路径:/data/data/com.android.providers.downloads/cache/"); |
|
||||||
} |
|
||||||
|
|
||||||
// get download service and enqueue file
|
|
||||||
final DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); |
|
||||||
|
|
||||||
final long id = manager.enqueue(request); |
|
||||||
// 注册广播监听系统的下载完成事件。
|
|
||||||
IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE); |
|
||||||
|
|
||||||
final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { |
|
||||||
@Override |
|
||||||
public void onReceive(Context context, Intent intent) { |
|
||||||
long ID = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); |
|
||||||
if (ID == id) { |
|
||||||
listener.onFinish(manager.getUriForDownloadedFile(id)); |
|
||||||
context.unregisterReceiver(mBroadcastReceiverMap.get(id)); |
|
||||||
mBroadcastReceiverMap.remove(id); |
|
||||||
/* Toast.makeText(getApplicationContext(), "任务:" + Id + " 下载完成!", Toast.LENGTH_LONG).show();*/ |
|
||||||
} |
|
||||||
} |
|
||||||
}; |
|
||||||
context.registerReceiver(broadcastReceiver, intentFilter); |
|
||||||
mBroadcastReceiverMap.put(id, broadcastReceiver); |
|
||||||
|
|
||||||
} catch (Exception e) { |
|
||||||
listener.onError(e.toString()); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 文件下载(有回调,有通知) |
|
||||||
* |
|
||||||
* @param context |
|
||||||
* @param fileDir |
|
||||||
* @param fileName |
|
||||||
* @param url |
|
||||||
* @param title |
|
||||||
* @param listener |
|
||||||
*/ |
|
||||||
public static void downloadFileOnNotificationByFinishListener(final Context context, final String fileDir, final String fileName, final String url, |
|
||||||
final String title, final DownloadCompleteListener listener) { |
|
||||||
try { |
|
||||||
if (isPermission(context)) { |
|
||||||
Log.d("http download:", url); |
|
||||||
|
|
||||||
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)); |
|
||||||
request.setTitle(title); |
|
||||||
|
|
||||||
// in order for this if to run, you must use the android 3.2 to compile your app
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { |
|
||||||
request.allowScanningByMediaScanner(); |
|
||||||
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE); |
|
||||||
} |
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT > 17) { |
|
||||||
/* File file = new File(Environment.getExternalStorageDirectory() + "/gxdw/apk/app_gxdw_186.apk"); |
|
||||||
if (!file.exists()){ |
|
||||||
boolean flag = file.createNewFile(); |
|
||||||
}*/ |
|
||||||
request.setDestinationInExternalPublicDir(fileDir, fileName); |
|
||||||
|
|
||||||
} else { |
|
||||||
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { |
|
||||||
request.setDestinationInExternalPublicDir(fileDir, fileName); |
|
||||||
} else { |
|
||||||
Log.d("download", "android版本过低,不存在外部存储,下载路径无法指定,默认路径:/data/data/com.android.providers.downloads/cache/"); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// get download service and enqueue file
|
|
||||||
final DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); |
|
||||||
|
|
||||||
final long id = manager.enqueue(request); |
|
||||||
// 注册广播监听系统的下载完成事件。
|
|
||||||
IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE); |
|
||||||
|
|
||||||
final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { |
|
||||||
@Override |
|
||||||
public void onReceive(Context context, Intent intent) { |
|
||||||
long ID = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); |
|
||||||
if (ID == id) { |
|
||||||
listener.onFinish(manager.getUriForDownloadedFile(id)); |
|
||||||
context.unregisterReceiver(mBroadcastReceiverMap.get(id)); |
|
||||||
mBroadcastReceiverMap.remove(id); |
|
||||||
/* Toast.makeText(getApplicationContext(), "任务:" + Id + " 下载完成!", Toast.LENGTH_LONG).show();*/ |
|
||||||
} |
|
||||||
} |
|
||||||
}; |
|
||||||
context.registerReceiver(broadcastReceiver, intentFilter); |
|
||||||
mBroadcastReceiverMap.put(id, broadcastReceiver); |
|
||||||
} |
|
||||||
} catch (Exception e) { |
|
||||||
e.printStackTrace(); |
|
||||||
lowVersionDownloadFileOnNotificationByFinishListener(context, fileDir, fileName, url, title, listener); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 低版本文件下载(有回调,有通知) |
|
||||||
* |
|
||||||
* @param context |
|
||||||
* @param fileDir |
|
||||||
* @param fileName |
|
||||||
* @param url |
|
||||||
* @param title |
|
||||||
* @param listener |
|
||||||
*/ |
|
||||||
private static void lowVersionDownloadFileOnNotificationByFinishListener(final Context context, final String fileDir, final String fileName, final String url, |
|
||||||
final String title, final DownloadCompleteListener listener) { |
|
||||||
|
|
||||||
|
|
||||||
try { |
|
||||||
|
|
||||||
Log.d("http download:", url); |
|
||||||
|
|
||||||
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)); |
|
||||||
request.setTitle(title); |
|
||||||
|
|
||||||
// in order for this if to run, you must use the android 3.2 to compile your app
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { |
|
||||||
request.allowScanningByMediaScanner(); |
|
||||||
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { |
|
||||||
request.setDestinationInExternalPublicDir(APPCONST.FILE_DIR, fileName); |
|
||||||
} else { |
|
||||||
Log.d("download", "android版本过低,不存在外部存储,下载路径无法指定,默认路径:/data/data/com.android.providers.downloads/cache/"); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
// get download service and enqueue file
|
|
||||||
final DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); |
|
||||||
|
|
||||||
final long id = manager.enqueue(request); |
|
||||||
// 注册广播监听系统的下载完成事件。
|
|
||||||
IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE); |
|
||||||
|
|
||||||
final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { |
|
||||||
@Override |
|
||||||
public void onReceive(Context context, Intent intent) { |
|
||||||
long ID = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); |
|
||||||
if (ID == id) { |
|
||||||
listener.onFinish(manager.getUriForDownloadedFile(id)); |
|
||||||
context.unregisterReceiver(mBroadcastReceiverMap.get(id)); |
|
||||||
mBroadcastReceiverMap.remove(id); |
|
||||||
} |
|
||||||
} |
|
||||||
}; |
|
||||||
context.registerReceiver(broadcastReceiver, intentFilter); |
|
||||||
mBroadcastReceiverMap.put(id, broadcastReceiver); |
|
||||||
|
|
||||||
} catch (Exception e) { |
|
||||||
e.printStackTrace(); |
|
||||||
listener.onError(e.toString()); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* 读写权限判断 |
|
||||||
* |
|
||||||
* @param context |
|
||||||
* @return |
|
||||||
*/ |
|
||||||
public static boolean isPermission(Context context) { |
|
||||||
boolean permission = false; |
|
||||||
if (Build.VERSION.SDK_INT >= 23) { |
|
||||||
int checkReadPhoneStatePermission = ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE); |
|
||||||
if (checkReadPhoneStatePermission != PackageManager.PERMISSION_GRANTED) { |
|
||||||
// 弹出对话框接收权限
|
|
||||||
ActivityCompat.requestPermissions((AppCompatActivity) context, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1); |
|
||||||
ToastUtils.showWarring("当前应用未拥有存储设备读写权限"); |
|
||||||
} else if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { |
|
||||||
// 弹出对话框接收权限
|
|
||||||
ActivityCompat.requestPermissions((AppCompatActivity) context, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1); |
|
||||||
ToastUtils.showWarring("当前应用未拥有存储设备读写权限"); |
|
||||||
} else { |
|
||||||
permission = true; |
|
||||||
} |
|
||||||
} else { |
|
||||||
permission = true; |
|
||||||
} |
|
||||||
return permission; |
|
||||||
} |
|
||||||
|
|
||||||
public interface DownloadCompleteListener { |
|
||||||
void onFinish(Uri uri); |
|
||||||
|
|
||||||
void onError(String s); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
} |
|
@ -1,14 +0,0 @@ |
|||||||
package xyz.fycz.myreader.util; |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public class IdHelper { |
|
||||||
|
|
||||||
public static String getId(){ |
|
||||||
java.util.Date date = new java.util.Date(); |
|
||||||
int rand = (int)(1+ Math.random()*(25-0+1)); |
|
||||||
// char c = (char) ('a' + rand);
|
|
||||||
return String.valueOf(date.getTime()%100000000); |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
@ -1,266 +0,0 @@ |
|||||||
package xyz.fycz.myreader.util; |
|
||||||
|
|
||||||
import java.text.ParseException; |
|
||||||
import java.text.SimpleDateFormat; |
|
||||||
import java.util.Calendar; |
|
||||||
import java.util.Date; |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public class Lunar |
|
||||||
{ |
|
||||||
private int year; |
|
||||||
private int month; |
|
||||||
private int day; |
|
||||||
private boolean leap; |
|
||||||
final static String chineseNumber[] = |
|
||||||
{ "一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二" }; |
|
||||||
final static String Big_Or_Small[] = |
|
||||||
{ "大", "小", "大", "小", "大", "小", "大", "大", "小", "大", "小", "大" }; |
|
||||||
private String[] LunarHolDayName = |
|
||||||
{ "小寒", "大寒", "立春", "雨水", "惊蛰", "春分", "清明", "谷雨", "立夏", "小满", "芒种", "夏至", |
|
||||||
"小暑", "大暑", "立秋", "处暑", "白露", "秋分", "寒露", "霜降", "立冬", "小雪", "大雪", |
|
||||||
"冬至" }; |
|
||||||
|
|
||||||
static SimpleDateFormat chineseDateFormat = new SimpleDateFormat(" yyyy年MM月dd日 "); |
|
||||||
final static long[] lunarInfo = new long[] |
|
||||||
{ 0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, |
|
||||||
0x09ad0, 0x055d2, 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, |
|
||||||
0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, 0x04970, 0x0a4b0, |
|
||||||
0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, |
|
||||||
0x04970, 0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, |
|
||||||
0x186e3, 0x092e0, 0x1c8d7, 0x0c950, 0x0d4a0, 0x1d8a6, 0x0b550, |
|
||||||
0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, |
|
||||||
0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5d0, 0x14573, 0x052d0, |
|
||||||
0x0a9a8, 0x0e950, 0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, |
|
||||||
0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, |
|
||||||
0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, |
|
||||||
0x0b5a0, 0x195a6, 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, |
|
||||||
0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, 0x04af5, 0x04970, |
|
||||||
0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, |
|
||||||
0x092e0, 0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, |
|
||||||
0x0abb7, 0x025d0, 0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4, |
|
||||||
0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, |
|
||||||
0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, |
|
||||||
0x0d260, 0x0ea65, 0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, |
|
||||||
0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, |
|
||||||
0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, |
|
||||||
0x06d20, 0x0ada0 }; |
|
||||||
|
|
||||||
// ====== 传回农历 y年的总天数
|
|
||||||
final private static int yearDays(int y) |
|
||||||
{ |
|
||||||
int i, sum = 348; |
|
||||||
for (i = 0x8000; i > 0x8; i >>= 1) |
|
||||||
{ |
|
||||||
if ((lunarInfo[y - 1900] & i) != 0) |
|
||||||
sum += 1; |
|
||||||
} |
|
||||||
return (sum + leapDays(y)); |
|
||||||
} |
|
||||||
|
|
||||||
// ====== 传回农历 y年闰月的天数
|
|
||||||
final private static int leapDays(int y) |
|
||||||
{ |
|
||||||
if (leapMonth(y) != 0) |
|
||||||
{ |
|
||||||
if ((lunarInfo[y - 1900] & 0x10000) != 0) |
|
||||||
return 30; |
|
||||||
else |
|
||||||
return 29; |
|
||||||
} |
|
||||||
else |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
// ====== 传回农历 y年闰哪个月 1-12 , 没闰传回 0
|
|
||||||
final private static int leapMonth(int y) |
|
||||||
{ |
|
||||||
return (int) (lunarInfo[y - 1900] & 0xf); |
|
||||||
} |
|
||||||
|
|
||||||
// ====== 传回农历 y年m月的总天数
|
|
||||||
final private static int monthDays(int y, int m) |
|
||||||
{ |
|
||||||
if ((lunarInfo[y - 1900] & (0x10000 >> m)) == 0) |
|
||||||
return 29; |
|
||||||
else |
|
||||||
return 30; |
|
||||||
} |
|
||||||
|
|
||||||
// ====== 传回农历 y年的生肖
|
|
||||||
final public String animalsYear() |
|
||||||
{ |
|
||||||
final String[] Animals = new String[] |
|
||||||
{ "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪" }; |
|
||||||
return Animals[(year - 4) % 12]; |
|
||||||
} |
|
||||||
|
|
||||||
// ====== 传入 月日的offset 传回干支, 0=甲子
|
|
||||||
final private static String cyclicalm(int num) |
|
||||||
{ |
|
||||||
final String[] Gan = new String[] |
|
||||||
{ "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸" }; |
|
||||||
final String[] Zhi = new String[] |
|
||||||
{ "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥" }; |
|
||||||
return (Gan[num % 10] + Zhi[num % 12]); |
|
||||||
} |
|
||||||
|
|
||||||
// ====== 传入 offset 传回干支, 0=甲子
|
|
||||||
final public String cyclical() |
|
||||||
{ |
|
||||||
int num = year - 1900 + 36; |
|
||||||
return (cyclicalm(num)); |
|
||||||
} |
|
||||||
|
|
||||||
/** */ |
|
||||||
/** |
|
||||||
* 传出y年m月d日对应的农历. yearCyl3:农历年与1864的相差数 ? monCyl4:从1900年1月31日以来,闰月数 |
|
||||||
* dayCyl5:与1900年1月31日相差的天数,再加40 ? |
|
||||||
* |
|
||||||
* @param cal |
|
||||||
* @return |
|
||||||
*/ |
|
||||||
public Lunar(Calendar cal) |
|
||||||
{ |
|
||||||
// cal.add(cal.get(Calendar.DAY_OF_MONTH),1);
|
|
||||||
@SuppressWarnings(" unused ") |
|
||||||
int yearCyl, monCyl, dayCyl; |
|
||||||
int leapMonth = 0; |
|
||||||
Date baseDate = null; |
|
||||||
try |
|
||||||
{ |
|
||||||
baseDate = chineseDateFormat.parse(" 1900年1月31日 "); |
|
||||||
} |
|
||||||
catch (ParseException e) |
|
||||||
{ |
|
||||||
e.printStackTrace(); // To change body of catch statement use
|
|
||||||
// Options | File Templates.
|
|
||||||
} |
|
||||||
|
|
||||||
// 求出和1900年1月31日相差的天数
|
|
||||||
int offset = (int) ((cal.getTime().getTime() - baseDate.getTime()) / 86400000L); |
|
||||||
dayCyl = offset + 40; |
|
||||||
monCyl = 14; |
|
||||||
|
|
||||||
// 用offset减去每农历年的天数
|
|
||||||
// 计算当天是农历第几天
|
|
||||||
// i最终结果是农历的年份
|
|
||||||
// offset是当年的第几天
|
|
||||||
int iYear, daysOfYear = 0; |
|
||||||
for (iYear = 1900; iYear < 2050 && offset > 0; iYear++) |
|
||||||
{ |
|
||||||
daysOfYear = yearDays(iYear); |
|
||||||
offset -= daysOfYear; |
|
||||||
monCyl += 12; |
|
||||||
} |
|
||||||
if (offset < 0) |
|
||||||
{ |
|
||||||
offset += daysOfYear; |
|
||||||
iYear--; |
|
||||||
monCyl -= 12; |
|
||||||
} |
|
||||||
// 农历年份
|
|
||||||
year = iYear; |
|
||||||
|
|
||||||
yearCyl = iYear - 1864; |
|
||||||
leapMonth = leapMonth(iYear); // 闰哪个月,1-12
|
|
||||||
leap = false; |
|
||||||
|
|
||||||
// 用当年的天数offset,逐个减去每月(农历)的天数,求出当天是本月的第几天
|
|
||||||
int iMonth, daysOfMonth = 0; |
|
||||||
for (iMonth = 1; iMonth < 13 && offset > 0; iMonth++) |
|
||||||
{ |
|
||||||
// 闰月
|
|
||||||
if (leapMonth > 0 && iMonth == (leapMonth + 1) && !leap) |
|
||||||
{ |
|
||||||
--iMonth; |
|
||||||
leap = true; |
|
||||||
daysOfMonth = leapDays(year); |
|
||||||
} |
|
||||||
else |
|
||||||
daysOfMonth = monthDays(year, iMonth); |
|
||||||
|
|
||||||
offset -= daysOfMonth; |
|
||||||
// 解除闰月
|
|
||||||
if (leap && iMonth == (leapMonth + 1)) |
|
||||||
leap = false; |
|
||||||
if (!leap) |
|
||||||
monCyl++; |
|
||||||
} |
|
||||||
// offset为0时,并且刚才计算的月份是闰月,要校正
|
|
||||||
if (offset == 0 && leapMonth > 0 && iMonth == leapMonth + 1) |
|
||||||
{ |
|
||||||
if (leap) |
|
||||||
{ |
|
||||||
leap = false; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
leap = true; |
|
||||||
--iMonth; |
|
||||||
--monCyl; |
|
||||||
} |
|
||||||
} |
|
||||||
// offset小于0时,也要校正
|
|
||||||
if (offset < 0) |
|
||||||
{ |
|
||||||
offset += daysOfMonth; |
|
||||||
--iMonth; |
|
||||||
--monCyl; |
|
||||||
} |
|
||||||
month = iMonth; |
|
||||||
day = offset + 1; |
|
||||||
} |
|
||||||
|
|
||||||
public static String getChinaDayString(int day) |
|
||||||
{ |
|
||||||
String chineseTen[] = |
|
||||||
{ "初", "十", "廿", "卅" }; |
|
||||||
int n = day % 10 == 0 ? 9 : day % 10 - 1; |
|
||||||
if (day > 30) |
|
||||||
return ""; |
|
||||||
if (day == 10) |
|
||||||
return "初十"; |
|
||||||
else |
|
||||||
return chineseTen[day / 10] + chineseNumber[n]; |
|
||||||
} |
|
||||||
|
|
||||||
public String toString() |
|
||||||
{ |
|
||||||
return /* cyclical() + "年" + */(leap ? "闰" : "") |
|
||||||
+ chineseNumber[month - 1] + "月" + getChinaDayString(day); |
|
||||||
} |
|
||||||
|
|
||||||
public String numeric_md() |
|
||||||
{// 返回阿拉伯数字的阴历日期
|
|
||||||
String temp_day; |
|
||||||
String temp_mon; |
|
||||||
temp_mon = month < 10 ? "0" + month : "" + month; |
|
||||||
temp_day = day < 10 ? "0" + day : "" + day; |
|
||||||
|
|
||||||
return temp_mon + temp_day; |
|
||||||
} |
|
||||||
|
|
||||||
public String get_month() |
|
||||||
{// 返回阴历的月份
|
|
||||||
return chineseNumber[month - 1]; |
|
||||||
} |
|
||||||
|
|
||||||
public String get_date(int year, int month, int date) |
|
||||||
{ |
|
||||||
/* // 返回阴历的天
|
|
||||||
LunarCalendar lunarCalendar = LunarCalendar.getInstance(); |
|
||||||
String str = lunarCalendar.CalculateLunarCalendar(year,month,date); |
|
||||||
if(StringHelper.isEmpty(str)){ |
|
||||||
str = getChinaDayString(day); |
|
||||||
}*/ |
|
||||||
return getChinaDayString(day); |
|
||||||
} |
|
||||||
|
|
||||||
public String get_Big_Or_Small() |
|
||||||
{// 返回的月份的大或小
|
|
||||||
return Big_Or_Small[month - 1]; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,326 +0,0 @@ |
|||||||
package xyz.fycz.myreader.util; |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import java.text.ParseException; |
|
||||||
import java.text.SimpleDateFormat; |
|
||||||
import java.util.Calendar; |
|
||||||
import java.util.Date; |
|
||||||
|
|
||||||
public class LunarCalendar { |
|
||||||
|
|
||||||
private int lyear; |
|
||||||
|
|
||||||
private int lmonth; |
|
||||||
|
|
||||||
private int lday; |
|
||||||
|
|
||||||
private boolean leap; |
|
||||||
|
|
||||||
private String solarTerms = ""; |
|
||||||
|
|
||||||
private int yearCyl, monCyl, dayCyl; |
|
||||||
|
|
||||||
private String solarFestival = ""; |
|
||||||
|
|
||||||
private String lunarFestival = ""; |
|
||||||
|
|
||||||
private Calendar baseDate = Calendar.getInstance(); |
|
||||||
|
|
||||||
private Calendar offDate = Calendar.getInstance(); |
|
||||||
|
|
||||||
private SimpleDateFormat chineseDateFormat = new SimpleDateFormat( |
|
||||||
"yyyy年MM月dd日"); |
|
||||||
|
|
||||||
final static long[] lunarInfo = new long[]{0x04bd8, 0x04ae0, 0x0a570, |
|
||||||
0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, |
|
||||||
0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, |
|
||||||
0x0ada2, 0x095b0, 0x14977, 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, |
|
||||||
0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, 0x06566, |
|
||||||
0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, |
|
||||||
0x1c8d7, 0x0c950, 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, |
|
||||||
0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, 0x06ca0, 0x0b550, |
|
||||||
0x15355, 0x04da0, 0x0a5d0, 0x14573, 0x052d0, 0x0a9a8, 0x0e950, |
|
||||||
0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, |
|
||||||
0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, 0x04dd5, 0x04ad0, |
|
||||||
0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0, 0x195a6, |
|
||||||
0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, |
|
||||||
0x0af46, 0x0ab60, 0x09570, 0x04af5, 0x04970, 0x064b0, 0x074a3, |
|
||||||
0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0, 0x0c960, |
|
||||||
0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, |
|
||||||
0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, |
|
||||||
0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, 0x07954, 0x06aa0, |
|
||||||
0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, |
|
||||||
0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0, |
|
||||||
0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, 0x056d0, 0x055b2, |
|
||||||
0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0}; |
|
||||||
|
|
||||||
final static String[] Gan = new String[]{"甲", "乙", "丙", "丁", "戊", "己", |
|
||||||
"庚", "辛", "壬", "癸"}; |
|
||||||
|
|
||||||
final static String[] Zhi = new String[]{"子", "丑", "寅", "卯", "辰", "巳", |
|
||||||
"午", "未", "申", "酉", "戌", "亥"}; |
|
||||||
|
|
||||||
final static String[] Animals = new String[]{"鼠", "牛", "虎", "兔", "龙", |
|
||||||
"蛇", "马", "羊", "猴", "鸡", "狗", "猪"}; |
|
||||||
|
|
||||||
final static String[] SolarTerm = new String[]{"小寒", "大寒", "立春", "雨水", |
|
||||||
"惊蛰", "春分", "清明", "谷雨", "立夏", "小满", "芒种", "夏至", "小暑", "大暑", "立秋", |
|
||||||
"处暑", "白露", "秋分", "寒露", "霜降", "立冬", "小雪", "大雪", "冬至"}; |
|
||||||
final static long[] STermInfo = new long[]{0, 21208, 42467, 63836, 85337, |
|
||||||
107014, 128867, 150921, 173149, 195551, 218072, 240693, 263343, |
|
||||||
285989, 308563, 331033, 353350, 375494, 397447, 419210, 440795, |
|
||||||
462224, 483532, 504758}; |
|
||||||
|
|
||||||
final static String chineseMonthNumber[] = {"正", "二", "三", "四", "五", "六", |
|
||||||
"七", "八", "九", "十", "冬", "腊"}; |
|
||||||
|
|
||||||
final static String[] sFtv = new String[]{"0101*元旦", "0214 情人节", |
|
||||||
"0308 妇女节", "0312 植树节", /*"0314 国际警察日", "0315 消费者权益日", "0323 世界气象日",*/ |
|
||||||
"0401 愚人节", /*"0407 世界卫生日",*/ "0501*劳动节", "0504 青年节", /*"0508 红十字日",*/ |
|
||||||
"0512 护士节", /*"0515 国际家庭日", "0517 世界电信日", "0519 全国助残日", "0531 世界无烟日",*/ |
|
||||||
"0601 儿童节", /*"0605 世界环境日", "0606 全国爱眼日", "0623 奥林匹克日", "0625 全国土地日",*/ |
|
||||||
/*"0626 反毒品日",*/ "0701 建党节", /*"0707 抗战纪念日", "0711 世界人口日",*/ "0801 建军节", |
|
||||||
/* "0908 国际扫盲日", "0909 毛xx逝世纪念",*/ "0910 教师节", /*"0917 国际和平日",*/ |
|
||||||
/* "0920 国际爱牙日", "0922 国际聋人节", "0927 世界旅游日", "0928 孔子诞辰",*/ "1001*国庆节", |
|
||||||
/* "1004 世界动物日", "1006 老人节", "1007 国际住房日", "1009 世界邮政日", "1015 国际盲人节",*/ |
|
||||||
/* "1016 世界粮食日", "1024 联合国日", */"1031 万圣节",/* "1108 中国记者日", "1109 消防宣传日",*/ |
|
||||||
/* "1112 孙中山诞辰", "1114 世界糖尿病日", "1117 国际大学生节",*/ "1128 感恩节", |
|
||||||
/* "1201 世界艾滋病日", "1203 世界残疾人日", "1209 世界足球日", "1220 澳门回归",*/ |
|
||||||
"1225 圣诞节", /*"1226 毛xx诞辰"*/}; |
|
||||||
|
|
||||||
final static String[] lFtv = {"0101*春节", "0115 元宵", "0505 端午", |
|
||||||
"0707 七夕", "0815 中秋", "0909 重阳", "1208 腊八", "1223 小年", |
|
||||||
"0100*除夕"}; |
|
||||||
|
|
||||||
final static String[] wFtv = {"0521 母亲节", "0631 父亲节"};//每年6月第3个星期日是父亲节,5月的第2个星期日是母亲节
|
|
||||||
|
|
||||||
//星期日是一个周的第1天第3个星期日也就是第3个完整周的第一天
|
|
||||||
|
|
||||||
//
|
|
||||||
private LunarCalendar() { |
|
||||||
baseDate.setMinimalDaysInFirstWeek(7);//设置一个月的第一个周是一个完整周
|
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
final private static int lYearDays(int y)//====== 传回农历 y年的总天数
|
|
||||||
{ |
|
||||||
int i, sum = 348; |
|
||||||
for (i = 0x8000; i > 0x8; i >>= 1) { |
|
||||||
if ((lunarInfo[y - 1900] & i) != 0) |
|
||||||
sum += 1; |
|
||||||
} |
|
||||||
return (sum + leapDays(y)); |
|
||||||
} |
|
||||||
|
|
||||||
final private static int leapDays(int y)//====== 传回农历 y年闰月的天数
|
|
||||||
{ |
|
||||||
if (leapMonth(y) != 0) { |
|
||||||
if ((lunarInfo[y - 1900] & 0x10000) != 0) |
|
||||||
return 30; |
|
||||||
else |
|
||||||
return 29; |
|
||||||
} else |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
final private static int leapMonth(int y)//====== 传回农历 y年闰哪个月 1-12 , 没闰传回 0
|
|
||||||
{ |
|
||||||
return (int) (lunarInfo[y - 1900] & 0xf); |
|
||||||
} |
|
||||||
|
|
||||||
final public static int monthDays(int y, int m)//====== 传回农历 y年m月的总天数
|
|
||||||
{ |
|
||||||
if ((lunarInfo[y - 1900] & (0x10000 >> m)) == 0) |
|
||||||
return 29; |
|
||||||
else |
|
||||||
return 30; |
|
||||||
} |
|
||||||
|
|
||||||
final private static String AnimalsYear(int y)//====== 传回农历 y年的生肖
|
|
||||||
{ |
|
||||||
|
|
||||||
return Animals[(y - 4) % 12]; |
|
||||||
} |
|
||||||
|
|
||||||
final private static String cyclical(int num)//====== 传入 的offset 传回干支,
|
|
||||||
// 0=甲子
|
|
||||||
{ |
|
||||||
|
|
||||||
return (Gan[num % 10] + Zhi[num % 12]); |
|
||||||
} |
|
||||||
|
|
||||||
// ===== 某年的第n个节气为几日(从0小寒起算)
|
|
||||||
final private int sTerm(int y, int n) { |
|
||||||
|
|
||||||
offDate.set(1900, 0, 6, 2, 5, 0); |
|
||||||
long temp = offDate.getTime().getTime(); |
|
||||||
offDate |
|
||||||
.setTime(new Date( |
|
||||||
(long) ((31556925974.7 * (y - 1900) + STermInfo[n] * 60000L) + temp))); |
|
||||||
|
|
||||||
return offDate.get(Calendar.DAY_OF_MONTH); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 传出y年m月d日对应的农历. |
|
||||||
*/ |
|
||||||
public String CalculateLunarCalendar(int y, int m, int d) { |
|
||||||
|
|
||||||
int leapMonth = 0; |
|
||||||
|
|
||||||
try { |
|
||||||
baseDate.setTime(chineseDateFormat.parse("1900年1月31日")); |
|
||||||
|
|
||||||
} catch (ParseException e) { |
|
||||||
e.printStackTrace(); |
|
||||||
} |
|
||||||
long base = baseDate.getTimeInMillis(); |
|
||||||
try { |
|
||||||
baseDate.setTime(chineseDateFormat.parse(y + "年" + m + "月" + d |
|
||||||
+ "日")); |
|
||||||
|
|
||||||
} catch (ParseException e) { |
|
||||||
e.printStackTrace(); |
|
||||||
} |
|
||||||
long obj = baseDate.getTimeInMillis(); |
|
||||||
|
|
||||||
|
|
||||||
int offset = (int) ((obj - base) / 86400000L); |
|
||||||
//System.out.println(offset);
|
|
||||||
//求出和1900年1月31日相差的天数
|
|
||||||
|
|
||||||
dayCyl = offset + 40;//干支天
|
|
||||||
monCyl = 14;//干支月
|
|
||||||
|
|
||||||
//用offset减去每农历年的天数
|
|
||||||
// 计算当天是农历第几天
|
|
||||||
//i最终结果是农历的年份
|
|
||||||
//offset是当年的第几天
|
|
||||||
int iYear, daysOfYear = 0; |
|
||||||
for (iYear = 1900; iYear < 2050 && offset > 0; iYear++) { |
|
||||||
daysOfYear = lYearDays(iYear); |
|
||||||
offset -= daysOfYear; |
|
||||||
monCyl += 12; |
|
||||||
} |
|
||||||
if (offset < 0) { |
|
||||||
offset += daysOfYear; |
|
||||||
iYear--; |
|
||||||
monCyl -= 12; |
|
||||||
} |
|
||||||
//农历年份
|
|
||||||
lyear = iYear; |
|
||||||
|
|
||||||
yearCyl = iYear - 1864;//***********干支年**********//
|
|
||||||
|
|
||||||
leapMonth = leapMonth(iYear); //闰哪个月,1-12
|
|
||||||
leap = false; |
|
||||||
|
|
||||||
//用当年的天数offset,逐个减去每月(农历)的天数,求出当天是本月的第几天
|
|
||||||
int iMonth, daysOfMonth = 0; |
|
||||||
for (iMonth = 1; iMonth < 13 && offset > 0; iMonth++) { |
|
||||||
//闰月
|
|
||||||
if (leapMonth > 0 && iMonth == (leapMonth + 1) && !leap) { |
|
||||||
--iMonth; |
|
||||||
leap = true; |
|
||||||
daysOfMonth = leapDays(iYear); |
|
||||||
} else |
|
||||||
daysOfMonth = monthDays(iYear, iMonth); |
|
||||||
|
|
||||||
offset -= daysOfMonth; |
|
||||||
//解除闰月
|
|
||||||
if (leap && iMonth == (leapMonth + 1)) |
|
||||||
leap = false; |
|
||||||
if (!leap) |
|
||||||
monCyl++; |
|
||||||
} |
|
||||||
//offset为0时,并且刚才计算的月份是闰月,要校正
|
|
||||||
if (offset == 0 && leapMonth > 0 && iMonth == leapMonth + 1) { |
|
||||||
if (leap) { |
|
||||||
leap = false; |
|
||||||
} else { |
|
||||||
leap = true; |
|
||||||
--iMonth; |
|
||||||
--monCyl; |
|
||||||
} |
|
||||||
} |
|
||||||
//offset小于0时,也要校正
|
|
||||||
if (offset < 0) { |
|
||||||
offset += daysOfMonth; |
|
||||||
--iMonth; |
|
||||||
--monCyl; |
|
||||||
} |
|
||||||
lmonth = iMonth; |
|
||||||
lday = offset + 1; |
|
||||||
|
|
||||||
//******************计算节气**********//
|
|
||||||
|
|
||||||
if (d == sTerm(y, (m - 1) * 2)) |
|
||||||
solarTerms = SolarTerm[(m - 1) * 2]; |
|
||||||
else if (d == sTerm(y, (m - 1) * 2 + 1)) |
|
||||||
solarTerms = SolarTerm[(m - 1) * 2 + 1]; |
|
||||||
else |
|
||||||
solarTerms = ""; |
|
||||||
|
|
||||||
//计算公历节日
|
|
||||||
this.solarFestival = ""; |
|
||||||
for (int i = 0; i < sFtv.length; i++) { |
|
||||||
if (Integer.parseInt(sFtv[i].substring(0, 2)) == m |
|
||||||
&& Integer.parseInt(sFtv[i].substring(2, 4)) == d) { |
|
||||||
solarFestival = sFtv[i].substring(5); |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
//计算农历节日
|
|
||||||
this.lunarFestival = ""; |
|
||||||
for (int i = 0; i < lFtv.length; i++) { |
|
||||||
if (Integer.parseInt(lFtv[i].substring(0, 2)) == lmonth |
|
||||||
&& Integer.parseInt(lFtv[i].substring(2, 4)) == lday) { |
|
||||||
lunarFestival = lFtv[i].substring(5); |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
//计算月周节日
|
|
||||||
|
|
||||||
// System.out.println(baseDate.get(Calendar.WEEK_OF_MONTH) + ""
|
|
||||||
// + baseDate.get(Calendar.DAY_OF_WEEK));
|
|
||||||
|
|
||||||
for (int i = 0; i < wFtv.length; i++) { |
|
||||||
if (Integer.parseInt(wFtv[i].substring(0, 2)) == m |
|
||||||
&& Integer.parseInt(wFtv[i].substring(2, 3)) == baseDate |
|
||||||
.get(Calendar.WEEK_OF_MONTH) |
|
||||||
&& Integer.parseInt(wFtv[i].substring(3, 4)) == baseDate |
|
||||||
.get(Calendar.DAY_OF_WEEK)) { |
|
||||||
solarFestival += wFtv[i].substring(5); |
|
||||||
} |
|
||||||
} |
|
||||||
if(!StringHelper.isEmpty(lunarFestival)){ |
|
||||||
return lunarFestival; |
|
||||||
} |
|
||||||
if(!StringHelper.isEmpty(solarFestival)){ |
|
||||||
return solarFestival; |
|
||||||
} |
|
||||||
if(!StringHelper.isEmpty(solarTerms)){ |
|
||||||
return solarTerms; |
|
||||||
} |
|
||||||
return ""; |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
//set方法
|
|
||||||
public void set(int y, int m, int d) { |
|
||||||
|
|
||||||
CalculateLunarCalendar(y, m, d); |
|
||||||
} |
|
||||||
|
|
||||||
public void set(Calendar cal) { |
|
||||||
|
|
||||||
CalculateLunarCalendar(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH)); |
|
||||||
} |
|
||||||
|
|
||||||
// //get方法组
|
|
||||||
public static LunarCalendar getInstance() { |
|
||||||
|
|
||||||
return new LunarCalendar(); |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,68 @@ |
|||||||
|
package xyz.fycz.myreader.util.utils; |
||||||
|
|
||||||
|
import android.graphics.drawable.Drawable; |
||||||
|
import android.view.View; |
||||||
|
import android.widget.TextView; |
||||||
|
import androidx.annotation.NonNull; |
||||||
|
import com.google.android.material.snackbar.Snackbar; |
||||||
|
import xyz.fycz.myreader.R; |
||||||
|
import xyz.fycz.myreader.application.MyApplication; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Created by zhouas666 on 2017/12/28. |
||||||
|
* Snackbar工具类 |
||||||
|
*/ |
||||||
|
public class SnackbarUtils { |
||||||
|
|
||||||
|
|
||||||
|
public static void show(@NonNull View view, @NonNull String msg) { |
||||||
|
show(view, msg, true, null, null); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 展示snackBar |
||||||
|
* |
||||||
|
* @param view view |
||||||
|
* @param msg 消息 |
||||||
|
* @param isDismiss 是否自动消失 |
||||||
|
* @param action 事件名 |
||||||
|
* @param iSnackBarClickEvent 事件处理接口 |
||||||
|
*/ |
||||||
|
public static void show(@NonNull View view, @NonNull String msg, boolean isDismiss, String action, final ISnackBarClickEvent iSnackBarClickEvent) { |
||||||
|
//snackBar默认显示时间为LENGTH_LONG
|
||||||
|
int duringTime = Snackbar.LENGTH_LONG; |
||||||
|
if (!isDismiss) { |
||||||
|
duringTime = Snackbar.LENGTH_INDEFINITE; |
||||||
|
} |
||||||
|
Snackbar snackbar; |
||||||
|
snackbar = Snackbar.make(view, msg, duringTime); |
||||||
|
if (action != null) |
||||||
|
snackbar.setAction(action, view1 -> { |
||||||
|
//以接口方式发送出去,便于使用者处理自己的业务逻辑
|
||||||
|
iSnackBarClickEvent.clickEvent(); |
||||||
|
}); |
||||||
|
//设置snackBar和titleBar颜色一致
|
||||||
|
snackbar.getView().setBackgroundColor(MyApplication.getmContext().getColor(R.color.textPrimary)); |
||||||
|
//设置action文字的颜色
|
||||||
|
snackbar.setActionTextColor(MyApplication.getmContext().getColor(R.color.md_white_1000)); |
||||||
|
//设置snackBar图标 这里是获取到snackBar的textView 然后给textView增加左边图标的方式来实现的
|
||||||
|
View snackBarView = snackbar.getView(); |
||||||
|
TextView textView = snackBarView.findViewById(R.id.snackbar_text); |
||||||
|
/*Drawable drawable = getResources().getDrawable(R.mipmap.ic_notification);//图片自己选择
|
||||||
|
drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight()); |
||||||
|
textView.setCompoundDrawables(drawable, null, null, null);*/ |
||||||
|
//增加文字和图标的距离
|
||||||
|
textView.setCompoundDrawablePadding(20); |
||||||
|
//展示snackBar
|
||||||
|
snackbar.show(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* snackBar的action事件 |
||||||
|
*/ |
||||||
|
public interface ISnackBarClickEvent { |
||||||
|
void clickEvent(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,161 @@ |
|||||||
|
package xyz.fycz.myreader.util.utils; |
||||||
|
|
||||||
|
import android.app.Activity; |
||||||
|
import android.os.Build; |
||||||
|
import android.view.View; |
||||||
|
import android.view.WindowManager; |
||||||
|
|
||||||
|
/** |
||||||
|
* 基于 Android 4.4 |
||||||
|
* |
||||||
|
* 主要参数说明: |
||||||
|
* |
||||||
|
* SYSTEM_UI_FLAG_FULLSCREEN : 隐藏StatusBar |
||||||
|
* SYSTEM_UI_FLAG_HIDE_NAVIGATION : 隐藏NavigationBar |
||||||
|
* SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN: 视图扩展到StatusBar的位置,并且StatusBar不消失。 |
||||||
|
* 这里需要一些处理,一般是将StatusBar设置为全透明或者半透明。之后还需要使用fitSystemWindows=防止视图扩展到Status |
||||||
|
* Bar上面(会在StatusBar上加一层View,该View可被移动) |
||||||
|
* SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION: 视图扩展到NavigationBar的位置 |
||||||
|
* SYSTEM_UI_FLAG_LAYOUT_STABLE:稳定效果 |
||||||
|
* SYSTEM_UI_FLAG_IMMERSIVE_STICKY:保证点击任意位置不会退出 |
||||||
|
* |
||||||
|
* 可设置特效说明: |
||||||
|
* 1. 全屏特效 |
||||||
|
* 2. 全屏点击不退出特效 |
||||||
|
* 3. 注意在19 <=sdk <=21 时候,必须通过Window设置透明栏 |
||||||
|
*/ |
||||||
|
|
||||||
|
public class SystemBarUtils { |
||||||
|
|
||||||
|
private static final int UNSTABLE_STATUS = View.SYSTEM_UI_FLAG_FULLSCREEN; |
||||||
|
private static final int UNSTABLE_NAV = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; |
||||||
|
private static final int STABLE_STATUS = View.SYSTEM_UI_FLAG_FULLSCREEN | |
||||||
|
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | |
||||||
|
View.SYSTEM_UI_FLAG_LAYOUT_STABLE | |
||||||
|
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; |
||||||
|
private static final int STABLE_NAV = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | |
||||||
|
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | |
||||||
|
View.SYSTEM_UI_FLAG_LAYOUT_STABLE | |
||||||
|
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; |
||||||
|
private static final int EXPAND_STATUS = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
||||||
|
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE; |
||||||
|
private static final int EXPAND_NAV = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
||||||
|
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE; |
||||||
|
|
||||||
|
|
||||||
|
//设置隐藏StatusBar(点击任意地方会恢复)
|
||||||
|
public static void hideUnStableStatusBar(Activity activity){ |
||||||
|
//App全屏,隐藏StatusBar
|
||||||
|
setFlag(activity, UNSTABLE_STATUS); |
||||||
|
} |
||||||
|
|
||||||
|
public static void showUnStableStatusBar(Activity activity){ |
||||||
|
clearFlag(activity, UNSTABLE_STATUS); |
||||||
|
} |
||||||
|
|
||||||
|
//隐藏NavigationBar(点击任意地方会恢复)
|
||||||
|
public static void hideUnStableNavBar(Activity activity){ |
||||||
|
setFlag(activity,UNSTABLE_NAV); |
||||||
|
} |
||||||
|
|
||||||
|
public static void showUnStableNavBar(Activity activity){ |
||||||
|
clearFlag(activity,UNSTABLE_NAV); |
||||||
|
} |
||||||
|
|
||||||
|
public static void hideStableStatusBar(Activity activity){ |
||||||
|
//App全屏,隐藏StatusBar
|
||||||
|
setFlag(activity,STABLE_STATUS); |
||||||
|
} |
||||||
|
|
||||||
|
public static void showStableStatusBar(Activity activity){ |
||||||
|
clearFlag(activity,STABLE_STATUS); |
||||||
|
} |
||||||
|
|
||||||
|
public static void hideStableNavBar(Activity activity){ |
||||||
|
//App全屏,隐藏StatusBar
|
||||||
|
setFlag(activity,STABLE_NAV); |
||||||
|
} |
||||||
|
|
||||||
|
public static void showStableNavBar(Activity activity){ |
||||||
|
clearFlag(activity,STABLE_NAV); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 视图扩充到StatusBar |
||||||
|
*/ |
||||||
|
public static void expandStatusBar(Activity activity){ |
||||||
|
setFlag(activity, EXPAND_STATUS); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 视图扩充到NavBar |
||||||
|
* @param activity |
||||||
|
*/ |
||||||
|
public static void expandNavBar(Activity activity){ |
||||||
|
setFlag(activity, EXPAND_NAV); |
||||||
|
} |
||||||
|
|
||||||
|
public static void transparentStatusBar(Activity activity){ |
||||||
|
if (Build.VERSION.SDK_INT >= 21){ |
||||||
|
expandStatusBar(activity); |
||||||
|
activity.getWindow() |
||||||
|
.setStatusBarColor(activity.getResources().getColor(android.R.color.transparent)); |
||||||
|
} |
||||||
|
else if (Build.VERSION.SDK_INT >= 19){ |
||||||
|
WindowManager.LayoutParams attrs = activity.getWindow().getAttributes(); |
||||||
|
attrs.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | attrs.flags); |
||||||
|
activity.getWindow().setAttributes(attrs); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static void transparentNavBar(Activity activity){ |
||||||
|
if (Build.VERSION.SDK_INT >= 21){ |
||||||
|
expandNavBar(activity); |
||||||
|
//下面这个方法在sdk:21以上才有
|
||||||
|
activity.getWindow() |
||||||
|
.setNavigationBarColor(activity.getResources().getColor(android.R.color.transparent)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static void setFlag(Activity activity, int flag){ |
||||||
|
if (Build.VERSION.SDK_INT >= 19){ |
||||||
|
View decorView = activity.getWindow().getDecorView(); |
||||||
|
int option = decorView.getSystemUiVisibility() | flag; |
||||||
|
decorView.setSystemUiVisibility(option); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
//取消flag
|
||||||
|
public static void clearFlag(Activity activity, int flag){ |
||||||
|
if (Build.VERSION.SDK_INT >= 19){ |
||||||
|
View decorView = activity.getWindow().getDecorView(); |
||||||
|
int option = decorView.getSystemUiVisibility() & (~flag); |
||||||
|
decorView.setSystemUiVisibility(option); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static void setToggleFlag(Activity activity, int option){ |
||||||
|
if (Build.VERSION.SDK_INT >= 19){ |
||||||
|
if (isFlagUsed(activity,option)){ |
||||||
|
clearFlag(activity,option); |
||||||
|
} |
||||||
|
else { |
||||||
|
setFlag(activity,option); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @param activity |
||||||
|
* @return flag是否已被使用 |
||||||
|
*/ |
||||||
|
public static boolean isFlagUsed(Activity activity, int flag) { |
||||||
|
int currentFlag = activity.getWindow().getDecorView().getSystemUiVisibility(); |
||||||
|
if((currentFlag & flag) |
||||||
|
== flag) { |
||||||
|
return true; |
||||||
|
}else { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,7 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<set xmlns:android="http://schemas.android.com/apk/res/android"> |
||||||
|
<translate |
||||||
|
android:fromYDelta="100%" |
||||||
|
android:toYDelta="0" |
||||||
|
android:duration="200"/> |
||||||
|
</set> |
@ -0,0 +1,7 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<set xmlns:android="http://schemas.android.com/apk/res/android"> |
||||||
|
<translate |
||||||
|
android:fromYDelta="0" |
||||||
|
android:toYDelta="100%" |
||||||
|
android:duration="200"/> |
||||||
|
</set> |
@ -0,0 +1,8 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<set xmlns:android="http://schemas.android.com/apk/res/android"> |
||||||
|
<translate android:fromXDelta="0" |
||||||
|
android:fromYDelta="-100%" |
||||||
|
android:toXDelta="0" |
||||||
|
android:toYDelta="0" |
||||||
|
android:duration="200"/> |
||||||
|
</set> |
@ -0,0 +1,6 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<set xmlns:android="http://schemas.android.com/apk/res/android"> |
||||||
|
<translate android:fromYDelta="0" |
||||||
|
android:toYDelta="-100%" |
||||||
|
android:duration="200"/> |
||||||
|
</set> |
Before Width: | Height: | Size: 169 B |
Before Width: | Height: | Size: 463 B |
Before Width: | Height: | Size: 460 B |
Before Width: | Height: | Size: 137 B |
Before Width: | Height: | Size: 308 B |
Before Width: | Height: | Size: 290 B |
Before Width: | Height: | Size: 7.9 KiB |
Before Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 428 KiB |
Before Width: | Height: | Size: 182 B |
Before Width: | Height: | Size: 604 B |
Before Width: | Height: | Size: 550 B |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 247 B |
Before Width: | Height: | Size: 205 B |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 898 B |
Before Width: | Height: | Size: 834 B |
Before Width: | Height: | Size: 244 B |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.1 KiB |
@ -1,11 +1,12 @@ |
|||||||
<?xml version="1.0" encoding="utf-8"?> |
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
android:width="24dp" |
android:width="24dp" |
||||||
android:height="24dp" |
android:height="24dp" |
||||||
android:viewportWidth="24" |
android:viewportWidth="1024" |
||||||
android:viewportHeight="24"> |
android:viewportHeight="1024"> |
||||||
|
<path |
||||||
<path |
android:fillColor="#FFFFFF" |
||||||
android:fillColor="@color/white" |
android:pathData="M364.9,460.4c-51.5,0 -93.5,-41.9 -93.5,-93.5 0,-51.5 41.9,-93.5 93.5,-93.5s93.5,41.9 93.5,93.5c-0.1,51.5 -42,93.5 -93.5,93.5zM364.9,319.2c-26.3,0 -47.7,21.4 -47.7,47.7 0,26.3 21.4,47.7 47.7,47.7s47.7,-21.4 47.7,-47.7c0,-26.3 -21.4,-47.7 -47.7,-47.7z"/> |
||||||
android:pathData="M5.938,4v16h1.414l4.648-2.789L16.649,20h1.411V4H5.938z M16.606,18.278l-4.605-2.763l-4.609,2.764 V5.454h9.215V18.278z" /> |
<path |
||||||
</vector> |
android:fillColor="#FFFFFF" |
||||||
|
android:pathData="M951.1,588.1L437.3,73.4c-5.3,-5.4 -12.5,-8.4 -20,-8.4L93,64c-7.7,0 -15.2,3 -20.6,8.5 -5.5,5.4 -8.5,12.8 -8.4,20.5l0.7,321.7c0.1,7.4 3.1,14.6 8.4,19.8l359,360.7c10.6,10.6 27.6,11.2 38.9,1.4 12.6,-10.9 13.3,-30.1 1.6,-41.9L127.8,408.3c-3.9,-3.9 -6.1,-9.1 -6.2,-14.6l0.3,-250.9c-0.2,-11.8 9.4,-21.4 21.1,-21.3l253.4,0.6c5.5,0 10.8,2.2 14.7,6.2l464.5,465.5c8.2,8.2 8.2,21.5 0,29.7L626.2,873c-8.2,8.2 -21.5,8.2 -29.7,0l-19,-19c-10.6,-10.6 -27.6,-11.2 -38.9,-1.4 -12.6,10.9 -13.3,30.1 -1.6,41.9l53.9,53.9c11.3,11.3 29.6,11.3 40.9,0L951.1,629c11.3,-11.3 11.3,-29.6 0,-40.9z"/> |
||||||
|
</vector> |
||||||
|
@ -0,0 +1,9 @@ |
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
android:width="24dp" |
||||||
|
android:height="24dp" |
||||||
|
android:viewportWidth="1024" |
||||||
|
android:viewportHeight="1024"> |
||||||
|
<path |
||||||
|
android:fillColor="#FFFFFF" |
||||||
|
android:pathData="M640,320 L192,320C156.61,320 128,348.61 128,384l0,512c0,35.33 28.61,64 64,64l448,0c35.39,0 64,-28.67 64,-64L704,384C704,348.61 675.39,320 640,320zM640,896 L192,896 192,384l448,0L640,896zM832,128 L352,128C334.34,128 320,142.34 320,160S334.34,192 352,192L832,192l0,544c0,17.66 14.34,32 32,32s32,-14.34 32,-32L896,192C896,156.61 867.39,128 832,128z"/> |
||||||
|
</vector> |
@ -1,14 +1,12 @@ |
|||||||
<?xml version="1.0" encoding="utf-8"?> |
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
android:width="24dp" |
android:width="24dp" |
||||||
android:height="24dp" |
android:height="24dp" |
||||||
android:viewportWidth="24" |
android:viewportWidth="1024" |
||||||
android:viewportHeight="24"> |
android:viewportHeight="1024"> |
||||||
|
<path |
||||||
<path |
android:fillColor="#FFFFFF" |
||||||
android:fillColor="#FFFFFF" |
android:pathData="M762.24,506.88a32,32 0,0 1,-46.08 -44.16l55.68,-58.24a125.76,125.76 0,0 0,-12.16 -171.2c-48.32,-50.24 -119.68,-54.72 -160,-12.48L444.16,384a125.76,125.76 0,0 0,12.16 171.2,32 32,0 0,1 0,45.12 32,32 0,0 1,-45.44 0,189.44 189.44,0 0,1 -12.16,-259.52l155.52,-162.24c66.88,-69.76 180.48,-64 252.8,12.8A189.44,189.44 0,0 1,818.24 448z"/> |
||||||
android:pathData="M18.545,18.304c0,0.131-0.11,0.242-0.241,0.242H5.696c-0.131,0-0.242-0.111-0.242-0.242V5.697 c0-0.131,0.111-0.243,0.242-0.243H12V4H5.696C4.76,4,4,4.762,4,5.697v12.606C4,19.239,4.76,20,5.696,20h12.607 C19.239,20,20,19.239,20,18.304v-6.303h-1.455V18.304z" /> |
<path |
||||||
<path |
android:fillColor="#FFFFFF" |
||||||
android:fillColor="#FFFFFF" |
android:pathData="M229.76,517.12a32,32 0,0 1,46.08 44.16l-55.68,58.24a125.76,125.76 0,0 0,12.16 171.2c48.32,50.24 119.68,54.72 160,12.48L547.84,640a125.76,125.76 0,0 0,-12.16 -171.2,32 32,0 0,1 0,-45.12 32,32 0,0 1,45.44 0,189.44 189.44,0 0,1 12.16,259.52L437.76,845.44c-66.88,69.76 -180.48,64 -252.8,-12.8A189.44,189.44 0,0 1,173.76 576z"/> |
||||||
android:pathData="M 19.272 4 L 13.843 4 L 13.843 5.454 L 17.517 5.454 L 7.464 15.508 L 8.491 16.536 L 18.545 6.482 L 18.545 10.157 L 20 10.157 L 20 4.727 L 20 4 Z" /> |
</vector> |
||||||
</vector> |
|
||||||
|
@ -0,0 +1,9 @@ |
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
android:width="24.117188dp" |
||||||
|
android:height="24dp" |
||||||
|
android:viewportWidth="1029" |
||||||
|
android:viewportHeight="1024"> |
||||||
|
<path |
||||||
|
android:fillColor="#9fc6ff" |
||||||
|
android:pathData="M918.39,829.23 L749.22,660.07c-2.93,-2.93 -6.58,-4.37 -9.99,-6.58 98.28,-138.95 86.08,-332.16 -38.34,-456.58 -139.01,-139.07 -364.46,-139.07 -503.54,0 -139.07,139.01 -139.07,364.4 0,503.54 125.79,125.79 321.64,136.56 460.95,34.81 2.21,3.17 3.59,6.64 6.34,9.45l169.16,169.16c23.45,23.39 61.25,23.39 84.58,0C941.71,890.43 941.71,852.56 918.39,829.23L918.39,829.23zM629.65,629.09c-99.65,99.65 -261.22,99.65 -360.93,0 -99.65,-99.65 -99.65,-261.28 0,-360.93 99.65,-99.65 261.22,-99.65 360.93,0C729.36,367.87 729.36,529.43 629.65,629.09L629.65,629.09z"/> |
||||||
|
</vector> |
@ -1,241 +0,0 @@ |
|||||||
<?xml version="1.0" encoding="utf-8"?> |
|
||||||
<LinearLayout 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:fitsSystemWindows="true" |
|
||||||
android:orientation="vertical"> |
|
||||||
|
|
||||||
<include layout="@layout/toolbar" /> |
|
||||||
|
|
||||||
<RelativeLayout |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="match_parent"> |
|
||||||
<!--背景图片--> |
|
||||||
<ImageView |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="match_parent" |
|
||||||
android:scaleType="fitXY" |
|
||||||
app:srcCompat="@drawable/bg_login" /> |
|
||||||
<!--添加虚化层--> |
|
||||||
<io.alterac.blurkit.BlurLayout |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="match_parent" |
|
||||||
app:blk_blurRadius="5" |
|
||||||
app:blk_fps="0" /> |
|
||||||
|
|
||||||
<!-- 猫头鹰--> |
|
||||||
<!-- <RelativeLayout--> |
|
||||||
<!-- android:layout_width="300dp"--> |
|
||||||
<!-- android:layout_height="200dp"--> |
|
||||||
<!-- android:layout_centerHorizontal="true"--> |
|
||||||
<!-- android:layout_alignTop="@+id/bg"--> |
|
||||||
<!-- android:layout_marginTop="-75dp">--> |
|
||||||
|
|
||||||
<!-- <!–头像–>--> |
|
||||||
<!-- <ImageView--> |
|
||||||
<!-- android:id="@+id/iv_head"--> |
|
||||||
<!-- android:layout_width="wrap_content"--> |
|
||||||
<!-- android:layout_height="wrap_content"--> |
|
||||||
<!-- android:src="@drawable/owl_head"--> |
|
||||||
<!-- android:layout_centerHorizontal="true"--> |
|
||||||
<!-- />--> |
|
||||||
|
|
||||||
<!-- <!–手掌–>--> |
|
||||||
<!-- <ImageView--> |
|
||||||
<!-- android:id="@+id/iv_left_hand"--> |
|
||||||
<!-- android:layout_width="50dp"--> |
|
||||||
<!-- android:layout_height="60dp"--> |
|
||||||
<!-- android:src="@drawable/icon_hand"--> |
|
||||||
<!-- android:layout_alignParentLeft="true"--> |
|
||||||
<!-- android:layout_alignBottom="@+id/iv_head"--> |
|
||||||
<!-- android:layout_marginBottom="-25dp"--> |
|
||||||
<!-- android:layout_marginLeft="10dp"/>--> |
|
||||||
<!-- <ImageView--> |
|
||||||
<!-- android:id="@+id/iv_right_hand"--> |
|
||||||
<!-- android:layout_width="50dp"--> |
|
||||||
<!-- android:layout_height="60dp"--> |
|
||||||
<!-- android:src="@drawable/icon_hand"--> |
|
||||||
<!-- android:layout_alignParentRight="true"--> |
|
||||||
<!-- android:layout_alignBottom="@+id/iv_head"--> |
|
||||||
<!-- android:layout_marginBottom="-25dp"--> |
|
||||||
<!-- android:layout_marginRight="10dp"/>--> |
|
||||||
|
|
||||||
<!-- <!–翅膀–>--> |
|
||||||
<!-- <ImageView--> |
|
||||||
<!-- android:id="@+id/iv_left_arm"--> |
|
||||||
<!-- android:layout_width="65dp"--> |
|
||||||
<!-- android:layout_height="40dp"--> |
|
||||||
<!-- android:src="@drawable/arm_left"--> |
|
||||||
<!-- android:layout_below="@+id/iv_head"--> |
|
||||||
<!-- android:layout_alignParentLeft="true"--> |
|
||||||
<!-- android:layout_marginLeft="20dp"/>--> |
|
||||||
|
|
||||||
<!-- <ImageView--> |
|
||||||
<!-- android:id="@+id/iv_right_arm"--> |
|
||||||
<!-- android:layout_width="65dp"--> |
|
||||||
<!-- android:layout_height="40dp"--> |
|
||||||
<!-- android:src="@drawable/arm_right"--> |
|
||||||
<!-- android:layout_below="@+id/iv_head"--> |
|
||||||
<!-- android:layout_alignParentRight="true"--> |
|
||||||
<!-- android:layout_marginRight="20dp"/>--> |
|
||||||
<!-- </RelativeLayout>--> |
|
||||||
|
|
||||||
<View |
|
||||||
android:id="@+id/bg" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="280dp" |
|
||||||
android:layout_centerInParent="true" |
|
||||||
android:layout_marginLeft="20dp" |
|
||||||
android:layout_marginRight="20dp" |
|
||||||
android:background="@drawable/input_bg_shape" /> |
|
||||||
|
|
||||||
<io.alterac.blurkit.BlurLayout |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="280dp" |
|
||||||
android:layout_centerInParent="true" |
|
||||||
android:layout_marginLeft="20dp" |
|
||||||
android:layout_marginRight="20dp" |
|
||||||
app:blk_blurRadius="20" |
|
||||||
app:blk_fps="0" /> |
|
||||||
|
|
||||||
<!--添加标题和输入框--> |
|
||||||
<LinearLayout |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:layout_centerInParent="true" |
|
||||||
android:layout_marginLeft="20dp" |
|
||||||
android:layout_marginRight="20dp" |
|
||||||
android:orientation="vertical" |
|
||||||
android:padding="20dp"> |
|
||||||
|
|
||||||
<!--标题--> |
|
||||||
<TextView |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:text="@string/text_login" |
|
||||||
android:textAlignment="center" |
|
||||||
android:textColor="@color/textSecondary" |
|
||||||
android:textSize="20dp" /> |
|
||||||
|
|
||||||
<!--添加输入框--> |
|
||||||
<!--<EditText |
|
||||||
android:id="@+id/et_user" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="50dp" |
|
||||||
android:background="@drawable/editview_shape" |
|
||||||
android:drawableStart="@drawable/iconfont_user" |
|
||||||
android:drawablePadding="10dp" |
|
||||||
android:hint="@string/et_account_tip" |
|
||||||
android:inputType="text" |
|
||||||
android:maxLines="1" |
|
||||||
android:paddingStart="10dp" |
|
||||||
android:textSize="18dp" />--> |
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout |
|
||||||
android:id="@+id/et_user" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:layout_marginTop="20dp" |
|
||||||
android:drawablePadding="10dp" |
|
||||||
app:counterEnabled="true" |
|
||||||
app:counterMaxLength="14"> |
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:hint="@string/et_account_tip" |
|
||||||
android:inputType="text"/> |
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout> |
|
||||||
<!--<EditText |
|
||||||
android:id="@+id/et_password" |
|
||||||
style="@style/EditTextStyle" |
|
||||||
android:background="@drawable/editview_shape" |
|
||||||
android:drawableStart="@drawable/iconfont_password" |
|
||||||
android:hint="@string/et_password_tip" |
|
||||||
android:inputType="textPassword" |
|
||||||
android:textSize="18dp" />--> |
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout |
|
||||||
android:id="@+id/et_password" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:drawablePadding="10dp" |
|
||||||
app:counterEnabled="true" |
|
||||||
app:counterMaxLength="16" |
|
||||||
app:passwordToggleEnabled="true" |
|
||||||
app:passwordToggleTintMode="src_in"> |
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:hint="@string/et_password_tip" |
|
||||||
android:inputType="textPassword"/> |
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout> |
|
||||||
<LinearLayout |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:orientation="horizontal"> |
|
||||||
|
|
||||||
<!--<EditText |
|
||||||
android:id="@+id/et_captcha" |
|
||||||
style="@style/EditTextStyle" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_weight="1" |
|
||||||
android:background="@drawable/editview_shape" |
|
||||||
android:hint="@string/et_rp_captcha" |
|
||||||
android:inputType="text" |
|
||||||
android:textSize="18dp" />--> |
|
||||||
<com.google.android.material.textfield.TextInputLayout |
|
||||||
android:id="@+id/et_captcha" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:layout_weight="1" |
|
||||||
android:drawablePadding="10dp" |
|
||||||
app:counterEnabled="true" |
|
||||||
app:counterMaxLength="4"> |
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:hint="@string/et_rp_captcha" |
|
||||||
android:inputType="text"/> |
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout> |
|
||||||
|
|
||||||
<ImageView |
|
||||||
android:id="@+id/iv_captcha" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:layout_weight="3" |
|
||||||
android:layout_gravity="center_vertical" |
|
||||||
android:paddingStart="7dp" /> |
|
||||||
|
|
||||||
</LinearLayout> |
|
||||||
<!--登录按钮--> |
|
||||||
<Button |
|
||||||
android:id="@+id/bt_login" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="50dp" |
|
||||||
android:layout_marginTop="20dp" |
|
||||||
android:background="@drawable/login_btn_selector" |
|
||||||
android:enabled="false" |
|
||||||
android:text="@string/text_login" |
|
||||||
android:textAlignment="center" |
|
||||||
android:textColor="@color/textPrimaryInverted" |
|
||||||
android:textSize="25dp" /> |
|
||||||
|
|
||||||
<TextView |
|
||||||
android:id="@+id/tv_register" |
|
||||||
android:layout_width="wrap_content" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:layout_marginTop="10dp" |
|
||||||
android:text="@string/tv_register" |
|
||||||
android:textColor="@color/colorAccent" /> |
|
||||||
</LinearLayout> |
|
||||||
</RelativeLayout> |
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout> |
|
@ -0,0 +1,199 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
xmlns:tools="http://schemas.android.com/tools" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"> |
||||||
|
|
||||||
|
<com.google.android.material.appbar.AppBarLayout |
||||||
|
android:id="@+id/read_abl_top_menu" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:background="@color/read_menu_bg" |
||||||
|
android:visibility="gone" |
||||||
|
tools:visibility="visible"> |
||||||
|
|
||||||
|
<LinearLayout |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:orientation="vertical"> |
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar |
||||||
|
android:id="@+id/toolbar" |
||||||
|
style="@style/NoPaddingToolbar" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="45dp" |
||||||
|
android:minHeight="?attr/actionBarSize" |
||||||
|
android:gravity="center_vertical" |
||||||
|
android:theme="?attr/actionBarStyle" |
||||||
|
android:transitionName="sharedView" |
||||||
|
app:title="大主宰" |
||||||
|
app:layout_scrollFlags="scroll|enterAlways" |
||||||
|
app:popupTheme="@style/AppTheme.PopupOverlay"> |
||||||
|
</androidx.appcompat.widget.Toolbar> |
||||||
|
<View |
||||||
|
android:layout_width="fill_parent" |
||||||
|
android:layout_height="0.5dp" |
||||||
|
android:background="@color/sys_dialog_setting_line" /> |
||||||
|
<LinearLayout |
||||||
|
android:id="@+id/ll_chapter_view" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="40dp" |
||||||
|
android:orientation="vertical"> |
||||||
|
<TextView android:id="@+id/tv_chapter_title_top" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_marginStart="14dp" |
||||||
|
android:layout_marginEnd="14dp" |
||||||
|
android:textSize="15sp" |
||||||
|
android:text="章节名称" |
||||||
|
android:ellipsize="end" |
||||||
|
android:maxLines="1" |
||||||
|
android:textColor="@color/read_menu_text"> |
||||||
|
</TextView> |
||||||
|
<TextView android:id="@+id/tv_chapter_url" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_marginStart="14dp" |
||||||
|
android:layout_marginEnd="14dp" |
||||||
|
android:ellipsize="end" |
||||||
|
android:textSize="13sp" |
||||||
|
android:text="章节链接" |
||||||
|
android:maxLines="1" |
||||||
|
android:textColor="@color/read_menu_text"> |
||||||
|
</TextView> |
||||||
|
</LinearLayout> |
||||||
|
</LinearLayout> |
||||||
|
</com.google.android.material.appbar.AppBarLayout> |
||||||
|
|
||||||
|
<!--阅读页面--> |
||||||
|
<xyz.fycz.myreader.widget.page.PageView |
||||||
|
android:id="@+id/read_pv_content" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent" |
||||||
|
android:clickable="true" |
||||||
|
tools:visibility="gone"/> |
||||||
|
<com.h6ah4i.android.widget.verticalseekbar.VerticalSeekBarWrapper |
||||||
|
android:layout_width="wrap_content" |
||||||
|
android:layout_height="match_parent" |
||||||
|
android:layout_marginTop="20dp" |
||||||
|
android:layout_marginBottom="20dp"> |
||||||
|
<com.h6ah4i.android.widget.verticalseekbar.VerticalSeekBar |
||||||
|
android:id="@+id/pb_nextPage" |
||||||
|
android:layout_width="wrap_content" |
||||||
|
android:layout_height="match_parent" |
||||||
|
android:splitTrack="false" |
||||||
|
app:seekBarRotation="CW270" |
||||||
|
android:visibility="invisible" |
||||||
|
tools:visibility="visible"/> |
||||||
|
</com.h6ah4i.android.widget.verticalseekbar.VerticalSeekBarWrapper> |
||||||
|
<ProgressBar |
||||||
|
android:id="@+id/pb_loading" |
||||||
|
android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_centerInParent="true" |
||||||
|
android:visibility="gone" |
||||||
|
tools:visibility="visible"/> |
||||||
|
|
||||||
|
<!--切换页面提示--> |
||||||
|
<TextView |
||||||
|
android:id="@+id/read_tv_page_tip" |
||||||
|
android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_above="@+id/read_ll_bottom_menu" |
||||||
|
android:layout_centerHorizontal="true" |
||||||
|
android:layout_marginBottom="10dp" |
||||||
|
android:background="@color/read_menu_bg" |
||||||
|
android:gravity="center" |
||||||
|
android:paddingLeft="12dp" |
||||||
|
android:paddingTop="8dp" |
||||||
|
android:paddingRight="12dp" |
||||||
|
android:paddingBottom="8dp" |
||||||
|
android:text="1/12" |
||||||
|
android:textColor="@color/md_white_1000" |
||||||
|
android:visibility="gone"/> |
||||||
|
|
||||||
|
<!--底部页面--> |
||||||
|
<LinearLayout |
||||||
|
android:id="@+id/read_ll_bottom_menu" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_alignParentBottom="true" |
||||||
|
android:background="@color/read_menu_bg" |
||||||
|
android:clickable="true" |
||||||
|
android:orientation="vertical" |
||||||
|
android:visibility="gone" |
||||||
|
tools:visibility="visible"> |
||||||
|
|
||||||
|
<!--页面进度栏--> |
||||||
|
<LinearLayout |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="60dp" |
||||||
|
android:gravity="center_vertical" |
||||||
|
android:orientation="horizontal"> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:id="@+id/read_tv_pre_chapter" |
||||||
|
style="@style/MAppTheme.TextAppearance.Read.BottomMenu" |
||||||
|
android:layout_width="80dp" |
||||||
|
android:layout_height="match_parent" |
||||||
|
android:gravity="center" |
||||||
|
android:text="上一章"/> |
||||||
|
|
||||||
|
<SeekBar |
||||||
|
android:id="@+id/read_sb_chapter_progress" |
||||||
|
android:layout_width="0dp" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_weight="1" |
||||||
|
android:max="100" |
||||||
|
android:maxHeight="3dp" |
||||||
|
android:minHeight="3dp" |
||||||
|
android:progressDrawable="@drawable/seekbar_bg" |
||||||
|
android:thumb="@mipmap/thumb" |
||||||
|
android:thumbOffset="10dp"/> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:id="@+id/read_tv_next_chapter" |
||||||
|
style="@style/MAppTheme.TextAppearance.Read.BottomMenu" |
||||||
|
android:layout_width="80dp" |
||||||
|
android:layout_height="match_parent" |
||||||
|
android:gravity="center" |
||||||
|
android:text="下一章"/> |
||||||
|
</LinearLayout> |
||||||
|
<View |
||||||
|
android:layout_width="fill_parent" |
||||||
|
android:layout_height="0.5dp" |
||||||
|
android:background="@color/sys_dialog_setting_line" /> |
||||||
|
<!--菜单栏--> |
||||||
|
<LinearLayout |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="72dp" |
||||||
|
android:orientation="horizontal" |
||||||
|
android:paddingTop="12dp" |
||||||
|
android:paddingBottom="12dp"> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:id="@+id/read_tv_category" |
||||||
|
style="@style/AppTheme.TextAppearance.Read.BottomMenu.Button" |
||||||
|
android:drawableTop="@mipmap/t3" |
||||||
|
android:text="目录"/> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:id="@+id/read_tv_download" |
||||||
|
style="@style/AppTheme.TextAppearance.Read.BottomMenu.Button" |
||||||
|
android:drawableTop="@mipmap/download" |
||||||
|
android:text="下载"/> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:id="@+id/read_tv_night_mode" |
||||||
|
style="@style/AppTheme.TextAppearance.Read.BottomMenu.Button" |
||||||
|
android:drawableTop="@mipmap/ao" |
||||||
|
android:text="夜间"/> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:id="@+id/read_tv_setting" |
||||||
|
style="@style/AppTheme.TextAppearance.Read.BottomMenu.Button" |
||||||
|
android:drawableTop="@mipmap/t6" |
||||||
|
android:text="设置"/> |
||||||
|
</LinearLayout> |
||||||
|
</LinearLayout> |
||||||
|
</RelativeLayout> |
@ -1,59 +0,0 @@ |
|||||||
<?xml version="1.0" encoding="utf-8"?> |
|
||||||
<androidx.drawerlayout.widget.DrawerLayout |
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android" |
|
||||||
xmlns:tools="http://schemas.android.com/tools" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" |
|
||||||
android:fitsSystemWindows="true" |
|
||||||
android:id="@+id/read_activity_new" |
|
||||||
tools:context="xyz.fycz.myreader.ui.activity.ReadActivity"> |
|
||||||
|
|
||||||
<RelativeLayout |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="match_parent"> |
|
||||||
|
|
||||||
<!--阅读页面--> |
|
||||||
<xyz.fycz.myreader.widget.page.PageView |
|
||||||
android:id="@+id/read_pv_page" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="match_parent" |
|
||||||
android:clickable="true" |
|
||||||
tools:visibility="gone"/> |
|
||||||
|
|
||||||
<com.h6ah4i.android.widget.verticalseekbar.VerticalSeekBarWrapper |
|
||||||
android:layout_width="wrap_content" |
|
||||||
android:layout_height="match_parent" |
|
||||||
android:layout_marginTop="20dp" |
|
||||||
android:layout_marginBottom="20dp"> |
|
||||||
<com.h6ah4i.android.widget.verticalseekbar.VerticalSeekBar |
|
||||||
android:id="@+id/pb_nextPage" |
|
||||||
android:layout_width="wrap_content" |
|
||||||
android:layout_height="match_parent" |
|
||||||
android:splitTrack="false" |
|
||||||
app:seekBarRotation="CW270" |
|
||||||
android:visibility="invisible"/> |
|
||||||
</com.h6ah4i.android.widget.verticalseekbar.VerticalSeekBarWrapper> |
|
||||||
|
|
||||||
<ProgressBar |
|
||||||
android:id="@+id/pb_loading" |
|
||||||
android:layout_width="wrap_content" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:layout_centerInParent="true" |
|
||||||
android:visibility="gone"/> |
|
||||||
|
|
||||||
<TextView |
|
||||||
android:id="@+id/tv_end_page_tip" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="35dp" |
|
||||||
android:layout_alignParentBottom="true" |
|
||||||
android:background="@color/sys_dialog_setting_line" |
|
||||||
android:textColor="@color/sys_dialog_setting_word_bright" |
|
||||||
android:text="@string/end_page_tip" |
|
||||||
android:gravity="center_vertical|start" |
|
||||||
android:paddingStart="15dp" |
|
||||||
android:textSize="14sp" |
|
||||||
android:visibility="gone"/> |
|
||||||
|
|
||||||
</RelativeLayout> |
|
||||||
|
|
||||||
</androidx.drawerlayout.widget.DrawerLayout> |
|
@ -1,205 +0,0 @@ |
|||||||
<?xml version="1.0" encoding="utf-8"?> |
|
||||||
<LinearLayout 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:fitsSystemWindows="true" |
|
||||||
android:orientation="vertical"> |
|
||||||
|
|
||||||
<include layout="@layout/toolbar" /> |
|
||||||
|
|
||||||
<RelativeLayout |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="match_parent"> |
|
||||||
<!--背景图片--> |
|
||||||
<ImageView |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="match_parent" |
|
||||||
android:scaleType="fitXY" |
|
||||||
app:srcCompat="@drawable/bg_login" /> |
|
||||||
<!--添加虚化层--> |
|
||||||
<io.alterac.blurkit.BlurLayout |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="match_parent" |
|
||||||
app:blk_blurRadius="5" |
|
||||||
app:blk_fps="0" /> |
|
||||||
|
|
||||||
<View |
|
||||||
android:id="@+id/bg" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="280dp" |
|
||||||
android:layout_centerInParent="true" |
|
||||||
android:layout_marginLeft="20dp" |
|
||||||
android:layout_marginRight="20dp" |
|
||||||
android:background="@drawable/input_bg_shape" /> |
|
||||||
|
|
||||||
<io.alterac.blurkit.BlurLayout |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="400dp" |
|
||||||
android:layout_centerInParent="true" |
|
||||||
android:layout_marginLeft="20dp" |
|
||||||
android:layout_marginRight="20dp" |
|
||||||
app:blk_blurRadius="20" |
|
||||||
app:blk_fps="0" /> |
|
||||||
|
|
||||||
<!--添加标题和输入框--> |
|
||||||
<LinearLayout |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:layout_centerInParent="true" |
|
||||||
android:layout_marginLeft="20dp" |
|
||||||
android:layout_marginRight="20dp" |
|
||||||
android:orientation="vertical" |
|
||||||
android:padding="20dp"> |
|
||||||
|
|
||||||
<!--标题--> |
|
||||||
<TextView |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:text="@string/text_register" |
|
||||||
android:textAlignment="center" |
|
||||||
android:textColor="@color/sys_word_little" |
|
||||||
android:textSize="20dp" /> |
|
||||||
|
|
||||||
<TextView |
|
||||||
android:id="@+id/tv_register_tip" |
|
||||||
android:layout_width="wrap_content" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:layout_marginTop="10dp" |
|
||||||
android:text="" |
|
||||||
android:textColor="@color/textError" |
|
||||||
android:visibility="gone" /> |
|
||||||
<!--添加输入框--> |
|
||||||
<com.google.android.material.textfield.TextInputLayout |
|
||||||
android:id="@+id/et_username" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:layout_marginTop="10dp" |
|
||||||
android:drawablePadding="10dp" |
|
||||||
app:counterEnabled="true" |
|
||||||
app:counterMaxLength="14"> |
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:hint="@string/et_account_tip" |
|
||||||
android:inputType="text"/> |
|
||||||
</com.google.android.material.textfield.TextInputLayout> |
|
||||||
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout |
|
||||||
android:id="@+id/et_password" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:drawablePadding="10dp" |
|
||||||
app:counterEnabled="true" |
|
||||||
app:counterMaxLength="16" |
|
||||||
app:passwordToggleEnabled="true" |
|
||||||
app:passwordToggleTintMode="src_in"> |
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:hint="@string/et_password_tip" |
|
||||||
android:inputType="textPassword"/> |
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout |
|
||||||
android:id="@+id/et_rp_password" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:drawablePadding="10dp" |
|
||||||
app:counterEnabled="true" |
|
||||||
app:counterMaxLength="16" |
|
||||||
app:passwordToggleEnabled="true" |
|
||||||
app:passwordToggleTintMode="src_in"> |
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:hint="@string/et_password_tip" |
|
||||||
android:inputType="textPassword"/> |
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout> |
|
||||||
<LinearLayout |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:orientation="horizontal"> |
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout |
|
||||||
android:id="@+id/et_captcha" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:layout_weight="1" |
|
||||||
android:drawablePadding="10dp" |
|
||||||
app:counterEnabled="true" |
|
||||||
app:counterMaxLength="4"> |
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:hint="@string/et_rp_captcha" |
|
||||||
android:inputType="text"/> |
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout> |
|
||||||
|
|
||||||
|
|
||||||
<ImageView |
|
||||||
android:id="@+id/iv_captcha" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:layout_gravity="center_vertical" |
|
||||||
android:layout_weight="3" |
|
||||||
android:paddingStart="7dp" /> |
|
||||||
|
|
||||||
</LinearLayout> |
|
||||||
|
|
||||||
<!--登录按钮--> |
|
||||||
<Button |
|
||||||
android:id="@+id/bt_register" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="50dp" |
|
||||||
android:layout_marginTop="10dp" |
|
||||||
android:background="@drawable/login_btn_selector" |
|
||||||
android:enabled="false" |
|
||||||
android:text="@string/text_register" |
|
||||||
android:textAlignment="center" |
|
||||||
android:textColor="#ffffff" |
|
||||||
android:textSize="25dp" /> |
|
||||||
|
|
||||||
<LinearLayout |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:layout_marginTop="10dp" |
|
||||||
android:orientation="horizontal"> |
|
||||||
|
|
||||||
<CheckBox |
|
||||||
android:id="@+id/cb_agreement" |
|
||||||
android:layout_width="wrap_content" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:text="@string/text_agreement_tip" |
|
||||||
android:textColor="@color/textSecondaryInverted" |
|
||||||
android:theme="@style/MyCheckBox" /> |
|
||||||
|
|
||||||
<TextView |
|
||||||
android:id="@+id/tv_agreement" |
|
||||||
android:layout_width="wrap_content" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:text="@string/link_agreement" |
|
||||||
android:textColor="@color/colorAccent" |
|
||||||
android:textSize="14dp" /> |
|
||||||
|
|
||||||
<TextView |
|
||||||
android:layout_width="wrap_content" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:text="》" |
|
||||||
android:textColor="@color/textSecondaryInverted" /> |
|
||||||
</LinearLayout> |
|
||||||
</LinearLayout> |
|
||||||
</RelativeLayout> |
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout> |
|
@ -0,0 +1,16 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:orientation="vertical"> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:id="@+id/dialog_tv_content" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:textIsSelectable="true" |
||||||
|
android:textColor="@color/textSecondary" |
||||||
|
android:textSize="@dimen/text_normal_size" |
||||||
|
android:text="神墓(辰东)"/> |
||||||
|
|
||||||
|
</LinearLayout> |
@ -1,297 +0,0 @@ |
|||||||
<?xml version="1.0" encoding="utf-8"?> |
|
||||||
<RelativeLayout 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:layout_gravity="center_vertical" > |
|
||||||
|
|
||||||
<LinearLayout |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="86dp" |
|
||||||
android:orientation="vertical"> |
|
||||||
<RelativeLayout |
|
||||||
android:id="@+id/rl_title_view" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="45dp" |
|
||||||
android:background="@color/sys_dialog_setting_bg"> |
|
||||||
|
|
||||||
<LinearLayout |
|
||||||
android:id="@+id/ll_title" |
|
||||||
android:layout_width="wrap_content" |
|
||||||
android:layout_height="match_parent" |
|
||||||
android:orientation="horizontal"> |
|
||||||
<LinearLayout |
|
||||||
android:id="@+id/ll_title_back" |
|
||||||
android:layout_width="wrap_content" |
|
||||||
android:layout_height="match_parent" |
|
||||||
android:orientation="horizontal" |
|
||||||
android:paddingLeft="10dp"> |
|
||||||
<ImageView |
|
||||||
android:layout_width="20dp" |
|
||||||
android:layout_height="20dp" |
|
||||||
android:layout_gravity="center" |
|
||||||
android:layout_margin="5dip" |
|
||||||
app:srcCompat="@mipmap/larrow3"/> |
|
||||||
</LinearLayout> |
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout |
|
||||||
android:id="@+id/ll_book_name" |
|
||||||
android:layout_width="wrap_content" |
|
||||||
android:layout_height="match_parent" |
|
||||||
android:gravity="center" |
|
||||||
android:orientation="horizontal" |
|
||||||
android:paddingRight="10dp"> |
|
||||||
<TextView |
|
||||||
android:id="@+id/tv_book_name_top" |
|
||||||
android:layout_width="wrap_content" |
|
||||||
android:layout_height="match_parent" |
|
||||||
android:gravity="center" |
|
||||||
android:layout_marginLeft="15dp" |
|
||||||
android:text="@string/app_name" |
|
||||||
android:textSize="20sp" |
|
||||||
android:textColor="@color/sys_dialog_setting_word"> |
|
||||||
</TextView> |
|
||||||
</LinearLayout> |
|
||||||
</LinearLayout> |
|
||||||
<LinearLayout |
|
||||||
android:layout_width="wrap_content" |
|
||||||
android:layout_height="match_parent" |
|
||||||
android:layout_alignParentRight="true" |
|
||||||
android:gravity="center" |
|
||||||
android:orientation="horizontal" |
|
||||||
android:paddingRight="10dp"> |
|
||||||
<ImageView |
|
||||||
android:id="@+id/iv_change_source" |
|
||||||
android:layout_width="30dp" |
|
||||||
android:layout_height="match_parent" |
|
||||||
android:src="@drawable/ic_change_source" |
|
||||||
app:tint="@color/little_black_white"/> |
|
||||||
<ImageView |
|
||||||
android:id="@+id/iv_refresh" |
|
||||||
android:layout_marginLeft="15dp" |
|
||||||
android:layout_width="30dp" |
|
||||||
android:layout_height="match_parent" |
|
||||||
android:src="@drawable/ic_refresh" |
|
||||||
app:tint="@color/little_black_white"/> |
|
||||||
<ImageView |
|
||||||
android:id="@+id/iv_book_mark" |
|
||||||
android:layout_marginLeft="12dp" |
|
||||||
android:layout_width="33dp" |
|
||||||
android:layout_height="match_parent" |
|
||||||
android:src="@drawable/ic_bookmark" |
|
||||||
app:tint="@color/little_black_white"/> |
|
||||||
<ImageView |
|
||||||
android:id="@+id/iv_voice_read" |
|
||||||
android:layout_width="25dp" |
|
||||||
android:layout_height="match_parent" |
|
||||||
android:layout_marginLeft="20dp" |
|
||||||
app:srcCompat="@mipmap/bd" |
|
||||||
android:visibility="gone"/> |
|
||||||
|
|
||||||
<ImageView |
|
||||||
android:id="@+id/iv_more" |
|
||||||
android:layout_width="25dp" |
|
||||||
android:layout_height="match_parent" |
|
||||||
android:layout_marginLeft="20dp" |
|
||||||
app:srcCompat="@mipmap/t8" |
|
||||||
android:visibility="gone"/> |
|
||||||
</LinearLayout> |
|
||||||
</RelativeLayout> |
|
||||||
<View |
|
||||||
android:layout_width="fill_parent" |
|
||||||
android:layout_height="1dp" |
|
||||||
android:background="@color/sys_dialog_setting_line" /> |
|
||||||
<LinearLayout |
|
||||||
android:id="@+id/ll_chapter_view" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="40dp" |
|
||||||
android:background="@color/sys_dialog_setting_bg" |
|
||||||
android:orientation="vertical"> |
|
||||||
<TextView android:id="@+id/tv_chapter_title_top" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:layout_marginLeft="14dp" |
|
||||||
android:textSize="15sp" |
|
||||||
android:text="章节名称" |
|
||||||
android:maxLines="1" |
|
||||||
android:textColor="@color/sys_dialog_setting_word"> |
|
||||||
</TextView> |
|
||||||
<TextView android:id="@+id/tv_chapter_url" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:layout_marginLeft="15dp" |
|
||||||
android:textSize="13sp" |
|
||||||
android:text="章节链接" |
|
||||||
android:maxLines="1" |
|
||||||
android:textColor="@color/sys_dialog_setting_word"> |
|
||||||
</TextView> |
|
||||||
</LinearLayout> |
|
||||||
</LinearLayout> |
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout |
|
||||||
android:id="@+id/ll_bottom_view" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:layout_alignParentBottom="true" |
|
||||||
android:layout_alignParentStart="true" |
|
||||||
android:background="@color/sys_dialog_setting_bg" |
|
||||||
android:orientation="vertical"> |
|
||||||
|
|
||||||
<LinearLayout |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:orientation="horizontal" |
|
||||||
android:paddingBottom="30dp" |
|
||||||
android:paddingLeft="10dp" |
|
||||||
android:paddingRight="10dp" |
|
||||||
android:paddingTop="30dp"> |
|
||||||
|
|
||||||
<TextView |
|
||||||
android:id="@+id/tv_last_chapter" |
|
||||||
android:layout_width="wrap_content" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:text="上一章" |
|
||||||
android:textColor="@color/sys_dialog_setting_word" |
|
||||||
android:textSize="15sp" /> |
|
||||||
|
|
||||||
<SeekBar |
|
||||||
android:id="@+id/sb_read_chapter_progress" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:layout_marginLeft="10dp" |
|
||||||
android:layout_marginRight="10dp" |
|
||||||
android:layout_weight="1" |
|
||||||
android:maxHeight="1dp" |
|
||||||
android:minHeight="1dp" |
|
||||||
android:progressDrawable="@drawable/seekbar_bg" |
|
||||||
android:thumb="@mipmap/thumb"/> |
|
||||||
|
|
||||||
<TextView |
|
||||||
android:id="@+id/tv_next_chapter" |
|
||||||
android:layout_width="wrap_content" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:text="下一章" |
|
||||||
android:textColor="@color/sys_dialog_setting_word" |
|
||||||
android:textSize="15sp"/> |
|
||||||
|
|
||||||
</LinearLayout> |
|
||||||
|
|
||||||
<ImageView |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="1px" |
|
||||||
app:srcCompat="@color/sys_dialog_setting_line" /> |
|
||||||
|
|
||||||
<LinearLayout |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:paddingBottom="10dp" |
|
||||||
android:paddingTop="10dp" |
|
||||||
android:gravity="center"> |
|
||||||
|
|
||||||
<LinearLayout |
|
||||||
android:id="@+id/ll_chapter_list" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_weight="1" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:orientation="vertical" |
|
||||||
android:gravity="center"> |
|
||||||
|
|
||||||
<ImageView |
|
||||||
android:layout_width="wrap_content" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
app:srcCompat="@mipmap/t3" /> |
|
||||||
|
|
||||||
<TextView |
|
||||||
android:layout_width="wrap_content" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:layout_marginTop="5dp" |
|
||||||
android:text="目录" |
|
||||||
android:textColor="@color/sys_dialog_setting_word" /> |
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout> |
|
||||||
|
|
||||||
<LinearLayout |
|
||||||
android:id="@+id/ll_download_cache" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:layout_weight="1" |
|
||||||
android:orientation="vertical" |
|
||||||
android:gravity="center"> |
|
||||||
|
|
||||||
<ImageView |
|
||||||
android:layout_width="wrap_content" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
app:srcCompat="@mipmap/download" /> |
|
||||||
|
|
||||||
<TextView |
|
||||||
android:id="@+id/tv_download_progress" |
|
||||||
android:layout_width="wrap_content" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:layout_marginTop="5dp" |
|
||||||
android:text="缓存" |
|
||||||
android:textColor="@color/sys_dialog_setting_word" /> |
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout> |
|
||||||
|
|
||||||
<LinearLayout |
|
||||||
android:id="@+id/ll_night_and_day" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:layout_weight="1" |
|
||||||
android:gravity="center" |
|
||||||
android:orientation="vertical"> |
|
||||||
|
|
||||||
<ImageView |
|
||||||
android:id="@+id/iv_night_and_day" |
|
||||||
android:layout_width="wrap_content" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
app:srcCompat="@mipmap/ao" /> |
|
||||||
|
|
||||||
<TextView |
|
||||||
android:id="@+id/tv_night_and_day" |
|
||||||
android:layout_width="wrap_content" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:layout_marginTop="5dp" |
|
||||||
android:text="夜间" |
|
||||||
android:textColor="@color/sys_dialog_setting_word" /> |
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout> |
|
||||||
|
|
||||||
<LinearLayout |
|
||||||
android:id="@+id/ll_setting" |
|
||||||
android:layout_width="match_parent" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:layout_weight="1" |
|
||||||
android:orientation="vertical" |
|
||||||
android:gravity="center"> |
|
||||||
|
|
||||||
<ImageView |
|
||||||
android:layout_width="wrap_content" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
app:srcCompat="@mipmap/t6" /> |
|
||||||
|
|
||||||
<TextView |
|
||||||
android:layout_width="wrap_content" |
|
||||||
android:layout_height="wrap_content" |
|
||||||
android:layout_marginTop="5dp" |
|
||||||
android:text="设置" |
|
||||||
android:textColor="@color/sys_dialog_setting_word" /> |
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout> |
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout> |
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</RelativeLayout> |
|
@ -0,0 +1,34 @@ |
|||||||
|
<?xml version ="1.0" encoding ="utf-8"?> |
||||||
|
<menu 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"> |
||||||
|
|
||||||
|
<item |
||||||
|
android:id="@+id/action_change_source" |
||||||
|
android:icon="@drawable/ic_change_source" |
||||||
|
android:title="@string/menu_change_source" |
||||||
|
app:showAsAction="ifRoom"/> |
||||||
|
<item |
||||||
|
android:id="@+id/action_reload" |
||||||
|
android:icon="@drawable/ic_refresh" |
||||||
|
android:title="@string/menu_reload" |
||||||
|
app:showAsAction="ifRoom"/> |
||||||
|
|
||||||
|
<group android:id="@+id/action_load_finish"> |
||||||
|
<item |
||||||
|
android:id="@+id/action_add_bookmark" |
||||||
|
android:icon="@drawable/ic_bookmark" |
||||||
|
android:title="@string/menu_add_bookmark" |
||||||
|
app:showAsAction="never"/> |
||||||
|
<item |
||||||
|
android:id="@+id/action_copy_content" |
||||||
|
android:icon="@drawable/ic_copy" |
||||||
|
android:title="@string/menu_copy_content" |
||||||
|
app:showAsAction="never"/> |
||||||
|
<item |
||||||
|
android:id="@+id/action_open_link" |
||||||
|
android:icon="@drawable/ic_link" |
||||||
|
android:title="@string/menu_open_link" |
||||||
|
app:showAsAction="never"/> |
||||||
|
</group> |
||||||
|
</menu> |
@ -0,0 +1,10 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"> |
||||||
|
<item |
||||||
|
android:id="@+id/action_tip" |
||||||
|
android:icon="@drawable/ic_question" |
||||||
|
android:title="提示" |
||||||
|
app:showAsAction="always" |
||||||
|
android:visible="true"/> |
||||||
|
</menu> |
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 110 B |
Before Width: | Height: | Size: 638 B |
Before Width: | Height: | Size: 373 B |
Before Width: | Height: | Size: 63 KiB |
After Width: | Height: | Size: 487 KiB |