This commit is contained in:
coco
2026-07-03 16:23:31 +08:00
commit 7a4fb0e6ae
1979 changed files with 101570 additions and 0 deletions
@@ -0,0 +1 @@
/build
@@ -0,0 +1,94 @@
def isBuildModule = rootProject.ext.module.isBuildModule
if (Boolean.valueOf(isBuildModule)) {
apply plugin: 'com.android.application'
} else {
apply plugin: 'com.android.library'
}
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-parcelize'
apply plugin: 'com.google.dagger.hilt.android'
android {
compileSdkVersion rootProject.ext.android.compileSdkVersion
buildToolsVersion rootProject.ext.android.buildToolsVersion
defaultConfig {
minSdkVersion rootProject.ext.android.minSdkVersion
targetSdkVersion rootProject.ext.android.targetSdkVersion
versionCode rootProject.ext.android.versionCode
versionName rootProject.ext.android.versionName
multiDexEnabled true
javaCompileOptions {
annotationProcessorOptions {
arguments += [
"room.schemaLocation":"$projectDir/schemas".toString(),
"room.incremental":"true",
"room.expandProjection":"true",
AROUTER_MODULE_NAME: project.getName()
]
}
}
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
}
buildFeatures {
viewBinding true
}
sourceSets {
main {
if (Boolean.valueOf(isBuildModule)) {
manifest.srcFile 'src/main/module/AndroidManifest.xml'
} else {
manifest.srcFile 'src/main/AndroidManifest.xml'
java {
//排除java/debug文件夹下的所有文件
exclude '*module'
}
}
}
}
}
kapt {
arguments {
arg("AROUTER_MODULE_NAME", project.getName())
}
generateStubs = true
useBuildCache = true
javacOptions {
option("-Xmaxerrs", 500)
}
}
dependencies {
implementation project(":common:common-base")
implementation project(":common:common-service")
kapt rootProject.ext.compiler["arouterCompiler"]
compileOnly(rootProject.ext.jetpack["hilt"])
kapt rootProject.ext.compiler["hiltAndroidCompiler"]
if (Boolean.valueOf(isBuildModule)) {
implementation project(":modules:module-collect")
implementation project(":modules:module-content")
implementation project(":modules:module-login")
}
}
@@ -0,0 +1,2 @@
-keep class com.bbgo.module_sys.bean.** {*;}
@@ -0,0 +1,23 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
-keep class com.bbgo.module_sys.bean.** {*;}
@@ -0,0 +1,24 @@
package com.bbgo.module_sys
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.bbgo.module_sys", appContext.packageName)
}
}
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.bbgo.module_sys">
</manifest>
@@ -0,0 +1,13 @@
package com.bbgo.module_sys
import com.bbgo.common_base.BaseApplication
import dagger.hilt.android.HiltAndroidApp
/**
* @Description:
* @Author: wangyuebin
* @Date: 2021/9/10 5:12 下午
*/
//@HiltAndroidApp
class SysApp : BaseApplication() {
}
@@ -0,0 +1,11 @@
package com.bbgo.module_sys.activity
import com.bbgo.common_base.base.BaseActivity
import com.bbgo.module_sys.R
import com.bbgo.module_sys.databinding.FragmentSysBinding
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class SysMainActivity : BaseActivity<FragmentSysBinding>() {
override fun inflateViewBinding() = FragmentSysBinding.inflate(layoutInflater)
}
@@ -0,0 +1,67 @@
package com.bbgo.module_sys.bean
import androidx.annotation.Keep
@Keep
data class ArticleData(
val curPage: Int,
val datas: MutableList<ArticleDetail>,
val offset: Int,
val over: Boolean,
val pageCount: Int,
val size: Int,
val total: Int
)
@Keep
data class NaviData(
val articles: ArrayList<ArticleDetail>,
val cid: Int,
val name: String,
var isSelected: Boolean
)
@Keep
data class ArticleDetail(
val apkLink: String,
val audit: Int,
val author: String,
val canEdit: Boolean,
val chapterId: Int,
val chapterName: String,
var collect: Boolean,
val courseId: Int,
val desc: String,
val descMd: String,
val envelopePic: String,
val fresh: Boolean,
val host: String,
val id: Int,
val link: String,
val niceDate: String,
val niceShareDate: String,
val origin: String,
val prefix: String,
val projectLink: String,
val publishTime: Long,
val realSuperChapterId: Int,
val selfVisible: Int,
val shareDate: Long,
val shareUser: String,
val superChapterId: Int,
val superChapterName: String,
val tags: List<Tag>,
val title: String,
val type: Int,
val userId: Int,
val visible: Int,
val zan: Int,
var top: String,
)
@Keep
data class Tag(
val name: String,
val url: String
)
@@ -0,0 +1,27 @@
package com.bbgo.module_sys.bean
import androidx.annotation.Keep
@Keep
data class KnowledgeTree(
val children: List<KnowledgeDetail>,
val courseId: Int,
val id: Int,
val name: String,
val order: Int,
val parentChapterId: Int,
val userControlSetTop: Boolean,
val visible: Int
)
@Keep
data class KnowledgeDetail(
val children: List<Any>,
val courseId: Int,
val id: Int,
val name: String,
val order: Int,
val parentChapterId: Int,
val userControlSetTop: Boolean,
val visible: Int
)
@@ -0,0 +1,43 @@
package com.bbgo.module_sys.net.api
import com.bbgo.common_base.bean.HttpResult
import com.bbgo.module_sys.bean.ArticleData
import com.bbgo.module_sys.bean.KnowledgeTree
import com.bbgo.module_sys.bean.NaviData
import kotlinx.coroutines.flow.Flow
import retrofit2.http.GET
import retrofit2.http.Path
import retrofit2.http.Query
/**
* author: wangyb
* date: 4/7/21 9:24 PM
* description: http api
*/
interface HttpSysApiService {
/**
* 获取知识体系
* http://www.wanandroid.com/tree/json
*/
@GET("tree/json")
fun getKnowledgeTree(): Flow<HttpResult<List<KnowledgeTree>>>
/**
* 知识体系下的文章
* http://www.wanandroid.com/article/list/0/json?cid=168
* @param page
* @param cid
*/
@GET("article/list/{page}/json")
fun getKnowledgeList(@Path("page") page: Int, @Query("cid") cid: Int): Flow<HttpResult<ArticleData>>
/**
* 导航数据
* http://www.wanandroid.com/navi/json
*/
@GET("navi/json")
fun getNavigationList(): Flow<HttpResult<List<NaviData>>>
}
@@ -0,0 +1,13 @@
package com.bbgo.module_sys.repository
import dagger.hilt.android.scopes.ActivityRetainedScoped
import javax.inject.Inject
/**
* author: wangyb
* date: 3/30/21 2:36 PM
* description: todo
*/
@ActivityRetainedScoped
class SysLocalRepository @Inject constructor(){
}
@@ -0,0 +1,35 @@
package com.bbgo.module_sys.repository
import com.bbgo.common_base.bean.HttpResult
import com.bbgo.common_base.net.ServiceCreators
import com.bbgo.module_sys.bean.ArticleData
import com.bbgo.module_sys.bean.KnowledgeTree
import com.bbgo.module_sys.bean.NaviData
import com.bbgo.module_sys.net.api.HttpSysApiService
import dagger.hilt.android.scopes.ActivityRetainedScoped
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject
/**
* author: wangyb
* date: 3/30/21 2:35 PM
* description: todo
*/
@ActivityRetainedScoped
class SysRemoteRepository @Inject constructor(){
private val service = ServiceCreators.create(HttpSysApiService::class.java)
fun getKnowledgeTree() : Flow<HttpResult<List<KnowledgeTree>>> {
return service.getKnowledgeTree()
}
fun getKnowledgeList(id: Int, page: Int) : Flow<HttpResult<ArticleData>> {
return service.getKnowledgeList(id, page)
}
fun getNavigationList() : Flow<HttpResult<List<NaviData>>> {
return service.getNavigationList()
}
}
@@ -0,0 +1,30 @@
package com.bbgo.module_sys.repository
import com.bbgo.common_base.bean.HttpResult
import com.bbgo.module_sys.bean.ArticleData
import com.bbgo.module_sys.bean.KnowledgeTree
import com.bbgo.module_sys.bean.NaviData
import dagger.hilt.android.scopes.ActivityRetainedScoped
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject
/**
* author: wangyb
* date: 3/29/21 9:32 PM
* description: todo
*/
@ActivityRetainedScoped
class SysRepository @Inject constructor(private val remoteRepository: SysRemoteRepository, private val localRepository: SysLocalRepository) {
fun getKnowledgeTree() : Flow<HttpResult<List<KnowledgeTree>>> {
return remoteRepository.getKnowledgeTree()
}
fun getKnowledgeList(id: Int, page: Int) : Flow<HttpResult<ArticleData>> {
return remoteRepository.getKnowledgeList(id, page)
}
fun getNavigationList() : Flow<HttpResult<List<NaviData>>> {
return remoteRepository.getNavigationList()
}
}
@@ -0,0 +1,29 @@
package com.bbgo.module_sys.ui
import android.text.Html
import com.bbgo.module_sys.R
import com.bbgo.module_sys.bean.KnowledgeTree
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.module.LoadMoreModule
import com.chad.library.adapter.base.viewholder.BaseViewHolder
/**
* @Description:
* @Author: wangyuebin
* @Date: 2021/8/13 2:47 下午
*/
class KnowledgeTreeAdapter : BaseQuickAdapter<KnowledgeTree, BaseViewHolder>(R.layout.item_knowledge_tree_list),
LoadMoreModule {
override fun convert(holder: BaseViewHolder, item: KnowledgeTree) {
holder.setText(R.id.title_first, item.name)
item.children.let {
holder.setText(
R.id.title_second,
it.joinToString(" ", transform = { child ->
Html.fromHtml(child.name)
})
)
}
}
}
@@ -0,0 +1,110 @@
package com.bbgo.module_sys.ui
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
import com.bbgo.common_base.base.BaseFragment
import com.bbgo.common_base.databinding.LayoutLoadingBinding
import com.bbgo.common_base.ext.Resource
import com.bbgo.common_base.ext.observe
import com.bbgo.common_base.widget.SpaceItemDecoration
import com.bbgo.module_sys.bean.KnowledgeTree
import com.bbgo.module_sys.databinding.FragmentRefreshLayoutBinding
import com.bbgo.module_sys.viewmodel.SysViewModel
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
/**
* Created by wangyb
*/
@AndroidEntryPoint
class KnowledgeTreeFragment : BaseFragment<FragmentRefreshLayoutBinding>() {
companion object {
fun getInstance(): KnowledgeTreeFragment {
return KnowledgeTreeFragment()
}
}
private lateinit var loadingBinding: LayoutLoadingBinding
@Inject
lateinit var sysViewModel: SysViewModel
/**
* datas
*/
private var knowledgeTreeList = mutableListOf<KnowledgeTree>()
/**
* RecyclerView Divider
*/
private val recyclerViewItemDecoration by lazy {
activity?.let {
SpaceItemDecoration(it)
}
}
/**
* LinearLayoutManager
*/
private val linearLayoutManager: LinearLayoutManager by lazy {
LinearLayoutManager(activity)
}
/**
* Adapter
*/
private val mAdapter: KnowledgeTreeAdapter by lazy {
KnowledgeTreeAdapter()
}
override fun initView() {
loadingBinding = LayoutLoadingBinding.bind(binding.root)
binding.swipeRefreshLayout.setColorSchemeResources(
android.R.color.holo_blue_bright,
android.R.color.holo_green_light,
android.R.color.holo_orange_light,
android.R.color.holo_red_light)
binding.swipeRefreshLayout.setOnRefreshListener {
sysViewModel.getKnowledgeTree()
}
binding.recyclerView.run {
layoutManager = linearLayoutManager
adapter = mAdapter
itemAnimator = DefaultItemAnimator()
recyclerViewItemDecoration?.let { addItemDecoration(it) }
}
}
override fun lazyLoad() {
sysViewModel.getKnowledgeTree()
}
override fun observe() {
observe(sysViewModel.treeLiveData, ::handleInfo)
}
private fun handleInfo(status: Resource<List<KnowledgeTree>>) {
when(status) {
is Resource.Loading -> {
loadingBinding.progressBar.visibility = View.VISIBLE
}
is Resource.Success -> {
loadingBinding.progressBar.visibility = View.GONE
binding.swipeRefreshLayout.isRefreshing = false
knowledgeTreeList.clear()
knowledgeTreeList.addAll(status.data)
mAdapter.setList(knowledgeTreeList)
}
}
}
override fun inflateViewBinding(
inflater: LayoutInflater,
container: ViewGroup?
) = FragmentRefreshLayoutBinding.inflate(inflater, container, false)
}
@@ -0,0 +1,29 @@
package com.bbgo.module_sys.ui
import android.widget.TextView
import com.bbgo.module_sys.R
import com.bbgo.module_sys.bean.NaviData
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
/**
* Created by wangyb on 2019/4/28 17:44
*/
class LeftNaviAdapter(listData: ArrayList<NaviData>) :
BaseQuickAdapter<NaviData, BaseViewHolder>(R.layout.item_navi, listData) {
/**
* kotlin中函数作为参数,不用再写接口
*/
private lateinit var mOnItemSelectListener: (postion: Int) -> Unit
fun setOnItemSelectListener(listener: (postion: Int) -> Unit) {
mOnItemSelectListener = listener
}
override fun convert(holder: BaseViewHolder, item: NaviData) {
holder.setText(R.id.tv_title, item.name)
holder.getView<TextView>(R.id.tv_title).isSelected = item.isSelected
}
}
@@ -0,0 +1,33 @@
package com.bbgo.module_sys.ui
import android.graphics.Color
import android.widget.TextView
import com.bbgo.module_sys.R
import com.bbgo.module_sys.bean.ArticleDetail
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import java.util.*
/**
* Created by wangyb on 2019/4/28 17:44
*/
class NaviTagAdapter(listData: ArrayList<ArticleDetail>) :
BaseQuickAdapter<ArticleDetail, BaseViewHolder>(R.layout.layout_navi_tag, listData) {
override fun convert(holder: BaseViewHolder, item: ArticleDetail) {
val mNaviTagView = holder.getView<TextView>(R.id.tv_navi_tag)
mNaviTagView.text = item.title
mNaviTagView.setTextColor(randomColor())
}
private fun randomColor(): Int {
val random = Random()
val red = random.nextInt(150) + 50//50-199
val green = random.nextInt(150) + 50//50-199
val blue = random.nextInt(150) + 50//50-199
return Color.rgb(red, green, blue)
}
}
@@ -0,0 +1,142 @@
package com.bbgo.module_sys.ui
import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.bbgo.common_base.base.BaseFragment
import com.bbgo.common_base.databinding.LayoutLoadingBinding
import com.bbgo.common_base.ext.Resource
import com.bbgo.common_base.ext.observe
import com.bbgo.module_sys.bean.NaviData
import com.bbgo.module_sys.databinding.FragmentNavigationBinding
import com.bbgo.module_sys.viewmodel.SysViewModel
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
/**
* Created by wangyb
*/
@AndroidEntryPoint
class NavigationFragment : BaseFragment<FragmentNavigationBinding>() {
companion object {
fun getInstance(): NavigationFragment {
return NavigationFragment()
}
}
private lateinit var loadingBinding: LayoutLoadingBinding
@Inject
lateinit var sysViewModel: SysViewModel
private var currentPosition = 0
private var naviList = ArrayList<NaviData>()
private val naviLayoutManager by lazy {
LinearLayoutManager(activity, RecyclerView.VERTICAL, false)
}
private val naviContentLayoutManager by lazy {
LinearLayoutManager(activity, RecyclerView.VERTICAL, false)
}
private val mAdapter by lazy {
LeftNaviAdapter(naviList)
}
private val contentAdapter by lazy {
RightNaviAdapter(naviList)
}
@SuppressLint("NotifyDataSetChanged")
override fun initView() {
loadingBinding = LayoutLoadingBinding.bind(binding.root)
binding.refreshLayout.setColorSchemeResources(
android.R.color.holo_blue_bright,
android.R.color.holo_green_light,
android.R.color.holo_orange_light,
android.R.color.holo_red_light)
binding.refreshLayout.setOnRefreshListener {
binding.refreshLayout.isRefreshing = false
contentAdapter.notifyDataSetChanged()
}
binding.rvNavi.layoutManager = naviLayoutManager
binding.rvNavi.adapter = mAdapter
binding.rvNaviDetail.layoutManager = naviContentLayoutManager
binding.rvNaviDetail.adapter = contentAdapter
mAdapter.setOnItemClickListener { _, _, position ->
selectItem(position)
moveToCenter(position)
naviContentLayoutManager.scrollToPositionWithOffset(position, 0)
}
binding.rvNaviDetail.addOnScrollListener(object : RecyclerView.OnScrollListener(){
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
val itemPosition = naviContentLayoutManager.findFirstVisibleItemPosition()
if (currentPosition != itemPosition) {
selectItem(itemPosition)
moveToCenter(itemPosition)
}
}
})
}
override fun lazyLoad() {
sysViewModel.getNavigationList()
}
override fun observe() {
observe(sysViewModel.naviLiveData, ::handleInfo)
}
private fun handleInfo(status: Resource<List<NaviData>>) {
when(status) {
is Resource.Loading -> {
loadingBinding.progressBar.visibility = View.VISIBLE
}
is Resource.Success -> {
loadingBinding.progressBar.visibility = View.GONE
naviList.clear()
naviList.addAll(status.data)
naviList[0].isSelected = true // 默认第一个被选中
contentAdapter.setList(naviList)
mAdapter.setList(naviList)
}
}
}
private fun selectItem(position: Int) {
if (position < 0 || naviList.size < position) {
return
}
naviList[currentPosition].isSelected = false
mAdapter.notifyItemChanged(currentPosition)
currentPosition = position
naviList[position].isSelected = true
mAdapter.notifyItemChanged(position)
}
private fun moveToCenter(position: Int) {
//将点击的position转换为当前屏幕上可见的item的位置以便于计算距离顶部的高度,从而进行移动居中
val viewAt = binding.rvNavi.getChildAt(position - naviLayoutManager.findFirstVisibleItemPosition())
if (viewAt != null) {
val y = viewAt.top - binding.rvNavi.height / 2
binding.rvNavi.smoothScrollBy(0, y)
}
}
override fun inflateViewBinding(
inflater: LayoutInflater,
container: ViewGroup?
) = FragmentNavigationBinding.inflate(inflater, container, false)
}
@@ -0,0 +1,32 @@
package com.bbgo.module_sys.ui
import androidx.recyclerview.widget.RecyclerView
import com.bbgo.common_base.BaseApplication
import com.bbgo.module_sys.R
import com.bbgo.module_sys.bean.NaviData
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import com.google.android.flexbox.*
/**
* Created by wangyb on 2019/4/28 17:44
*/
class RightNaviAdapter(listData: ArrayList<NaviData>) :
BaseQuickAdapter<NaviData, BaseViewHolder>(R.layout.item_navi_content, listData) {
override fun convert(holder: BaseViewHolder, item: NaviData) {
holder.setText(R.id.navi_content_name, item.name)
if (!item.articles.isNullOrEmpty()) {
val flexBoxLayoutManager = FlexboxLayoutManager(BaseApplication.getContext())
flexBoxLayoutManager.flexWrap = FlexWrap.WRAP //按正常方向换行
flexBoxLayoutManager.flexDirection = FlexDirection.ROW //主轴为水平方向,起点在左端
flexBoxLayoutManager.alignItems = AlignItems.CENTER //定义项目在副轴轴上如何对齐
flexBoxLayoutManager.justifyContent = JustifyContent.FLEX_START //多个轴对齐方式
val mRecyclerView = holder.getView<RecyclerView>(R.id.navi_content_tag_rv)
mRecyclerView.layoutManager = flexBoxLayoutManager
mRecyclerView.adapter = NaviTagAdapter(item.articles)
}
}
}
@@ -0,0 +1,56 @@
package com.bbgo.module_sys.ui
import android.view.LayoutInflater
import android.view.ViewGroup
import com.alibaba.android.arouter.facade.annotation.Route
import com.bbgo.common_base.base.BaseFragment
import com.bbgo.common_base.constants.RouterPath
import com.bbgo.common_base.ext.viewBinding
import com.bbgo.module_sys.R
import com.bbgo.module_sys.databinding.FragmentNavigationBinding
import com.bbgo.module_sys.databinding.FragmentSysBinding
import com.google.android.material.tabs.TabLayoutMediator
import dagger.hilt.android.AndroidEntryPoint
/**
* author: wangyb
* date: 2021/5/20 3:04 下午
* description: todo
*/
@Route(path = RouterPath.Sys.PAGE_SYS)
@AndroidEntryPoint
class SysFragment : BaseFragment<FragmentSysBinding>() {
private val titleList = mutableListOf<String>()
/**
* ViewPagerAdapter
*/
private val viewPagerAdapter: SysPagerAdapter by lazy {
SysPagerAdapter(this)
}
override fun lazyLoad() {
}
override fun observe() {
}
override fun initView() {
titleList.add(getString(R.string.knowledge_system))
titleList.add(getString(R.string.navigation))
binding.viewPager.adapter = viewPagerAdapter
TabLayoutMediator(binding.tabLayout, binding.viewPager, true, true) { tab, position ->
tab.text = titleList[position]
}.attach()
}
companion object {
private const val TAG = "SysFragment"
}
override fun inflateViewBinding(
inflater: LayoutInflater,
container: ViewGroup?
) = FragmentSysBinding.inflate(inflater, container, false)
}
@@ -0,0 +1,24 @@
package com.bbgo.module_sys.ui
import androidx.fragment.app.Fragment
import androidx.viewpager2.adapter.FragmentStateAdapter
class SysPagerAdapter(fm: Fragment) : FragmentStateAdapter(fm) {
private val fragments = mutableListOf<Fragment>()
init {
fragments.add(KnowledgeTreeFragment.getInstance())
fragments.add(NavigationFragment.getInstance())
}
override fun getItemCount(): Int {
return fragments.size
}
override fun createFragment(position: Int): Fragment {
return fragments[position]
}
}
@@ -0,0 +1,74 @@
package com.bbgo.module_sys.viewmodel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.bbgo.common_base.ext.HTTP_REQUEST_ERROR
import com.bbgo.common_base.ext.Resource
import com.bbgo.common_base.util.log.Logs
import com.bbgo.module_sys.bean.KnowledgeTree
import com.bbgo.module_sys.bean.NaviData
import com.bbgo.module_sys.repository.SysRepository
import dagger.hilt.android.scopes.ActivityRetainedScoped
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import javax.inject.Inject
/**
* author: wangyb
* date: 3/29/21 9:31 PM
* description: todo
*/
@ActivityRetainedScoped
class SysViewModel @Inject constructor(private val repository: SysRepository) : ViewModel() {
private val TAG = "SysViewModel"
val treeLiveData = MutableLiveData<Resource<List<KnowledgeTree>>>()
val naviLiveData = MutableLiveData<Resource<List<NaviData>>>()
fun getKnowledgeTree() = viewModelScope.launch {
/**
* 1.必须要有异常处理
* 2.必须要有collect,否则map里面的代码不执行
*/
repository.getKnowledgeTree()
.map {
if (it.errorCode == HTTP_REQUEST_ERROR) {
Resource.Error(Exception(it.errorMsg))
} else {
Resource.Success(it.data)
}
}
.catch {
Logs.e(TAG, it.message, it)
}
.collectLatest {
treeLiveData.value = it
}
}
fun getNavigationList() = viewModelScope.launch {
/**
* 1.必须要有异常处理
* 2.必须要有collect,否则map里面的代码不执行
*/
repository.getNavigationList()
.map {
if (it.errorCode == HTTP_REQUEST_ERROR) {
Resource.Error(Exception(it.errorMsg))
} else {
Resource.Success(it.data)
}
}
.catch {
Logs.e(TAG, it.message, it)
}
.collectLatest {
naviLiveData.value = it
}
}
}
@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.bbgo.module_sys">
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <!-- 配置权限,用来记录应用配置信息 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- 重力加速度传感器权限 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <!-- Android8.0安装apk需要请求安装权限 -->
<uses-permission android:name="android.permission.VIBRATE" /> <!-- 小米push -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.REORDER_TASKS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.hardware.sensor.accelerometer" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<application
android:name=".SysApp"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".activity.SysMainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
@@ -0,0 +1,30 @@
<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="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke android:color="@color/Red"
android:width="@dimen/dp_05"/>
<corners android:radius="@dimen/dp_2" />
</shape>
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke
android:width="@dimen/dp_05"
android:color="@color/colorAccent" />
<corners android:radius="@dimen/dp_2" />
</shape>
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="@color/arrow_color"
android:pathData="M10,6L8.59,7.41 13.17,12l-4.58,4.59L10,18l6,-6z"/>
</vector>
@@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>
@@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#00BCD4"
android:alpha="0.8">
<path
android:fillColor="@android:color/white"
android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z"/>
</vector>
@@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#9E9E9E"
android:alpha="0.8">
<path
android:fillColor="@android:color/white"
android:pathData="M22,9.24l-7.19,-0.62L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21 12,17.27 18.18,21l-1.63,-7.03L22,9.24zM12,15.4l-3.76,2.27 1,-4.28 -3.32,-2.88 4.38,-0.38L12,6.1l1.71,4.04 4.38,0.38 -3.32,2.88 1,4.28L12,15.4z"/>
</vector>
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/transparent" android:state_selected="true" />
<item android:drawable="@color/Grey100" />
</selector>
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/colorAccent" android:state_selected="true" />
<item android:color="@color/colorContent" />
</selector>
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<corners android:radius="15dp" />
<solid android:color="@color/color_page_bg" />
<padding
android:bottom="5dp"
android:left="15dp"
android:right="15dp"
android:top="5dp" />
</shape>
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:name="com.bbgo.module_sys.ui.SysFragment"
android:layout_width="match_parent"
android:layout_height="match_parent">
</fragment>
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/refresh_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_navi"
android:layout_width="0dp"
android:layout_height="match_parent"
android:scrollbars="none"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.3" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_navi_detail"
android:layout_width="0dp"
android:layout_height="match_parent"
android:scrollbars="vertical"
app:layout_constraintLeft_toRightOf="@id/rv_navi"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.7" />
<include layout="@layout/layout_loading" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/viewBackground">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
style="@style/RecyclerViewStyle"
tools:listitem="@layout/item_refresh_list"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent" />
<include layout="@layout/layout_loading" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/viewBackground"
android:orientation="vertical">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
style="@style/MyTabLayoutStyle"
android:theme="@style/AppTheme.AppBarOverlay"
android:layout_height="0dp"
app:tabGravity="center"
app:tabMode="scrollable"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintHeight_percent="0.06" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="horizontal"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
app:layout_constraintTop_toBottomOf="@id/tabLayout"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintHeight_percent="0.94"/>
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/cardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:foreground="?attr/selectableItemBackground"
app:cardBackgroundColor="@color/viewBackground"
app:cardCornerRadius="@dimen/dp_1"
app:cardElevation="@dimen/dp_1">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_margin="@dimen/dp_10"
android:layout_toLeftOf="@+id/imageView"
android:layout_toStartOf="@+id/imageView"
android:gravity="start"
android:orientation="vertical">
<TextView
android:id="@+id/title_first"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/item_title"
android:textSize="@dimen/sp_16"
tools:text="@string/app_name" />
<TextView
android:id="@+id/title_second"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_10"
android:textColor="@color/item_desc"
tools:text="Android Studio相关 gradle 官方发布" />
</LinearLayout>
<ImageView
android:id="@+id/imageView"
android:layout_width="@dimen/dp_24"
android:layout_height="@dimen/dp_24"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="@dimen/dp_10"
app:srcCompat="@drawable/ic_arrow_right_24dp" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
@@ -0,0 +1,16 @@
<?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:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/select_navi_bg"
android:padding="8dp"
android:textColor="@drawable/select_navi_text"
android:textSize="14sp"
tools:text="常用网站"/>
</LinearLayout>
@@ -0,0 +1,26 @@
<?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:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/navi_content_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:textColor="@color/colorTabText"
android:textSize="15sp"
android:textStyle="bold"
tools:text="网址导航" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/navi_content_tag_rv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="17dp"
android:layout_marginEnd="10dp"
android:background="@color/White" />
</LinearLayout>
@@ -0,0 +1,152 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/cardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:foreground="?attr/selectableItemBackground"
app:cardBackgroundColor="@color/viewBackground"
app:cardCornerRadius="@dimen/dp_1"
app:cardElevation="@dimen/dp_1">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/item_content_padding"
android:paddingRight="@dimen/item_content_padding"
android:paddingBottom="@dimen/item_content_padding">
<TextView
android:id="@+id/tv_article_top"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dp_10"
android:background="@drawable/bg_fresh"
android:paddingLeft="@dimen/dp_4"
android:paddingTop="@dimen/dp_2"
android:paddingRight="@dimen/dp_4"
android:paddingBottom="@dimen/dp_2"
android:text="@string/top_tip"
android:textColor="@color/Red"
android:textSize="@dimen/sp_10"
android:visibility="gone"
tools:visibility="visible" />
<TextView
android:id="@+id/tv_article_fresh"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dp_10"
android:layout_toRightOf="@+id/tv_article_top"
android:background="@drawable/bg_fresh"
android:paddingLeft="@dimen/dp_4"
android:paddingTop="@dimen/dp_2"
android:paddingRight="@dimen/dp_4"
android:paddingBottom="@dimen/dp_2"
android:text="@string/new_fresh"
android:textColor="@color/Red"
android:textSize="@dimen/sp_10"
android:visibility="gone"
tools:visibility="visible" />
<TextView
android:id="@+id/tv_article_tag"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dp_10"
android:layout_toRightOf="@+id/tv_article_fresh"
android:background="@drawable/bg_tag"
android:paddingLeft="@dimen/dp_4"
android:paddingTop="@dimen/dp_2"
android:paddingRight="@dimen/dp_4"
android:paddingBottom="@dimen/dp_2"
android:textColor="@color/colorAccent"
android:textSize="@dimen/sp_10"
android:visibility="gone"
tools:text="@string/app_name"
tools:visibility="visible" />
<TextView
android:id="@+id/tv_article_author"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/tv_article_top"
android:layout_marginLeft="@dimen/dp_10"
android:layout_toRightOf="@+id/tv_article_tag"
android:textColor="@color/item_author"
android:textSize="@dimen/item_tv_author"
tools:text="@string/app_name" />
<TextView
android:id="@+id/tv_article_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/tv_article_top"
android:layout_alignParentRight="true"
android:textColor="@color/item_date"
android:textSize="@dimen/item_tv_date"
tools:text="@string/app_name" />
<ImageView
android:id="@+id/iv_article_thumbnail"
android:layout_width="@dimen/item_img_width"
android:layout_height="@dimen/item_img_height"
android:layout_below="@+id/tv_article_author"
android:layout_marginLeft="@dimen/dp_10"
android:layout_marginTop="@dimen/dp_8"
android:scaleType="centerCrop" />
<TextView
android:id="@+id/tv_article_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_article_author"
android:layout_marginLeft="@dimen/dp_10"
android:layout_marginTop="@dimen/dp_8"
android:layout_toRightOf="@+id/iv_article_thumbnail"
android:ellipsize="end"
android:gravity="top|start"
android:lineSpacingExtra="2dp"
android:maxLines="2"
android:paddingBottom="@dimen/dp_6"
android:textColor="@color/item_title"
android:textSize="@dimen/item_tv_title" />
<TextView
android:id="@+id/tv_article_chapterName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_article_title"
android:layout_alignParentBottom="true"
android:layout_marginStart="@dimen/dp_10"
android:layout_marginLeft="@dimen/dp_10"
android:layout_marginTop="@dimen/dp_10"
android:layout_marginEnd="@dimen/dp_10"
android:layout_marginRight="@dimen/dp_10"
android:layout_toRightOf="@+id/iv_article_thumbnail"
android:gravity="center"
android:textColor="@color/item_chapter"
android:textSize="@dimen/item_tv_tag"
tools:text="@string/app_name" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:orientation="horizontal">
<ImageView
android:id="@+id/iv_like"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_like_not" />
</LinearLayout>
</RelativeLayout>
</androidx.cardview.widget.CardView>
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/tv_navi_tag"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:background="@drawable/shape_navi_tag"
android:textColor="@color/colorTabText"
android:textSize="12sp"
android:gravity="center"
tools:text="title"/>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/colorPrimary"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,16 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.WanAndroid" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_200</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/black</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_200</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<!--tag标签栏文字的颜色-->
<color name="colorTabText">#585858</color>
<color name="colorSmallRed">#faebeb</color>
<color name="color_page_bg">#F1F3F4</color>
<color name="transparent">#00000000</color>
<color name="backgroundColor">#CCFFFFFF</color>
<color name="colorContent">#ff333333</color>
</resources>
@@ -0,0 +1,9 @@
<resources>
<string name="app_name">体系模块</string>
<string name="knowledge_system">体系</string>
<string name="navigation">导航</string>
<string name="collect_success">收藏成功</string>
<string name="cancel_collect_success">已取消收藏</string>
<string name="new_fresh"></string>
<string name="top_tip">置顶</string>
</resources>
@@ -0,0 +1,16 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.WanAndroid" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>
@@ -0,0 +1,17 @@
package com.bbgo.module_sys
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}