parent
31c16a6004
commit
36a2647ccb
@ -0,0 +1,37 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project version="4"> |
||||
<component name="WizardSettings"> |
||||
<option name="children"> |
||||
<map> |
||||
<entry key="imageWizard"> |
||||
<value> |
||||
<PersistentState /> |
||||
</value> |
||||
</entry> |
||||
<entry key="vectorWizard"> |
||||
<value> |
||||
<PersistentState> |
||||
<option name="children"> |
||||
<map> |
||||
<entry key="vectorAssetStep"> |
||||
<value> |
||||
<PersistentState> |
||||
<option name="values"> |
||||
<map> |
||||
<entry key="assetSourceType" value="FILE" /> |
||||
<entry key="outputName" value="ic_group" /> |
||||
<entry key="sourceFile" value="F:\SVG图标\分组.svg" /> |
||||
</map> |
||||
</option> |
||||
</PersistentState> |
||||
</value> |
||||
</entry> |
||||
</map> |
||||
</option> |
||||
</PersistentState> |
||||
</value> |
||||
</entry> |
||||
</map> |
||||
</option> |
||||
</component> |
||||
</project> |
Binary file not shown.
@ -0,0 +1,55 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project version="4"> |
||||
<component name="navEditor-manualLayoutAlgorithm2"> |
||||
<option name="myPositions"> |
||||
<map> |
||||
<entry key="mobile_navigation.xml"> |
||||
<value> |
||||
<LayoutPositions> |
||||
<option name="myPositions"> |
||||
<map> |
||||
<entry key="navigation_dashboard"> |
||||
<value> |
||||
<LayoutPositions> |
||||
<option name="myPosition"> |
||||
<Point> |
||||
<option name="x" value="256" /> |
||||
<option name="y" value="12" /> |
||||
</Point> |
||||
</option> |
||||
</LayoutPositions> |
||||
</value> |
||||
</entry> |
||||
<entry key="navigation_home"> |
||||
<value> |
||||
<LayoutPositions> |
||||
<option name="myPosition"> |
||||
<Point> |
||||
<option name="x" value="12" /> |
||||
<option name="y" value="12" /> |
||||
</Point> |
||||
</option> |
||||
</LayoutPositions> |
||||
</value> |
||||
</entry> |
||||
<entry key="navigation_notifications"> |
||||
<value> |
||||
<LayoutPositions> |
||||
<option name="myPosition"> |
||||
<Point> |
||||
<option name="x" value="12" /> |
||||
<option name="y" value="368" /> |
||||
</Point> |
||||
</option> |
||||
</LayoutPositions> |
||||
</value> |
||||
</entry> |
||||
</map> |
||||
</option> |
||||
</LayoutPositions> |
||||
</value> |
||||
</entry> |
||||
</map> |
||||
</option> |
||||
</component> |
||||
</project> |
@ -0,0 +1,10 @@ |
||||
_csrfToken=AfAoas8MBYmg6LNiXTCqRB4GqdvAIjLhoMhq0dMR; newstatisticUUID=1600428458_1590109905, |
||||
_csrfToken=JoeVbiYLyXUa1F1afAe7vopVMTCIAy9gjYjgs3vG; newstatisticUUID=1600428473_81078399, |
||||
_csrfToken=HrhdGbLO43Q1sqYB3fE2HFxTOgjA06Qb4tMdk4oP; newstatisticUUID=1600428493_975004371, |
||||
_csrfToken=ipGWAeoYVu786drUzlLunN24Z9aujs5nh5n9BRkO; newstatisticUUID=1600428519_644819972, |
||||
_csrfToken=XagcA1H7EuyKRlcCnYxBEXh96LdxehdF79bAshVq; newstatisticUUID=1600428535_1734949593, |
||||
_csrfToken=b6ZsEBvH8DizXhKHa7XG9s6kPN81vo0FujgQkBss; newstatisticUUID=1600428547_1240575899, |
||||
_csrfToken=AN09KVoEyMW1b7A2h0WICDw0iZRh10YJPHrPMyuF; newstatisticUUID=1600428559_1890659047, |
||||
_csrfToken=NPv5rB13eOhAw2PM5GKUbMCrpPXMHEozqs6fTIA7; newstatisticUUID=1600428572_110329628, |
||||
_csrfToken=it9IyUnSOXK7xC8fQXADlyrem8ZtGNKFSPt65kj1; newstatisticUUID=1600428591_1594511991, |
||||
_csrfToken=HJPozY5Rdj0Ij0HcyXT3L3VW3OLqeOQooCayuMLG; newstatisticUUID=1600428602_278088659 |
@ -0,0 +1,10 @@ |
||||
_csrfToken=6aY1oV18xaiLFe342vi6RRTJ1CsuZ7PZPqz2Tl9A; newstatisticUUID=1600427331_759036854, |
||||
_csrfToken=PnRLboRVY2ag0eGbG3e3dA3X4B96SpihEkCDGle7; newstatisticUUID=1600427449_1941387289, |
||||
_csrfToken=Ia5w2vTL03IHyPKiS5PJFgocvzHWbMgi4dBEvrox; newstatisticUUID=1600427497_1599098587, |
||||
_csrfToken=GjyWEsVXIta60t4YXkbtO0hsDc2VVBbfKy6GIBRg; newstatisticUUID=1600427528_887702937, |
||||
_csrfToken=iPjMCVKGnvL8QrbsdYIxCDNQZkJVSscN1CQFFSdF; newstatisticUUID=1600427557_1213608979, |
||||
_csrfToken=Iby8oSKxp767d25frgCGjOAWFWbYwwyRA36nBaxO; newstatisticUUID=1600427589_1737201533, |
||||
_csrfToken=IR81KoIAQxXYb6e9Agv8WuXDkAKukMLnlLe9BYha; newstatisticUUID=1600427619_487685580, |
||||
_csrfToken=YM1F8lgqaePVMceunc7z7ndjys5ngAx5sYsemg60; newstatisticUUID=1600427643_2022665645, |
||||
_csrfToken=8bRnXJseSCajlTcG6lhyWOF0rWwDCiMVpCGvKvQj; newstatisticUUID=1600427644_1615074434, |
||||
_csrfToken=AehQ3WVD6wLbFGhFsnSW4DRF6BS1wqVvHU6PbiiX; newstatisticUUID=1600427644_575162687 |
@ -0,0 +1,15 @@ |
||||
package xyz.fycz.myreader.creator; |
||||
|
||||
import android.content.Context; |
||||
import androidx.appcompat.app.AlertDialog; |
||||
import xyz.fycz.myreader.R; |
||||
|
||||
/** |
||||
* @author fengyue |
||||
* @date 2020/9/20 9:48 |
||||
*/ |
||||
public class MyAlertDialog { |
||||
public static AlertDialog.Builder build(Context context){ |
||||
return new AlertDialog.Builder(context, R.style.alertDialogTheme); |
||||
} |
||||
} |
@ -0,0 +1,80 @@ |
||||
package xyz.fycz.myreader.entity.bookstore; |
||||
|
||||
/** |
||||
* @author fengyue |
||||
* @date 2020/9/18 20:46 |
||||
*/ |
||||
public class QDBook { |
||||
protected String bid; |
||||
protected String bName; |
||||
protected String bAuth; |
||||
protected String img; |
||||
protected String cat; |
||||
protected int catId; |
||||
protected String cnt; |
||||
protected String desc; |
||||
|
||||
public String getBid() { |
||||
return bid; |
||||
} |
||||
|
||||
public void setBid(String bid) { |
||||
this.bid = bid; |
||||
} |
||||
|
||||
public String getbName() { |
||||
return bName; |
||||
} |
||||
|
||||
public void setbName(String bName) { |
||||
this.bName = bName; |
||||
} |
||||
|
||||
public String getbAuth() { |
||||
return bAuth; |
||||
} |
||||
|
||||
public void setbAuth(String bAuth) { |
||||
this.bAuth = bAuth; |
||||
} |
||||
|
||||
public String getImg() { |
||||
return img; |
||||
} |
||||
|
||||
public void setImg(String img) { |
||||
this.img = img; |
||||
} |
||||
|
||||
public String getCat() { |
||||
return cat; |
||||
} |
||||
|
||||
public void setCat(String cat) { |
||||
this.cat = cat; |
||||
} |
||||
|
||||
public int getCatId() { |
||||
return catId; |
||||
} |
||||
|
||||
public void setCatId(int catId) { |
||||
this.catId = catId; |
||||
} |
||||
|
||||
public String getCnt() { |
||||
return cnt; |
||||
} |
||||
|
||||
public void setCnt(String cnt) { |
||||
this.cnt = cnt; |
||||
} |
||||
|
||||
public String getDesc() { |
||||
return desc; |
||||
} |
||||
|
||||
public void setDesc(String desc) { |
||||
this.desc = desc; |
||||
} |
||||
} |
@ -0,0 +1,38 @@ |
||||
package xyz.fycz.myreader.entity.bookstore; |
||||
|
||||
/** |
||||
* @author fengyue |
||||
* @date 2020/9/16 22:56 |
||||
*/ |
||||
public class RankBook extends QDBook{ |
||||
/*bAuth: "净无痕" |
||||
bName: "伏天氏" |
||||
bid: "1011058239" |
||||
cat: "玄幻" |
||||
catId: 21 |
||||
cnt: "636.1万字" |
||||
desc: "东方神州,有人皇立道统,有圣贤宗门传道,有诸侯雄踞一方王国,诸强林立,神州动乱千万载,值此之时,一代天骄叶青帝及东凰大帝横空出世,东方神州一统!然,叶青帝忽然暴毙,世间雕像尽皆被毁,于世间除名,沦为禁忌;从此神州唯东凰大帝独尊!十五年后,东海青州城,一名为叶伏天的少年,开启了他的传奇之路…" |
||||
rankCnt: "5996月票" |
||||
rankNum: 21*/ |
||||
|
||||
|
||||
private String rankCnt; |
||||
private int rankNum; |
||||
|
||||
|
||||
public String getRankCnt() { |
||||
return rankCnt; |
||||
} |
||||
|
||||
public void setRankCnt(String rankCnt) { |
||||
this.rankCnt = rankCnt; |
||||
} |
||||
|
||||
public int getRankNum() { |
||||
return rankNum; |
||||
} |
||||
|
||||
public void setRankNum(int rankNum) { |
||||
this.rankNum = rankNum; |
||||
} |
||||
} |
@ -0,0 +1,27 @@ |
||||
package xyz.fycz.myreader.entity.bookstore; |
||||
|
||||
/** |
||||
* @author fengyue |
||||
* @date 2020/9/18 20:43 |
||||
*/ |
||||
public class SortBook extends QDBook{ |
||||
/*bAuth: "老鸡吃蘑菇" |
||||
bName: "全世界都不知道我多强" |
||||
bid: 1021781295 |
||||
cat: "玄幻" |
||||
catId: 21 |
||||
cid: 406957810 |
||||
cnt: "72.68万字" |
||||
desc: "【日更过万,质量保证!】当梁凡从地底爬出来之后,才发现不是变秃才能变强!我要控制我自己,要是不小心一拳打爆这个星球怎么办?安静的隐藏在世俗,全世界都不知道我有多强,虽然这个世界妖魔鬼怪很变态,但苟着享" |
||||
state: "连载"*/ |
||||
|
||||
private String state; |
||||
|
||||
public String getState() { |
||||
return state; |
||||
} |
||||
|
||||
public void setState(String state) { |
||||
this.state = state; |
||||
} |
||||
} |
@ -0,0 +1,40 @@ |
||||
package xyz.fycz.myreader.enums; |
||||
|
||||
import java.io.Serializable; |
||||
|
||||
/** |
||||
* 小说源 |
||||
* Created by zhao on 2020/04/13. |
||||
*/ |
||||
|
||||
public enum FindType implements Serializable { |
||||
|
||||
qidian("排行榜[起点中文网]", "https://www.qidian.com/rank"), |
||||
qidianns("排行榜[起点女生网]", "https://www.qidian.com/mm/rank"), |
||||
qb5("书城[全本小说]", "https://www.qb5.tw"), |
||||
biquge("书城[笔趣阁]", "https://www.52bqg.com"); |
||||
private String text; |
||||
private String url; |
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
FindType(String text, String url) { |
||||
this.text = text; |
||||
this.url = url; |
||||
} |
||||
|
||||
public static FindType get(int var0) { |
||||
return values()[var0]; |
||||
} |
||||
|
||||
public static FindType fromString(String string) { |
||||
return valueOf(string); |
||||
} |
||||
|
||||
public String getText() { |
||||
return text; |
||||
} |
||||
|
||||
public String getUrl() { |
||||
return url; |
||||
} |
||||
} |
@ -0,0 +1,70 @@ |
||||
package xyz.fycz.myreader.greendao.entity; |
||||
|
||||
import org.greenrobot.greendao.annotation.Entity; |
||||
import org.greenrobot.greendao.annotation.Id; |
||||
import org.greenrobot.greendao.annotation.NotNull; |
||||
import org.greenrobot.greendao.annotation.Generated; |
||||
|
||||
/** |
||||
* @author fengyue |
||||
* @date 2020/9/23 22:18 |
||||
*/ |
||||
@Entity |
||||
public class BookGroup { |
||||
@Id |
||||
private String id; |
||||
|
||||
@NotNull |
||||
private int num; |
||||
|
||||
@NotNull |
||||
private String name; |
||||
|
||||
private String desc; |
||||
|
||||
@Generated(hash = 1387727906) |
||||
public BookGroup(String id, int num, @NotNull String name, String desc) { |
||||
this.id = id; |
||||
this.num = num; |
||||
this.name = name; |
||||
this.desc = desc; |
||||
} |
||||
|
||||
@Generated(hash = 511810489) |
||||
public BookGroup() { |
||||
} |
||||
|
||||
public String getId() { |
||||
return this.id; |
||||
} |
||||
|
||||
public void setId(String id) { |
||||
this.id = id; |
||||
} |
||||
|
||||
public String getName() { |
||||
return this.name; |
||||
} |
||||
|
||||
public void setName(String name) { |
||||
this.name = name; |
||||
} |
||||
|
||||
public String getDesc() { |
||||
return this.desc; |
||||
} |
||||
|
||||
public void setDesc(String desc) { |
||||
this.desc = desc; |
||||
} |
||||
|
||||
public int getNum() { |
||||
return this.num; |
||||
} |
||||
|
||||
public void setNum(int num) { |
||||
this.num = num; |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,77 @@ |
||||
package xyz.fycz.myreader.greendao.service; |
||||
|
||||
import xyz.fycz.myreader.greendao.GreenDaoManager; |
||||
import xyz.fycz.myreader.greendao.entity.BookGroup; |
||||
import xyz.fycz.myreader.greendao.gen.BookGroupDao; |
||||
import xyz.fycz.myreader.greendao.gen.BookMarkDao; |
||||
import xyz.fycz.myreader.util.StringHelper; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* @author fengyue |
||||
* @date 2020/9/26 12:14 |
||||
*/ |
||||
public class BookGroupService extends BaseService{ |
||||
private static volatile BookGroupService sInstance; |
||||
|
||||
public static BookGroupService getInstance() { |
||||
if (sInstance == null){ |
||||
synchronized (BookGroupService.class){ |
||||
if (sInstance == null){ |
||||
sInstance = new BookGroupService(); |
||||
} |
||||
} |
||||
} |
||||
return sInstance; |
||||
} |
||||
|
||||
/** |
||||
* 获取所有书籍分组 |
||||
* @return |
||||
*/ |
||||
public List<BookGroup> getAllGroups(){ |
||||
return GreenDaoManager.getInstance().getSession().getBookGroupDao() |
||||
.queryBuilder() |
||||
.orderAsc(BookGroupDao.Properties.Num) |
||||
.list(); |
||||
} |
||||
|
||||
/** |
||||
* 通过I的获取书籍分组 |
||||
* @param groupId |
||||
* @return |
||||
*/ |
||||
public BookGroup getGroupById(String groupId){ |
||||
return GreenDaoManager.getInstance().getSession().getBookGroupDao() |
||||
.queryBuilder() |
||||
.where(BookGroupDao.Properties.Id.eq(groupId)) |
||||
.unique(); |
||||
} |
||||
|
||||
/** |
||||
* 添加书籍分组 |
||||
* @param bookGroup |
||||
*/ |
||||
public void addBookGroup(BookGroup bookGroup){ |
||||
bookGroup.setNum(countBookGroup()); |
||||
bookGroup.setId(StringHelper.getStringRandom(25)); |
||||
addEntity(bookGroup); |
||||
} |
||||
|
||||
/** |
||||
* 删除书籍分组 |
||||
* @param bookGroup |
||||
*/ |
||||
public void deleteBookGroup(BookGroup bookGroup){ |
||||
deleteEntity(bookGroup); |
||||
} |
||||
|
||||
|
||||
private int countBookGroup(){ |
||||
return (int) GreenDaoManager.getInstance().getSession().getBookGroupDao() |
||||
.queryBuilder() |
||||
.count(); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,420 @@ |
||||
package xyz.fycz.myreader.ui.activity; |
||||
|
||||
import android.annotation.SuppressLint; |
||||
import android.content.Intent; |
||||
import android.os.Bundle; |
||||
import android.os.Handler; |
||||
import android.os.Message; |
||||
import android.view.Menu; |
||||
import android.view.MenuItem; |
||||
import android.view.View; |
||||
import android.widget.ProgressBar; |
||||
import androidx.appcompat.widget.Toolbar; |
||||
import androidx.recyclerview.widget.LinearLayoutManager; |
||||
import androidx.recyclerview.widget.RecyclerView; |
||||
import butterknife.BindView; |
||||
import com.scwang.smartrefresh.layout.SmartRefreshLayout; |
||||
import xyz.fycz.myreader.R; |
||||
import xyz.fycz.myreader.application.MyApplication; |
||||
import xyz.fycz.myreader.base.BaseActivity2; |
||||
import xyz.fycz.myreader.callback.ResultCallback; |
||||
import xyz.fycz.myreader.common.APPCONST; |
||||
import xyz.fycz.myreader.creator.ChangeSourceDialog; |
||||
import xyz.fycz.myreader.creator.DialogCreator; |
||||
import xyz.fycz.myreader.entity.bookstore.BookType; |
||||
import xyz.fycz.myreader.entity.bookstore.QDBook; |
||||
import xyz.fycz.myreader.entity.bookstore.RankBook; |
||||
import xyz.fycz.myreader.entity.bookstore.SortBook; |
||||
import xyz.fycz.myreader.greendao.entity.Book; |
||||
import xyz.fycz.myreader.greendao.service.BookService; |
||||
import xyz.fycz.myreader.ui.adapter.BookStoreBookAdapter; |
||||
import xyz.fycz.myreader.ui.adapter.BookStoreBookTypeAdapter; |
||||
import xyz.fycz.myreader.util.SharedPreUtils; |
||||
import xyz.fycz.myreader.util.ToastUtils; |
||||
import xyz.fycz.myreader.webapi.BookStoreApi; |
||||
import xyz.fycz.myreader.webapi.crawler.FindCrawler; |
||||
import xyz.fycz.myreader.webapi.crawler.find.ABC; |
||||
import xyz.fycz.myreader.widget.RefreshLayout; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* @author fengyue |
||||
* @date 2020/9/13 21:11 |
||||
*/ |
||||
public class BookstoreActivity extends BaseActivity2 { |
||||
@BindView(R.id.refresh_layout) |
||||
RefreshLayout mRlRefresh; |
||||
@BindView(R.id.rv_type_list) |
||||
RecyclerView rvTypeList; |
||||
@BindView(R.id.rv_book_list) |
||||
RecyclerView rvBookList; |
||||
@BindView(R.id.srl_book_list) |
||||
SmartRefreshLayout srlBookList; |
||||
@BindView(R.id.pb_loading) |
||||
ProgressBar pbLoading; |
||||
|
||||
private FindCrawler findCrawler; |
||||
private LinearLayoutManager mLinearLayoutManager; |
||||
private BookStoreBookTypeAdapter mBookStoreBookTypeAdapter; |
||||
private List<BookType> mBookTypes; |
||||
|
||||
private BookStoreBookAdapter mBookStoreBookAdapter; |
||||
private List<Book> bookList = new ArrayList<>(); |
||||
|
||||
private BookType curType; |
||||
|
||||
private int page = 1; |
||||
|
||||
private String title = ""; |
||||
|
||||
@SuppressLint("HandlerLeak") |
||||
private Handler mHandler = new Handler() { |
||||
@Override |
||||
public void handleMessage(Message msg) { |
||||
if (!MyApplication.isDestroy(BookstoreActivity.this)) { |
||||
switch (msg.what) { |
||||
case 1: |
||||
initTypeList(); |
||||
mRlRefresh.showFinish(); |
||||
break; |
||||
case 2: |
||||
List<Book> bookList = (List<Book>) msg.obj; |
||||
initBookList(bookList); |
||||
srlBookList.setEnableRefresh(true); |
||||
srlBookList.setEnableLoadMore(true); |
||||
pbLoading.setVisibility(View.GONE); |
||||
break; |
||||
case 3: |
||||
pbLoading.setVisibility(View.VISIBLE); |
||||
break; |
||||
case 4: |
||||
pbLoading.setVisibility(View.GONE); |
||||
srlBookList.finishRefresh(false); |
||||
srlBookList.finishLoadMore(false); |
||||
break; |
||||
case 5: |
||||
mRlRefresh.showError(); |
||||
break; |
||||
case 6: |
||||
DialogCreator.createTipDialog(BookstoreActivity.this, |
||||
getResources().getString(R.string.top_sort_tip, title)); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
}; |
||||
|
||||
@Override |
||||
protected int getContentId() { |
||||
return R.layout.actiity_bookstore; |
||||
} |
||||
|
||||
@Override |
||||
protected void setUpToolbar(Toolbar toolbar) { |
||||
super.setUpToolbar(toolbar); |
||||
setStatusBarColor(R.color.colorPrimary, true); |
||||
String subTitle = ""; |
||||
if (findCrawler != null) { |
||||
String name = findCrawler.getFindName(); |
||||
title = name.substring(0, name.indexOf("[")); |
||||
subTitle = name.substring(name.indexOf("[") + 1, name.length() - 1); |
||||
} |
||||
getSupportActionBar().setTitle(title); |
||||
getSupportActionBar().setSubtitle(subTitle); |
||||
} |
||||
|
||||
@Override |
||||
protected void initData(Bundle savedInstanceState) { |
||||
super.initData(savedInstanceState); |
||||
findCrawler = (FindCrawler) getIntent().getSerializableExtra(APPCONST.FIND_CRAWLER); |
||||
} |
||||
|
||||
@Override |
||||
protected void initWidget() { |
||||
super.initWidget(); |
||||
srlBookList.setEnableRefresh(false); |
||||
srlBookList.setEnableLoadMore(false); |
||||
//小说列表下拉加载更多事件
|
||||
srlBookList.setOnLoadMoreListener(refreshLayout -> { |
||||
page++; |
||||
getBooksData(); |
||||
}); |
||||
|
||||
//小说列表上拉刷新事件
|
||||
srlBookList.setOnRefreshListener(refreshLayout -> { |
||||
page = 1; |
||||
getBooksData(); |
||||
}); |
||||
|
||||
mBookStoreBookAdapter = new BookStoreBookAdapter(findCrawler.hasImg(), this); |
||||
rvBookList.setLayoutManager(new LinearLayoutManager(this)); |
||||
rvBookList.setAdapter(mBookStoreBookAdapter); |
||||
mRlRefresh.setOnReloadingListener(this::getData); |
||||
} |
||||
|
||||
@Override |
||||
protected void initClick() { |
||||
super.initClick(); |
||||
mBookStoreBookAdapter.setOnItemClickListener((view, pos) -> { |
||||
Book book = bookList.get(pos); |
||||
if (!findCrawler.hasImg()) { |
||||
goToBookDetail(book); |
||||
} else { |
||||
if (BookService.getInstance().isBookCollected(book)) { |
||||
goToBookDetail(book); |
||||
return; |
||||
} |
||||
mHandler.sendMessage(mHandler.obtainMessage(3)); |
||||
ChangeSourceDialog csd = new ChangeSourceDialog(this, book); |
||||
csd.initOneBook(new ResultCallback() { |
||||
@Override |
||||
public void onFinish(Object o, int code) { |
||||
Book searchBook = (Book) o; |
||||
book.setChapterUrl(searchBook.getChapterUrl()); |
||||
book.setSource(searchBook.getSource()); |
||||
goToBookDetail(book); |
||||
mHandler.sendMessage(mHandler.obtainMessage(4)); |
||||
} |
||||
|
||||
@Override |
||||
public void onError(Exception e) { |
||||
DialogCreator.createTipDialog(BookstoreActivity.this, "未搜索到该书籍,无法进入书籍详情!"); |
||||
mHandler.sendMessage(mHandler.obtainMessage(4)); |
||||
} |
||||
}); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
@Override |
||||
protected void processLogic() { |
||||
super.processLogic(); |
||||
getData(); |
||||
if (findCrawler.hasImg()) { |
||||
SharedPreUtils spu = SharedPreUtils.getInstance(); |
||||
boolean isReadTopTip = spu.getBoolean("isReadTopTip", false); |
||||
if (!isReadTopTip) { |
||||
DialogCreator.createCommonDialog(this, "提示", getResources().getString(R.string.top_sort_tip, title), |
||||
true, "知道了", "不再提示", null, |
||||
(dialog, which) -> spu.putBoolean("isReadTopTip", true)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 获取页面数据 |
||||
*/ |
||||
private void getData() { |
||||
if (findCrawler instanceof ABC) { |
||||
SharedPreUtils spu = SharedPreUtils.getInstance(); |
||||
if (spu.getString("qdCookie", "").equals("")) { |
||||
((ABC) findCrawler).initCookie(this, new ResultCallback() { |
||||
@Override |
||||
public void onFinish(Object o, int code) { |
||||
spu.putString("qdCookie", (String) o); |
||||
mBookTypes = ((ABC) findCrawler).getRankTypes(); |
||||
curType = mBookTypes.get(0); |
||||
mHandler.sendMessage(mHandler.obtainMessage(1)); |
||||
page = 1; |
||||
getBooksData(); |
||||
} |
||||
|
||||
@Override |
||||
public void onError(Exception e) { |
||||
mRlRefresh.showError(); |
||||
e.printStackTrace(); |
||||
} |
||||
}); |
||||
} else { |
||||
mBookTypes = ((ABC) findCrawler).getRankTypes(); |
||||
curType = mBookTypes.get(0); |
||||
mHandler.sendMessage(mHandler.obtainMessage(1)); |
||||
page = 1; |
||||
getBooksData(); |
||||
} |
||||
} else { |
||||
BookStoreApi.getBookTypeList(findCrawler, new ResultCallback() { |
||||
@Override |
||||
public void onFinish(Object o, int code) { |
||||
mBookTypes = (ArrayList<BookType>) o; |
||||
curType = mBookTypes.get(0); |
||||
mHandler.sendMessage(mHandler.obtainMessage(1)); |
||||
page = 1; |
||||
getBooksData(); |
||||
} |
||||
|
||||
@Override |
||||
public void onError(Exception e) { |
||||
e.printStackTrace(); |
||||
mHandler.sendEmptyMessage(5); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
} |
||||
|
||||
/** |
||||
* 获取小数列表数据 |
||||
*/ |
||||
private void getBooksData() { |
||||
if (findCrawler.getTypePage(curType, page)) { |
||||
srlBookList.finishLoadMoreWithNoMoreData(); |
||||
return; |
||||
} |
||||
|
||||
mHandler.sendEmptyMessage(3); |
||||
if (findCrawler instanceof ABC) { |
||||
((ABC) findCrawler).getRankBooks(curType, new ResultCallback() { |
||||
@Override |
||||
public void onFinish(Object o, int code) { |
||||
List<Book> books = new ArrayList<>(); |
||||
for (QDBook rb : (List<QDBook>) o) { |
||||
Book book = new Book(); |
||||
book.setName(rb.getbName()); |
||||
book.setAuthor(rb.getbAuth()); |
||||
book.setImgUrl(rb.getImg()); |
||||
String cat = rb.getCat(); |
||||
book.setType(cat.contains("小说") || cat.length() >= 4 ? cat : cat + "小说"); |
||||
book.setNewestChapterTitle(rb.getDesc()); |
||||
book.setDesc(rb.getDesc()); |
||||
if (rb instanceof RankBook) { |
||||
boolean hasRankCnt = !((RankBook) rb).getRankCnt().equals("null") && |
||||
MyApplication.isApkInDebug(BookstoreActivity.this); |
||||
book.setUpdateDate(hasRankCnt ? book.getType() + "-" + rb.getCnt() : rb.getCnt()); |
||||
book.setNewestChapterId(hasRankCnt ? ((RankBook) rb).getRankCnt() : book.getType()); |
||||
} else if (rb instanceof SortBook) { |
||||
book.setUpdateDate(rb.getCnt()); |
||||
book.setNewestChapterId(((SortBook) rb).getState()); |
||||
} |
||||
books.add(book); |
||||
} |
||||
mHandler.sendMessage(mHandler.obtainMessage(2, books)); |
||||
} |
||||
|
||||
@Override |
||||
public void onError(Exception e) { |
||||
mHandler.sendMessage(mHandler.obtainMessage(4)); |
||||
ToastUtils.showError("数据加载失败!\n" + e.getMessage()); |
||||
e.printStackTrace(); |
||||
} |
||||
}); |
||||
} else { |
||||
BookStoreApi.getBookRankList(curType.getUrl(), findCrawler, new ResultCallback() { |
||||
@Override |
||||
public void onFinish(Object o, int code) { |
||||
mHandler.sendMessage(mHandler.obtainMessage(2, o)); |
||||
} |
||||
|
||||
@Override |
||||
public void onError(Exception e) { |
||||
mHandler.sendMessage(mHandler.obtainMessage(4)); |
||||
ToastUtils.showError("数据加载失败!\n" + e.getMessage()); |
||||
e.printStackTrace(); |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 初始化类别列表 |
||||
*/ |
||||
private void initTypeList() { |
||||
|
||||
//设置布局管理器
|
||||
mLinearLayoutManager = new LinearLayoutManager(this); |
||||
mLinearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); |
||||
rvTypeList.setLayoutManager(mLinearLayoutManager); |
||||
mBookStoreBookTypeAdapter = new BookStoreBookTypeAdapter(this, mBookTypes); |
||||
rvTypeList.setAdapter(mBookStoreBookTypeAdapter); |
||||
|
||||
//点击事件
|
||||
mBookStoreBookTypeAdapter.setOnItemClickListener((pos, view) -> { |
||||
if (curType.equals(mBookTypes.get(pos))) { |
||||
return; |
||||
} |
||||
page = 1; |
||||
curType = mBookTypes.get(pos); |
||||
srlBookList.resetNoMoreData(); |
||||
getBooksData(); |
||||
}); |
||||
|
||||
|
||||
} |
||||
|
||||
|
||||
/** |
||||
* 初始化小说列表 |
||||
*/ |
||||
private void initBookList(List<Book> bookList) { |
||||
if (page == 1) { |
||||
mBookStoreBookAdapter.refreshItems(bookList); |
||||
this.bookList.clear(); |
||||
this.bookList.addAll(bookList); |
||||
rvBookList.scrollToPosition(0); |
||||
} else { |
||||
this.bookList.addAll(bookList); |
||||
mBookStoreBookAdapter.addItems(bookList); |
||||
} |
||||
|
||||
//刷新动作完成
|
||||
srlBookList.finishRefresh(); |
||||
//加载更多完成
|
||||
srlBookList.finishLoadMore(); |
||||
|
||||
} |
||||
|
||||
/** |
||||
* 前往书籍详情 |
||||
* |
||||
* @param book |
||||
*/ |
||||
private void goToBookDetail(Book book) { |
||||
Intent intent = new Intent(this, BookDetailedActivity.class); |
||||
intent.putExtra(APPCONST.BOOK, book); |
||||
BookstoreActivity.this.startActivity(intent); |
||||
} |
||||
|
||||
/********************************Event***************************************/ |
||||
/** |
||||
* 创建菜单 |
||||
* |
||||
* @param menu |
||||
* @return |
||||
*/ |
||||
@Override |
||||
public boolean onCreateOptionsMenu(Menu menu) { |
||||
getMenuInflater().inflate(R.menu.menu_store, menu); |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public boolean onPrepareOptionsMenu(Menu menu) { |
||||
if (findCrawler.hasImg()) { |
||||
menu.findItem(R.id.action_tip).setVisible(true); |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* 导航栏菜单点击事件 |
||||
* |
||||
* @param item |
||||
* @return |
||||
*/ |
||||
@Override |
||||
public boolean onOptionsItemSelected(MenuItem item) { |
||||
switch (item.getItemId()) { |
||||
case R.id.action_tip: |
||||
mHandler.sendEmptyMessage(6); |
||||
return true; |
||||
case R.id.action_refresh: |
||||
mRlRefresh.showLoading(); |
||||
getData(); |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
} |
@ -1,77 +1,117 @@ |
||||
package xyz.fycz.myreader.ui.activity; |
||||
|
||||
import android.os.Bundle; |
||||
import android.widget.EditText; |
||||
import android.widget.ImageView; |
||||
import android.widget.RelativeLayout; |
||||
import android.view.Menu; |
||||
import android.view.MenuInflater; |
||||
import android.view.MenuItem; |
||||
import androidx.appcompat.widget.SearchView; |
||||
import androidx.appcompat.widget.Toolbar; |
||||
import androidx.viewpager.widget.ViewPager; |
||||
import butterknife.BindView; |
||||
import butterknife.ButterKnife; |
||||
import com.google.android.material.tabs.TabLayout; |
||||
import xyz.fycz.myreader.R; |
||||
import xyz.fycz.myreader.base.BaseActivity; |
||||
import xyz.fycz.myreader.ui.presenter.CatalogActivityPresenter; |
||||
import xyz.fycz.myreader.base.BaseActivity2; |
||||
import xyz.fycz.myreader.common.APPCONST; |
||||
import xyz.fycz.myreader.greendao.entity.Book; |
||||
import xyz.fycz.myreader.ui.adapter.TabFragmentPageAdapter; |
||||
import xyz.fycz.myreader.ui.fragment.BookMarkFragment; |
||||
import xyz.fycz.myreader.ui.fragment.CatalogFragment; |
||||
|
||||
/** |
||||
* @author fengyue |
||||
* @date 2020/7/22 8:04 |
||||
* 书籍目录activity |
||||
*/ |
||||
public class CatalogActivity extends BaseActivity { |
||||
@BindView(R.id.tl_tab_menu) |
||||
TabLayout tlTabMenu; |
||||
@BindView(R.id.iv_search) |
||||
ImageView ivSearch; |
||||
@BindView(R.id.rl_common_title) |
||||
RelativeLayout rlCommonTitle; |
||||
@BindView(R.id.vp_content) |
||||
ViewPager vpContent; |
||||
@BindView(R.id.iv_back) |
||||
ImageView tvBack; |
||||
|
||||
@BindView(R.id.et_search) |
||||
EditText etSearch; |
||||
@BindView(R.id.iv_cancel) |
||||
ImageView ivCancel; |
||||
|
||||
|
||||
private CatalogActivityPresenter mCatalogPresenter; |
||||
public class CatalogActivity extends BaseActivity2 { |
||||
|
||||
|
||||
@BindView(R.id.catalog_tab) |
||||
TabLayout catalogTab; |
||||
@BindView(R.id.toolbar) |
||||
Toolbar toolbar; |
||||
@BindView(R.id.catalog_vp) |
||||
ViewPager viewPager; |
||||
private SearchView searchView; |
||||
|
||||
private Book mBook; |
||||
|
||||
private TabFragmentPageAdapter tabAdapter; |
||||
|
||||
/*******************Public**********************************/ |
||||
|
||||
public Book getmBook() { |
||||
return mBook; |
||||
} |
||||
|
||||
/*********************Initialization****************************/ |
||||
|
||||
|
||||
@Override |
||||
protected void onCreate(Bundle savedInstanceState) { |
||||
super.onCreate(savedInstanceState); |
||||
setContentView(R.layout.activity_catalog); |
||||
ButterKnife.bind(this); |
||||
setStatusBar(0, false); |
||||
mCatalogPresenter = new CatalogActivityPresenter(this); |
||||
mCatalogPresenter.start(); |
||||
protected void initData(Bundle savedInstanceState) { |
||||
super.initData(savedInstanceState); |
||||
mBook = (Book) getIntent().getSerializableExtra(APPCONST.BOOK); |
||||
} |
||||
|
||||
public TabLayout getTlTabMenu() { |
||||
return tlTabMenu; |
||||
@Override |
||||
protected int getContentId() { |
||||
return R.layout.activity_catalog; |
||||
} |
||||
|
||||
public ImageView getIvSearch() { |
||||
return ivSearch; |
||||
@Override |
||||
protected void setUpToolbar(Toolbar toolbar) { |
||||
super.setUpToolbar(toolbar); |
||||
setStatusBarColor(R.color.colorPrimary, true); |
||||
tabAdapter = new TabFragmentPageAdapter(getSupportFragmentManager()); |
||||
tabAdapter.addFragment(new CatalogFragment(), "目录"); |
||||
tabAdapter.addFragment(new BookMarkFragment(), "书签"); |
||||
} |
||||
|
||||
public RelativeLayout getRlCommonTitle() { |
||||
return rlCommonTitle; |
||||
@Override |
||||
protected void initWidget() { |
||||
super.initWidget(); |
||||
viewPager.setAdapter(tabAdapter); |
||||
viewPager.setOffscreenPageLimit(2); |
||||
catalogTab.setupWithViewPager(viewPager); |
||||
} |
||||
|
||||
public ViewPager getVpContent() { |
||||
return vpContent; |
||||
|
||||
/*************************************************************************/ |
||||
@Override |
||||
public boolean onCreateOptionsMenu(Menu menu) { |
||||
MenuInflater inflater = getMenuInflater(); |
||||
inflater.inflate(R.menu.menu_view_search, menu); |
||||
MenuItem search = menu.findItem(R.id.action_search); |
||||
searchView = (SearchView) search.getActionView(); |
||||
searchView.setMaxWidth(getResources().getDisplayMetrics().widthPixels); |
||||
searchView.onActionViewCollapsed(); |
||||
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { |
||||
@Override |
||||
public boolean onQueryTextSubmit(String query) { |
||||
return false; |
||||
} |
||||
|
||||
public ImageView getTvBack() { |
||||
return tvBack; |
||||
@Override |
||||
public boolean onQueryTextChange(String newText) { |
||||
switch (viewPager.getCurrentItem()){ |
||||
case 0: |
||||
((CatalogFragment) tabAdapter.getItem(0)).getmCatalogPresent().startSearch(newText); |
||||
break; |
||||
case 1: |
||||
((BookMarkFragment) tabAdapter.getItem(1)).getmBookMarkPresenter().startSearch(newText); |
||||
break; |
||||
} |
||||
return false; |
||||
} |
||||
}); |
||||
return super.onCreateOptionsMenu(menu); |
||||
} |
||||
|
||||
@Override |
||||
public boolean onOptionsItemSelected(MenuItem item) { |
||||
switch (item.getItemId()) { |
||||
case R.id.home: |
||||
|
||||
public EditText getEtSearch() { |
||||
return etSearch; |
||||
return true; |
||||
} |
||||
|
||||
public ImageView getIvCancel() { |
||||
return ivCancel; |
||||
return super.onOptionsItemSelected(item); |
||||
} |
||||
|
||||
} |
||||
|
@ -0,0 +1,54 @@ |
||||
package xyz.fycz.myreader.ui.adapter; |
||||
|
||||
import androidx.annotation.NonNull; |
||||
import androidx.fragment.app.Fragment; |
||||
import androidx.fragment.app.FragmentManager; |
||||
import androidx.fragment.app.FragmentPagerAdapter; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Created by Zhouas666 on 2019-03-28 |
||||
* Github: https://github.com/zas023
|
||||
*/ |
||||
public class TabFragmentPageAdapter extends FragmentPagerAdapter { |
||||
|
||||
private List<Fragment> mFragmentList; |
||||
private List<String> mTitleList; |
||||
|
||||
public TabFragmentPageAdapter(@NonNull FragmentManager fm) { |
||||
super(fm); |
||||
mFragmentList = new ArrayList<>(); |
||||
mTitleList = new ArrayList<>(); |
||||
} |
||||
|
||||
public void addFragment(Fragment fragment) { |
||||
mFragmentList.add(fragment); |
||||
} |
||||
|
||||
public void addFragment(Fragment fragment,String title) { |
||||
mFragmentList.add(fragment); |
||||
mTitleList.add(title); |
||||
} |
||||
|
||||
public void addTitle(String title) { |
||||
mTitleList.add(title); |
||||
} |
||||
|
||||
@NonNull |
||||
@Override |
||||
public Fragment getItem(int position) { |
||||
return mFragmentList.get(position); |
||||
} |
||||
|
||||
@Override |
||||
public int getCount() { |
||||
return mFragmentList.size(); |
||||
} |
||||
|
||||
@Override |
||||
public CharSequence getPageTitle(int position) { |
||||
return mTitleList.get(position); |
||||
} |
||||
} |
@ -0,0 +1,82 @@ |
||||
package xyz.fycz.myreader.ui.adapter.holder; |
||||
|
||||
import android.app.Activity; |
||||
import android.content.Intent; |
||||
import android.view.View; |
||||
import android.widget.ImageView; |
||||
import android.widget.LinearLayout; |
||||
import android.widget.TextView; |
||||
import com.bumptech.glide.Glide; |
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners; |
||||
import com.bumptech.glide.request.RequestOptions; |
||||
import xyz.fycz.myreader.R; |
||||
import xyz.fycz.myreader.application.MyApplication; |
||||
import xyz.fycz.myreader.base.adapter.ViewHolderImpl; |
||||
import xyz.fycz.myreader.common.APPCONST; |
||||
import xyz.fycz.myreader.enums.BookSource; |
||||
import xyz.fycz.myreader.greendao.entity.Book; |
||||
import xyz.fycz.myreader.ui.activity.BookDetailedActivity; |
||||
|
||||
/** |
||||
* @author fengyue |
||||
* @date 2020/9/7 7:35 |
||||
*/ |
||||
public class BookStoreBookHolder extends ViewHolderImpl<Book> { |
||||
|
||||
private ImageView tvBookImg; |
||||
private TextView tvBookName; |
||||
private TextView tvBookAuthor; |
||||
private TextView tvBookTime; |
||||
private TextView tvBookNewestChapter; |
||||
private TextView tvBookSource; |
||||
|
||||
private boolean hasImg; |
||||
private Activity mActivity; |
||||
|
||||
public BookStoreBookHolder(boolean hasImg, Activity mActivity) { |
||||
this.hasImg = hasImg; |
||||
this.mActivity = mActivity; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
protected int getItemLayoutId() { |
||||
return R.layout.listview_book_store_book_item; |
||||
} |
||||
|
||||
@Override |
||||
public void initView() { |
||||
tvBookImg = findById(R.id.iv_book_img); |
||||
tvBookName = findById(R.id.tv_book_name); |
||||
tvBookAuthor = findById(R.id.tv_book_author); |
||||
tvBookNewestChapter = findById(R.id.tv_book_newest_chapter); |
||||
tvBookTime = findById(R.id.tv_book_time); |
||||
tvBookSource = findById(R.id.tv_book_source); |
||||
} |
||||
|
||||
@Override |
||||
public void onBind(Book data, int pos) { |
||||
tvBookName.setText(data.getName()); |
||||
tvBookAuthor.setText(data.getAuthor()); |
||||
tvBookNewestChapter.setText(data.getNewestChapterTitle()); |
||||
tvBookTime.setText(data.getUpdateDate()); |
||||
if (hasImg){ |
||||
tvBookImg.setVisibility(View.VISIBLE); |
||||
if (!MyApplication.isDestroy(mActivity)) { |
||||
Glide.with(getContext()) |
||||
.load(data.getImgUrl()) |
||||
.error(R.mipmap.no_image) |
||||
.placeholder(R.mipmap.no_image) |
||||
//设置圆角
|
||||
.apply(RequestOptions.bitmapTransform(new RoundedCorners(8))) |
||||
.into(tvBookImg); |
||||
} |
||||
} |
||||
if (data.getSource() != null) { |
||||
tvBookSource.setText("书源:" + BookSource.fromString(data.getSource()).text); |
||||
}else { |
||||
tvBookSource.setText(data.getNewestChapterId()); |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,57 @@ |
||||
package xyz.fycz.myreader.ui.fragment; |
||||
|
||||
import android.content.Intent; |
||||
import android.widget.RelativeLayout; |
||||
import butterknife.BindView; |
||||
import xyz.fycz.myreader.R; |
||||
import xyz.fycz.myreader.base.BaseFragment; |
||||
import xyz.fycz.myreader.common.APPCONST; |
||||
import xyz.fycz.myreader.ui.activity.BookstoreActivity; |
||||
import xyz.fycz.myreader.webapi.crawler.FindCrawler; |
||||
import xyz.fycz.myreader.webapi.crawler.QB5ReadCrawler; |
||||
import xyz.fycz.myreader.webapi.crawler.find.ABC; |
||||
|
||||
/** |
||||
* @author fengyue |
||||
* @date 2020/9/13 21:07 |
||||
*/ |
||||
public class FindFragment extends BaseFragment { |
||||
@BindView(R.id.find_rl_qidian_top) |
||||
RelativeLayout mRlQiDianTop; |
||||
@BindView(R.id.find_rl_qidian_ns_top) |
||||
RelativeLayout mRlQiDianNSTop; |
||||
@BindView(R.id.find_rl_qidian_sort) |
||||
RelativeLayout mRlQiDianSort; |
||||
@BindView(R.id.find_rl_qidian_ns_sort) |
||||
RelativeLayout mRlQiDianNSSort; |
||||
@BindView(R.id.find_rl_qb5_store) |
||||
RelativeLayout mRlQB5Store; |
||||
@BindView(R.id.find_rl_biquge_store) |
||||
RelativeLayout mRlBiQuGeStore; |
||||
|
||||
@Override |
||||
protected int getContentId() { |
||||
return R.layout.fragment_find; |
||||
} |
||||
|
||||
@Override |
||||
protected void initClick() { |
||||
super.initClick(); |
||||
mRlQiDianTop.setOnClickListener(v -> comeToBookstore(new ABC(false))); |
||||
mRlQiDianNSTop.setOnClickListener(v -> comeToBookstore(new ABC(true))); |
||||
mRlQiDianSort.setOnClickListener(v -> comeToBookstore(new ABC(false, true))); |
||||
mRlQiDianNSSort.setOnClickListener(v -> comeToBookstore(new ABC(true, true))); |
||||
mRlQB5Store.setOnClickListener(v -> comeToBookstore(new QB5ReadCrawler())); |
||||
} |
||||
|
||||
|
||||
private void comeToBookstore(FindCrawler findCrawler){ |
||||
Intent intent = new Intent(getContext(), BookstoreActivity.class); |
||||
intent.putExtra(APPCONST.FIND_CRAWLER, findCrawler); |
||||
startActivity(intent); |
||||
} |
||||
|
||||
public boolean isRecreate() { |
||||
return unbinder == null; |
||||
} |
||||
} |
@ -0,0 +1,397 @@ |
||||
package xyz.fycz.myreader.ui.fragment; |
||||
|
||||
import android.annotation.SuppressLint; |
||||
import android.content.*; |
||||
import android.os.Bundle; |
||||
import android.os.Handler; |
||||
import android.os.Message; |
||||
import android.widget.ArrayAdapter; |
||||
import android.widget.RelativeLayout; |
||||
import android.widget.TextView; |
||||
import androidx.annotation.NonNull; |
||||
import androidx.annotation.Nullable; |
||||
import androidx.appcompat.app.AlertDialog; |
||||
import butterknife.BindView; |
||||
import xyz.fycz.myreader.R; |
||||
import xyz.fycz.myreader.application.MyApplication; |
||||
import xyz.fycz.myreader.application.SysManager; |
||||
import xyz.fycz.myreader.backup.BackupAndRestore; |
||||
import xyz.fycz.myreader.backup.UserService; |
||||
import xyz.fycz.myreader.base.BaseFragment; |
||||
import xyz.fycz.myreader.common.APPCONST; |
||||
import xyz.fycz.myreader.creator.DialogCreator; |
||||
import xyz.fycz.myreader.creator.MyAlertDialog; |
||||
import xyz.fycz.myreader.entity.Setting; |
||||
import xyz.fycz.myreader.greendao.entity.Book; |
||||
import xyz.fycz.myreader.greendao.service.BookService; |
||||
import xyz.fycz.myreader.ui.activity.AboutActivity; |
||||
import xyz.fycz.myreader.ui.activity.LoginActivity; |
||||
import xyz.fycz.myreader.ui.activity.MoreSettingActivity; |
||||
import xyz.fycz.myreader.util.SharedPreUtils; |
||||
import xyz.fycz.myreader.util.ToastUtils; |
||||
import xyz.fycz.myreader.util.utils.NetworkUtils; |
||||
|
||||
import java.io.File; |
||||
import java.text.SimpleDateFormat; |
||||
import java.util.ArrayList; |
||||
import java.util.Date; |
||||
|
||||
import static android.app.Activity.RESULT_OK; |
||||
|
||||
/** |
||||
* @author fengyue |
||||
* @date 2020/9/13 13:20 |
||||
*/ |
||||
public class MineFragment extends BaseFragment { |
||||
@BindView(R.id.mine_rl_user) |
||||
RelativeLayout mRlUser; |
||||
@BindView(R.id.tv_user) |
||||
TextView mTvUser; |
||||
@BindView(R.id.mine_rl_backup) |
||||
RelativeLayout mRlBackup; |
||||
@BindView(R.id.mine_rl_syn) |
||||
RelativeLayout mRlSyn; |
||||
@BindView(R.id.mine_rl_setting) |
||||
RelativeLayout mRlSetting; |
||||
@BindView(R.id.mine_rl_theme_mode) |
||||
RelativeLayout mRlThemeMode; |
||||
@BindView(R.id.tv_theme_mode_select) |
||||
TextView tvThemeModeSelect; |
||||
@BindView(R.id.mine_rl_feedback) |
||||
RelativeLayout mRlFeedback; |
||||
@BindView(R.id.mine_rl_about) |
||||
RelativeLayout mRlAbout; |
||||
|
||||
private boolean isLogin; |
||||
private BackupAndRestore mBackupAndRestore; |
||||
private Setting mSetting; |
||||
private String[] webSynMenu; |
||||
private String[] backupMenu; |
||||
private AlertDialog themeModeDia; |
||||
private int themeMode; |
||||
private String[] themeModeArr; |
||||
@SuppressLint("HandlerLeak") |
||||
private Handler mHandler = new Handler() { |
||||
@Override |
||||
public void handleMessage(@NonNull Message msg) { |
||||
switch (msg.what) { |
||||
case 1: |
||||
mTvUser.setText("登录/注册"); |
||||
break; |
||||
case 2: |
||||
backup(); |
||||
break; |
||||
case 3: |
||||
restore(); |
||||
break; |
||||
} |
||||
} |
||||
}; |
||||
|
||||
public MineFragment() { |
||||
} |
||||
|
||||
@Override |
||||
protected int getContentId() { |
||||
return R.layout.fragment_mine; |
||||
} |
||||
|
||||
@Override |
||||
protected void initData(Bundle savedInstanceState) { |
||||
super.initData(savedInstanceState); |
||||
isLogin = UserService.isLogin(); |
||||
mBackupAndRestore = new BackupAndRestore(); |
||||
mSetting = SysManager.getSetting(); |
||||
webSynMenu = new String[]{ |
||||
MyApplication.getmContext().getString(R.string.menu_backup_webBackup), |
||||
MyApplication.getmContext().getString(R.string.menu_backup_webRestore), |
||||
MyApplication.getmContext().getString(R.string.menu_backup_autoSyn) |
||||
}; |
||||
backupMenu = new String[]{ |
||||
MyApplication.getmContext().getResources().getString(R.string.menu_backup_backup), |
||||
MyApplication.getmContext().getResources().getString(R.string.menu_backup_restore), |
||||
}; |
||||
themeMode = MyApplication.getApplication().isNightFS() ? 0 : mSetting.isDayStyle() ? 1 : 2; |
||||
themeModeArr = getResources().getStringArray(R.array.theme_mode_arr); |
||||
} |
||||
|
||||
@Override |
||||
protected void initWidget(Bundle savedInstanceState) { |
||||
super.initWidget(savedInstanceState); |
||||
if (isLogin) { |
||||
mTvUser.setText(UserService.readUsername()); |
||||
} |
||||
tvThemeModeSelect.setText(themeModeArr[themeMode]); |
||||
} |
||||
|
||||
@Override |
||||
protected void initClick() { |
||||
super.initClick(); |
||||
mRlUser.setOnClickListener(v -> { |
||||
if (isLogin) { |
||||
DialogCreator.createCommonDialog(getActivity(), "退出登录", "确定要退出登录吗?" |
||||
, true, (dialog, which) -> { |
||||
File file = MyApplication.getApplication().getFileStreamPath("userConfig.fy"); |
||||
if (file.delete()) { |
||||
ToastUtils.showSuccess("退出成功"); |
||||
isLogin = false; |
||||
mHandler.sendEmptyMessage(1); |
||||
Intent intent = new Intent(getActivity(), LoginActivity.class); |
||||
getActivity().startActivityForResult(intent, APPCONST.REQUEST_LOGIN); |
||||
} else { |
||||
ToastUtils.showError("退出失败(Error:file.delete())"); |
||||
} |
||||
}, (dialog, which) -> dialog.dismiss()); |
||||
} else { |
||||
Intent intent = new Intent(getActivity(), LoginActivity.class); |
||||
getActivity().startActivityForResult(intent, APPCONST.REQUEST_LOGIN); |
||||
} |
||||
}); |
||||
mRlBackup.setOnClickListener(v -> { |
||||
AlertDialog bookDialog = MyAlertDialog.build(getContext()) |
||||
.setTitle(getContext().getResources().getString(R.string.menu_bookcase_backup)) |
||||
.setItems(backupMenu, (dialog, which) -> { |
||||
switch (which) { |
||||
case 0: |
||||
mHandler.sendMessage(mHandler.obtainMessage(2)); |
||||
break; |
||||
case 1: |
||||
mHandler.sendMessage(mHandler.obtainMessage(3)); |
||||
break; |
||||
} |
||||
}) |
||||
.setNegativeButton(null, null) |
||||
.setPositiveButton(null, null) |
||||
.create(); |
||||
bookDialog.show(); |
||||
}); |
||||
mRlSyn.setOnClickListener(v -> { |
||||
if (!UserService.isLogin()) { |
||||
ToastUtils.showWarring("请先登录!"); |
||||
Intent loginIntent = new Intent(getActivity(), LoginActivity.class); |
||||
getActivity().startActivityForResult(loginIntent, APPCONST.REQUEST_LOGIN); |
||||
return; |
||||
} |
||||
if (mSetting.isAutoSyn()) { |
||||
webSynMenu[2] = MyApplication.getmContext().getString(R.string.menu_backup_autoSyn) + "已开启"; |
||||
} else { |
||||
webSynMenu[2] = MyApplication.getmContext().getString(R.string.menu_backup_autoSyn) + "已关闭"; |
||||
} |
||||
MyAlertDialog.build(getContext()) |
||||
.setTitle(getActivity().getString(R.string.menu_bookcase_syn)) |
||||
.setItems(webSynMenu, (dialog, which) -> { |
||||
switch (which) { |
||||
case 0: |
||||
synBookcaseToWeb(false); |
||||
break; |
||||
case 1: |
||||
webRestore(); |
||||
break; |
||||
case 2: |
||||
String tip = ""; |
||||
if (mSetting.isAutoSyn()) { |
||||
mSetting.setAutoSyn(false); |
||||
tip = "每日自动同步已关闭!"; |
||||
} else { |
||||
mSetting.setAutoSyn(true); |
||||
tip = "每日自动同步已开启!"; |
||||
} |
||||
SysManager.saveSetting(mSetting); |
||||
ToastUtils.showSuccess(tip); |
||||
break; |
||||
} |
||||
}) |
||||
.setNegativeButton(null, null) |
||||
.setPositiveButton(null, null) |
||||
.show(); |
||||
}); |
||||
mRlSetting.setOnClickListener(v -> { |
||||
Intent settingIntent = new Intent(getActivity(), MoreSettingActivity.class); |
||||
startActivity(settingIntent); |
||||
}); |
||||
mRlThemeMode.setOnClickListener(v -> { |
||||
if (themeModeDia != null) { |
||||
themeModeDia.show(); |
||||
return; |
||||
} |
||||
themeModeDia = MyAlertDialog.build(getContext()) |
||||
.setTitle("主题模式") |
||||
.setSingleChoiceItems(themeModeArr, themeMode |
||||
, (dialog, which) -> { |
||||
if (themeMode == which) { |
||||
dialog.dismiss(); |
||||
return; |
||||
} |
||||
themeMode = which; |
||||
switch (which) { |
||||
case 0: |
||||
SharedPreUtils.getInstance().putBoolean("isNightFS", true); |
||||
break; |
||||
case 1: |
||||
SharedPreUtils.getInstance().putBoolean("isNightFS", false); |
||||
mSetting.setDayStyle(true); |
||||
SysManager.saveSetting(mSetting); |
||||
break; |
||||
case 2: |
||||
SharedPreUtils.getInstance().putBoolean("isNightFS", false); |
||||
mSetting.setDayStyle(false); |
||||
SysManager.saveSetting(mSetting); |
||||
break; |
||||
} |
||||
dialog.dismiss(); |
||||
tvThemeModeSelect.setText(themeModeArr[themeMode]); |
||||
MyApplication.getApplication().initNightTheme(); |
||||
}) |
||||
.setNegativeButton("取消", null) |
||||
.create(); |
||||
themeModeDia.show(); |
||||
|
||||
}); |
||||
|
||||
mRlAbout.setOnClickListener(v -> { |
||||
Intent aboutIntent = new Intent(getActivity(), AboutActivity.class); |
||||
startActivity(aboutIntent); |
||||
}); |
||||
|
||||
mRlFeedback.setOnClickListener(v -> { |
||||
DialogCreator.createCommonDialog(getContext(), "问题反馈", "请加入QQ群(1085028304)反馈问题!", true, |
||||
"加入QQ群", "取消", (dialog, which) -> { |
||||
if (!MyApplication.joinQQGroup(getContext(),"8PIOnHFuH6A38hgxvD_Rp2Bu-Ke1ToBn")){ |
||||
ClipboardManager mClipboardManager = (ClipboardManager) getActivity().getSystemService(Context.CLIPBOARD_SERVICE); |
||||
//数据
|
||||
ClipData mClipData = ClipData.newPlainText("Label", "1085028304"); |
||||
//把数据设置到剪切板上
|
||||
assert mClipboardManager != null; |
||||
mClipboardManager.setPrimaryClip(mClipData); |
||||
ToastUtils.showError("未安装手Q或安装的版本不支持!\n已复制QQ群号,您可自行前往QQ添加!"); |
||||
} |
||||
}, null); |
||||
}); |
||||
} |
||||
|
||||
@Override |
||||
protected void processLogic() { |
||||
super.processLogic(); |
||||
} |
||||
|
||||
/** |
||||
* 备份 |
||||
*/ |
||||
private void backup() { |
||||
ArrayList<Book> mBooks = (ArrayList<Book>) BookService.getInstance().getAllBooks(); |
||||
if (mBooks.size() == 0) { |
||||
ToastUtils.showWarring("当前书架无任何书籍,无法备份!"); |
||||
return; |
||||
} |
||||
DialogCreator.createCommonDialog(getContext(), "确认备份吗?", "新备份会替换原有备份!", true, |
||||
(dialogInterface, i) -> { |
||||
dialogInterface.dismiss(); |
||||
if (mBackupAndRestore.backup("localBackup")) { |
||||
DialogCreator.createTipDialog(getContext(), "备份成功,备份文件路径:" + APPCONST.BACKUP_FILE_DIR); |
||||
} else { |
||||
DialogCreator.createTipDialog(getContext(), "未给予储存权限,备份失败!"); |
||||
} |
||||
}, (dialogInterface, i) -> dialogInterface.dismiss()); |
||||
} |
||||
|
||||
/** |
||||
* 恢复 |
||||
*/ |
||||
private void restore() { |
||||
DialogCreator.createCommonDialog(getContext(), "确认恢复吗?", "恢复书架会覆盖原有书架!", true, |
||||
(dialogInterface, i) -> { |
||||
dialogInterface.dismiss(); |
||||
if (mBackupAndRestore.restore("localBackup")) { |
||||
mHandler.sendMessage(mHandler.obtainMessage(7)); |
||||
// DialogCreator.createTipDialog(mMainActivity,
|
||||
// "恢复成功!\n注意:本功能属于实验功能,书架恢复后,书籍初次加载时可能加载失败,返回重新加载即可!");
|
||||
mSetting = SysManager.getSetting(); |
||||
ToastUtils.showSuccess("书架恢复成功!"); |
||||
} else { |
||||
DialogCreator.createTipDialog(getContext(), "未找到备份文件或未给予储存权限,恢复失败!"); |
||||
} |
||||
}, (dialogInterface, i) -> dialogInterface.dismiss()); |
||||
} |
||||
|
||||
/** |
||||
* 同步书架 |
||||
*/ |
||||
private void synBookcaseToWeb(boolean isAutoSyn) { |
||||
if (!NetworkUtils.isNetWorkAvailable()) { |
||||
if (!isAutoSyn) { |
||||
ToastUtils.showWarring("无网络连接!"); |
||||
} |
||||
return; |
||||
} |
||||
ArrayList<Book> mBooks = (ArrayList<Book>) BookService.getInstance().getAllBooks(); |
||||
if (mBooks.size() == 0) { |
||||
if (!isAutoSyn) { |
||||
ToastUtils.showWarring("当前书架无任何书籍,无法同步!"); |
||||
} |
||||
return; |
||||
} |
||||
Date nowTime = new Date(); |
||||
SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd"); |
||||
String nowTimeStr = sdf.format(nowTime); |
||||
SharedPreUtils spb = SharedPreUtils.getInstance(); |
||||
String synTime = spb.getString("synTime"); |
||||
if (!nowTimeStr.equals(synTime) || !isAutoSyn) { |
||||
MyApplication.getApplication().newThread(() -> { |
||||
if (UserService.webBackup()) { |
||||
spb.putString("synTime", nowTimeStr); |
||||
if (!isAutoSyn) { |
||||
DialogCreator.createTipDialog(getContext(), "成功将书架同步至网络!"); |
||||
} |
||||
} else { |
||||
if (!isAutoSyn) { |
||||
DialogCreator.createTipDialog(getContext(), "同步失败,请重试!"); |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 恢复 |
||||
*/ |
||||
private void webRestore() { |
||||
if (!NetworkUtils.isNetWorkAvailable()) { |
||||
ToastUtils.showWarring("无网络连接!"); |
||||
return; |
||||
} |
||||
DialogCreator.createCommonDialog(getContext(), "确认同步吗?", "将书架从网络同步至本地会覆盖原有书架!", true, |
||||
(dialogInterface, i) -> { |
||||
dialogInterface.dismiss(); |
||||
MyApplication.getApplication().newThread(() -> { |
||||
if (UserService.webRestore()) { |
||||
mHandler.sendMessage(mHandler.obtainMessage(7)); |
||||
// DialogCreator.createTipDialog(mMainActivity,
|
||||
// "恢复成功!\n注意:本功能属于实验功能,书架恢复后,书籍初次加载时可能加载失败,返回重新加载即可!");、
|
||||
mSetting = SysManager.getSetting(); |
||||
ToastUtils.showSuccess("成功将书架从网络同步至本地!"); |
||||
} else { |
||||
DialogCreator.createTipDialog(getContext(), "未找到同步文件,同步失败!"); |
||||
} |
||||
}); |
||||
}, (dialogInterface, i) -> dialogInterface.dismiss()); |
||||
} |
||||
|
||||
@Override |
||||
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { |
||||
if (resultCode == RESULT_OK) { |
||||
switch (requestCode) { |
||||
case APPCONST.REQUEST_LOGIN: |
||||
assert data != null; |
||||
isLogin = data.getBooleanExtra("isLogin", false); |
||||
if (isLogin) { |
||||
mTvUser.setText(UserService.readUsername()); |
||||
} |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
public boolean isRecreate() { |
||||
return unbinder == null; |
||||
} |
||||
} |
@ -1,62 +0,0 @@ |
||||
package xyz.fycz.myreader.ui.presenter; |
||||
|
||||
import android.annotation.SuppressLint; |
||||
import android.content.ClipData; |
||||
import android.content.ClipboardManager; |
||||
import android.content.Context; |
||||
import android.content.Intent; |
||||
import android.net.Uri; |
||||
import xyz.fycz.myreader.R; |
||||
import xyz.fycz.myreader.application.MyApplication; |
||||
import xyz.fycz.myreader.base.BasePresenter; |
||||
import xyz.fycz.myreader.creator.DialogCreator; |
||||
import xyz.fycz.myreader.ui.activity.AboutActivity; |
||||
import xyz.fycz.myreader.util.ShareUtils; |
||||
import xyz.fycz.myreader.util.SharedPreUtils; |
||||
import xyz.fycz.myreader.util.ToastUtils; |
||||
|
||||
/** |
||||
* @author fengyue |
||||
* @date 2020/7/31 11:39 |
||||
*/ |
||||
public class AboutPresenter implements BasePresenter { |
||||
|
||||
private AboutActivity mAboutActivity; |
||||
|
||||
public AboutPresenter(AboutActivity mAboutActivity) { |
||||
this.mAboutActivity = mAboutActivity; |
||||
} |
||||
|
||||
@SuppressLint("SetTextI18n") |
||||
@Override |
||||
public void start() { |
||||
mAboutActivity.getLlTitleBack().setOnClickListener(v -> mAboutActivity.finish()); |
||||
mAboutActivity.getTvTitleText().setText("关于"); |
||||
mAboutActivity.getTvVersionName().setText("风月读书v" + MyApplication.getStrVersionName()); |
||||
mAboutActivity.getVmAuthor().setOnClickListener(v -> { |
||||
ClipboardManager mClipboardManager = (ClipboardManager) mAboutActivity.getSystemService(Context.CLIPBOARD_SERVICE); |
||||
//数据
|
||||
ClipData mClipData = ClipData.newPlainText("Label", "fy@fycz.xyz"); |
||||
//把数据设置到剪切板上
|
||||
assert mClipboardManager != null; |
||||
mClipboardManager.setPrimaryClip(mClipData); |
||||
ToastUtils.showSuccess("邮箱复制成功!"); |
||||
}); |
||||
mAboutActivity.getVmShare().setOnClickListener(v -> ShareUtils.share(mAboutActivity, mAboutActivity.getString(R.string.share_text) + |
||||
SharedPreUtils.getInstance().getString("downloadLink"))); |
||||
mAboutActivity.getVmUpdate().setOnClickListener(v -> MyApplication.checkVersionByServer(mAboutActivity, true, null)); |
||||
mAboutActivity.getVmUpdateLog().setOnClickListener(v -> DialogCreator.createAssetTipDialog(mAboutActivity, "更新日志", "updatelog.fy")); |
||||
mAboutActivity.getVmGit().setOnClickListener(v -> openIntent(Intent.ACTION_VIEW, mAboutActivity.getString(R.string.this_github_url))); |
||||
mAboutActivity.getVmDisclaimer().setOnClickListener(v -> DialogCreator.createAssetTipDialog(mAboutActivity, "免责声明", "disclaimer.fy")); |
||||
} |
||||
|
||||
void openIntent(String intentName, String address) { |
||||
try { |
||||
Intent intent = new Intent(intentName); |
||||
intent.setData(Uri.parse(address)); |
||||
mAboutActivity.startActivity(intent); |
||||
} catch (Exception e) { |
||||
ToastUtils.showError(e.getLocalizedMessage()); |
||||
} |
||||
} |
||||
} |
@ -1,134 +0,0 @@ |
||||
package xyz.fycz.myreader.ui.presenter; |
||||
|
||||
import android.content.Context; |
||||
import android.text.Editable; |
||||
import android.text.TextWatcher; |
||||
import android.view.View; |
||||
import android.view.inputmethod.InputMethodManager; |
||||
import androidx.fragment.app.Fragment; |
||||
import androidx.fragment.app.FragmentPagerAdapter; |
||||
import xyz.fycz.myreader.R; |
||||
import xyz.fycz.myreader.application.SysManager; |
||||
import xyz.fycz.myreader.base.BasePresenter; |
||||
import xyz.fycz.myreader.entity.Setting; |
||||
import xyz.fycz.myreader.ui.activity.CatalogActivity; |
||||
import xyz.fycz.myreader.ui.fragment.CatalogFragment; |
||||
import xyz.fycz.myreader.ui.fragment.BookMarkFragment; |
||||
|
||||
import java.util.ArrayList; |
||||
|
||||
import static androidx.fragment.app.FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT; |
||||
|
||||
/** |
||||
* @author fengyue |
||||
* @date 2020/7/22 8:10 |
||||
*/ |
||||
public class CatalogActivityPresenter implements BasePresenter { |
||||
|
||||
private CatalogActivity mCatalogActivity; |
||||
private ArrayList<Fragment> mFragments = new ArrayList<>(); |
||||
private String[] tabTitle = {"目录", "书签"}; |
||||
private boolean isDayStyle; |
||||
private FragmentPagerAdapter tabAdapter; |
||||
|
||||
public CatalogActivityPresenter(CatalogActivity mCatalogActivity) { |
||||
this.mCatalogActivity = mCatalogActivity; |
||||
} |
||||
|
||||
@Override |
||||
public void start() { |
||||
Setting setting = SysManager.getSetting(); |
||||
isDayStyle = setting.isDayStyle(); |
||||
//设置日夜间
|
||||
if (!isDayStyle){ |
||||
mCatalogActivity.setStatusBar(R.color.sys_dialog_setting_bg, true); |
||||
mCatalogActivity.getRlCommonTitle().setBackground(mCatalogActivity.getDrawable(R.color.sys_dialog_setting_bg)); |
||||
mCatalogActivity.getTvBack().setImageDrawable(mCatalogActivity.getDrawable(R.mipmap.larrow_white2)); |
||||
mCatalogActivity.getIvCancel().setImageDrawable(mCatalogActivity.getDrawable(R.mipmap.ic_cha_black)); |
||||
mCatalogActivity.getIvSearch().setImageDrawable(mCatalogActivity.getDrawable(R.mipmap.b9)); |
||||
mCatalogActivity.getEtSearch().setTextColor(mCatalogActivity.getResources().getColor(R.color.sys_night_word)); |
||||
mCatalogActivity.getEtSearch().setHintTextColor(mCatalogActivity.getResources().getColor(R.color.sys_night_word)); |
||||
} |
||||
init(); |
||||
|
||||
InputMethodManager manager = ((InputMethodManager) mCatalogActivity.getSystemService(Context.INPUT_METHOD_SERVICE)); |
||||
|
||||
mCatalogActivity.getTvBack().setOnClickListener(v -> mCatalogActivity.finish()); |
||||
mCatalogActivity.getIvSearch().setOnClickListener(v -> { |
||||
mCatalogActivity.getTlTabMenu().setVisibility(View.GONE); |
||||
mCatalogActivity.getIvSearch().setVisibility(View.GONE); |
||||
mCatalogActivity.getEtSearch().setVisibility(View.VISIBLE); |
||||
mCatalogActivity.getIvCancel().setVisibility(View.VISIBLE); |
||||
mCatalogActivity.getEtSearch().setFocusable(true); |
||||
mCatalogActivity.getEtSearch().setFocusableInTouchMode(true); |
||||
mCatalogActivity.getEtSearch().requestFocus(); |
||||
}); |
||||
|
||||
mCatalogActivity.getEtSearch().setOnFocusChangeListener((v, hasFocus) -> { |
||||
if (hasFocus){ |
||||
if (manager != null) manager.showSoftInput(v, InputMethodManager.SHOW_IMPLICIT); |
||||
}else { |
||||
if (manager != null) manager.hideSoftInputFromWindow(v.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); |
||||
} |
||||
}); |
||||
|
||||
mCatalogActivity.getIvCancel().setOnClickListener(v -> { |
||||
mCatalogActivity.getTlTabMenu().setVisibility(View.VISIBLE); |
||||
mCatalogActivity.getIvSearch().setVisibility(View.VISIBLE); |
||||
mCatalogActivity.getEtSearch().setVisibility(View.GONE); |
||||
mCatalogActivity.getIvCancel().setVisibility(View.GONE); |
||||
if(!"".equals(mCatalogActivity.getEtSearch().getText().toString())){ |
||||
mCatalogActivity.getEtSearch().setText(""); |
||||
} |
||||
}); |
||||
|
||||
mCatalogActivity.getEtSearch().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) { |
||||
switch (mCatalogActivity.getVpContent().getCurrentItem()){ |
||||
case 0: |
||||
((CatalogFragment) tabAdapter.getItem(0)).getmCatalogPresent().startSearch(s.toString()); |
||||
break; |
||||
case 1: |
||||
((BookMarkFragment) tabAdapter.getItem(1)).getmBookMarkPresenter().startSearch(s.toString()); |
||||
break; |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
|
||||
private void init(){ |
||||
mFragments.add(new CatalogFragment()); |
||||
mFragments.add(new BookMarkFragment()); |
||||
tabAdapter = new FragmentPagerAdapter(mCatalogActivity.getSupportFragmentManager(),BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { |
||||
@Override |
||||
public Fragment getItem(int position) { |
||||
return mFragments.get(position); |
||||
} |
||||
|
||||
@Override |
||||
public int getCount() { |
||||
return mFragments.size(); |
||||
} |
||||
|
||||
@Override |
||||
public CharSequence getPageTitle(int position) { |
||||
return tabTitle[position]; |
||||
} |
||||
|
||||
}; |
||||
mCatalogActivity.getVpContent().setAdapter(tabAdapter); |
||||
mCatalogActivity.getTlTabMenu().setupWithViewPager(mCatalogActivity.getVpContent()); |
||||
mCatalogActivity.getVpContent().setCurrentItem(0); |
||||
} |
||||
} |
@ -1,118 +0,0 @@ |
||||
package xyz.fycz.myreader.ui.presenter; |
||||
|
||||
import android.annotation.SuppressLint; |
||||
import android.os.Handler; |
||||
import android.os.Message; |
||||
import android.view.View; |
||||
|
||||
import xyz.fycz.myreader.R; |
||||
import xyz.fycz.myreader.base.BasePresenter; |
||||
import xyz.fycz.myreader.common.APPCONST; |
||||
import xyz.fycz.myreader.enums.Font; |
||||
import xyz.fycz.myreader.ui.activity.FontsActivity; |
||||
import xyz.fycz.myreader.ui.adapter.FontsAdapter; |
||||
import xyz.fycz.myreader.util.IOUtils; |
||||
import xyz.fycz.myreader.util.ToastUtils; |
||||
import xyz.fycz.myreader.util.utils.FileUtils; |
||||
|
||||
import java.io.*; |
||||
import java.util.ArrayList; |
||||
|
||||
/** |
||||
* Created by zhao on 2017/8/7. |
||||
*/ |
||||
|
||||
public class FontsPresenter implements BasePresenter { |
||||
|
||||
private FontsActivity mFontsActivity; |
||||
private ArrayList<Font> mFonts; |
||||
private FontsAdapter mFontsAdapter; |
||||
|
||||
|
||||
@SuppressLint("HandlerLeak") |
||||
private Handler mHandler = new Handler(){ |
||||
@Override |
||||
public void handleMessage(Message msg) { |
||||
switch (msg.what){ |
||||
case 1: |
||||
init(); |
||||
break; |
||||
} |
||||
} |
||||
}; |
||||
|
||||
public FontsPresenter(FontsActivity fontsActivity) { |
||||
mFontsActivity = fontsActivity; |
||||
} |
||||
|
||||
@Override |
||||
public void start() { |
||||
mFontsActivity.getLlTitleBack().setOnClickListener(new View.OnClickListener() { |
||||
@Override |
||||
public void onClick(View v) { |
||||
mFontsActivity.finish(); |
||||
} |
||||
}); |
||||
mFontsActivity.getTvTitleText().setText(mFontsActivity.getString(R.string.font)); |
||||
init(); |
||||
} |
||||
|
||||
private void init() { |
||||
initFonts(); |
||||
mFontsAdapter = new FontsAdapter(mFontsActivity, R.layout.listview_font_item, mFonts, mFontsActivity); |
||||
mFontsActivity.getLvFonts().setAdapter(mFontsAdapter); |
||||
mFontsActivity.getPbLoading().setVisibility(View.GONE); |
||||
} |
||||
|
||||
private void initFonts() { |
||||
mFonts = new ArrayList<>(); |
||||
mFonts.add(Font.默认字体); |
||||
mFonts.add(Font.方正楷体); |
||||
mFonts.add(Font.经典宋体); |
||||
mFonts.add(Font.方正行楷); |
||||
mFonts.add(Font.迷你隶书); |
||||
mFonts.add(Font.方正黄草); |
||||
mFonts.add(Font.方正硬笔行书); |
||||
mFonts.add(Font.本地字体); |
||||
} |
||||
|
||||
public void notifyChange(){ |
||||
mFontsAdapter.notifyDataSetChanged(); |
||||
} |
||||
|
||||
public void saveLocalFont(String path){ |
||||
File fontFile = new File(path); |
||||
if (!fontFile.exists()){ |
||||
ToastUtils.showWarring("未找到字体文件!"); |
||||
return; |
||||
} |
||||
String fontName = fontFile.getName(); |
||||
if (!fontName.endsWith(".ttf")){ |
||||
ToastUtils.showError("字体更换失败,请选择ttf格式的字体文件!"); |
||||
return; |
||||
} |
||||
String dirPath = fontFile.getParentFile().getAbsolutePath() + "/"; |
||||
if (dirPath.equals(APPCONST.FONT_BOOK_DIR)){ |
||||
mFontsAdapter.saveLocalFontName(fontName); |
||||
return; |
||||
} |
||||
FileInputStream fis = null; |
||||
FileOutputStream fos = null; |
||||
try { |
||||
fis = new FileInputStream(fontFile); |
||||
fos = new FileOutputStream(FileUtils.getFile(APPCONST.FONT_BOOK_DIR + fontName)); |
||||
byte[] bytes = new byte[1021]; |
||||
int len = -1; |
||||
while ((len = fis.read(bytes)) != -1){ |
||||
fos.write(bytes, 0, len); |
||||
} |
||||
fos.flush(); |
||||
mFontsAdapter.saveLocalFontName(fontName); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
ToastUtils.showError("读取字体文件出错!\n" + e.getLocalizedMessage()); |
||||
}finally { |
||||
IOUtils.close(fis, fos); |
||||
} |
||||
} |
||||
} |
@ -1,137 +0,0 @@ |
||||
package xyz.fycz.myreader.ui.presenter; |
||||
|
||||
import android.annotation.SuppressLint; |
||||
import android.app.ProgressDialog; |
||||
import android.content.Intent; |
||||
import android.graphics.Bitmap; |
||||
import android.os.Handler; |
||||
import android.os.Message; |
||||
import android.view.View; |
||||
import xyz.fycz.myreader.backup.UserService; |
||||
import xyz.fycz.myreader.base.BasePresenter; |
||||
import xyz.fycz.myreader.callback.ResultCallback; |
||||
import xyz.fycz.myreader.common.APPCONST; |
||||
import xyz.fycz.myreader.creator.DialogCreator; |
||||
import xyz.fycz.myreader.ui.activity.LoginActivity; |
||||
import xyz.fycz.myreader.ui.activity.RegisterActivity; |
||||
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 java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* @author fengyue |
||||
* @date 2020/4/26 20:31 |
||||
*/ |
||||
|
||||
public class LoginPresenter implements BasePresenter { |
||||
private LoginActivity mLoginActivity; |
||||
private String code; |
||||
|
||||
public LoginPresenter(LoginActivity mLoginActivity) { |
||||
this.mLoginActivity = mLoginActivity; |
||||
} |
||||
|
||||
@SuppressLint("HandlerLeak") |
||||
private Handler mHandler = new Handler() { |
||||
@SuppressLint("HandlerLeak") |
||||
@Override |
||||
public void handleMessage(Message msg) { |
||||
switch (msg.what) { |
||||
case 1: |
||||
mLoginActivity.getLoginBtn().setEnabled(true); |
||||
break; |
||||
case 2: |
||||
createCaptcha(); |
||||
break; |
||||
} |
||||
} |
||||
}; |
||||
|
||||
@Override |
||||
public void start() { |
||||
mHandler.sendMessage(mHandler.obtainMessage(2)); |
||||
mLoginActivity.getTvTitleText().setText("登录"); |
||||
mLoginActivity.getLlTitleBack().setOnClickListener(v -> mLoginActivity.finish()); |
||||
String username = UserService.readUsername(); |
||||
mLoginActivity.getUser().setText(username); |
||||
mLoginActivity.getUser().requestFocus(username.length()); |
||||
//监听内容改变 -> 控制按钮的点击状态
|
||||
mLoginActivity.getUser().addTextChangedListener(mLoginActivity); |
||||
mLoginActivity.getPassword().addTextChangedListener(mLoginActivity); |
||||
mLoginActivity.getEtCaptcha().addTextChangedListener(mLoginActivity); |
||||
|
||||
mLoginActivity.getIvCaptcha().setOnClickListener(new View.OnClickListener() { |
||||
@Override |
||||
public void onClick(View v) { |
||||
mHandler.sendMessage(mHandler.obtainMessage(2)); |
||||
} |
||||
}); |
||||
|
||||
mLoginActivity.getLoginBtn().setOnClickListener(v -> { |
||||
mHandler.sendMessage(mHandler.obtainMessage(2)); |
||||
if (!code.toLowerCase().equals(mLoginActivity.getEtCaptcha().getText().toString().toLowerCase())){ |
||||
DialogCreator.createTipDialog(mLoginActivity, "验证码错误!"); |
||||
return; |
||||
} |
||||
if (!NetworkUtils.isNetWorkAvailable()) { |
||||
ToastUtils.showError("无网络连接!"); |
||||
return; |
||||
} |
||||
ProgressDialog dialog = DialogCreator.createProgressDialog(mLoginActivity, null, "正在登陆..."); |
||||
mLoginActivity.getLoginBtn().setEnabled(false); |
||||
final String loginName = mLoginActivity.getUser().getText().toString().trim(); |
||||
String loginPwd = mLoginActivity.getPassword().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); |
||||
mLoginActivity.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(); |
||||
} |
||||
}); |
||||
|
||||
}); |
||||
|
||||
mLoginActivity.getTvRegister().setOnClickListener(new View.OnClickListener() { |
||||
@Override |
||||
public void onClick(View v) { |
||||
Intent intent = new Intent(mLoginActivity, RegisterActivity.class); |
||||
mLoginActivity.startActivity(intent); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public void createCaptcha() { |
||||
code = CodeUtil.getInstance().createCode(); |
||||
Bitmap codeBitmap = CodeUtil.getInstance().createBitmap(code); |
||||
mLoginActivity.getIvCaptcha().setImageBitmap(codeBitmap); |
||||
} |
||||
} |
@ -1,134 +0,0 @@ |
||||
package xyz.fycz.myreader.ui.presenter; |
||||
|
||||
import android.content.DialogInterface; |
||||
import android.content.Intent; |
||||
|
||||
import androidx.fragment.app.Fragment; |
||||
import androidx.fragment.app.FragmentPagerAdapter; |
||||
import xyz.fycz.myreader.application.MyApplication; |
||||
import xyz.fycz.myreader.application.SysManager; |
||||
import xyz.fycz.myreader.base.BasePresenter; |
||||
import xyz.fycz.myreader.common.APPCONST; |
||||
import xyz.fycz.myreader.creator.DialogCreator; |
||||
import xyz.fycz.myreader.entity.Setting; |
||||
import xyz.fycz.myreader.ui.activity.MainActivity; |
||||
import xyz.fycz.myreader.ui.fragment.BookcaseFragment; |
||||
import xyz.fycz.myreader.ui.activity.SearchBookActivity; |
||||
import xyz.fycz.myreader.ui.activity.LoginActivity; |
||||
import xyz.fycz.myreader.util.ToastUtils; |
||||
|
||||
import java.io.File; |
||||
import java.util.ArrayList; |
||||
|
||||
import static androidx.fragment.app.FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT; |
||||
import static xyz.fycz.myreader.application.MyApplication.checkVersionByServer; |
||||
|
||||
|
||||
public class MainPresenter implements BasePresenter { |
||||
|
||||
private MainActivity mMainActivity; |
||||
private ArrayList<Fragment> mFragments = new ArrayList<>(); |
||||
|
||||
private String[] tabTitle = {"书架"}; |
||||
|
||||
private BookcaseFragment mBookcaseFragment; |
||||
|
||||
public MainPresenter(MainActivity mainActivity) { |
||||
mMainActivity = mainActivity; |
||||
} |
||||
|
||||
@Override |
||||
public void start() { |
||||
try { |
||||
Setting mSetting = SysManager.getSetting(); |
||||
int settingVersion = mSetting.getSettingVersion(); |
||||
if (settingVersion < APPCONST.SETTING_VERSION){ |
||||
SysManager.resetSetting(); |
||||
//DialogCreator.createTipDialog(mMainActivity, "因组件升级,阅读字体及背景颜色已恢复默认颜色!");
|
||||
} |
||||
}catch (Exception e){ |
||||
SysManager.resetSetting(); |
||||
//DialogCreator.createTipDialog(mMainActivity, "因组件升级,阅读字体及背景颜色已恢复默认颜色");
|
||||
} |
||||
init(); |
||||
checkVersionByServer(mMainActivity, false, (BookcaseFragment) mFragments.get(0)); |
||||
mMainActivity.getIvSearch().setOnClickListener(view -> { |
||||
Intent intent = new Intent(mMainActivity, SearchBookActivity.class); |
||||
mMainActivity.startActivity(intent); |
||||
}); |
||||
mMainActivity.getCivAvatar().setOnClickListener(v -> { |
||||
final File file = MyApplication.getApplication().getFileStreamPath("userConfig.fy"); |
||||
if (file.exists()) { |
||||
DialogCreator.createCommonDialog(mMainActivity, "退出登录", "确定要退出登录吗?" |
||||
, true, new DialogInterface.OnClickListener() { |
||||
@Override |
||||
public void onClick(DialogInterface dialog, int which) { |
||||
if (file.delete()) { |
||||
ToastUtils.showSuccess("退出成功"); |
||||
Intent intent = new Intent(mMainActivity, LoginActivity.class); |
||||
mMainActivity.startActivity(intent); |
||||
} else { |
||||
ToastUtils.showError("退出失败(Error:file.delete())"); |
||||
} |
||||
} |
||||
}, (dialog, which) -> dialog.dismiss()); |
||||
} else { |
||||
Intent intent = new Intent(mMainActivity, LoginActivity.class); |
||||
mMainActivity.startActivity(intent); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* 初始化 |
||||
*/ |
||||
private void init() { |
||||
mBookcaseFragment = new BookcaseFragment(); |
||||
mFragments.add(mBookcaseFragment); |
||||
mMainActivity.getVpContent().setAdapter(new FragmentPagerAdapter(mMainActivity.getSupportFragmentManager(), BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { |
||||
@Override |
||||
public Fragment getItem(int position) { |
||||
return mFragments.get(position); |
||||
} |
||||
|
||||
@Override |
||||
public int getCount() { |
||||
return mFragments.size(); |
||||
} |
||||
|
||||
@Override |
||||
public CharSequence getPageTitle(int position) { |
||||
return tabTitle[position]; |
||||
} |
||||
|
||||
}); |
||||
mMainActivity.getTlTabMenu().setupWithViewPager(mMainActivity.getVpContent()); |
||||
mMainActivity.getVpContent().setCurrentItem(0); |
||||
} |
||||
|
||||
/** |
||||
* 添加本地书籍 |
||||
* @param path |
||||
*/ |
||||
public void addLocalBook(String path){ |
||||
mBookcaseFragment.getmBookcasePresenter().addLocalBook(path); |
||||
} |
||||
|
||||
/** |
||||
* 取消编辑状态 |
||||
*/ |
||||
public void cancelEdit(){ |
||||
mBookcaseFragment.getmBookcasePresenter().cancelEdit(); |
||||
} |
||||
|
||||
/** |
||||
* 判断是否处于编辑状态 |
||||
* @return |
||||
*/ |
||||
public boolean ismEditState(){ |
||||
if (mBookcaseFragment.getmBookcasePresenter() == null) { |
||||
return false; |
||||
} |
||||
return mBookcaseFragment.getmBookcasePresenter().ismEditState(); |
||||
} |
||||
} |
@ -1,244 +0,0 @@ |
||||
package xyz.fycz.myreader.ui.presenter; |
||||
|
||||
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 xyz.fycz.myreader.backup.UserService; |
||||
import xyz.fycz.myreader.base.BasePresenter; |
||||
import xyz.fycz.myreader.callback.ResultCallback; |
||||
import xyz.fycz.myreader.creator.DialogCreator; |
||||
import xyz.fycz.myreader.ui.activity.RegisterActivity; |
||||
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/4/26 20:31 |
||||
*/ |
||||
|
||||
public class RegisterPresenter implements BasePresenter { |
||||
private RegisterActivity mRegisterActivity; |
||||
private String code; |
||||
private String username = ""; |
||||
private String password = ""; |
||||
private String rpPassword = ""; |
||||
private String inputCode = ""; |
||||
|
||||
public RegisterPresenter(RegisterActivity mRegisterActivity) { |
||||
this.mRegisterActivity = mRegisterActivity; |
||||
} |
||||
|
||||
@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: |
||||
mRegisterActivity.getTvRegisterTip().setVisibility(View.GONE); |
||||
break; |
||||
} |
||||
} |
||||
}; |
||||
|
||||
@Override |
||||
public void start() { |
||||
mHandler.sendMessage(mHandler.obtainMessage(1)); |
||||
mRegisterActivity.getTvTitleText().setText("注册"); |
||||
mRegisterActivity.getEtUsername().requestFocus(); |
||||
mRegisterActivity.getLlTitleBack().setOnClickListener(v -> mRegisterActivity.finish()); |
||||
|
||||
mRegisterActivity.getEtUsername().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(); |
||||
} |
||||
}); |
||||
|
||||
mRegisterActivity.getEtPassword().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(); |
||||
} |
||||
}); |
||||
|
||||
mRegisterActivity.getEtRpPassword().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(); |
||||
} |
||||
}); |
||||
|
||||
mRegisterActivity.getEtCaptcha().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(); |
||||
} |
||||
}); |
||||
|
||||
mRegisterActivity.getIvCaptcha().setOnClickListener(new View.OnClickListener() { |
||||
@Override |
||||
public void onClick(View v) { |
||||
mHandler.sendMessage(mHandler.obtainMessage(1)); |
||||
} |
||||
}); |
||||
|
||||
mRegisterActivity.getBtRegister().setOnClickListener(new View.OnClickListener() { |
||||
@Override |
||||
public void onClick(View v) { |
||||
if (!username.matches("^[A-Za-z][A-Za-z0-9]{5,13}$")){ |
||||
DialogCreator.createTipDialog(mRegisterActivity, "用户名格式错误", |
||||
"用户名必须在6-14位之间\n用户名只能以字母开头\n用户名只能由数字、字母、下划线、减号组成"); |
||||
}else if(password.matches("^\\d+$") || !password.matches("^.{8,16}$")){ |
||||
DialogCreator.createTipDialog(mRegisterActivity, "密码格式错误", |
||||
"密码必须在8-16位之间\n密码不能是纯数字"); |
||||
}else if(!password.equals(rpPassword)){ |
||||
DialogCreator.createTipDialog(mRegisterActivity, "重复密码错误", |
||||
"两次输入的密码不一致"); |
||||
}else if(!inputCode.trim().toLowerCase().equals(code.toLowerCase())){ |
||||
DialogCreator.createTipDialog(mRegisterActivity, "验证码错误"); |
||||
}else if(!mRegisterActivity.getCbAgreement().isChecked()){ |
||||
DialogCreator.createTipDialog(mRegisterActivity, "请勾选同意《用户服务协议》"); |
||||
}else { |
||||
ProgressDialog dialog = DialogCreator.createProgressDialog(mRegisterActivity, 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]); |
||||
mRegisterActivity.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)); |
||||
} |
||||
}); |
||||
|
||||
mRegisterActivity.getTvAgreement().setMovementMethod(LinkMovementMethod.getInstance()); |
||||
} |
||||
|
||||
|
||||
public void createCaptcha() { |
||||
code = CodeUtil.getInstance().createCode(); |
||||
Bitmap codeBitmap = CodeUtil.getInstance().createBitmap(code); |
||||
mRegisterActivity.getIvCaptcha().setImageBitmap(codeBitmap); |
||||
} |
||||
|
||||
public void showTip(String tip) { |
||||
mRegisterActivity.getTvRegisterTip().setVisibility(View.VISIBLE); |
||||
mRegisterActivity.getTvRegisterTip().setText(tip); |
||||
} |
||||
|
||||
public void checkNotNone(){ |
||||
if ("".equals(username) || "".equals(password) || "".equals(rpPassword) || "".equals(inputCode)){ |
||||
mRegisterActivity.getBtRegister().setEnabled(false); |
||||
}else { |
||||
mRegisterActivity.getBtRegister().setEnabled(true); |
||||
} |
||||
} |
||||
|
||||
} |
@ -1,354 +0,0 @@ |
||||
package xyz.fycz.myreader.ui.presenter; |
||||
|
||||
import android.annotation.SuppressLint; |
||||
import android.content.Context; |
||||
import android.content.Intent; |
||||
import android.os.Build; |
||||
import android.os.Handler; |
||||
import android.os.Message; |
||||
import android.text.Editable; |
||||
import android.text.TextWatcher; |
||||
import android.view.KeyEvent; |
||||
import android.view.View; |
||||
import android.view.inputmethod.EditorInfo; |
||||
import android.view.inputmethod.InputMethodManager; |
||||
|
||||
import xyz.fycz.myreader.application.MyApplication; |
||||
import xyz.fycz.myreader.webapi.crawler.*; |
||||
import xyz.fycz.myreader.entity.SearchBookBean; |
||||
import xyz.fycz.myreader.mulvalmap.ConcurrentMultiValueMap; |
||||
import xyz.fycz.myreader.ui.activity.BookDetailedActivity; |
||||
import xyz.fycz.myreader.R; |
||||
import xyz.fycz.myreader.base.BasePresenter; |
||||
import xyz.fycz.myreader.callback.ResultCallback; |
||||
import xyz.fycz.myreader.common.APPCONST; |
||||
import xyz.fycz.myreader.greendao.entity.Book; |
||||
import xyz.fycz.myreader.greendao.entity.SearchHistory; |
||||
import xyz.fycz.myreader.greendao.service.SearchHistoryService; |
||||
import xyz.fycz.myreader.ui.activity.SearchBookActivity; |
||||
import xyz.fycz.myreader.ui.adapter.SearchBookAdapter; |
||||
import xyz.fycz.myreader.ui.adapter.SearchHistoryAdapter; |
||||
import xyz.fycz.myreader.util.StringHelper; |
||||
import xyz.fycz.myreader.webapi.CommonApi; |
||||
|
||||
import java.io.UnsupportedEncodingException; |
||||
import java.net.URLEncoder; |
||||
import java.util.ArrayList; |
||||
import java.util.Arrays; |
||||
import java.util.Collections; |
||||
|
||||
|
||||
public class SearchBookPrensenter implements BasePresenter { |
||||
|
||||
private SearchBookActivity mSearchBookActivity; |
||||
private SearchBookAdapter mSearchBookAdapter; |
||||
private String searchKey;//搜索关键字
|
||||
private ArrayList<SearchBookBean> mBooksBean = new ArrayList<>(); |
||||
private ConcurrentMultiValueMap<SearchBookBean, Book> mBooks = new ConcurrentMultiValueMap<>(); |
||||
private ArrayList<Book> mAdapterBooks = new ArrayList<>(); |
||||
private ArrayList<SearchHistory> mSearchHistories = new ArrayList<>(); |
||||
private ArrayList<String> mSuggestions = new ArrayList<>(); |
||||
|
||||
private SearchHistoryService mSearchHistoryService; |
||||
|
||||
private SearchHistoryAdapter mSearchHistoryAdapter; |
||||
|
||||
private int curThreadCount; |
||||
|
||||
private int allThreadCount; |
||||
|
||||
private int inputConfirm = 0;//搜索输入确认
|
||||
private int confirmTime = 1000;//搜索输入确认时间(毫秒)
|
||||
|
||||
private static String[] suggestion = {"第一序列", "大道朝天", "伏天氏", "终极斗罗", "我师兄实在太稳健了", "烂柯棋缘", "诡秘之主"}; |
||||
private static String[] suggestion2 = {"不朽凡人", "圣墟", "我是至尊", "龙王传说", "太古神王", "一念永恒", "雪鹰领主", "大主宰"}; |
||||
|
||||
@SuppressLint("HandlerLeak") |
||||
private Handler mHandler = new Handler() { |
||||
@Override |
||||
public void handleMessage(Message msg) { |
||||
switch (msg.what) { |
||||
case 1: |
||||
search(); |
||||
break; |
||||
case 2: |
||||
if (curThreadCount == 0) { |
||||
initSearchList(); |
||||
mSearchBookActivity.getSrlSearchBookList().finishRefresh(); |
||||
mSearchBookActivity.getPbLoading().setVisibility(View.GONE); |
||||
}/*else { |
||||
notifyDataSetChanged(); |
||||
mSearchBookActivity.getSrlSearchBookList().finishRefresh(); |
||||
}*/ |
||||
break; |
||||
} |
||||
} |
||||
}; |
||||
|
||||
public SearchBookPrensenter(SearchBookActivity searchBookActivity) { |
||||
mSearchBookActivity = searchBookActivity; |
||||
mSearchHistoryService = SearchHistoryService.getInstance(); |
||||
for (int i = 0; i < suggestion.length; i++) { |
||||
mSuggestions.add(suggestion[i]); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void start() { |
||||
mSearchBookActivity.getTvTitleText().setText("搜索"); |
||||
mSearchBookActivity.getEtSearchKey().requestFocus();//get the focus
|
||||
//enter事件
|
||||
mSearchBookActivity.getEtSearchKey().setOnEditorActionListener((textView, i, keyEvent) -> { |
||||
if (i == EditorInfo.IME_ACTION_UNSPECIFIED) { |
||||
mHandler.sendMessage(mHandler.obtainMessage(1)); |
||||
return (keyEvent.getKeyCode() == KeyEvent.KEYCODE_ENTER); |
||||
} |
||||
return false; |
||||
}); |
||||
//换一批点击事件
|
||||
mSearchBookActivity.getRenewByImage().setOnClickListener(new RenewSuggestionBook()); |
||||
//换一批点击事件
|
||||
mSearchBookActivity.getRenewByText().setOnClickListener(new RenewSuggestionBook()); |
||||
//返回
|
||||
mSearchBookActivity.getLlTitleBack().setOnClickListener(view -> mSearchBookActivity.finish()); |
||||
//搜索框改变事件
|
||||
mSearchBookActivity.getEtSearchKey().addTextChangedListener(new TextWatcher() { |
||||
|
||||
@Override |
||||
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public void afterTextChanged(final Editable editable) { |
||||
searchKey = editable.toString(); |
||||
if (StringHelper.isEmpty(searchKey)) { |
||||
mHandler.sendMessage(mHandler.obtainMessage(1)); |
||||
} |
||||
|
||||
} |
||||
|
||||
}); |
||||
//进入书籍详情页
|
||||
mSearchBookActivity.getGvSearchBooksList().setOnItemClickListener((adapterView, view, i, l) -> { |
||||
Intent intent = new Intent(mSearchBookActivity, BookDetailedActivity.class); |
||||
intent.putExtra(APPCONST.SEARCH_BOOK_BEAN, new ArrayList<>(mBooks.getValues(mBooksBean.get(i)))); |
||||
mSearchBookActivity.startActivity(intent); |
||||
}); |
||||
//搜索按钮点击事件
|
||||
mSearchBookActivity.getTvSearchConform().setOnClickListener(view -> mHandler.sendMessage(mHandler.obtainMessage(1))); |
||||
//suggestion搜索事件
|
||||
mSearchBookActivity.getTgSuggestBook().setOnTagClickListener(tag -> { |
||||
mSearchBookActivity.getEtSearchKey().setText(tag); |
||||
mSearchBookActivity.getEtSearchKey().setSelection(tag.length()); |
||||
mHandler.sendMessage(mHandler.obtainMessage(1)); |
||||
}); |
||||
//历史记录搜索事件
|
||||
mSearchBookActivity.getLvHistoryList().setOnItemClickListener((parent, view, position, id) -> { |
||||
mSearchBookActivity.getEtSearchKey().setText(mSearchHistories.get(position).getContent()); |
||||
mSearchBookActivity.getEtSearchKey().setSelection(mSearchHistories.get(position).getContent().length()); |
||||
mHandler.sendMessage(mHandler.obtainMessage(1)); |
||||
}); |
||||
//清空历史记录
|
||||
mSearchBookActivity.getLlClearHistory().setOnClickListener(v -> { |
||||
mSearchHistoryService.clearHistory(); |
||||
initHistoryList(); |
||||
}); |
||||
//清除单个历史记录
|
||||
mSearchBookActivity.getLvHistoryList().setOnItemLongClickListener((parent, view, position, id) -> { |
||||
if (mSearchHistories.get(position) != null) { |
||||
mSearchHistoryService.deleteHistory(mSearchHistories.get(position)); |
||||
initHistoryList(); |
||||
} |
||||
return true; |
||||
}); |
||||
//上拉刷新
|
||||
mSearchBookActivity.getSrlSearchBookList().setOnRefreshListener(refreshLayout -> mHandler.sendMessage(mHandler.obtainMessage(1))); |
||||
mSearchBookActivity.getSrlSearchBookList().setEnableRefresh(false); |
||||
mSearchBookActivity.getGvSearchBooksList().setNumColumns(1); |
||||
mSearchBookActivity.getGvSearchBooksList().setDragModel(-1); |
||||
initSuggestionBook(); |
||||
initHistoryList(); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 初始化建议书目 |
||||
*/ |
||||
private void initSuggestionBook() { |
||||
mSearchBookActivity.getTgSuggestBook().setTags(suggestion); |
||||
} |
||||
|
||||
private class RenewSuggestionBook implements View.OnClickListener { |
||||
@Override |
||||
public void onClick(View v) { |
||||
String[] s = mSearchBookActivity.getTgSuggestBook().getTags(); |
||||
if (Arrays.equals(s, suggestion)) { |
||||
mSearchBookActivity.getTgSuggestBook().setTags(suggestion2); |
||||
} else { |
||||
mSearchBookActivity.getTgSuggestBook().setTags(suggestion); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 初始化历史列表 |
||||
*/ |
||||
private void initHistoryList() { |
||||
mSearchHistories = mSearchHistoryService.findAllSearchHistory(); |
||||
if (mSearchHistories == null || mSearchHistories.size() == 0) { |
||||
mSearchBookActivity.getLlHistoryView().setVisibility(View.GONE); |
||||
} else { |
||||
mSearchHistoryAdapter = new SearchHistoryAdapter(mSearchBookActivity, R.layout.listview_search_history_item, mSearchHistories); |
||||
mSearchBookActivity.getLvHistoryList().setAdapter(mSearchHistoryAdapter); |
||||
mSearchBookActivity.getLlHistoryView().setVisibility(View.VISIBLE); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 初始化搜索列表 |
||||
*/ |
||||
private void initSearchList() { |
||||
initmBooksBean(); |
||||
mSearchBookAdapter = new SearchBookAdapter(mSearchBookActivity, |
||||
R.layout.listview_search_book_item, mBooksBean, mBooks); |
||||
mSearchBookActivity.getGvSearchBooksList().setAdapter(mSearchBookAdapter); |
||||
mSearchBookActivity.getGvSearchBooksList().setVisibility(View.VISIBLE); |
||||
mSearchBookActivity.getLlSuggestBooksView().setVisibility(View.GONE); |
||||
mSearchBookActivity.getLlHistoryView().setVisibility(View.GONE); |
||||
} |
||||
|
||||
/** |
||||
* 更新搜索列表 |
||||
*/ |
||||
private void notifyDataSetChanged() { |
||||
if (curThreadCount == 0) { |
||||
mSearchBookActivity.getPbLoading().setVisibility(View.GONE); |
||||
} |
||||
initmBooksBean(); |
||||
} |
||||
|
||||
/** |
||||
* 初始化mBooksBean |
||||
*/ |
||||
private void initmBooksBean() { |
||||
synchronized (this) { |
||||
mBooksBean.clear(); |
||||
mBooksBean.addAll(mBooks.keySet()); |
||||
//排序,基于最符合关键字的搜书结果应该是最短的
|
||||
//TODO ;这里只做了简单的比较排序,还需要继续完善
|
||||
Collections.sort(mBooksBean, (o1, o2) -> { |
||||
if (searchKey.equals(o1.getName())) |
||||
return -1; |
||||
if (searchKey.equals(o2.getName())) |
||||
return 1; |
||||
if (searchKey.equals(o1.getAuthor())) |
||||
return -1; |
||||
if (searchKey.equals(o2.getAuthor())) |
||||
return 1; |
||||
if (o1.getName().length() < o2.getName().length()) |
||||
return -1; |
||||
if (o1.getName().length() == o2.getName().length()) |
||||
return 0; |
||||
return 1; |
||||
}); |
||||
/*MyApplication.runOnUiThread(new Runnable() { |
||||
@Override |
||||
public void run() { |
||||
mSearchBookAdapter.notifyDataSetChanged(); |
||||
} |
||||
});*/ |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 获取搜索数据 |
||||
*/ |
||||
private void getData() { |
||||
mBooksBean.clear(); |
||||
mBooks.clear(); |
||||
allThreadCount = 4; |
||||
curThreadCount = allThreadCount; |
||||
searchBookByCrawler(new BiQuGe44ReadCrawler(), ""); |
||||
searchBookByCrawler(new TianLaiReadCrawler(), ""); |
||||
searchBookByCrawler(new BiQuGeReadCrawler(), "gbk"); |
||||
searchBookByCrawler(new PinShuReadCrawler(), "gbk"); |
||||
} |
||||
|
||||
/** |
||||
* 搜索 |
||||
*/ |
||||
private void search() { |
||||
mSearchBookActivity.getPbLoading().setVisibility(View.VISIBLE); |
||||
if (StringHelper.isEmpty(searchKey)) { |
||||
mSearchBookActivity.getPbLoading().setVisibility(View.GONE); |
||||
mSearchBookActivity.getGvSearchBooksList().setVisibility(View.GONE); |
||||
mSearchBookActivity.getLlSuggestBooksView().setVisibility(View.VISIBLE); |
||||
initHistoryList(); |
||||
mSearchBookActivity.getGvSearchBooksList().setAdapter(null); |
||||
mSearchBookActivity.getSrlSearchBookList().setEnableRefresh(false); |
||||
} else { |
||||
mSearchBookActivity.getGvSearchBooksList().setVisibility(View.VISIBLE); |
||||
mSearchBookActivity.getLlSuggestBooksView().setVisibility(View.GONE); |
||||
mSearchBookActivity.getLlHistoryView().setVisibility(View.GONE); |
||||
getData(); |
||||
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { |
||||
if (mSearchBookActivity.getGvSearchBooksList().getmScrollView().getScrollY() == 0){ |
||||
mSearchBookActivity.getSrlSearchBookList().setEnableRefresh(true); |
||||
} |
||||
//滑动监听器
|
||||
mSearchBookActivity.getGvSearchBooksList().getmScrollView().setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> { |
||||
mSearchBookActivity.getSrlSearchBookList().setEnableRefresh(scrollY == 0); |
||||
}); |
||||
} |
||||
mSearchHistoryService.addOrUpadteHistory(searchKey); |
||||
//收起软键盘
|
||||
InputMethodManager imm = (InputMethodManager) MyApplication.getmContext().getSystemService(Context.INPUT_METHOD_SERVICE); |
||||
assert imm != null; |
||||
imm.hideSoftInputFromWindow(mSearchBookActivity.getEtSearchKey().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); |
||||
} |
||||
} |
||||
|
||||
public boolean onBackPressed() { |
||||
if (StringHelper.isEmpty(searchKey)) { |
||||
return false; |
||||
} else { |
||||
mSearchBookActivity.getEtSearchKey().setText(""); |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
private void searchBookByCrawler(ReadCrawler rc, String charset) { |
||||
String searchKey = this.searchKey; |
||||
if (charset.toLowerCase().equals("gbk")) { |
||||
try { |
||||
searchKey = URLEncoder.encode(this.searchKey, charset); |
||||
} catch (UnsupportedEncodingException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
CommonApi.search(searchKey, rc, new ResultCallback() { |
||||
@Override |
||||
public void onFinish(Object o, int code) { |
||||
ConcurrentMultiValueMap<SearchBookBean, Book> sbb = |
||||
(ConcurrentMultiValueMap<SearchBookBean, Book>) o; |
||||
mBooks.addAll(sbb); |
||||
curThreadCount--; |
||||
mHandler.sendMessage(mHandler.obtainMessage(2)); |
||||
} |
||||
|
||||
@Override |
||||
public void onError(Exception e) { |
||||
curThreadCount--; |
||||
mHandler.sendMessage(mHandler.obtainMessage(2)); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
} |
||||
|
@ -0,0 +1,61 @@ |
||||
package xyz.fycz.myreader.util.utils; |
||||
|
||||
import android.annotation.TargetApi; |
||||
import android.content.Context; |
||||
import android.graphics.Bitmap; |
||||
import android.os.Build; |
||||
import android.renderscript.Allocation; |
||||
import android.renderscript.Element; |
||||
import android.renderscript.RenderScript; |
||||
import android.renderscript.ScriptIntrinsicBlur; |
||||
import androidx.annotation.NonNull; |
||||
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; |
||||
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; |
||||
|
||||
import java.security.MessageDigest; |
||||
|
||||
public class BlurTransformation extends BitmapTransformation { |
||||
private RenderScript rs; |
||||
private int radius; |
||||
|
||||
public BlurTransformation(Context context, int radius) { |
||||
super(); |
||||
rs = RenderScript.create(context); |
||||
this.radius = radius; |
||||
} |
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) |
||||
@Override |
||||
protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) { |
||||
Bitmap blurredBitmap = toTransform.copy(Bitmap.Config.ARGB_8888, true); |
||||
|
||||
// Allocate memory for Renderscript to work with
|
||||
//分配用于渲染脚本的内存
|
||||
Allocation input = Allocation.createFromBitmap(rs, blurredBitmap, Allocation.MipmapControl.MIPMAP_FULL, Allocation.USAGE_SHARED); |
||||
Allocation output = Allocation.createTyped(rs, input.getType()); |
||||
|
||||
// Load up an instance of the specific script that we want to use.
|
||||
//加载我们想要使用的特定脚本的实例。
|
||||
ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); |
||||
script.setInput(input); |
||||
|
||||
// Set the blur radius
|
||||
//设置模糊半径
|
||||
script.setRadius(radius); |
||||
|
||||
// Start the ScriptIntrinsicBlur
|
||||
//启动 ScriptIntrinsicBlur,
|
||||
script.forEach(output); |
||||
|
||||
// Copy the output to the blurred bitmap
|
||||
//将输出复制到模糊的位图
|
||||
output.copyTo(blurredBitmap); |
||||
|
||||
return blurredBitmap; |
||||
} |
||||
|
||||
@Override |
||||
public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) { |
||||
messageDigest.update("blur transformation".getBytes()); |
||||
} |
||||
} |
@ -0,0 +1,80 @@ |
||||
package xyz.fycz.myreader.util.utils; |
||||
|
||||
import android.graphics.Color; |
||||
import androidx.annotation.ColorInt; |
||||
import androidx.annotation.FloatRange; |
||||
|
||||
@SuppressWarnings({"unused", "WeakerAccess"}) |
||||
public class ColorUtil { |
||||
|
||||
public static String intToString(int intColor) { |
||||
return String.format("#%06X", 0xFFFFFF & intColor); |
||||
} |
||||
|
||||
|
||||
public static int stripAlpha(@ColorInt int color) { |
||||
return 0xff000000 | color; |
||||
} |
||||
|
||||
@ColorInt |
||||
public static int shiftColor(@ColorInt int color, @FloatRange(from = 0.0f, to = 2.0f) float by) { |
||||
if (by == 1f) return color; |
||||
int alpha = Color.alpha(color); |
||||
float[] hsv = new float[3]; |
||||
Color.colorToHSV(color, hsv); |
||||
hsv[2] *= by; // value component
|
||||
return (alpha << 24) + (0x00ffffff & Color.HSVToColor(hsv)); |
||||
} |
||||
|
||||
@ColorInt |
||||
public static int darkenColor(@ColorInt int color) { |
||||
return shiftColor(color, 0.9f); |
||||
} |
||||
|
||||
@ColorInt |
||||
public static int lightenColor(@ColorInt int color) { |
||||
return shiftColor(color, 1.1f); |
||||
} |
||||
|
||||
public static boolean isColorLight(@ColorInt int color) { |
||||
final double darkness = 1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255; |
||||
return darkness < 0.4; |
||||
} |
||||
|
||||
@ColorInt |
||||
public static int invertColor(@ColorInt int color) { |
||||
final int r = 255 - Color.red(color); |
||||
final int g = 255 - Color.green(color); |
||||
final int b = 255 - Color.blue(color); |
||||
return Color.argb(Color.alpha(color), r, g, b); |
||||
} |
||||
|
||||
@ColorInt |
||||
public static int adjustAlpha(@ColorInt int color, @FloatRange(from = 0.0, to = 1.0) float factor) { |
||||
int alpha = Math.round(Color.alpha(color) * factor); |
||||
int red = Color.red(color); |
||||
int green = Color.green(color); |
||||
int blue = Color.blue(color); |
||||
return Color.argb(alpha, red, green, blue); |
||||
} |
||||
|
||||
@ColorInt |
||||
public static int withAlpha(@ColorInt int baseColor, @FloatRange(from = 0.0, to = 1.0) float alpha) { |
||||
int a = Math.min(255, Math.max(0, (int) (alpha * 255))) << 24; |
||||
int rgb = 0x00ffffff & baseColor; |
||||
return a + rgb; |
||||
} |
||||
|
||||
/** |
||||
* Taken from CollapsingToolbarLayout's CollapsingTextHelper class. |
||||
*/ |
||||
public static int blendColors(int color1, int color2, @FloatRange(from = 0.0, to = 1.0) float ratio) { |
||||
final float inverseRatio = 1f - ratio; |
||||
float a = (Color.alpha(color1) * inverseRatio) + (Color.alpha(color2) * ratio); |
||||
float r = (Color.red(color1) * inverseRatio) + (Color.red(color2) * ratio); |
||||
float g = (Color.green(color1) * inverseRatio) + (Color.green(color2) * ratio); |
||||
float b = (Color.blue(color1) * inverseRatio) + (Color.blue(color2) * ratio); |
||||
return Color.argb((int) a, (int) r, (int) g, (int) b); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,23 @@ |
||||
package xyz.fycz.myreader.webapi.crawler; |
||||
|
||||
import xyz.fycz.myreader.entity.bookstore.BookType; |
||||
import xyz.fycz.myreader.greendao.entity.Book; |
||||
|
||||
import java.io.Serializable; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* @author fengyue |
||||
* @date 2020/9/14 18:36 |
||||
*/ |
||||
public abstract class FindCrawler implements Serializable { |
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
public abstract String getCharset(); |
||||
public abstract String getFindName(); |
||||
public abstract String getFindUrl(); |
||||
public abstract boolean getTypePage(BookType curType, int page); |
||||
public abstract boolean hasImg(); |
||||
public abstract List<BookType> getBookTypeList(String html); |
||||
public abstract List<Book> getRankBookList(String html); |
||||
} |
@ -0,0 +1,287 @@ |
||||
package xyz.fycz.myreader.webapi.crawler; |
||||
|
||||
import android.text.Html; |
||||
import org.jsoup.Jsoup; |
||||
import org.jsoup.nodes.Document; |
||||
import org.jsoup.nodes.Element; |
||||
import org.jsoup.select.Elements; |
||||
import xyz.fycz.myreader.entity.SearchBookBean; |
||||
import xyz.fycz.myreader.entity.bookstore.BookType; |
||||
import xyz.fycz.myreader.enums.BookSource; |
||||
import xyz.fycz.myreader.greendao.entity.Book; |
||||
import xyz.fycz.myreader.greendao.entity.Chapter; |
||||
import xyz.fycz.myreader.mulvalmap.ConcurrentMultiValueMap; |
||||
import xyz.fycz.myreader.util.StringHelper; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
|
||||
public class QB5ReadCrawler extends FindCrawler implements ReadCrawler, BookInfoCrawler { |
||||
private static final String NAME_SPACE = "https://www.qb5.tw"; |
||||
private static final String NOVEL_SEARCH = "https://www.qb5.tw/modules/article/search.php"; |
||||
public static final String FIND_URL = "https://www.qb5.tw"; |
||||
public static final String FIND_NAME = "书城[全本小说]"; |
||||
private static final String SEARCH_KEY = "searchkey"; |
||||
private static final String CHARSET = "GBK"; |
||||
public static final String SEARCH_CHARSET = "GBK"; |
||||
|
||||
@Override |
||||
public String getSearchLink() { |
||||
return NOVEL_SEARCH; |
||||
} |
||||
|
||||
@Override |
||||
public String getNameSpace() { |
||||
return NAME_SPACE; |
||||
} |
||||
|
||||
@Override |
||||
public String getSearchKey() { |
||||
return SEARCH_KEY; |
||||
} |
||||
|
||||
@Override |
||||
public String getCharset() { |
||||
return CHARSET; |
||||
} |
||||
|
||||
@Override |
||||
public String getFindName() { |
||||
return FIND_NAME; |
||||
} |
||||
|
||||
@Override |
||||
public String getFindUrl() { |
||||
return FIND_URL; |
||||
} |
||||
|
||||
@Override |
||||
public String getSearchCharset() { |
||||
return SEARCH_CHARSET; |
||||
} |
||||
|
||||
@Override |
||||
public boolean hasImg() { |
||||
return false; |
||||
} |
||||
/** |
||||
* 获取书城小说分类列表 |
||||
* |
||||
* @param html |
||||
* @return |
||||
*/ |
||||
public List<BookType> getBookTypeList(String html) { |
||||
List<BookType> bookTypes = new ArrayList<>(); |
||||
Document doc = Jsoup.parse(html); |
||||
Elements divs = doc.getElementsByClass("nav_cont"); |
||||
if (divs.size() > 0) { |
||||
Elements uls = divs.get(0).getElementsByTag("ul"); |
||||
if (uls.size() > 0) { |
||||
for (Element li : uls.get(0).children()) { |
||||
Element a = li.child(0); |
||||
BookType bookType = new BookType(); |
||||
bookType.setTypeName(a.attr("title")); |
||||
bookType.setUrl(a.attr("href")); |
||||
if (bookType.getTypeName().contains("首页") || bookType.getTypeName().contains("热门小说")) continue; |
||||
if (!StringHelper.isEmpty(bookType.getTypeName())) { |
||||
bookTypes.add(bookType); |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
return bookTypes; |
||||
} |
||||
|
||||
/** |
||||
* 获取某一分类小说排行榜列表 |
||||
* |
||||
* @param html |
||||
* @return |
||||
*/ |
||||
public List<Book> getBookRankList(String html) { |
||||
List<Book> books = new ArrayList<>(); |
||||
Document doc = Jsoup.parse(html); |
||||
Elements divs = doc.getElementsByClass("r"); |
||||
if (divs.size() > 0) { |
||||
Elements uls = divs.get(0).getElementsByTag("ul"); |
||||
if (uls.size() > 0) { |
||||
for (Element li : uls.get(0).children()) { |
||||
Book book = new Book(); |
||||
Element scanS1 = li.getElementsByClass("s1").get(0); |
||||
Element scanS2 = li.getElementsByClass("s2").get(0); |
||||
Element scanS5 = li.getElementsByClass("s5").get(0); |
||||
book.setType(scanS1.html().replace("[", "").replace("]", "")); |
||||
Element a = scanS2.getElementsByTag("a").get(0); |
||||
book.setName(a.attr("title")); |
||||
book.setChapterUrl(a.attr("href")); |
||||
book.setAuthor(scanS5.html()); |
||||
book.setSource(BookSource.biquge.toString()); |
||||
books.add(book); |
||||
} |
||||
} |
||||
} |
||||
|
||||
return books; |
||||
} |
||||
|
||||
public List<Book> getRankBookList(String html) { |
||||
List<Book> books = new ArrayList<>(); |
||||
Document doc = Jsoup.parse(html); |
||||
String type = doc.select("meta[name=keywords]").attr("content").replace(",全本小说网", ""); |
||||
Element div = doc.getElementById("tlist"); |
||||
Elements uls = div.getElementsByTag("ul"); |
||||
if (uls.size() > 0) { |
||||
for (Element li : uls.get(0).children()) { |
||||
Book book = new Book(); |
||||
Element aName = li.getElementsByClass("name").get(0); |
||||
Element divZz = li.getElementsByClass("zz").get(0); |
||||
Element divAuthor = li.getElementsByClass("author").get(0); |
||||
Element divSj = li.getElementsByClass("sj").get(0); |
||||
book.setType(type); |
||||
book.setName(aName.attr("title")); |
||||
book.setChapterUrl(aName.attr("href")); |
||||
book.setNewestChapterTitle(divZz.text()); |
||||
book.setAuthor(divAuthor.text()); |
||||
book.setUpdateDate(divSj.text()); |
||||
book.setSource(BookSource.qb5.toString()); |
||||
books.add(book); |
||||
} |
||||
} |
||||
|
||||
return books; |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public String getContentFormHtml(String html) { |
||||
Document doc = Jsoup.parse(html); |
||||
Element divBook = doc.getElementsByClass("nav-style").get(0); |
||||
String bookName = divBook.getElementsByTag("a").get(1).attr("title"); |
||||
Element divContent = doc.getElementById("content"); |
||||
if (divContent != null) { |
||||
String content = Html.fromHtml(divContent.html()).toString(); |
||||
char c = 160; |
||||
String spaec = "" + c; |
||||
content = content.replace(spaec, " "); |
||||
content = content.replace("全本小说网 www.qb5.tw,最快更新", "") |
||||
.replace(bookName, "") |
||||
.replace("最新章节!", ""); |
||||
return content; |
||||
} else { |
||||
return ""; |
||||
} |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public ArrayList<Chapter> getChaptersFromHtml(String html) { |
||||
ArrayList<Chapter> chapters = new ArrayList<>(); |
||||
Document doc = Jsoup.parse(html); |
||||
String readUrl = doc.select("meta[property=og:novel:read_url]").attr("content"); |
||||
int num = 0; |
||||
Element zjbox = doc.getElementsByClass("zjbox").get(0); |
||||
Elements as = zjbox.getElementsByTag("a"); |
||||
for (int i = 12; i < as.size(); i++) { |
||||
Element a = as.get(i); |
||||
Chapter chapter = new Chapter(); |
||||
chapter.setNumber(num++); |
||||
chapter.setTitle(a.text()); |
||||
chapter.setUrl(readUrl + a.attr("href")); |
||||
chapters.add(chapter); |
||||
} |
||||
|
||||
return chapters; |
||||
} |
||||
|
||||
/** |
||||
* 从搜索html中得到书列表 |
||||
* |
||||
* @param html |
||||
* @return |
||||
*/ |
||||
public ConcurrentMultiValueMap<SearchBookBean, Book> getBooksFromSearchHtml(String html) { |
||||
final ConcurrentMultiValueMap<SearchBookBean, Book> books = new ConcurrentMultiValueMap<>(); |
||||
Document doc = Jsoup.parse(html); |
||||
String urlType = doc.select("meta[property=og:type]").attr("content"); |
||||
if ("novel".equals(urlType)) { |
||||
String readUrl = doc.select("meta[property=og:novel:read_url]").attr("content"); |
||||
Book book = new Book(); |
||||
book.setChapterUrl(readUrl); |
||||
getBookInfo(html, book); |
||||
SearchBookBean sbb = new SearchBookBean(book.getName(), book.getAuthor()); |
||||
books.add(sbb, book); |
||||
} else { |
||||
Elements divs = doc.getElementsByClass("grid"); |
||||
Element div = divs.get(0); |
||||
Elements elementsByTag = div.getElementsByTag("tr"); |
||||
for (int i = 1; i < elementsByTag.size(); i++) { |
||||
Element element = elementsByTag.get(i); |
||||
Book book = new Book(); |
||||
Elements info = element.getElementsByTag("td"); |
||||
book.setName(info.get(0).text()); |
||||
book.setChapterUrl(info.get(0).getElementsByTag("a").attr("href")); |
||||
book.setNewestChapterTitle(info.get(1).text()); |
||||
book.setAuthor(info.get(2).text()); |
||||
book.setSource(BookSource.qb5.toString()); |
||||
SearchBookBean sbb = new SearchBookBean(book.getName(), book.getAuthor()); |
||||
books.add(sbb, book); |
||||
} |
||||
} |
||||
return books; |
||||
} |
||||
|
||||
/** |
||||
* 获取小说详细信息 |
||||
* |
||||
* @param html |
||||
* @return |
||||
*/ |
||||
public Book getBookInfo(String html, Book book) { |
||||
//小说源
|
||||
book.setSource(BookSource.qb5.toString()); |
||||
Document doc = Jsoup.parse(html); |
||||
//书名
|
||||
String name = doc.select("meta[property=og:title]").attr("content"); |
||||
book.setName(name); |
||||
//作者
|
||||
String author = doc.select("meta[property=og:novel:author]").attr("content"); |
||||
book.setAuthor(author); |
||||
//最新章节
|
||||
String newestChapter = doc.select("meta[property=og:novel:latest_chapter_name]").attr("content"); |
||||
book.setNewestChapterTitle(newestChapter); |
||||
//更新时间
|
||||
String updateTime = doc.select("meta[property=og:novel:update_time]").attr("content"); |
||||
book.setUpdateDate(updateTime); |
||||
//图片url
|
||||
Element divImg = doc.getElementsByClass("img_in").get(0); |
||||
Element img = divImg.getElementsByTag("img").get(0); |
||||
book.setImgUrl(img.attr("src")); |
||||
//简介
|
||||
Element divIntro = doc.getElementById("intro"); |
||||
book.setDesc(divIntro.text()); |
||||
//类型
|
||||
String type = doc.select("meta[property=og:novel:category]").attr("content"); |
||||
book.setType(type); |
||||
return book; |
||||
} |
||||
|
||||
|
||||
public boolean getTypePage(BookType curType, int page){ |
||||
if (page > 10){ |
||||
return true; |
||||
} |
||||
if (!curType.getTypeName().equals("完本小说")) { |
||||
curType.setUrl(curType.getUrl().substring(0, curType.getUrl().lastIndexOf("_") + 1) + page + "/"); |
||||
}else { |
||||
if (page > 1){ |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
|
||||
|
||||
} |
@ -1,75 +0,0 @@ |
||||
package xyz.fycz.myreader.webapi.crawler; |
||||
|
||||
import org.jsoup.Jsoup; |
||||
import org.jsoup.nodes.Document; |
||||
import org.jsoup.nodes.Element; |
||||
import org.jsoup.select.Elements; |
||||
import xyz.fycz.myreader.entity.bookstore.BookType; |
||||
import xyz.fycz.myreader.greendao.entity.Book; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* @author fengyue |
||||
* @date 2020/5/27 11:17 |
||||
*/ |
||||
public class QiDianRankList { |
||||
|
||||
public static final String[] TYPE_NAME = { |
||||
"月票榜", "畅销榜", "阅读榜", "推荐榜", "收藏榜" |
||||
}; |
||||
|
||||
/** |
||||
* 获取书城小说分类列表 |
||||
* |
||||
* @param html |
||||
* @return |
||||
*/ |
||||
public static List<BookType> getBookTypeList(String html) { |
||||
List<BookType> bookTypes = new ArrayList<>(); |
||||
Document doc = Jsoup.parse(html); |
||||
Elements divs = doc.getElementsByClass("more"); |
||||
for (int i = 0; i < 5; i++) { |
||||
BookType bookType = new BookType(); |
||||
bookType.setTypeName(TYPE_NAME[i]); |
||||
bookType.setUrl("https:" + divs.get(i).attr("href")); |
||||
bookTypes.add(bookType); |
||||
} |
||||
return bookTypes; |
||||
} |
||||
|
||||
/** |
||||
* 获取某一分类小说排行榜列表 |
||||
* |
||||
* @param html |
||||
* @return |
||||
*/ |
||||
public static List<Book> getBookRankList(String html) { |
||||
List<Book> books = new ArrayList<>(); |
||||
Document doc = Jsoup.parse(html); |
||||
Elements lis = doc.getElementsByTag("li"); |
||||
if (lis.size() > 0) { |
||||
Elements bookLis = lis.select("data-rid"); |
||||
if (bookLis.size() > 0) { |
||||
for (Element li : bookLis) { |
||||
Book book = new Book(); |
||||
String imgSrc = li.getElementsByClass("book-img-box").get(0) |
||||
.getElementsByTag("img").attr("src"); |
||||
book.setImgUrl("https:" + imgSrc); |
||||
Element bookInfo = li.getElementsByClass("book-mid-info").get(0); |
||||
Elements tagA = bookInfo.getElementsByTag("a"); |
||||
book.setName(tagA.get(0).text()); |
||||
book.setAuthor(tagA.get(1).text()); |
||||
book.setType(tagA.get(2).text()); |
||||
book.setNewestChapterTitle(tagA.get(3).text()); |
||||
String desc = bookInfo.getElementsByClass("intro").get(0).text(); |
||||
book.setDesc(desc); |
||||
books.add(book); |
||||
} |
||||
} |
||||
} |
||||
return books; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,117 @@ |
||||
package xyz.fycz.myreader.webapi.crawler.find; |
||||
|
||||
import android.content.Context; |
||||
import android.graphics.Bitmap; |
||||
import android.util.Log; |
||||
import android.webkit.*; |
||||
import okhttp3.*; |
||||
import org.json.JSONArray; |
||||
import org.json.JSONException; |
||||
import org.json.JSONObject; |
||||
import xyz.fycz.myreader.application.MyApplication; |
||||
import xyz.fycz.myreader.callback.ResultCallback; |
||||
import xyz.fycz.myreader.creator.DialogCreator; |
||||
import xyz.fycz.myreader.entity.bookstore.BookType; |
||||
import xyz.fycz.myreader.entity.bookstore.QDBook; |
||||
import xyz.fycz.myreader.entity.bookstore.RankBook; |
||||
import xyz.fycz.myreader.entity.bookstore.SortBook; |
||||
import xyz.fycz.myreader.greendao.entity.Book; |
||||
import xyz.fycz.myreader.util.IOUtils; |
||||
import xyz.fycz.myreader.util.SharedPreUtils; |
||||
import xyz.fycz.myreader.util.StringHelper; |
||||
import xyz.fycz.myreader.webapi.CommonApi; |
||||
import xyz.fycz.myreader.webapi.crawler.FindCrawler; |
||||
|
||||
import java.io.BufferedReader; |
||||
import java.io.IOException; |
||||
import java.io.InputStreamReader; |
||||
import java.text.SimpleDateFormat; |
||||
import java.util.*; |
||||
|
||||
/** |
||||
* @author fengyue |
||||
* @date 2020/9/16 22:01 |
||||
*/ |
||||
public class ABC extends FindCrawler { |
||||
private String rankUrl = ""; |
||||
private String sortUrl = ""; |
||||
private String[] sex = {"male", "female"}; |
||||
private String aParam = ""; |
||||
private String imgUrl = ""; |
||||
private String defaultCookie = ""; |
||||
private String yearmonthFormat = ""; |
||||
private LinkedHashMap<String, String> rankName = new LinkedHashMap<>(); |
||||
private LinkedHashMap<String, Integer> sortName = new LinkedHashMap<>(); |
||||
private boolean isFemale; |
||||
private boolean isSort; |
||||
|
||||
public ABC(boolean isFemale) { |
||||
this.isFemale = isFemale; |
||||
} |
||||
|
||||
public ABC(boolean isFemale, boolean isSort) { |
||||
this.isFemale = isFemale; |
||||
this.isSort = isSort; |
||||
} |
||||
|
||||
private void initMaleRankName() { |
||||
|
||||
} |
||||
|
||||
private void initSortNames() { |
||||
} |
||||
|
||||
|
||||
public List<BookType> getRankTypes() { |
||||
return null; |
||||
} |
||||
|
||||
public void getRankBooks(BookType bookType, ResultCallback rc) { |
||||
|
||||
} |
||||
|
||||
private List<QDBook> getBooksFromJson(String json) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public String getCharset() { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public String getFindName() { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public String getFindUrl() { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public boolean getTypePage(BookType curType, int page) { |
||||
return false; |
||||
} |
||||
|
||||
@Override |
||||
public boolean hasImg() { |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public List<BookType> getBookTypeList(String html) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public List<Book> getRankBookList(String html) { |
||||
return null; |
||||
} |
||||
|
||||
|
||||
public void initCookie(Context mContext, ResultCallback rc) { |
||||
|
||||
} |
||||
|
||||
} |
@ -0,0 +1,8 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"> |
||||
<alpha |
||||
android:duration="1000" |
||||
android:fromAlpha="0" |
||||
android:interpolator="@android:anim/decelerate_interpolator" |
||||
android:toAlpha="1.0"/> |
||||
</set> |
@ -0,0 +1,8 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"> |
||||
<alpha |
||||
android:duration="1500" |
||||
android:fromAlpha="1.0" |
||||
android:interpolator="@android:anim/decelerate_interpolator" |
||||
android:toAlpha="0"/> |
||||
</set> |
@ -0,0 +1,5 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android"> |
||||
<item android:color="@color/colorAccent" android:state_checked="true" /> |
||||
<item android:color="@color/textSecondary" android:state_checked="false"/> |
||||
</selector> |
@ -1,6 +1,6 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android"> |
||||
<item android:color="@color/gray" android:state_enabled="false" /> |
||||
<item android:color="@color/white" android:state_pressed="true" /> |
||||
<item android:color="@color/textSecondary" android:state_enabled="false" /> |
||||
<item android:color="@color/textAssist" android:state_pressed="true" /> |
||||
<item android:color="@color/colorAccent"/> |
||||
</selector> |
@ -1,9 +1,13 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> |
||||
|
||||
<item> |
||||
<shape android:shape="oval"> |
||||
<solid android:color="@color/textSecondary"/> |
||||
</shape> |
||||
</item> |
||||
<item android:bottom="1dp" android:left="1dp" android:right="1dp" android:top="1dp"> |
||||
<shape android:shape="oval"> |
||||
<solid android:color="@color/sys_common_bg"/> |
||||
<solid android:color="@color/textPrimaryInverted"/> |
||||
</shape> |
||||
</item> |
||||
</layer-list> |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue