Merge branch 'master' of https://github.com/gedoor/legado into 跟随主干
commit
c18cebda9a
@ -0,0 +1,129 @@ |
||||
## 常见问题 |
||||
|
||||
1.为什么第一次安装好之后什么东西都没有? |
||||
* 因为阅读只是一个转码工具,不提供内容,第一次安装app,需要自己手动导入书源,可以从QQ群、公众号“开源阅读软件”、酷安评论里获取由书友制作分享的书源。 |
||||
|
||||
2.如何导入本地书源文件? |
||||
* 下载群文件里的书源文件(书源格式后缀有txt、json,其中json文件某些情况下无法导入,需要修改后缀为txt格式才可导入); |
||||
* 打开阅读软件; |
||||
* 我的 - 点击“书源管理”; |
||||
* 点击右上角选择“本地导入”; |
||||
* 左下角选择书源文件所在的路径; |
||||
* 点击书源文件导入; |
||||
* 导入后返回书源管理界面; |
||||
* 新版qq下载路径:Android/data/com.tencent.mobileqq/Tencent/QQfile_recv/ |
||||
|
||||
3.如何新建大佬发的单独书源? |
||||
* 复制书源代码; |
||||
* 打开阅读软件; |
||||
* 我的 - 点击“书源管理”; |
||||
* 右上角选择“新建书源”; |
||||
* 进入新建书源后点击右上角“粘贴源”; |
||||
* 粘贴书源完成后点击上方保存; |
||||
* 本次新建单独书源操作完成。 |
||||
* 注:如果书源有错误或者复制不全会显示格式错误,请重新复制。 |
||||
|
||||
4.为什么导入2.0书源后看不了书? |
||||
* 2.0部分书源并不适用3.0,建议导入后进行筛选。 |
||||
|
||||
5.阅读2.0数据如何导入阅读3.0? |
||||
* 先对阅读2.0的数据进行备份,然后进入阅读3.0,点击“我的”,选择“备份与恢复”,再点击“导入旧版本数据”。 |
||||
|
||||
6.如何给朋友分享我的书源? |
||||
* 打开阅读软件; |
||||
* 点击备份; |
||||
* 打开手机自带的文件管理; |
||||
* 手机自带内存根目录找到YueDu3.0文件夹; |
||||
* 找到myBookSource.json长按选择分享; |
||||
* 选择微信分享或者QQ分享; |
||||
* 选择你要分享的好友点击发送; |
||||
* 好友接收后在手机自带内存根目录找到myBookSource.json文件(QQ在tencent--QQfile_recv微信在Tencent--MicroMsg--Download); |
||||
* 复制该文件到手机自带内存根目录找到YueDu3.0文件夹(如已有该文件请先删除该文件或者备份到其他地方再复制到文件夹); |
||||
* 打开阅读软件点击恢复。 |
||||
* 注:备份路径如已修改过请在修改后的路径下查找书源文件。 |
||||
|
||||
7.目前阅读支持哪些格式的本地书籍? |
||||
* 目前支持TXT、EPUB格式(只支持显示EPUB里的文本内容,还不支持显示图片)。 |
||||
|
||||
8.如何刷新书架? |
||||
* 在书架界面下拉即可刷新。 |
||||
|
||||
9.书架界面书籍右上角的红色或者灰色背景小数字代表什么? |
||||
* 红色代表书籍有更新,灰色代表无更新,数字代表未读章节。 |
||||
|
||||
10.如何查看书籍详情? |
||||
* 长按书籍。 |
||||
|
||||
11.如何对书架上的书进行删除、切换书架的操作? |
||||
* 书籍详情页操作即可。 |
||||
|
||||
12.如何禁止或允许某本书更新? |
||||
* 书籍详情页,点击右上角 - “允许更新”。 |
||||
|
||||
13.如何更换小说封面、名字、作者或简介? |
||||
* 书籍详情页,点击右上角修改按钮。 |
||||
|
||||
14.怎么使用自定义字体? |
||||
* 阅读界面 - 字体-点击右上角选择字体文件路径。 |
||||
|
||||
15.目前支持哪些格式的字体文件? |
||||
* 目前支持ttf、otf格式。 |
||||
|
||||
16.书籍经常“正在加载中”怎么办? |
||||
* 在线书籍出现这个问题通常是由于源质量不好或不兼容引起的,可以换其它源多试试;本地书籍出现这个问题大概率是目录规则问题,手动切换规则可以解决。 |
||||
|
||||
17.书籍内容只有标题,正文内容是路径怎么办? |
||||
* 通常是缓存路径引起的,更换缓存路径即可。 |
||||
|
||||
18.效验书源显示失效就说明书源不能用了吗? |
||||
* 效验书源只是测试书源,可以做个参考,失效了不代表书源不能用了。 |
||||
|
||||
19.发现和正版书源能不能使用? |
||||
* 发现和正版书源只能用来找书,看排行榜,不能用来看书,如需看书请切换书源。 |
||||
|
||||
20.替换净化是什么? |
||||
* 替换净化可以去除书籍内容里的广告、错别字、屏蔽词等。 |
||||
|
||||
21.如何自己填写净化替换规则? |
||||
* 第一行:替换规则名称 - 根据自己需求对替换净化规则进行命名; |
||||
* 第二行:分组 - 净化规则的分组组别; |
||||
* 第三行:替换规则 - 填写需要被替换的内容; |
||||
* 第四行:替换为 - 填写想替换成的内容(如不填则默认表示删除第二行里填写的内容); |
||||
* 第五行:替换范围,选填书名或者源名 - 填写此替换净化规则需要对哪本书籍或者哪个书源生效(如不填则对所有书籍和书源生效)。 |
||||
* 注:如常规去除方法去除不掉,则需要勾选“使用正则表达式”,同时第二行里的替换规则也需要按照正则表达式来填写(正则表达式填写方法可自行百度学习)。 |
||||
|
||||
22.如何听书? |
||||
* 可以使用手机自带的朗读引擎,也可使用第三方如谷歌、小米等朗读引擎。 |
||||
* 【具体操作:安装-系统设置-其他高级设置-辅助功能-TTS输出-选择安装的朗读引擎(不同品牌手机的操作方法及步骤也不同,视情况而定)。】 |
||||
|
||||
23.如何设置屏幕方向、屏幕显示时长、显示/隐藏状态栏、显示/隐藏导航栏、音量键翻页、长按选择文本、点击总是翻下一页、自定义翻页案件? |
||||
* 阅读界面,设置(可上划,下面还有其他设置)。 |
||||
|
||||
24.搜索的时候感觉手机卡顿,如何解决? |
||||
* 我的 - 其他设置 - “更新和搜索线程数”调低。 |
||||
|
||||
25.更新前有什么注意事项? |
||||
* 要做好备份。 |
||||
|
||||
26.看书时如遇到“目录为空”、“加载失败”和长串英文等情况怎么办? |
||||
* 一般是书源问题,切换书源即可。 |
||||
|
||||
27.为什么书源这么多,发现里却只有一点点? |
||||
* 书源想要在发现界面里显示需要在书源里添加发现规则,并不是所有书源都有发现规则。 |
||||
|
||||
28.云备份在哪? |
||||
* 我的 - 备份与恢复 - WebDav设置。 |
||||
|
||||
29.如何操作进行云备份? |
||||
* 侧栏设置,WebDav设置; |
||||
* 正确填写WebDAV 服务器地址、WebDAV 账号、WebDAV 密码;(要获得这三项的信息,需要注册一个坚果云账号,如果直接在手机上注册,坚果云会让你下载app,过程比较麻烦,为了一步到位,最好是在电脑上打开这个注册链接:https://www.jianguoyun.com/d/signup;注册后,进入坚果云;点击右上角账户名处选择 “账户信息”,然后选择“安全选项”;在“安全选项” 中找到“第三方应用管理”,并选择“添加应用”,输入名称如“阅读”后,会生成密码,选择完成;其中https://dav.jianguoyun.com/dav/就是填入“WebDAV 服务器地址”的内容,“使用情况”后面的邮箱地址就是你的“WebDAV 账号”,点击显示密码后得到的密码就是你的“WebDAV 密码”。) |
||||
* 无需操作,APP默认每天自动云备份一次。 |
||||
|
||||
30.关于云备份的相关说明 |
||||
* 在正确设置好云备份的情况下,APP默认每天自动云备份一次,当日多次手动云备份会对当日的旧云备份文件进行覆盖,并不会覆盖之前及之后不同日期的备份文件,每天所自动云备份的文件会按照日期进行命名。 |
||||
|
||||
31.本地备份和云备份都能备份哪些东西? |
||||
* 书架、看书进度、搜索记录、书源、替换、APP设置等都会备份,基本涵盖所有内容。 |
||||
|
||||
32.出现某些未知bug怎么办? |
||||
* 清除软件数据试试看,不行再进行反馈。 |
@ -0,0 +1,93 @@ |
||||
package io.legado.app.model |
||||
|
||||
import io.legado.app.App |
||||
import io.legado.app.data.entities.SearchBook |
||||
import io.legado.app.help.AppConfig |
||||
import io.legado.app.help.coroutine.Coroutine |
||||
import io.legado.app.utils.getPrefString |
||||
import kotlinx.coroutines.CoroutineScope |
||||
import kotlinx.coroutines.Dispatchers.IO |
||||
import kotlinx.coroutines.asCoroutineDispatcher |
||||
import java.util.concurrent.Executors |
||||
|
||||
class SearchBookModel(private val scope: CoroutineScope, private val callBack: CallBack) { |
||||
private var searchPool = |
||||
Executors.newFixedThreadPool(AppConfig.threadCount).asCoroutineDispatcher() |
||||
private var mSearchId = System.currentTimeMillis() |
||||
private var searchPage = 1 |
||||
private var searchKey: String = "" |
||||
private var task: Coroutine<*>? = null |
||||
|
||||
private fun initSearchPool() { |
||||
searchPool = |
||||
Executors.newFixedThreadPool(AppConfig.threadCount).asCoroutineDispatcher() |
||||
} |
||||
|
||||
fun search(searchId: Long, key: String) { |
||||
if (searchId != mSearchId) { |
||||
task?.cancel() |
||||
searchPool.close() |
||||
initSearchPool() |
||||
mSearchId = searchId |
||||
searchPage = 1 |
||||
if (key.isEmpty()) { |
||||
return |
||||
} else { |
||||
this.searchKey = key |
||||
} |
||||
} else { |
||||
searchPage++ |
||||
} |
||||
task = Coroutine.async(scope, searchPool) { |
||||
val searchGroup = App.INSTANCE.getPrefString("searchGroup") ?: "" |
||||
val bookSourceList = if (searchGroup.isBlank()) { |
||||
App.db.bookSourceDao().allEnabled |
||||
} else { |
||||
App.db.bookSourceDao().getEnabledByGroup(searchGroup) |
||||
} |
||||
for (item in bookSourceList) { |
||||
//task取消时自动取消 by (scope = this@execute) |
||||
WebBook(item).searchBook( |
||||
searchKey, |
||||
searchPage, |
||||
scope = this, |
||||
context = searchPool |
||||
) |
||||
.timeout(30000L) |
||||
.onSuccess(IO) { |
||||
if (searchId == mSearchId) { |
||||
callBack.onSearchSuccess(it) |
||||
} |
||||
} |
||||
} |
||||
}.onStart { |
||||
callBack.onSearchStart() |
||||
} |
||||
|
||||
task?.invokeOnCompletion { |
||||
if (searchId == mSearchId) { |
||||
callBack.onSearchFinish() |
||||
} |
||||
} |
||||
} |
||||
|
||||
fun cancelSearch() { |
||||
task?.cancel() |
||||
mSearchId = 0 |
||||
callBack.onSearchCancel() |
||||
} |
||||
|
||||
fun close() { |
||||
task?.cancel() |
||||
mSearchId = 0 |
||||
searchPool.close() |
||||
} |
||||
|
||||
interface CallBack { |
||||
fun onSearchStart() |
||||
fun onSearchSuccess(searchBooks: ArrayList<SearchBook>) |
||||
fun onSearchFinish() |
||||
fun onSearchCancel() |
||||
} |
||||
|
||||
} |
@ -1,36 +0,0 @@ |
||||
package io.legado.app.ui.main.bookshelf |
||||
|
||||
import androidx.fragment.app.Fragment |
||||
import androidx.viewpager2.adapter.FragmentStateAdapter |
||||
import io.legado.app.data.entities.BookGroup |
||||
import io.legado.app.ui.main.bookshelf.books.BooksFragment |
||||
|
||||
|
||||
class BookshelfAdapter(fragment: Fragment, val callBack: CallBack) : |
||||
FragmentStateAdapter(fragment) { |
||||
|
||||
private val ids = hashSetOf<Long>() |
||||
|
||||
override fun getItemCount(): Int { |
||||
return callBack.groupSize |
||||
} |
||||
|
||||
override fun getItemId(position: Int): Long { |
||||
return callBack.getGroup(position).groupId.toLong() |
||||
} |
||||
|
||||
override fun containsItem(itemId: Long): Boolean { |
||||
return ids.contains(itemId) |
||||
} |
||||
|
||||
override fun createFragment(position: Int): Fragment { |
||||
val groupId = callBack.getGroup(position).groupId |
||||
ids.add(groupId.toLong()) |
||||
return BooksFragment.newInstance(position, groupId) |
||||
} |
||||
|
||||
interface CallBack { |
||||
val groupSize: Int |
||||
fun getGroup(position: Int): BookGroup |
||||
} |
||||
} |
@ -0,0 +1,17 @@ |
||||
package io.legado.app.ui.rss.read |
||||
|
||||
import android.content.Context |
||||
import android.util.AttributeSet |
||||
import android.view.View |
||||
import android.webkit.WebView |
||||
|
||||
class VisibleWebView( |
||||
context: Context, |
||||
attrs: AttributeSet? = null |
||||
) : WebView(context, attrs) { |
||||
|
||||
override fun onWindowVisibilityChanged(visibility: Int) { |
||||
super.onWindowVisibilityChanged(View.VISIBLE) |
||||
} |
||||
|
||||
} |
@ -0,0 +1,110 @@ |
||||
package io.legado.app.ui.widget |
||||
|
||||
import android.app.SearchableInfo |
||||
import android.content.Context |
||||
import android.graphics.Canvas |
||||
import android.graphics.Paint |
||||
import android.graphics.drawable.Drawable |
||||
import android.text.Spannable |
||||
import android.text.SpannableStringBuilder |
||||
import android.text.style.ImageSpan |
||||
import android.util.AttributeSet |
||||
import android.util.TypedValue |
||||
import android.view.Gravity |
||||
import android.widget.TextView |
||||
import androidx.appcompat.widget.SearchView |
||||
import io.legado.app.R |
||||
|
||||
class SearchView : SearchView { |
||||
private var mSearchHintIcon: Drawable? = null |
||||
private var textView: TextView? = null |
||||
|
||||
constructor( |
||||
context: Context?, |
||||
attrs: AttributeSet? = null |
||||
) : super(context, attrs) |
||||
|
||||
constructor( |
||||
context: Context?, |
||||
attrs: AttributeSet?, |
||||
defStyleAttr: Int |
||||
) : super(context, attrs, defStyleAttr) |
||||
|
||||
override fun onLayout( |
||||
changed: Boolean, |
||||
left: Int, |
||||
top: Int, |
||||
right: Int, |
||||
bottom: Int |
||||
) { |
||||
super.onLayout(changed, left, top, right, bottom) |
||||
try { |
||||
if (textView == null) { |
||||
textView = findViewById(androidx.appcompat.R.id.search_src_text) |
||||
mSearchHintIcon = this.context.getDrawable(R.drawable.ic_search_hint) |
||||
updateQueryHint() |
||||
} |
||||
// 改变字体 |
||||
textView!!.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14f) |
||||
textView!!.gravity = Gravity.CENTER_VERTICAL |
||||
} catch (e: Exception) { |
||||
e.printStackTrace() |
||||
} |
||||
} |
||||
|
||||
private fun getDecoratedHint(hintText: CharSequence): CharSequence { |
||||
// If the field is always expanded or we don't have a search hint icon, |
||||
// then don't add the search icon to the hint. |
||||
if (mSearchHintIcon == null) { |
||||
return hintText |
||||
} |
||||
val textSize = (textView!!.textSize * 0.8).toInt() |
||||
mSearchHintIcon!!.setBounds(0, 0, textSize, textSize) |
||||
val ssb = SpannableStringBuilder(" ") |
||||
ssb.setSpan(CenteredImageSpan(mSearchHintIcon), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) |
||||
ssb.append(hintText) |
||||
return ssb |
||||
} |
||||
|
||||
private fun updateQueryHint() { |
||||
textView?.let { |
||||
it.hint = getDecoratedHint(queryHint ?: "") |
||||
} |
||||
} |
||||
|
||||
override fun setIconifiedByDefault(iconified: Boolean) { |
||||
super.setIconifiedByDefault(iconified) |
||||
updateQueryHint() |
||||
} |
||||
|
||||
override fun setSearchableInfo(searchable: SearchableInfo?) { |
||||
super.setSearchableInfo(searchable) |
||||
searchable?.let { |
||||
updateQueryHint() |
||||
} |
||||
} |
||||
|
||||
override fun setQueryHint(hint: CharSequence?) { |
||||
super.setQueryHint(hint) |
||||
updateQueryHint() |
||||
} |
||||
|
||||
internal class CenteredImageSpan(drawable: Drawable?) : ImageSpan(drawable!!) { |
||||
override fun draw( |
||||
canvas: Canvas, text: CharSequence, |
||||
start: Int, end: Int, x: Float, |
||||
top: Int, y: Int, bottom: Int, paint: Paint |
||||
) { |
||||
// image to draw |
||||
val b = drawable |
||||
// font metrics of text to be replaced |
||||
val fm = paint.fontMetricsInt |
||||
val transY = ((y + fm.descent + y + fm.ascent) / 2 |
||||
- b.bounds.bottom / 2) |
||||
canvas.save() |
||||
canvas.translate(x, transY.toFloat()) |
||||
b.draw(canvas) |
||||
canvas.restore() |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,185 @@ |
||||
package io.legado.app.ui.widget |
||||
|
||||
import android.content.Context |
||||
import android.graphics.Canvas |
||||
import android.graphics.Color |
||||
import android.graphics.Paint |
||||
import android.graphics.RectF |
||||
import android.util.AttributeSet |
||||
import android.view.View |
||||
import android.widget.RelativeLayout |
||||
import io.legado.app.R |
||||
import io.legado.app.utils.getCompatColor |
||||
|
||||
/** |
||||
* ShadowLayout.java |
||||
* |
||||
* |
||||
* Created by lijiankun on 17/8/11. |
||||
*/ |
||||
class ShadowLayout( |
||||
context: Context, |
||||
attrs: AttributeSet? = null |
||||
) : RelativeLayout(context, attrs) { |
||||
private val mPaint = |
||||
Paint(Paint.ANTI_ALIAS_FLAG) |
||||
private val mRectF = RectF() |
||||
|
||||
/** |
||||
* 阴影的颜色 |
||||
*/ |
||||
private var mShadowColor = Color.TRANSPARENT |
||||
|
||||
/** |
||||
* 阴影的大小范围 |
||||
*/ |
||||
private var mShadowRadius = 0f |
||||
|
||||
/** |
||||
* 阴影 x 轴的偏移量 |
||||
*/ |
||||
private var mShadowDx = 0f |
||||
|
||||
/** |
||||
* 阴影 y 轴的偏移量 |
||||
*/ |
||||
private var mShadowDy = 0f |
||||
|
||||
/** |
||||
* 阴影显示的边界 |
||||
*/ |
||||
private var mShadowSide = ALL |
||||
|
||||
/** |
||||
* 阴影的形状,圆形/矩形 |
||||
*/ |
||||
private var mShadowShape = SHAPE_RECTANGLE |
||||
|
||||
|
||||
init { |
||||
setLayerType(View.LAYER_TYPE_SOFTWARE, null) // 关闭硬件加速 |
||||
setWillNotDraw(false) // 调用此方法后,才会执行 onDraw(Canvas) 方法 |
||||
val typedArray = |
||||
context.obtainStyledAttributes(attrs, R.styleable.ShadowLayout) |
||||
mShadowColor = typedArray.getColor( |
||||
R.styleable.ShadowLayout_shadowColor, |
||||
context.getCompatColor(android.R.color.black) |
||||
) |
||||
mShadowRadius = |
||||
typedArray.getDimension(R.styleable.ShadowLayout_shadowRadius, dip2px(0f)) |
||||
mShadowDx = typedArray.getDimension(R.styleable.ShadowLayout_shadowDx, dip2px(0f)) |
||||
mShadowDy = typedArray.getDimension(R.styleable.ShadowLayout_shadowDy, dip2px(0f)) |
||||
mShadowSide = |
||||
typedArray.getInt(R.styleable.ShadowLayout_shadowSide, ALL) |
||||
mShadowShape = typedArray.getInt( |
||||
R.styleable.ShadowLayout_shadowShape, |
||||
SHAPE_RECTANGLE |
||||
) |
||||
typedArray.recycle() |
||||
|
||||
setUpShadowPaint() |
||||
} |
||||
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { |
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec) |
||||
val effect = mShadowRadius + dip2px(5f) |
||||
var rectLeft = 0f |
||||
var rectTop = 0f |
||||
var rectRight = this.measuredWidth.toFloat() |
||||
var rectBottom = this.measuredHeight.toFloat() |
||||
var paddingLeft = 0 |
||||
var paddingTop = 0 |
||||
var paddingRight = 0 |
||||
var paddingBottom = 0 |
||||
this.width |
||||
if (mShadowSide and LEFT == LEFT) { |
||||
rectLeft = effect |
||||
paddingLeft = effect.toInt() |
||||
} |
||||
if (mShadowSide and TOP == TOP) { |
||||
rectTop = effect |
||||
paddingTop = effect.toInt() |
||||
} |
||||
if (mShadowSide and RIGHT == RIGHT) { |
||||
rectRight = this.measuredWidth - effect |
||||
paddingRight = effect.toInt() |
||||
} |
||||
if (mShadowSide and BOTTOM == BOTTOM) { |
||||
rectBottom = this.measuredHeight - effect |
||||
paddingBottom = effect.toInt() |
||||
} |
||||
if (mShadowDy != 0.0f) { |
||||
rectBottom -= mShadowDy |
||||
paddingBottom += mShadowDy.toInt() |
||||
} |
||||
if (mShadowDx != 0.0f) { |
||||
rectRight -= mShadowDx |
||||
paddingRight += mShadowDx.toInt() |
||||
} |
||||
mRectF.left = rectLeft |
||||
mRectF.top = rectTop |
||||
mRectF.right = rectRight |
||||
mRectF.bottom = rectBottom |
||||
setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom) |
||||
} |
||||
|
||||
/** |
||||
* 真正绘制阴影的方法 |
||||
*/ |
||||
override fun onDraw(canvas: Canvas) { |
||||
super.onDraw(canvas) |
||||
setUpShadowPaint() |
||||
if (mShadowShape == SHAPE_RECTANGLE) { |
||||
canvas.drawRect(mRectF, mPaint) |
||||
} else if (mShadowShape == SHAPE_OVAL) { |
||||
canvas.drawCircle( |
||||
mRectF.centerX(), |
||||
mRectF.centerY(), |
||||
mRectF.width().coerceAtMost(mRectF.height()) / 2, |
||||
mPaint |
||||
) |
||||
} |
||||
} |
||||
|
||||
fun setShadowColor(shadowColor: Int) { |
||||
mShadowColor = shadowColor |
||||
requestLayout() |
||||
postInvalidate() |
||||
} |
||||
|
||||
fun setShadowRadius(shadowRadius: Float) { |
||||
mShadowRadius = shadowRadius |
||||
requestLayout() |
||||
postInvalidate() |
||||
} |
||||
|
||||
private fun setUpShadowPaint() { |
||||
mPaint.reset() |
||||
mPaint.isAntiAlias = true |
||||
mPaint.color = Color.TRANSPARENT |
||||
mPaint.setShadowLayer(mShadowRadius, mShadowDx, mShadowDy, mShadowColor) |
||||
} |
||||
|
||||
/** |
||||
* dip2px dp 值转 px 值 |
||||
* |
||||
* @param dpValue dp 值 |
||||
* @return px 值 |
||||
*/ |
||||
private fun dip2px(dpValue: Float): Float { |
||||
val dm = context.resources.displayMetrics |
||||
val scale = dm.density |
||||
return dpValue * scale + 0.5f |
||||
} |
||||
|
||||
companion object { |
||||
const val ALL = 0x1111 |
||||
const val LEFT = 0x0001 |
||||
const val TOP = 0x0010 |
||||
const val RIGHT = 0x0100 |
||||
const val BOTTOM = 0x1000 |
||||
const val SHAPE_RECTANGLE = 0x0001 |
||||
const val SHAPE_OVAL = 0x0010 |
||||
} |
||||
|
||||
} |
@ -0,0 +1,21 @@ |
||||
package io.legado.app.ui.widget.prefs |
||||
|
||||
import android.content.Context |
||||
import android.util.AttributeSet |
||||
import android.widget.TextView |
||||
import androidx.preference.PreferenceViewHolder |
||||
import io.legado.app.R |
||||
|
||||
class EditTextPreference(context: Context, attrs: AttributeSet) : androidx.preference.EditTextPreference(context, attrs) { |
||||
|
||||
init { |
||||
// isPersistent = true |
||||
layoutResource = R.layout.view_preference |
||||
} |
||||
|
||||
override fun onBindViewHolder(holder: PreferenceViewHolder?) { |
||||
Preference.bindView<TextView>(context, holder, icon, title, summary, null, null) |
||||
super.onBindViewHolder(holder) |
||||
} |
||||
|
||||
} |
@ -0,0 +1,85 @@ |
||||
package io.legado.app.ui.widget.prefs |
||||
|
||||
import android.content.Context |
||||
import android.graphics.drawable.Drawable |
||||
import android.util.AttributeSet |
||||
import android.view.LayoutInflater |
||||
import android.view.View |
||||
import android.widget.FrameLayout |
||||
import android.widget.ImageView |
||||
import android.widget.TextView |
||||
import androidx.core.view.isVisible |
||||
import androidx.preference.PreferenceViewHolder |
||||
import io.legado.app.R |
||||
import io.legado.app.lib.theme.accentColor |
||||
import org.jetbrains.anko.layoutInflater |
||||
import kotlin.math.roundToInt |
||||
|
||||
class Preference(context: Context, attrs: AttributeSet) : androidx.preference.Preference(context, attrs) { |
||||
|
||||
init { |
||||
// isPersistent = true |
||||
layoutResource = R.layout.view_preference |
||||
} |
||||
|
||||
companion object { |
||||
|
||||
fun <T: View> bindView(context: Context, it: PreferenceViewHolder?, icon: Drawable?, title: CharSequence?, summary: CharSequence?, weightLayoutRes: Int?, viewId: Int?, |
||||
weightWidth: Int = 0, weightHeight: Int = 0): T? { |
||||
if (it == null) return null |
||||
val view = it.findViewById(R.id.preference_title) |
||||
if (view is TextView) { |
||||
view.text = title |
||||
view.isVisible = title != null && title.isNotEmpty() |
||||
|
||||
val tvSummary = it.findViewById(R.id.preference_desc) |
||||
if (tvSummary is TextView) { |
||||
tvSummary.text = summary |
||||
tvSummary.isVisible = summary != null && summary.isNotEmpty() |
||||
} |
||||
|
||||
val iconView = it.findViewById(R.id.preference_icon) |
||||
if (iconView is ImageView) { |
||||
iconView.isVisible = icon != null && icon.isVisible |
||||
iconView.setImageDrawable(icon) |
||||
iconView.setColorFilter(context.accentColor) |
||||
} |
||||
} |
||||
|
||||
if (weightLayoutRes != null && weightLayoutRes != 0 && viewId != null && viewId != 0) { |
||||
val lay = it.findViewById(R.id.preference_widget) |
||||
if (lay is FrameLayout) { |
||||
var v = it.itemView.findViewById<T>(viewId) |
||||
if (v == null) { |
||||
val inflater: LayoutInflater = context.layoutInflater |
||||
val childView = inflater.inflate(weightLayoutRes, null) |
||||
lay.removeAllViews() |
||||
lay.addView(childView) |
||||
lay.isVisible = true |
||||
v = lay.findViewById(viewId) |
||||
} |
||||
|
||||
if (weightWidth > 0 || weightHeight > 0) { |
||||
val lp = lay.layoutParams |
||||
if (weightHeight > 0) |
||||
lp.height = (context.resources.displayMetrics.density * weightHeight).roundToInt() |
||||
if (weightWidth > 0) |
||||
lp.width = (context.resources.displayMetrics.density * weightWidth).roundToInt() |
||||
lay.layoutParams = lp |
||||
} |
||||
|
||||
return v |
||||
} |
||||
} |
||||
|
||||
return null |
||||
} |
||||
|
||||
} |
||||
|
||||
override fun onBindViewHolder(holder: PreferenceViewHolder?) { |
||||
bindView<View>(context, holder, icon, title, summary, null, null) |
||||
super.onBindViewHolder(holder) |
||||
} |
||||
|
||||
} |
@ -0,0 +1,66 @@ |
||||
package io.legado.app.utils |
||||
|
||||
import org.jsoup.internal.StringUtil |
||||
import org.jsoup.nodes.CDataNode |
||||
import org.jsoup.nodes.Element |
||||
import org.jsoup.nodes.Node |
||||
import org.jsoup.nodes.TextNode |
||||
import org.jsoup.select.NodeTraversor |
||||
import org.jsoup.select.NodeVisitor |
||||
|
||||
|
||||
fun Element.textArray(): Array<String> { |
||||
val accum = StringUtil.borrowBuilder() |
||||
NodeTraversor.traverse(object : NodeVisitor { |
||||
override fun head(node: Node, depth: Int) { |
||||
if (node is TextNode) { |
||||
appendNormalisedText(accum, node) |
||||
} else if (node is Element) { |
||||
if (accum.isNotEmpty() && |
||||
(node.isBlock || node.tag().name == "br") && |
||||
!lastCharIsWhitespace(accum) |
||||
) accum.append("\n") |
||||
} |
||||
} |
||||
|
||||
override fun tail(node: Node, depth: Int) { |
||||
if (node is Element) { |
||||
if (node.isBlock && node.nextSibling() is TextNode && !lastCharIsWhitespace( |
||||
accum |
||||
) |
||||
) accum.append("\n") |
||||
} |
||||
} |
||||
}, this) |
||||
val text = StringUtil.releaseBuilder(accum).trim { it <= ' ' } |
||||
return text.splitNotBlank("\n") |
||||
} |
||||
|
||||
private fun appendNormalisedText(accum: StringBuilder, textNode: TextNode) { |
||||
val text = textNode.wholeText |
||||
if (preserveWhitespace(textNode.parentNode()) || textNode is CDataNode) |
||||
accum.append(text) |
||||
else StringUtil.appendNormalisedWhitespace( |
||||
accum, |
||||
text, |
||||
lastCharIsWhitespace(accum) |
||||
) |
||||
} |
||||
|
||||
private fun preserveWhitespace(node: Node?): Boolean { |
||||
if (node is Element) { |
||||
var el = node as Element? |
||||
var i = 0 |
||||
do { |
||||
if (el!!.tag().preserveWhitespace()) return true |
||||
el = el.parent() |
||||
i++ |
||||
} while (i < 6 && el != null) |
||||
} |
||||
return false |
||||
} |
||||
|
||||
private fun lastCharIsWhitespace(sb: java.lang.StringBuilder): Boolean { |
||||
return sb.isNotEmpty() && sb[sb.length - 1] == ' ' |
||||
} |
||||
|
@ -1,24 +0,0 @@ |
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:width="108dp" |
||||
android:height="108dp" |
||||
android:viewportWidth="108" |
||||
android:viewportHeight="108"> |
||||
<path |
||||
android:pathData="M34.73,33.55l-0.09,13.54A5.17,5.17 0,0 1,33.23 50c-0.23,0.06 -0.38,0 -0.44,-0.18l0.09,-6.41L33,34.25l-0.09,-2.55 2,0.71c0.18,0.06 0.21,0.17 0.09,0.35ZM43.08,40.41c0.11,0.06 0.11,0.14 0,0.26l-0.27,0.53 -0.52,2.55c-0.12,0.47 0,0.73 0.35,0.79a4.7,4.7 0,0 0,1.84 -0.18c0.41,0 0.74,-0.38 1,-1.14a0.26,0.26 0,0 1,0.18 -0.09s0.08,0.06 0.08,0.18c-0.11,0.7 0,1.11 0.27,1.23 0.64,0.76 0.44,1.32 -0.62,1.67a6,6 0,0 1,-2.72 0.17c-1.06,-0.29 -1.56,-1.23 -1.5,-2.81l0.09,-2.2L41.26,39.79L39.47,39.79l1.23,0.53c0.12,0.06 0.12,0.15 0,0.26l-0.26,0.35a19.72,19.72 0,0 1,-5.62 7c-0.18,0.05 -0.21,0 -0.09,-0.18a19.79,19.79 0,0 0,4.22 -8h-0.71a3.35,3.35 0,0 1,-1.05 1.41c-0.3,0.17 -0.47,0.14 -0.53,-0.09l0.09,-2.46L36.75,37.42q0,-0.44 -0.09,-1.41v-0.79q0,-0.09 0.18,-0.09l1.49,0.79 2.9,-0.08a16,16 0,0 0,1.14 -4l1.94,0.62c0.11,0 0.11,0.17 0,0.35s-0.5,0.52 -1,1l-1.76,1.94L43,35.75l0.79,-1 1.76,1c0.11,0 0.11,0 0,0.17l-0.44,0.7L45,39.35l0.18,0.27c0,0.11 0,0.17 -0.09,0.17L41.76,39.79ZM35.17,28.72a0.87,0.87 0,0 1,0.26 0.08c1.93,0.65 2.87,1.18 2.81,1.59s-0.26,1 -1,1.67c-0.41,0.17 -0.68,0.08 -0.79,-0.27a8,8 0,0 0,-1.5 -2.9C34.93,28.72 35,28.66 35.17,28.72ZM37.89,32.41c1.47,0.64 2.23,1.23 2.29,1.76a1.51,1.51 0,0 1,-0.88 1.23c-0.35,0.06 -0.56,-0.06 -0.62,-0.36a3.14,3.14 0,0 0,-0.88 -2.46C37.74,32.41 37.77,32.35 37.89,32.41ZM38.24,36.41v3L43,39.26v-3ZM42.46,31.41a20,20 0,0 0,-2.72 0.18L39,31l7.65,-0.26 1,-1.06 1.67,1.15h0.09c0.05,0.05 0,0.14 -0.09,0.26l-0.62,1 0.09,8.79L49,45.68a4.38,4.38 0,0 1,-2.73 4.13,0.66 0.66,0 0,1 -0.26,0.09c-0.06,-0.06 -0.06,-0.15 0,-0.26a2.43,2.43 0,0 0,-0.88 -1.85,0.26 0.26,0 0,1 -0.09,-0.18c0,-0.06 0,-0.08 0.09,-0.08 1.23,0 1.79,-0.24 1.67,-0.88l-0.09,-15.47Z" |
||||
android:fillColor="#fff" /> |
||||
<path |
||||
android:pathData="M63.27,43.66c0.18,-0.06 0.21,0 0.09,0.17L60.28,47a21.87,21.87 0,0 0,-1.67 1.67c-0.06,0.12 -0.14,0.12 -0.26,0L57,47.35c-0.17,-0.12 -0.2,-0.2 -0.09,-0.26 0.82,-0.41 1.44,-0.71 1.85,-0.88l-0.09,-10 -1.49,0.09a6.65,6.65 0,0 0,-1.76 0.17l-0.79,-0.7 3.78,-0.09 1,-1.14 1.75,1q0.18,0.09 0,0.27l-0.44,0.61 -0.61,9ZM57.27,29.24c1.69,0.65 2.69,1.26 3,1.85a1.93,1.93 0,0 1,-1 1.85,0.6 0.6,0 0,1 -0.88,-0.27 6.33,6.33 0,0 0,-1.32 -3.25C57.06,29.24 57.12,29.19 57.3,29.24ZM67.84,36.1l2.38,0.79c0.17,0.06 0.2,0.21 0.08,0.44l-0.43,0.62 -0.27,2.9a9.75,9.75 0,0 1,-0.26 1.4l3.6,-0.09 1.23,-1.4 1.76,1.58q0.18,0.18 -0.09,0.18l-6.59,0.26q-0.61,5.1 -11.51,7.56 -0.27,0 -0.27,-0.09a0.28,0.28 0,0 1,0.18 -0.26q9,-2.46 9.75,-7.21L64.77,43a13,13 0,0 0,-2 0.17,1.48 1.48,0 0,1 -0.44,0.09l-0.53,-0.7 5.71,-0.18A5.35,5.35 0,0 0,67.67 41l0.17,-1.76a18,18 0,0 0,0 -2.55ZM65.91,32.58c-0.82,0.06 -1.58,0.15 -2.29,0.27l-0.7,-0.71 4.31,-0.08v-0.62c0,-1.17 0,-2.08 -0.09,-2.72l2.37,0.61q0.18,0 0.18,0.09a0.28,0.28 0,0 1,-0.09 0.35,1.9 1.9,0 0,0 -0.35,1.32l-0.09,0.88 2.29,-0.09 1,-1.05 1.41,1.23 0.09,0.17a0.26,0.26 0,0 1,-0.18 0.09l-4.66,0.18v2.63L72.68,35l0.88,-1 2.11,1.84a0.29,0.29 0,0 1,0.17 0.27,0.9 0.9,0 0,1 -0.26,0.17 5.83,5.83 0,0 0,-3.34 1.41q-0.27,0.09 -0.18,-0.18l0.62,-2 -7.3,0.18a7.26,7.26 0,0 0,-0.79 0.09c-0.94,0.11 -1.55,0.2 -1.84,0.26L62,35.4l5.19,-0.18L67.19,32.58ZM62.83,38.74c1.82,0.47 2.79,0.93 2.9,1.4a1.47,1.47 0,0 1,-0.52 1.41c-0.36,0.29 -0.62,0.23 -0.79,-0.18A8.87,8.87 0,0 0,62.75 39C62.63,38.82 62.66,38.74 62.83,38.74ZM64.15,36.36c1.58,0.35 2.4,0.71 2.46,1.06a1.54,1.54 0,0 1,-0.44 1.32c-0.35,0.23 -0.58,0.17 -0.7,-0.18a3.66,3.66 0,0 0,-1.32 -2Q63.9,36.45 64.15,36.36ZM69.15,44.36q3.87,1.23 4.92,2.46c0.24,0.47 0.09,1.15 -0.44,2 -0.23,0.24 -0.41,0.36 -0.52,0.36s-0.27,-0.15 -0.44,-0.44a11.71,11.71 0,0 0,-3.61 -4.22Q69,44.45 69.16,44.36Z" |
||||
android:fillColor="#fff" /> |
||||
<path |
||||
android:pathData="M44.5,53.5l0,0 0,0a2,2 0,0 1,0.57 -0.33,2.29 2.29,0 0,1 0.69,-0.14v0.49a1.39,1.39 0,0 0,-0.5 0.09,1.27 1.27,0 0,0 -0.42,0.25 1.23,1.23 0,0 0,-0.29 0.35,1.33 1.33,0 0,0 -0.14,0.44v2.16H44V53h0.52Z" |
||||
android:fillColor="#fff" /> |
||||
<path |
||||
android:pathData="M51.49,56.35a2.72,2.72 0,0 1,-0.71 0.29,2.57 2.57,0 0,1 -0.72,0.11 2.42,2.42 0,0 1,-1 -0.2,2.22 2.22,0 0,1 -0.42,-0.25 1.88,1.88 0,0 1,-0.34 -0.35,1.54 1.54,0 0,1 -0.24,-0.48 2,2 0,0 1,-0.09 -0.61,2 2,0 0,1 0.09,-0.62 1.69,1.69 0,0 1,0.23 -0.51,1.86 1.86,0 0,1 0.36,-0.38 2.43,2.43 0,0 1,0.44 -0.26,2.06 2.06,0 0,1 0.76,-0.17 1.92,1.92 0,0 1,0.74 0.15,2.22 2.22,0 0,1 0.42,0.25 1.48,1.48 0,0 1,0.33 0.37,1.76 1.76,0 0,1 0.22,0.48 2.23,2.23 0,0 1,0.08 0.6L51.64,55L48.51,55a1.41,1.41 0,0 0,0.09 0.38,1.29 1.29,0 0,0 0.16,0.31 1.47,1.47 0,0 0,0.55 0.44,2 2,0 0,0 0.75,0.14 2.36,2.36 0,0 0,0.58 -0.07,2.31 2.31,0 0,0 0.57,-0.24ZM49.33,53.51a1.51,1.51 0,0 0,-0.5 0.38,1.4 1.4,0 0,0 -0.29,0.64h2.58a1.3,1.3 0,0 0,-0.24 -0.66,1.35 1.35,0 0,0 -0.49,-0.37 1.27,1.27 0,0 0,-0.52 -0.1A1.37,1.37 0,0 0,49.33 53.51Z" |
||||
android:fillColor="#fff" /> |
||||
<path |
||||
android:pathData="M53.9,53.46a1.72,1.72 0,0 1,0.53 -0.34,2.83 2.83,0 0,1 0.5,-0.13 2.45,2.45 0,0 1,0.54 0,1.86 1.86,0 0,1 0.52,0.11 1.13,1.13 0,0 1,0.43 0.26,0.89 0.89,0 0,1 0.25,0.34 1.4,1.4 0,0 1,0.14 0.56c0,0.2 0,0.43 0,0.68h0v1.76h-0.51v-0.34a1.82,1.82 0,0 1,-0.36 0.2,2.35 2.35,0 0,1 -0.37,0.14 1.71,1.71 0,0 1,-0.84 0,1.09 1.09,0 0,1 -0.83,-0.73 1.17,1.17 0,0 1,-0.05 -0.38,1 1,0 0,1 0.08,-0.42 1.13,1.13 0,0 1,0.24 -0.36,1.31 1.31,0 0,1 0.28,-0.2l0.32,-0.11 0.34,-0.05 0.38,0 0.39,0a2.7,2.7 0,0 0,0.41 -0.06,1.44 1.44,0 0,0 -0.1,-0.48 0.72,0.72 0,0 0,-0.14 -0.19,0.85 0.85,0 0,0 -0.28,-0.16 1.53,1.53 0,0 0,-0.36 -0.07,1.8 1.8,0 0,0 -0.8,0.13 0.75,0.75 0,0 0,-0.2 0.1,0.76 0.76,0 0,0 -0.17,0.13ZM56.32,54.92h0v-0.1l-0.41,0 -0.38,0 -0.56,0a0.82,0.82 0,0 0,-0.42 0.19,0.53 0.53,0 0,0 -0.12,0.2 0.49,0.49 0,0 0,0 0.25,0.69 0.69,0 0,0 0.13,0.43 0.61,0.61 0,0 0,0.36 0.23,1.18 1.18,0 0,0 0.59,0 2,2 0,0 0,0.43 -0.19,2.15 2.15,0 0,0 0.43,-0.33Z" |
||||
android:fillColor="#fff" /> |
||||
<path |
||||
android:pathData="M62,56.74h-0.9a1.67,1.67 0,0 1,-0.71 -0.15,1.79 1.79,0 0,1 -0.56,-0.42 2,2 0,0 1,-0.36 -0.6,1.92 1.92,0 0,1 -0.13,-0.72 2,2 0,0 1,0.49 -1.34,1.76 1.76,0 0,1 0.56,-0.41 1.67,1.67 0,0 1,0.71 -0.15L62,52.95v-1.4h0.51v5.19L62,56.74ZM62,53.43h-0.9a1.12,1.12 0,0 0,-0.48 0.1,1.24 1.24,0 0,0 -0.39,0.29 1.29,1.29 0,0 0,-0.27 0.45,1.57 1.57,0 0,0 -0.1,0.58 1.47,1.47 0,0 0,0.1 0.56,1.29 1.29,0 0,0 0.27,0.45 1.11,1.11 0,0 0,0.39 0.29,1.13 1.13,0 0,0 0.48,0.11L62,56.26Z" |
||||
android:fillColor="#fff" /> |
||||
</vector> |
@ -1,56 +0,0 @@ |
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||
xmlns:aapt="http://schemas.android.com/aapt" |
||||
android:width="108dp" |
||||
android:height="108dp" |
||||
android:viewportWidth="108" |
||||
android:viewportHeight="108"> |
||||
<path |
||||
android:pathData="M0,0h108v108h-108z" |
||||
android:fillColor="#4d4d4d" /> |
||||
<path android:pathData="M0,108H54V64c0,-12 -54,-5 -54,-5Z"> |
||||
<aapt:attr name="android:fillColor"> |
||||
<gradient |
||||
android:startY="79.39" |
||||
android:startX="0.55" |
||||
android:endY="88.08" |
||||
android:endX="53.13" |
||||
android:type="linear"> |
||||
<item |
||||
android:offset="0" |
||||
android:color="#FFFFFFFF" /> |
||||
<item |
||||
android:offset="1" |
||||
android:color="#FFCCCCCC" /> |
||||
</gradient> |
||||
</aapt:attr> |
||||
</path> |
||||
<path |
||||
android:pathData="M108,108H54V64c0,-12 54,-5 54,-5Z" |
||||
android:fillColor="#fff" /> |
||||
<path android:pathData="M71.5,70 L78,76V57a94.89,94.89 0,0 0,-13 0.75V76Z"> |
||||
<aapt:attr name="android:fillColor"> |
||||
<gradient |
||||
android:startY="57.11" |
||||
android:startX="71.5" |
||||
android:endY="76" |
||||
android:endX="71.5" |
||||
android:type="linear"> |
||||
<item |
||||
android:offset="0" |
||||
android:color="#FFFFFFFF" /> |
||||
<item |
||||
android:offset="0.24" |
||||
android:color="#FFFFE1DD" /> |
||||
<item |
||||
android:offset="0.58" |
||||
android:color="#FFFFBEB6" /> |
||||
<item |
||||
android:offset="0.84" |
||||
android:color="#FFFFA89D" /> |
||||
<item |
||||
android:offset="1" |
||||
android:color="#FFFFA094" /> |
||||
</gradient> |
||||
</aapt:attr> |
||||
</path> |
||||
</vector> |
@ -0,0 +1,7 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" > |
||||
<!-- 角度 --> |
||||
<corners android:radius="6dp"/> |
||||
<!-- 填充色 --> |
||||
<solid android:color="@color/transparent10" /> |
||||
</shape> |
@ -0,0 +1,10 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:color="@color/btn_bg_press"> |
||||
<item> |
||||
<shape android:shape="rectangle"> |
||||
<solid android:color="@color/background_prefs" /> |
||||
<corners android:radius="0dp" /> |
||||
</shape> |
||||
</item> |
||||
</ripple> |
@ -0,0 +1,11 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" > |
||||
<!-- 角度 --> |
||||
<corners android:radius="35dp"/> |
||||
<!-- 填充色 --> |
||||
<solid android:color="@color/transparent10" /> |
||||
<!-- 描边 设置线宽及颜色 --> |
||||
<stroke |
||||
android:color="@color/transparent10" |
||||
android:width="0.5dp" /> |
||||
</shape> |
@ -0,0 +1,9 @@ |
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:width="64dp" |
||||
android:height="64dp" |
||||
android:viewportWidth="1024" |
||||
android:viewportHeight="1024"> |
||||
<path |
||||
android:pathData="M512,685.25l-278.62,-278.62 45.25,-45.25L512,594.75l233.38,-233.38 45.25,45.25z" |
||||
android:fillColor="#181818"/> |
||||
</vector> |
@ -0,0 +1,9 @@ |
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:width="64dp" |
||||
android:height="64dp" |
||||
android:viewportWidth="1024" |
||||
android:viewportHeight="1024"> |
||||
<path |
||||
android:pathData="M434.94,790.62l-45.25,-45.25L623.04,512l-233.38,-233.38 45.25,-45.25L713.57,512z" |
||||
android:fillColor="#181818"/> |
||||
</vector> |
@ -0,0 +1,5 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android"> |
||||
<item android:drawable="@drawable/ic_bottom_books_e" android:state_checked="false" /> |
||||
<item android:drawable="@drawable/ic_bottom_books_s" android:state_checked="true" /> |
||||
</selector> |
@ -0,0 +1,12 @@ |
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:width="24dp" |
||||
android:height="24dp" |
||||
android:viewportWidth="24" |
||||
android:viewportHeight="24"> |
||||
<path |
||||
android:pathData="M23,3V2.5a0.5,0.5 0,0 0,-0.5 -0.5H5.69A4.63,4.63 0,0 0,1 6.06,4.51 4.51,0 0,0 5.5,11h17a0.5,0.5 0,0 0,0.5 -0.5V10a0.5,0.5 0,0 0,-0.41 -0.5,3 3,0 0,1 0,-5.94A0.5,0.5 0,0 0,23 3ZM2.56,5.9A3.09,3.09 0,0 1,5.62 3.5H19.67a4.43,4.43 0,0 0,0 6H5.5A3,3 0,0 1,2.56 5.9Z" |
||||
android:fillColor="#2f45a6" /> |
||||
<path |
||||
android:pathData="M1,21v0.53a0.5,0.5 0,0 0,0.5 0.5H18.31A4.63,4.63 0,0 0,23 17.94,4.51 4.51,0 0,0 18.5,13H1.5a0.5,0.5 0,0 0,-0.5 0.5V14a0.5,0.5 0,0 0,0.41 0.5,3 3,0 0,1 0,5.94A0.5,0.5 0,0 0,1 21ZM21.44,18.1a3.09,3.09 0,0 1,-3.06 2.4h-14a4.43,4.43 0,0 0,0 -6H18.5A3,3 0,0 1,21.44 18.1Z" |
||||
android:fillColor="#2f45a6" /> |
||||
</vector> |
@ -0,0 +1,12 @@ |
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:width="24dp" |
||||
android:height="24dp" |
||||
android:viewportWidth="24" |
||||
android:viewportHeight="24"> |
||||
<path |
||||
android:pathData="M20,6.5a3,3 0,0 1,2.59 -3A0.5,0.5 0,0 0,23 3V2.5a0.5,0.5 0,0 0,-0.5 -0.5H5.69A4.63,4.63 0,0 0,1 6.06,4.51 4.51,0 0,0 5.5,11h17a0.5,0.5 0,0 0,0.5 -0.5V10a0.5,0.5 0,0 0,-0.41 -0.5A3,3 0,0 1,20 6.5Z" |
||||
android:fillColor="#2f45a6" /> |
||||
<path |
||||
android:pathData="M4,17.5a3,3 0,0 1,-2.59 3A0.5,0.5 0,0 0,1 21v0.53a0.5,0.5 0,0 0,0.5 0.5H18.31A4.63,4.63 0,0 0,23 17.94,4.51 4.51,0 0,0 18.5,13H1.5a0.5,0.5 0,0 0,-0.5 0.5V14a0.5,0.5 0,0 0,0.41 0.5A3,3 0,0 1,4 17.5Z" |
||||
android:fillColor="#2f45a6" /> |
||||
</vector> |
@ -0,0 +1,5 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android"> |
||||
<item android:drawable="@drawable/ic_bottom_explore_e" android:state_checked="false" /> |
||||
<item android:drawable="@drawable/ic_bottom_explore_s" android:state_checked="true" /> |
||||
</selector> |
@ -0,0 +1,12 @@ |
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:width="24dp" |
||||
android:height="24dp" |
||||
android:viewportWidth="24" |
||||
android:viewportHeight="24"> |
||||
<path |
||||
android:pathData="M12,2.5A9.5,9.5 0,1 1,2.5 12,9.51 9.51,0 0,1 12,2.5M12,1A11,11 0,1 0,23 12,11 11,0 0,0 12,1Z" |
||||
android:fillColor="#2f45a6" /> |
||||
<path |
||||
android:pathData="M13.93,10.07l-1.29,2.57 -2.57,1.29 1.29,-2.57 2.57,-1.29M16.85,7a0.18,0.18 0,0 0,-0.1 0l-6.51,3.26L7,16.75a0.2,0.2 0,0 0,0.17 0.29,0.18 0.18,0 0,0 0.1,0l6.51,-3.26L17,7.25A0.2,0.2 0,0 0,16.85 7Z" |
||||
android:fillColor="#2f45a6" /> |
||||
</vector> |
@ -0,0 +1,9 @@ |
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:width="24dp" |
||||
android:height="24dp" |
||||
android:viewportWidth="24" |
||||
android:viewportHeight="24"> |
||||
<path |
||||
android:pathData="M12,1A11,11 0,1 0,23 12,11 11,0 0,0 12,1ZM17,7.25 L13.74,13.76L7.25,17A0.2,0.2 0,0 1,7 16.75l3.26,-6.51L16.75,7A0.2,0.2 0,0 1,17 7.25Z" |
||||
android:fillColor="#2f45a6" /> |
||||
</vector> |
@ -0,0 +1,5 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android"> |
||||
<item android:drawable="@drawable/ic_bottom_person_e" android:state_checked="false" /> |
||||
<item android:drawable="@drawable/ic_bottom_person_s" android:state_checked="true" /> |
||||
</selector> |
@ -0,0 +1,12 @@ |
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:width="24dp" |
||||
android:height="24dp" |
||||
android:viewportWidth="24" |
||||
android:viewportHeight="24"> |
||||
<path |
||||
android:pathData="M12,2.5A4.5,4.5 0,1 1,7.5 7,4.51 4.51,0 0,1 12,2.5M12,1a6,6 0,1 0,6 6,6 6,0 0,0 -6,-6Z" |
||||
android:fillColor="#2f45a6" /> |
||||
<path |
||||
android:pathData="M3.5,21A4.49,4.49 0,0 1,8 16.5h8A4.49,4.49 0,0 1,20.5 21v2H21a1,1 0,0 0,1 -1V21a6,6 0,0 0,-6 -6H8a6,6 0,0 0,-6 6v1a1,1 0,0 0,1 1h0.5Z" |
||||
android:fillColor="#2f45a6" /> |
||||
</vector> |
@ -0,0 +1,12 @@ |
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:width="24dp" |
||||
android:height="24dp" |
||||
android:viewportWidth="24" |
||||
android:viewportHeight="24"> |
||||
<path |
||||
android:pathData="M12,7m-6,0a6,6 0,1 1,12 0a6,6 0,1 1,-12 0" |
||||
android:fillColor="#2f45a6" /> |
||||
<path |
||||
android:pathData="M8,15h8a6,6 0,0 1,6 6v1a1,1 0,0 1,-1 1H3a1,1 0,0 1,-1 -1V21A6,6 0,0 1,8 15Z" |
||||
android:fillColor="#2f45a6" /> |
||||
</vector> |
@ -0,0 +1,5 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android"> |
||||
<item android:drawable="@drawable/ic_bottom_rss_feed_e" android:state_checked="false" /> |
||||
<item android:drawable="@drawable/ic_bottom_rss_feed_s" android:state_checked="true" /> |
||||
</selector> |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue