| @ -1,7 +1,6 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <project version="4"> | ||||
|   <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" /> | ||||
|   </component> | ||||
| </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" | ||||
|     android:width="24dp" | ||||
|     android:height="24dp" | ||||
|     android:viewportWidth="24" | ||||
|     android:viewportHeight="24"> | ||||
| 
 | ||||
|     <path | ||||
|         android:fillColor="@color/white" | ||||
|         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" /> | ||||
| </vector> | ||||
|     android:viewportWidth="1024" | ||||
|     android:viewportHeight="1024"> | ||||
|   <path | ||||
|       android:fillColor="#FFFFFF" | ||||
|       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"/> | ||||
|   <path | ||||
|       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" | ||||
|     android:width="24dp" | ||||
|     android:height="24dp" | ||||
|     android:viewportWidth="24" | ||||
|     android:viewportHeight="24"> | ||||
| 
 | ||||
|     <path | ||||
|         android:fillColor="#FFFFFF" | ||||
|         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 | ||||
|         android:fillColor="#FFFFFF" | ||||
|         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> | ||||
|     android:viewportWidth="1024" | ||||
|     android:viewportHeight="1024"> | ||||
|   <path | ||||
|       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"/> | ||||
|   <path | ||||
|       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"/> | ||||
| </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 |