添加权限请求

pull/32/head
Invinciblelee 6 years ago
parent 514dd5173a
commit 2c8a0c330a
  1. 1
      app/build.gradle
  2. 3
      app/src/main/AndroidManifest.xml
  3. 20
      app/src/main/java/io/legado/app/help/permission/ActivitySource.kt
  4. 19
      app/src/main/java/io/legado/app/help/permission/FragmentSource.kt
  5. 5
      app/src/main/java/io/legado/app/help/permission/OnPermissionsDeniedCallback.kt
  6. 7
      app/src/main/java/io/legado/app/help/permission/OnPermissionsGrantedCallback.kt
  7. 9
      app/src/main/java/io/legado/app/help/permission/OnPermissionsResultCallback.kt
  8. 11
      app/src/main/java/io/legado/app/help/permission/OnRequestPermissionsResultCallback.kt
  9. 77
      app/src/main/java/io/legado/app/help/permission/PermissionActivity.kt
  10. 72
      app/src/main/java/io/legado/app/help/permission/Permissions.kt
  11. 78
      app/src/main/java/io/legado/app/help/permission/PermissionsCompat.kt
  12. 199
      app/src/main/java/io/legado/app/help/permission/Request.kt
  13. 67
      app/src/main/java/io/legado/app/help/permission/RequestManager.kt
  14. 20
      app/src/main/java/io/legado/app/help/permission/RequestPlugins.kt
  15. 13
      app/src/main/java/io/legado/app/help/permission/RequestSource.kt
  16. 78
      app/src/main/java/io/legado/app/ui/main/MainActivity.kt
  17. 2
      app/src/main/java/io/legado/app/ui/widget/TitleBar.kt
  18. 6
      app/src/main/res/layout/activity_search.xml
  19. 2
      app/src/main/res/layout/app_bar_main.xml
  20. 10
      app/src/main/res/values/strings.xml
  21. 15
      app/src/main/res/values/styles.xml

@ -76,7 +76,6 @@ dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.1'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.2.1'
//
implementation 'pub.devrel:easypermissions:3.0.0'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.jayway.jsonpath:json-path:2.4.0'
implementation 'org.jsoup:jsoup:1.12.1'

@ -40,6 +40,9 @@
</intent-filter>
</activity>
<activity android:name=".ui.replacerule.ReplaceRuleActivity"/>
<activity android:name=".help.permission.PermissionActivity"
android:theme="@style/Activity.Permission"/>
</application>
</manifest>

@ -0,0 +1,20 @@
package io.legado.app.help.permission
import android.content.Context
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import java.lang.ref.WeakReference
internal class ActivitySource(activity: AppCompatActivity) : RequestSource {
private val actRef: WeakReference<AppCompatActivity> = WeakReference(activity)
override val context: Context?
get() = actRef.get()
override fun startActivity(intent: Intent) {
actRef.get()?.startActivity(intent)
}
}

@ -0,0 +1,19 @@
package io.legado.app.help.permission
import android.content.Context
import android.content.Intent
import androidx.fragment.app.Fragment
import java.lang.ref.WeakReference
internal class FragmentSource(fragment: Fragment) : RequestSource {
private val fragRef: WeakReference<Fragment> = WeakReference(fragment)
override val context: Context?
get() = fragRef.get()?.requireContext()
override fun startActivity(intent: Intent) {
fragRef.get()?.startActivity(intent)
}
}

@ -0,0 +1,5 @@
package io.legado.app.help.permission
interface OnPermissionsDeniedCallback {
fun onPermissionsDenied(requestCode: Int, deniedPermissions: Array<String>)
}

@ -0,0 +1,7 @@
package io.legado.app.help.permission
interface OnPermissionsGrantedCallback {
fun onPermissionsGranted(requestCode: Int)
}

@ -0,0 +1,9 @@
package io.legado.app.help.permission
interface OnPermissionsResultCallback {
fun onPermissionsGranted(requestCode: Int)
fun onPermissionsDenied(requestCode: Int, deniedPermissions: Array<String>)
}

@ -0,0 +1,11 @@
package io.legado.app.help.permission
import android.content.Intent
interface OnRequestPermissionsResultCallback {
fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray)
fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?)
}

@ -0,0 +1,77 @@
package io.legado.app.help.permission
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.provider.Settings
import android.view.KeyEvent
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import io.legado.app.R
import org.jetbrains.anko.toast
class PermissionActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val intent = intent
when (intent.getIntExtra(KEY_INPUT_REQUEST_TYPE, Request.TYPE_REQUEST_PERMISSION)) {
Request.TYPE_REQUEST_PERMISSION//权限请求
-> {
val requestCode = intent.getIntExtra(KEY_INPUT_PERMISSIONS_CODE, 1000)
val permissions = intent.getStringArrayExtra(KEY_INPUT_PERMISSIONS)
if (permissions != null) {
ActivityCompat.requestPermissions(this, permissions, requestCode)
} else {
finish()
}
}
Request.TYPE_REQUEST_SETTING//跳转到设置界面
-> try {
val settingIntent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
settingIntent.data = Uri.fromParts("package", packageName, null)
startActivityForResult(settingIntent, Request.TYPE_REQUEST_SETTING)
} catch (e: Exception) {
toast(R.string.tip_cannot_jump_setting_page)
finish()
}
}
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
RequestPlugins.sRequestCallback?.onRequestPermissionsResult(requestCode, permissions, grantResults)
finish()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
RequestPlugins.sRequestCallback?.onActivityResult(requestCode, resultCode, data)
finish()
}
override fun startActivity(intent: Intent) {
super.startActivity(intent)
overridePendingTransition(0, 0)
}
override fun finish() {
super.finish()
overridePendingTransition(0, 0)
}
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
return if (keyCode == KeyEvent.KEYCODE_BACK) {
true
} else super.onKeyDown(keyCode, event)
}
companion object {
const val KEY_INPUT_REQUEST_TYPE = "KEY_INPUT_REQUEST_TYPE"
const val KEY_INPUT_PERMISSIONS_CODE = "KEY_INPUT_PERMISSIONS_CODE"
const val KEY_INPUT_PERMISSIONS = "KEY_INPUT_PERMISSIONS"
}
}

@ -0,0 +1,72 @@
package io.legado.app.help.permission
object Permissions {
const val READ_CALENDAR = "android.permission.READ_CALENDAR"
const val WRITE_CALENDAR = "android.permission.WRITE_CALENDAR"
const val CAMERA = "android.permission.CAMERA"
const val READ_CONTACTS = "android.permission.READ_CONTACTS"
const val WRITE_CONTACTS = "android.permission.WRITE_CONTACTS"
const val GET_ACCOUNTS = "android.permission.GET_ACCOUNTS"
const val ACCESS_FINE_LOCATION = "android.permission.ACCESS_FINE_LOCATION"
const val ACCESS_COARSE_LOCATION = "android.permission.ACCESS_COARSE_LOCATION"
const val RECORD_AUDIO = "android.permission.RECORD_AUDIO"
const val READ_PHONE_STATE = "android.permission.READ_PHONE_STATE"
const val CALL_PHONE = "android.permission.CALL_PHONE"
const val READ_CALL_LOG = "android.permission.READ_CALL_LOG"
const val WRITE_CALL_LOG = "android.permission.WRITE_CALL_LOG"
const val ADD_VOICEMAIL = "com.android.voicemail.permission.ADD_VOICEMAIL"
const val USE_SIP = "android.permission.USE_SIP"
const val PROCESS_OUTGOING_CALLS = "android.permission.PROCESS_OUTGOING_CALLS"
const val BODY_SENSORS = "android.permission.BODY_SENSORS"
const val SEND_SMS = "android.permission.SEND_SMS"
const val RECEIVE_SMS = "android.permission.RECEIVE_SMS"
const val READ_SMS = "android.permission.READ_SMS"
const val RECEIVE_WAP_PUSH = "android.permission.RECEIVE_WAP_PUSH"
const val RECEIVE_MMS = "android.permission.RECEIVE_MMS"
const val READ_EXTERNAL_STORAGE = "android.permission.READ_EXTERNAL_STORAGE"
const val WRITE_EXTERNAL_STORAGE = "android.permission.WRITE_EXTERNAL_STORAGE"
object Group {
val CALENDAR = arrayOf(READ_CALENDAR, WRITE_CALENDAR)
val CAMERA = arrayOf(Permissions.CAMERA)
val CONTACTS = arrayOf(READ_CONTACTS, WRITE_CONTACTS, GET_ACCOUNTS)
val LOCATION = arrayOf(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION)
val MICROPHONE = arrayOf(RECORD_AUDIO)
val PHONE = arrayOf(
READ_PHONE_STATE,
CALL_PHONE,
READ_CALL_LOG,
WRITE_CALL_LOG,
ADD_VOICEMAIL,
USE_SIP,
PROCESS_OUTGOING_CALLS
)
val SENSORS = arrayOf(BODY_SENSORS)
val SMS = arrayOf(
SEND_SMS,
RECEIVE_SMS,
READ_SMS,
RECEIVE_WAP_PUSH,
RECEIVE_MMS
)
val STORAGE = arrayOf(READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE)
}
}

@ -0,0 +1,78 @@
package io.legado.app.help.permission
import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
class PermissionsCompat private constructor() {
private var mRequest: Request? = null
fun request() {
RequestManager.pushRequest(mRequest)
}
class Builder {
private val mRequest: Request
constructor(activity: AppCompatActivity) {
mRequest = Request(activity)
}
constructor(fragment: Fragment) {
mRequest = Request(fragment)
}
fun addPermissions(vararg permissions: String): Builder {
mRequest.addPermissions(*permissions)
return this
}
fun requestCode(requestCode: Int): Builder {
mRequest.setRequestCode(requestCode)
return this
}
fun onGranted(callback: (requestCode: Int) -> Unit): Builder {
mRequest.setOnGrantedCallback(object : OnPermissionsGrantedCallback {
override fun onPermissionsGranted(requestCode: Int) {
callback(requestCode)
}
})
return this
}
fun onDenied(callback: (requestCode: Int, deniedPermissions: Array<String>) -> Unit): Builder {
mRequest.setOnDeniedCallback(object : OnPermissionsDeniedCallback {
override fun onPermissionsDenied(requestCode: Int, deniedPermissions: Array<String>) {
callback(requestCode, deniedPermissions)
}
})
return this
}
fun rationale(rationale: CharSequence): Builder {
mRequest.setRationale(rationale)
return this
}
fun rationale(@StringRes resId: Int): Builder {
mRequest.setRationale(resId)
return this
}
fun build(): PermissionsCompat {
val compat = PermissionsCompat()
compat.mRequest = mRequest
return compat
}
fun request(): PermissionsCompat {
val compat = build()
compat.mRequest = mRequest
compat.request()
return compat
}
}
}

@ -0,0 +1,199 @@
package io.legado.app.help.permission
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import io.legado.app.R
import org.jetbrains.anko.startActivity
import java.util.*
internal class Request : OnRequestPermissionsResultCallback {
var startTime: Long = 0
private set
private var requestCode: Int = 0
private var source: RequestSource? = null
private var permissions: ArrayList<String>? = null
private var grantedCallback: OnPermissionsGrantedCallback? = null
private var deniedCallback: OnPermissionsDeniedCallback? = null
private var rationaleResId: Int = 0
private var rationale: CharSequence? = null
private var rationaleDialog: AlertDialog? = null
private val deniedPermissions: Array<String>?
get() {
val permissions: Array<String>?
val size = this.permissions?.size ?: 0
if (size > 0) {
permissions = this.permissions?.toTypedArray()
} else {
permissions = null
}
return getDeniedPermissions(permissions)
}
constructor(activity: AppCompatActivity) {
source = ActivitySource(activity)
permissions = ArrayList()
}
constructor(fragment: Fragment) {
source = FragmentSource(fragment)
permissions = ArrayList()
}
fun addPermissions(vararg permissions: String) {
this.permissions?.addAll(Arrays.asList(*permissions))
}
fun setRequestCode(requestCode: Int) {
this.requestCode = requestCode
}
fun setOnGrantedCallback(callback: OnPermissionsGrantedCallback) {
grantedCallback = callback
}
fun setOnDeniedCallback(callback: OnPermissionsDeniedCallback) {
deniedCallback = callback
}
fun setRationale(@StringRes resId: Int) {
rationaleResId = resId
rationale = null
}
fun setRationale(rationale: CharSequence) {
this.rationale = rationale
rationaleResId = 0
}
fun start() {
RequestPlugins.setOnRequestPermissionsCallback(this)
val deniedPermissions = deniedPermissions
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
if (deniedPermissions == null) {
onPermissionsGranted(requestCode)
} else {
val rationale = if (rationaleResId != 0) source?.context?.getText(rationaleResId) else rationale
if (rationale != null) {
showSettingDialog(rationale) { onPermissionsDenied(requestCode, deniedPermissions) }
} else {
onPermissionsDenied(requestCode, deniedPermissions)
}
}
} else {
if (deniedPermissions != null) {
source?.context?.startActivity<PermissionActivity>(
Pair(PermissionActivity.KEY_INPUT_REQUEST_TYPE, TYPE_REQUEST_PERMISSION),
Pair(PermissionActivity.KEY_INPUT_PERMISSIONS_CODE, requestCode),
Pair(PermissionActivity.KEY_INPUT_PERMISSIONS, deniedPermissions)
)
} else {
onPermissionsGranted(requestCode)
}
}
startTime = System.currentTimeMillis()
}
fun clear() {
grantedCallback = null
deniedCallback = null
}
private fun getDeniedPermissions(permissions: Array<String>?): Array<String>? {
if (permissions != null) {
val deniedPermissionList = ArrayList<String>()
for (permission in permissions) {
if (source?.context?.let {
ContextCompat.checkSelfPermission(
it,
permission
)
} != PackageManager.PERMISSION_GRANTED
) {
deniedPermissionList.add(permission)
}
}
val size = deniedPermissionList.size
if (size > 0) {
return deniedPermissionList.toTypedArray()
}
}
return null
}
private fun showSettingDialog(rationale: CharSequence, cancel: () -> Unit) {
rationaleDialog?.dismiss()
source?.context?.let {
rationaleDialog = AlertDialog.Builder(it)
.setTitle(R.string.dialog_title)
.setMessage(rationale)
.setPositiveButton(R.string.dialog_setting) { _, _ ->
it.startActivity<PermissionActivity>(
Pair(
PermissionActivity.KEY_INPUT_REQUEST_TYPE,
TYPE_REQUEST_SETTING
)
)
}
.setNegativeButton(R.string.dialog_cancel) { _, _ -> cancel() }
.show()
}
}
private fun onPermissionsGranted(requestCode: Int) {
try {
grantedCallback?.onPermissionsGranted(requestCode)
} catch (ignore: Exception) {
}
RequestPlugins.sResultCallback?.onPermissionsGranted(requestCode)
}
private fun onPermissionsDenied(requestCode: Int, deniedPermissions: Array<String>) {
try {
deniedCallback?.onPermissionsDenied(requestCode, deniedPermissions)
} catch (ignore: Exception) {
}
RequestPlugins.sResultCallback?.onPermissionsDenied(requestCode, deniedPermissions)
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
val deniedPermissions = getDeniedPermissions(permissions)
if (deniedPermissions != null) {
val rationale = if (rationaleResId != 0) source?.context?.getText(rationaleResId) else rationale
if (rationale != null) {
showSettingDialog(rationale) { onPermissionsDenied(requestCode, deniedPermissions) }
} else {
onPermissionsDenied(requestCode, deniedPermissions)
}
} else {
onPermissionsGranted(requestCode)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
val deniedPermissions = deniedPermissions
if (deniedPermissions == null) {
onPermissionsGranted(this.requestCode)
} else {
onPermissionsDenied(this.requestCode, deniedPermissions)
}
}
companion object {
const val TYPE_REQUEST_PERMISSION = 1
const val TYPE_REQUEST_SETTING = 2
}
}

@ -0,0 +1,67 @@
package io.legado.app.help.permission
import android.os.Handler
import java.util.*
internal object RequestManager : OnPermissionsResultCallback {
private var requests: Stack<Request>? = null
private var request: Request? = null
private val handler = Handler()
private val requestRunnable = Runnable {
request?.start()
}
private val isCurrentRequestInvalid: Boolean
get() = request?.let { System.currentTimeMillis() - it.startTime > 5 * 1000L } ?: true
init {
RequestPlugins.setOnPermissionsResultCallback(this)
}
fun pushRequest(request: Request?) {
if (request == null) return
if (requests == null) {
requests = Stack()
}
requests?.let {
val index = it.indexOf(request)
if (index >= 0) {
val to = it.size - 1
if (index != to) {
Collections.swap(requests, index, to)
}
} else {
it.push(request)
}
if (isCurrentRequestInvalid) {
this.request = it.pop()
handler.post(requestRunnable)
}
}
}
private fun startNextRequest() {
request?.clear()
request = null
requests?.let {
request = if (it.empty()) null else it.pop()
request?.let { handler.post(requestRunnable) }
}
}
override fun onPermissionsGranted(requestCode: Int) {
startNextRequest()
}
override fun onPermissionsDenied(requestCode: Int, deniedPermissions: Array<String>) {
startNextRequest()
}
}

@ -0,0 +1,20 @@
package io.legado.app.help.permission
internal object RequestPlugins {
@Volatile
var sRequestCallback: OnRequestPermissionsResultCallback? = null
@Volatile
var sResultCallback: OnPermissionsResultCallback? = null
fun setOnRequestPermissionsCallback(callback: OnRequestPermissionsResultCallback) {
sRequestCallback = callback
}
fun setOnPermissionsResultCallback(callback: OnPermissionsResultCallback) {
sResultCallback = callback
}
}

@ -0,0 +1,13 @@
package io.legado.app.help.permission
import android.content.Context
import android.content.Intent
import androidx.fragment.app.FragmentManager
interface RequestSource {
val context: Context?
fun startActivity(intent: Intent)
}

@ -2,18 +2,32 @@ package io.legado.app.ui.main
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.core.view.GravityCompat
import androidx.drawerlayout.widget.DrawerLayout
import com.google.android.material.navigation.NavigationView
import com.jayway.jsonpath.Configuration
import com.jayway.jsonpath.JsonPath
import com.jayway.jsonpath.Option
import io.legado.app.App
import io.legado.app.R
import io.legado.app.base.BaseActivity
import io.legado.app.constant.AppConst.APP_TAG
import io.legado.app.data.entities.ReplaceRule
import io.legado.app.help.permission.Permissions
import io.legado.app.help.permission.PermissionsCompat
import io.legado.app.ui.replacerule.ReplaceRuleActivity
import io.legado.app.ui.search.SearchActivity
import io.legado.app.utils.getViewModel
import io.legado.app.utils.*
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.app_bar_main.*
import org.jetbrains.anko.doAsync
import org.jetbrains.anko.startActivity
import org.jetbrains.anko.uiThread
import java.io.File
class MainActivity : BaseActivity<MainDataBinding, MainViewModel>(), NavigationView.OnNavigationItemSelectedListener {
override val viewModel: MainViewModel
@ -26,7 +40,7 @@ class MainActivity : BaseActivity<MainDataBinding, MainViewModel>(), NavigationV
fab.setOnClickListener { startActivity(Intent(this, SearchActivity::class.java)) }
val toggle = ActionBarDrawerToggle(
this, drawer_layout, titleBar.toolbar,
this, drawer_layout, title_bar.toolbar,
R.string.navigation_drawer_open,
R.string.navigation_drawer_close
)
@ -58,6 +72,20 @@ class MainActivity : BaseActivity<MainDataBinding, MainViewModel>(), NavigationV
override fun onNavigationItemSelected(item: MenuItem): Boolean {
// Handle navigation view item clicks here.
when (item.itemId) {
R.id.nav_backup -> {
// Handle the camera action
}
R.id.nav_import -> {
}
R.id.nav_import_old -> PermissionsCompat.Builder(this)
.addPermissions(*Permissions.Group.STORAGE)
.rationale(R.string.tip_perm_request_storage)
.onGranted { importYueDu() }.request()
R.id.nav_import_github -> {
}
R.id.nav_replace_rule -> startActivity<ReplaceRuleActivity>()
R.id.nav_send -> {
}
@ -66,4 +94,50 @@ class MainActivity : BaseActivity<MainDataBinding, MainViewModel>(), NavigationV
drawerLayout.closeDrawer(GravityCompat.START)
return true
}
/*
* import from YueDu backup data
* */
fun importYueDu() {
val yuedu = File(getSdPath(), "YueDu")
val jsonPath = JsonPath.using(
Configuration.builder()
.options(Option.SUPPRESS_EXCEPTIONS)
.build()
)
// Replace rules
val rFile = File(yuedu, "myBookReplaceRule.json")
val replaceRules = mutableListOf<ReplaceRule>()
if (rFile.exists()) try {
val items: List<Map<String, Any>> = jsonPath.parse(rFile.readText()).read("$.*")
for (item in items) {
val jsonItem = jsonPath.parse(item)
val rRule = ReplaceRule()
rRule.name = jsonItem.readString("$.replaceSummary")
rRule.pattern = jsonItem.readString("$.regex")
rRule.replacement = jsonItem.readString("$.replacement")
rRule.isRegex = jsonItem.readBool("$.isRegex")
rRule.scope = jsonItem.readString("$.useTo")
rRule.isEnabled = jsonItem.readBool("$.enable")
rRule.order = jsonItem.readInt("$.serialNumber")
replaceRules.add(rRule)
// Log.e(APP_TAG, rRule.toString())
}
doAsync {
App.db.replaceRuleDao().insert(*replaceRules.toTypedArray())
val count = App.db.replaceRuleDao().all.size
val maxId = App.db.replaceRuleDao().maxOrder
uiThread {
Log.e(APP_TAG, "$count records were inserted to database, and max id is $maxId.")
}
}
} catch (e: Exception) {
Log.e(APP_TAG, e.localizedMessage)
}
}
}

@ -37,7 +37,6 @@ class TitleBar(context: Context, attrs: AttributeSet?) : AppBarLayout(context, a
val attachToActivity = a.getBoolean(R.styleable.TitleBar_attachToActivity, true)
val titleText = a.getString(R.styleable.TitleBar_title)
val subtitleText = a.getString(R.styleable.TitleBar_subtitle)
a.recycle()
toolbar.apply {
if(showNavigationIcon){
@ -71,6 +70,7 @@ class TitleBar(context: Context, attrs: AttributeSet?) : AppBarLayout(context, a
}
}
a.recycle()
if (attachToActivity) {
attachToActivity(context)

@ -12,7 +12,7 @@
tools:context="io.legado.app.ui.search.SearchActivity">
<io.legado.app.ui.widget.TitleBar
android:id="@+id/titleBar"
android:id="@+id/title_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
@ -22,11 +22,11 @@
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/titleBar">
app:layout_constraintTop_toBottomOf="@id/title_bar">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/searchList"
android:id="@+id/rv_search_list"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

@ -8,7 +8,7 @@
tools:context=".ui.main.MainActivity">
<io.legado.app.ui.widget.TitleBar
android:id="@+id/titleBar"
android:id="@+id/title_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

@ -15,9 +15,17 @@
<string name="menu_send">Send</string>
<string name="dialog_title">提示</string>
<string name="dialog_cancel">取消</string>
<string name="dialog_confirm">确定</string>
<string name="dialog_setting">去设置</string>
<string name="tip_cannot_jump_setting_page">无法跳转至设置界面</string>
<string name="tip_perm_request_storage">阅读需要访问存储卡权限,请前往“设置”—”应用权限“—打开所需权限</string>
<string name="dynamic_click_retry">点击重试</string>
<string name="dynamic_loading">正在加载</string>
<string name="perm_request_storage">阅读需要访问存储卡权限:</string>
<string name="edit">编辑</string>
<string name="delete">删除</string>
</resources>

@ -1,4 +1,4 @@
<resources>
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
@ -14,6 +14,19 @@
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar"/>
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light"/>
<style name="Activity.Permission" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowDisablePreview">true</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowTranslucentStatus" tools:targetApi="kitkat">true</item>
<item name="android:windowAnimationStyle">@null</item>
</style>
<style name="Style.Line" parent="android:Widget">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">0.5dp</item>
<item name="android:background">@color/divider</item>
</style>
<style name="Style.Text.Primary.Normal" parent="android:Widget">
<item name="android:layout_width">match_parent</item>

Loading…
Cancel
Save