@ -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() |
||||
} |
||||
|
||||
} |
@ -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,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,15 @@ |
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:width="24dp" |
||||
android:height="24dp" |
||||
android:viewportWidth="24" |
||||
android:viewportHeight="24"> |
||||
<path |
||||
android:fillColor="#FF000000" |
||||
android:pathData="M12,4.5A7.5,7.5 0,1 1,4.5 12,7.5 7.5,0 0,1 12,4.5M12,3a9,9 0,1 0,9 9,9 9,0 0,0 -9,-9Z"/> |
||||
<path |
||||
android:fillColor="#FF000000" |
||||
android:pathData="M11.25,10.5h1.5v6h-1.5z"/> |
||||
<path |
||||
android:fillColor="#FF000000" |
||||
android:pathData="M12,8.5m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0"/> |
||||
</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:fillColor="#FF000000" |
||||
android:pathData="M9.94,4H5A2,2 0,0 0,3 6V18a2,2 0,0 0,2 2H19a2,2 0,0 0,2 -2V8a2,2 0,0 0,-2 -2H13.23a1.49,1.49 0,0 1,-1 -0.42L11,4.42a1.49,1.49 0,0 0,-1 -0.42ZM4.5,9.25V6A0.5,0.5 0,0 1,5 5.5H9.94l1.21,1.16a3,3 0,0 0,2.08 0.84H19a0.5,0.5 0,0 1,0.5 0.5V9.25ZM5,18.5a0.5,0.5 0,0 1,-0.5 -0.5V10.75h15V18a0.5,0.5 0,0 1,-0.5 0.5Z"/> |
||||
</vector> |
@ -0,0 +1,5 @@ |
||||
<vector android:height="32dp" android:viewportHeight="24" |
||||
android:viewportWidth="24" android:width="32dp" xmlns:android="http://schemas.android.com/apk/res/android"> |
||||
<path android:fillColor="#FF000000" android:pathData="M12,4.5A7.5,7.5 0,1 1,4.5 12,7.5 7.5,0 0,1 12,4.5M12,3a9,9 0,1 0,9 9,9 9,0 0,0 -9,-9Z"/> |
||||
<path android:fillColor="#FF000000" android:pathData="M12,5.25v13.5a6.75,6.75 0,0 0,0 -13.5Z"/> |
||||
</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:fillColor="#FF000000" |
||||
android:pathData="M12,4.5A7.5,7.5 0,1 1,4.5 12,7.5 7.5,0 0,1 12,4.5M12,3a9,9 0,1 0,9 9,9 9,0 0,0 -9,-9Z"/> |
||||
<path |
||||
android:fillColor="#FF000000" |
||||
android:pathData="M15.01,7.25l-1.49,0l-1.51,2.59l-1.5,-2.59l-1.5,0l1.6,2.75l-1.6,0l0,1.5l2.24,0l0,1l-2.24,0l0,1.5l2.24,0l0,2.75l1.5,0l0,-2.75l2.24,0l0,-1.5l-2.24,0l0,-1l2.24,0l0,-1.5l-1.58,0l1.6,-2.75z"/> |
||||
</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:fillColor="#FF000000" |
||||
android:pathData="M12,10.5A1.5,1.5 0,1 1,10.5 12,1.5 1.5,0 0,1 12,10.5M12,9a3,3 0,1 0,3 3,3 3,0 0,0 -3,-3Z"/> |
||||
<path |
||||
android:fillColor="#FF000000" |
||||
android:pathData="M15.62,5.5h0L19.28,12l-3.66,6.5H8.38L4.72,12 8.38,5.5h7.24m0,-1.5H8.38a1.5,1.5 0,0 0,-1.31 0.77L3.41,11.26a1.55,1.55 0,0 0,0 1.48l3.66,6.49A1.5,1.5 0,0 0,8.38 20h7.24a1.5,1.5 0,0 0,1.31 -0.77l3.66,-6.49a1.55,1.55 0,0 0,0 -1.48L16.93,4.77A1.5,1.5 0,0 0,15.62 4Z"/> |
||||
</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:fillColor="#FF000000" |
||||
android:pathData="M10.84,19.2V17.8a5.1,5.1 0,0 1,-5.13 -4.2,0.64 0.64,0 0,1 0.68,-0.7 0.87,0.87 0,0 1,0.82 0.69,3.66 3.66,0 0,0 3.63,2.81V15l3,2.1 -3,2.1Z"/> |
||||
<path |
||||
android:fillColor="#FF000000" |
||||
android:pathData="M5.93,3 L3,10.52L4.61,10.52l0.62,-1.71h3l0.66,1.71h1.65L7.53,3ZM5.7,7.54l1,-2.79 1,2.79ZM20.63,17.69A2,2 0,0 0,19.57 17a1.76,1.76 0,0 0,0.78 -0.67,1.79 1.79,0 0,0 0,-1.84 2,2 0,0 0,-0.58 -0.63,1.91 1.91,0 0,0 -0.78,-0.31 8.48,8.48 0,0 0,-1.33 -0.08h-3L14.66,21h2.56c1,0 1.58,0 1.83,-0.05a2.21,2.21 0,0 0,1 -0.36,2 2,0 0,0 0.65,-0.77 2.23,2.23 0,0 0,0.24 -1A1.78,1.78 0,0 0,20.63 17.69ZM16.22,14.69h0.87c0.72,0 1.15,0 1.3,0A0.9,0.9 0,0 1,19 15a0.84,0.84 0,0 1,0.19 0.57,0.8 0.8,0 0,1 -0.22,0.59 1,1 0,0 1,-0.61 0.27c-0.14,0 -0.51,0 -1.1,0h-1ZM19.22,19.35a0.94,0.94 0,0 1,-0.55 0.3,7.41 7.41,0 0,1 -1,0L16.22,19.65v-2h1.23a5.11,5.11 0,0 1,1.34 0.11,1 1,0 0,1 0.48,0.34 1,1 0,0 1,0.16 0.58,0.93 0.93,0 0,1 -0.21,0.64Z"/> |
||||
</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:fillColor="#FF000000" |
||||
android:pathData="M20.59,4.2A15,15 0,0 0,18.12 4,20 20,0 0,0 12,5 20,20 0,0 0,5.88 4a15,15 0,0 0,-2.47 0.2c-0.24,0 -0.41,0.25 -0.41,1.1L3,18.68a0.48,0.48 0,0 0,0.49 0.48h0.08A14.08,14.08 0,0 1,5.88 19a19.58,19.58 0,0 1,5.39 0.8L12,20l0.66,-0.2A19.85,19.85 0,0 1,18.12 19a14.08,14.08 0,0 1,2.31 0.18h0.08a0.48,0.48 0,0 0,0.49 -0.49L21,4.7A0.5,0.5 0,0 0,20.59 4.2ZM11.27,18.2a21.47,21.47 0,0 0,-5.39 -0.74c-0.48,0 -1,0 -1.42,0.06v-12A13.24,13.24 0,0 1,5.88 5.5a19,19 0,0 1,5.39 0.85ZM19.54,17.52c-0.46,0 -0.94,-0.06 -1.42,-0.06a21.27,21.27 0,0 0,-5.39 0.74L12.73,6.35a19.14,19.14 0,0 1,5.39 -0.85,13.11 13.11,0 0,1 1.42,0.07Z"/> |
||||
<path |
||||
android:fillColor="#FF000000" |
||||
android:pathData="M18.12,8.45l0.5,0V7l-0.5,0a19.49,19.49 0,0 0,-4.5 0.56V9.05A18.3,18.3 0,0 1,18.12 8.45Z"/> |
||||
</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:fillColor="#FF000000" |
||||
android:pathData="M20.37,4.75 L16,3H14.29A2.5,2.5 0,0 1,9.71 3H8L3.63,4.75A1,1 0,0 0,3 5.68V10a1.05,1.05 0,0 0,1 1.05,1 1,0 0,0 0.3,-0.05L6.5,10v9a2,2 0,0 0,2 2h7a2,2 0,0 0,2 -2V10l2.18,1A1,1 0,0 0,21 10V5.68A1,1 0,0 0,20.37 4.75ZM19.5,9.27 L16.72,8a0.51,0.51 0,0 0,-0.72 0.46V19a0.5,0.5 0,0 1,-0.5 0.5h-7A0.5,0.5 0,0 1,8 19V8.45A0.5,0.5 0,0 0,7.29 8L4.5,9.27V6L8.29,4.5H8.9a4,4 0,0 0,6.2 0h0.61L19.5,6Z"/> |
||||
</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:fillColor="#FF000000" |
||||
android:pathData="M19.62,7.23A8.83,8.83 0,0 0,18.72 6,9 9,0 0,0 13.24,3.1 3.86,3.86 0,0 0,12.75 3c-0.25,0 -0.5,0 -0.75,0s-0.5,0 -0.75,0a3.86,3.86 0,0 0,-0.49 0.06A9,9 0,0 0,5.28 6a8.83,8.83 0,0 0,-0.9 1.21,8.93 8.93,0 0,0 0,9.54A8.83,8.83 0,0 0,5.28 18a9,9 0,0 0,5.48 2.92,3.86 3.86,0 0,0 0.49,0.06c0.25,0 0.5,0 0.75,0s0.5,0 0.75,0a3.86,3.86 0,0 0,0.49 -0.06A9,9 0,0 0,18.72 18a8.83,8.83 0,0 0,0.9 -1.21,8.93 8.93,0 0,0 0,-9.54ZM19.46,11.23L16,11.23A13.84,13.84 0,0 0,15.67 9a13.7,13.7 0,0 0,2.65 -1A7.36,7.36 0,0 1,19.46 11.25ZM17.37,6.77a12.57,12.57 0,0 1,-2.1 0.78A13.83,13.83 0,0 0,14 4.77,7.56 7.56,0 0,1 17.37,6.77ZM12,14.5a14.51,14.51 0,0 0,-2.2 0.19,12.41 12.41,0 0,1 -0.26,-1.94h4.92a12.41,12.41 0,0 1,-0.26 1.94A14.51,14.51 0,0 0,12 14.5ZM13.78,16.14A12.69,12.69 0,0 1,12 19.47a12.69,12.69 0,0 1,-1.78 -3.33A13,13 0,0 1,12 16,13 13,0 0,1 13.78,16.14ZM9.54,11.25A12.41,12.41 0,0 1,9.8 9.31,14.51 14.51,0 0,0 12,9.5a14.51,14.51 0,0 0,2.2 -0.19,12.41 12.41,0 0,1 0.26,1.94ZM10.22,7.86A12.69,12.69 0,0 1,12 4.53a12.69,12.69 0,0 1,1.78 3.33A13,13 0,0 1,12 8,13 13,0 0,1 10.22,7.86ZM10,4.77a13.83,13.83 0,0 0,-1.3 2.78,12.57 12.57,0 0,1 -2.1,-0.78A7.56,7.56 0,0 1,10 4.77ZM8.33,9A13.84,13.84 0,0 0,8 11.25L4.54,11.25A7.36,7.36 0,0 1,5.68 8,13.7 13.7,0 0,0 8.33,9ZM4.54,12.75L8,12.75A13.84,13.84 0,0 0,8.33 15a13.7,13.7 0,0 0,-2.65 1A7.36,7.36 0,0 1,4.54 12.75ZM6.63,17.23a12.57,12.57 0,0 1,2.1 -0.78A13.83,13.83 0,0 0,10 19.23,7.56 7.56,0 0,1 6.63,17.23ZM13.97,19.23a13.83,13.83 0,0 0,1.3 -2.78,12.57 12.57,0 0,1 2.1,0.78A7.56,7.56 0,0 1,14 19.23ZM15.67,15A13.84,13.84 0,0 0,16 12.75h3.5A7.36,7.36 0,0 1,18.32 16,13.7 13.7,0 0,0 15.67,15Z"/> |
||||
</vector> |
@ -1,15 +1,12 @@ |
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:width="200dp" |
||||
android:height="200dp" |
||||
android:viewportWidth="200" |
||||
android:viewportHeight="200"> |
||||
<path |
||||
android:fillColor="#FF000000" |
||||
android:pathData="M100.1,181.4c-10.9,0 -21.5,-2.1 -31.4,-6.3c-9.6,-4.1 -18.2,-9.9 -25.7,-17.3s-13.2,-16 -17.3,-25.7c-4.2,-10 -6.3,-20.5 -6.3,-31.4c0,-10.9 2.1,-21.5 6.3,-31.4C29.8,59.7 35.6,51 43,43.6c7.4,-7.4 16,-13.2 25.7,-17.3c10,-4.2 20.5,-6.3 31.4,-6.3s21.5,2.1 31.4,6.3c9.6,4.1 18.2,9.9 25.7,17.3c7.4,7.4 13.2,16 17.3,25.7c4.2,10 6.3,20.5 6.3,31.4s-2.1,21.5 -6.3,31.4c-4.1,9.6 -9.9,18.2 -17.3,25.7c-7.4,7.4 -16,13.2 -25.7,17.3C121.6,179.3 111,181.4 100.1,181.4zM100.1,31.6C62,31.6 31,62.6 31,100.7c0,38.1 31,69.2 69.2,69.2s69.2,-31 69.2,-69.2C169.3,62.6 138.2,31.6 100.1,31.6L100.1,31.6z" /> |
||||
<path |
||||
android:fillColor="#FF000000" |
||||
android:pathData="M114.1,78.8c0,-7.1 -4.2,-12.9 -14,-12.9c-6.3,0 -12.2,3.1 -18,9.2l-3.5,-3.3C84.8,65.5 91,61 100.6,61c12.1,0 19.2,7.3 19.2,17.4c0,15.1 -22.3,19 -19,34.4h-5.3C92,95.9 114.1,90.9 114.1,78.8zM98.5,122.6c3.3,0 6.4,2.3 6.4,6.4c0,4.2 -3.1,6.5 -6.4,6.5c-3.4,0 -6.4,-2.3 -6.4,-6.5C92,125 95.1,122.6 98.5,122.6z" /> |
||||
<path |
||||
android:fillColor="#FF000000" |
||||
android:pathData="M98.5,138.1c-5.1,0 -8.9,-3.8 -8.9,-9c0,-5.1 3.7,-8.9 8.9,-8.9c5.1,0 8.9,3.8 8.9,8.9C107.4,134.9 102.8,138.1 98.5,138.1zM98.5,125.1c-1.8,0 -4,1 -4,4c0,3 2.2,4.1 4,4.1c2,0 4,-1.3 4,-4.1C102.5,126.3 100.4,125.1 98.5,125.1zM103.8,115.2H93.6l-0.4,-1.9c-1,-4.9 -0.2,-9.4 2.4,-13.6c2.2,-3.6 5.3,-6.5 8.3,-9.3c4.2,-3.9 7.9,-7.4 7.9,-11.6c0,-3.9 -1.5,-10.4 -11.5,-10.4c-5.5,0 -10.8,2.8 -16.2,8.4l-1.7,1.8l-7.1,-6.7l1.7,-1.8c6.8,-6.9 13.4,-11.5 23.7,-11.5c13,0 21.7,8 21.7,19.8c0,8.3 -5.7,13.6 -10.8,18.2c-5.2,4.8 -9.7,9 -8.3,15.6L103.8,115.2L103.8,115.2zM97.7,110.3h0.4c-0.3,-7.7 5.2,-12.8 10.1,-17.3c4.7,-4.4 9.2,-8.5 9.2,-14.6c0,-9.1 -6.6,-14.9 -16.8,-14.9c-0.1,0 -0.2,0 -0.3,0c10,0.1 16.2,5.9 16.2,15.3c0,6.3 -4.8,10.8 -9.4,15.2C102,98.7 97.1,103.3 97.7,110.3L97.7,110.3zM95.2,64c-3,0.7 -5.7,1.9 -8.2,3.7C89.7,65.9 92.4,64.7 95.2,64z" /> |
||||
android:width="22dp" |
||||
android:height="22dp" |
||||
android:viewportWidth="1024" |
||||
android:viewportHeight="1024"> |
||||
<path |
||||
android:fillColor="#8F000000" |
||||
android:pathData="M474.84,721.55c0,21.68 17.55,38.71 38.71,38.71 21.68,0 38.71,-17.55 38.71,-38.71 0,-13.94 -7.23,-26.84 -19.61,-33.55 -11.87,-6.71 -26.84,-6.71 -38.71,0s-19.1,19.61 -19.1,33.55zM474.84,721.55M509.94,263.74C433.55,263.74 371.61,325.16 371.61,401.03c0,17.03 13.94,31.48 31.48,31.48 17.03,0 30.97,-13.94 31.48,-31.48 0,-41.81 33.03,-74.32 75.87,-74.32 41.81,0 75.87,34.06 75.87,76.39 0,16 -22.71,38.71 -42.84,58.84 -29.94,29.94 -64,64 -64,109.94v45.42c0.52,16.52 14.45,29.94 31.48,29.94s30.45,-13.42 30.97,-29.94v-45.42c0,-19.61 24.26,-44.39 45.94,-65.55 29.94,-29.94 60.9,-60.9 60.9,-102.71 -1.03,-77.42 -62.97,-139.87 -138.84,-139.87zM509.94,263.74"/> |
||||
<path |
||||
android:fillColor="#8F000000" |
||||
android:pathData="M512,157.42c195.61,0 354.06,158.97 354.58,354.58 0,195.61 -158.97,354.58 -354.58,354.58s-354.58,-158.97 -354.58,-354.58 159.48,-354.58 354.58,-354.58m0,-68.65c-233.81,0 -423.23,189.42 -423.23,423.23s189.42,423.23 423.23,423.23 423.23,-189.42 423.23,-423.23 -189.42,-423.23 -423.23,-423.23zM512,88.77"/> |
||||
</vector> |
||||
|
@ -0,0 +1,8 @@ |
||||
<vector android:height="8dp" |
||||
android:viewportHeight="1024" |
||||
android:viewportWidth="1024" |
||||
android:width="8dp" |
||||
xmlns:android="http://schemas.android.com/apk/res/android"> |
||||
<path android:fillColor="#c0c0c0" android:pathData="M462.43,894.32c-242.22,0 -439.3,-197.03 -439.3,-439.3S220.16,15.78 462.43,15.78s439.3,197.03 439.3,439.3 -197.07,439.25 -439.3,439.25zM462.43,62.32c-216.58,0 -392.75,176.17 -392.75,392.75s176.17,392.75 392.75,392.75c216.53,0 392.75,-176.17 392.75,-392.75s-176.22,-392.75 -392.75,-392.75z"/> |
||||
<path android:fillColor="#c0c0c0" android:pathData="M977.64,991.98a23.37,23.37 0,0 1,-16.48 -6.8l-211.22,-211.22a23.27,23.27 0,0 1,32.91 -32.91l211.22,211.22a23.27,23.27 0,0 1,-16.43 39.7z"/> |
||||
</vector> |
@ -0,0 +1,65 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||
xmlns:tools="http://schemas.android.com/tools" |
||||
android:background="@drawable/bg_prefs_color" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="wrap_content" |
||||
android:paddingLeft="16dp" |
||||
android:paddingTop="10dp" |
||||
android:paddingRight="16dp" |
||||
android:paddingBottom="4dp" |
||||
android:minHeight="42dp" |
||||
android:clickable="true" |
||||
android:orientation="horizontal" |
||||
android:focusable="true"> |
||||
|
||||
<ImageView |
||||
android:id="@+id/preference_icon" |
||||
android:layout_marginRight="16dp" |
||||
android:scaleType="fitCenter" |
||||
android:visibility="visible" |
||||
android:paddingTop="1dp" |
||||
android:layout_width="24dp" |
||||
android:layout_height="24dp" |
||||
tools:ignore="ContentDescription,RtlHardcoded" /> |
||||
|
||||
<LinearLayout |
||||
android:orientation="vertical" |
||||
android:layout_weight="1.0" |
||||
android:layout_width="0dp" |
||||
android:layout_height="wrap_content"> |
||||
|
||||
<TextView |
||||
android:id="@+id/preference_title" |
||||
android:paddingBottom="8dp" |
||||
android:singleLine="true" |
||||
android:textSize="16sp" |
||||
android:text="@string/title" |
||||
android:textColor="@color/tv_text_default" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="wrap_content" /> |
||||
|
||||
<TextView |
||||
android:id="@+id/preference_desc" |
||||
android:paddingBottom="8dp" |
||||
android:textSize="14sp" |
||||
android:textColor="@color/tv_text_summary" |
||||
android:text="@string/default1" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="wrap_content" /> |
||||
</LinearLayout> |
||||
|
||||
<FrameLayout |
||||
android:id="@+id/preference_widget" |
||||
android:orientation="vertical" |
||||
android:layout_gravity="center" |
||||
android:layout_marginLeft="8dp" |
||||
android:layout_marginTop="8dp" |
||||
android:layout_marginBottom="8dp" |
||||
android:visibility="gone" |
||||
android:gravity="right|center_vertical" |
||||
android:layout_width="wrap_content" |
||||
android:layout_height="wrap_content" |
||||
tools:ignore="RtlHardcoded" /> |
||||
|
||||
</LinearLayout> |
@ -0,0 +1,29 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<LinearLayout |
||||
xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="wrap_content" |
||||
android:orientation="vertical" > |
||||
|
||||
<View |
||||
android:id="@+id/preference_divider_above" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="8dp" /> |
||||
|
||||
<TextView |
||||
android:id="@+id/preference_title" |
||||
android:paddingTop="16dip" |
||||
android:paddingBottom="8dip" |
||||
android:background="@drawable/bg_prefs_color" |
||||
android:paddingLeft="16dp" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="wrap_content" |
||||
/> |
||||
|
||||
<View |
||||
android:id="@+id/preference_divider_below" |
||||
android:layout_width="match_parent" |
||||
android:visibility="gone" |
||||
android:layout_height="8dp" /> |
||||
|
||||
</LinearLayout> |
@ -1,15 +1,17 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<androidx.appcompat.widget.SearchView |
||||
<io.legado.app.ui.widget.SearchView |
||||
xmlns:android="http://schemas.android.com/apk/res/android" |
||||
xmlns:app="http://schemas.android.com/apk/res-auto" |
||||
android:id="@+id/search_view" |
||||
android:theme="?attr/actionBarStyle" |
||||
android:background="@drawable/bg_searchview" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="34dp" |
||||
android:layout_marginTop="8dp" |
||||
android:layout_marginBottom="8dp" |
||||
android:layout_height="30dp" |
||||
android:layout_marginTop="10dp" |
||||
android:layout_marginBottom="10dp" |
||||
android:imeOptions="actionSearch" |
||||
android:focusable="false" |
||||
app:queryBackground="@null" |
||||
app:submitBackground="@null" |
||||
app:searchHintIcon="@drawable/ic_search_hint" |
||||
app:defaultQueryHint="搜索"/> |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |