Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
android_vedio
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
android
android_vedio
Commits
cda8590c
Commit
cda8590c
authored
Aug 14, 2023
by
mengcuiguang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
代码优化
parent
4e0cc1f4
Changes
41
Hide whitespace changes
Inline
Side-by-side
Showing
41 changed files
with
2732 additions
and
71 deletions
+2732
-71
build.gradle
video/app/build.gradle
+1
-0
MintsApplication.java
...rc/main/java/com/duben/happyplaylet/MintsApplication.java
+2
-2
MainTypeAdapter.kt
...java/com/duben/happyplaylet/ui/adapter/MainTypeAdapter.kt
+51
-0
MainFragment.kt
...n/java/com/duben/happyplaylet/ui/fragment/MainFragment.kt
+25
-42
fragment_main.xml
video/app/src/main/res/layout/fragment_main.xml
+11
-15
item_video_tab.xml
video/app/src/main/res/layout/item_video_tab.xml
+20
-11
gradle.properties
video/gradle.properties
+1
-1
build.gradle
video/library_tagflow/build.gradle
+40
-0
consumer-rules.pro
video/library_tagflow/consumer-rules.pro
+0
-0
proguard-rules.pro
video/library_tagflow/proguard-rules.pro
+21
-0
AndroidManifest.xml
video/library_tagflow/src/main/AndroidManifest.xml
+4
-0
GridLayoutItemDecoration.kt
...in/java/com/framework/tagflow/GridLayoutItemDecoration.kt
+73
-0
MultiTagFlowLayout.kt
...src/main/java/com/framework/tagflow/MultiTagFlowLayout.kt
+975
-0
BaseTagAdapter.kt
...main/java/com/framework/tagflow/adapter/BaseTagAdapter.kt
+78
-0
BaseTagBean.kt
...w/src/main/java/com/framework/tagflow/bean/BaseTagBean.kt
+46
-0
OnTagClickListener.kt
...java/com/framework/tagflow/interfac/OnTagClickListener.kt
+14
-0
OnTagSelectedListener.kt
...a/com/framework/tagflow/interfac/OnTagSelectedListener.kt
+15
-0
ColorfulStrokeTagView.kt
.../java/com/framework/tagflow/tags/ColorfulStrokeTagView.kt
+31
-0
ColorfulTagView.kt
...c/main/java/com/framework/tagflow/tags/ColorfulTagView.kt
+32
-0
DefaultTagView.kt
...rc/main/java/com/framework/tagflow/tags/DefaultTagView.kt
+136
-0
MutSelectedTagView.kt
...ain/java/com/framework/tagflow/tags/MutSelectedTagView.kt
+69
-0
StrokeTagView.kt
...src/main/java/com/framework/tagflow/tags/StrokeTagView.kt
+39
-0
DensityUtils.kt
...src/main/java/com/framework/tagflow/utils/DensityUtils.kt
+70
-0
ControlScrollView.kt
...main/java/com/framework/tagflow/view/ControlScrollView.kt
+57
-0
FlowLayout.kt
...ow/src/main/java/com/framework/tagflow/view/FlowLayout.kt
+256
-0
common_icon_down_arrow.png
...ow/src/main/res/drawable-xhdpi/common_icon_down_arrow.png
+0
-0
tag_flow_layout_arrow_bg.xml
.../src/main/res/drawable-xhdpi/tag_flow_layout_arrow_bg.xml
+8
-0
toast_background.xml
..._tagflow/src/main/res/drawable-xhdpi/toast_background.xml
+5
-0
common_bg_radius_15_white.xml
...gflow/src/main/res/drawable/common_bg_radius_15_white.xml
+6
-0
common_bg_radius_white.xml
..._tagflow/src/main/res/drawable/common_bg_radius_white.xml
+6
-0
common_icon_down_arrow.png
..._tagflow/src/main/res/drawable/common_icon_down_arrow.png
+0
-0
tag_flow_layout_arrow_bg.xml
...agflow/src/main/res/drawable/tag_flow_layout_arrow_bg.xml
+8
-0
toast_background.xml
...ibrary_tagflow/src/main/res/drawable/toast_background.xml
+5
-0
custom_toast.xml
video/library_tagflow/src/main/res/layout/custom_toast.xml
+18
-0
layout_empty_not_data.xml
...ary_tagflow/src/main/res/layout/layout_empty_not_data.xml
+28
-0
tag_flow_layout.xml
...o/library_tagflow/src/main/res/layout/tag_flow_layout.xml
+71
-0
attrs.xml
video/library_tagflow/src/main/res/values/attrs.xml
+28
-0
colors.xml
video/library_tagflow/src/main/res/values/colors.xml
+57
-0
dimens.xml
video/library_tagflow/src/main/res/values/dimens.xml
+417
-0
strings.xml
video/library_tagflow/src/main/res/values/strings.xml
+7
-0
settings.gradle
video/settings.gradle
+1
-0
No files found.
video/app/build.gradle
View file @
cda8590c
...
...
@@ -228,6 +228,7 @@ dependencies {
api
project
(
':wxpay'
)
api
project
(
':alipay'
)
api
project
(
':oaid'
)
api
project
(
':library_tagflow'
)
implementation
'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.4'
// bugly
implementation
'com.tencent.bugly:crashreport:3.3.92'
...
...
video/app/src/main/java/com/duben/happyplaylet/MintsApplication.java
View file @
cda8590c
...
...
@@ -56,8 +56,8 @@ public class MintsApplication extends MultiDexApplication {
// 友盟SDK预初始化函数
// preInit预初始化函数耗时极少,不会影响App首次冷启动用户体验
UmengManager
.
INSTANCE
.
preInit
(
this
,
MateUtils
.
INSTANCE
.
getAppMetaData
(
this
,
"CHANNEL_NAME"
));
//
UmengManager.INSTANCE.preInit(this,
//
MateUtils.INSTANCE.getAppMetaData(this, "CHANNEL_NAME"));
// 判断应用是否在前台
ForegroundOrBackground
.
init
(
this
);
...
...
video/app/src/main/java/com/duben/happyplaylet/ui/adapter/MainTypeAdapter.kt
0 → 100755
View file @
cda8590c
package
com.duben.happyplaylet.ui.adapter
import
android.annotation.SuppressLint
import
android.app.Activity
import
android.view.LayoutInflater
import
android.view.View
import
android.view.ViewGroup
import
android.widget.TextView
import
androidx.core.content.ContextCompat
import
com.duben.happyplaylet.R
import
com.duben.happyplaylet.mvp.model.HotStyleTypesBean
import
com.framework.tagflow.adapter.BaseTagAdapter
@SuppressLint
(
"ViewHolder"
)
class
MainTypeAdapter
(
private
val
mActivity
:
Activity
)
:
BaseTagAdapter
<
HotStyleTypesBean
?
>()
{
var
currentCheckedItemPosition
=
0
override
fun
getView
(
position
:
Int
,
convertView
:
View
?,
parent
:
ViewGroup
):
View
{
val
view
=
LayoutInflater
.
from
(
mActivity
).
inflate
(
R
.
layout
.
item_video_tab
,
parent
,
false
)
val
textView
:
TextView
=
view
.
findViewById
<
TextView
>(
R
.
id
.
item_tv
)
val
bean
=
getItem
(
position
)
if
(
bean
!=
null
)
{
if
(
position
%
2
==
0
){
textView
.
text
=
bean
.
type
}
else
{
textView
.
text
=
bean
.
type
+
"testtesttesttest"
}
}
if
(
currentCheckedItemPosition
==
position
)
{
textView
.
setTextColor
(
ContextCompat
.
getColor
(
mActivity
,
R
.
color
.
red
))
}
else
{
textView
.
setTextColor
(
ContextCompat
.
getColor
(
mActivity
,
R
.
color
.
color_8D8F90
))
}
return
view
}
fun
setCheck
(
position
:
Int
)
{
currentCheckedItemPosition
=
position
notifyDataSetChanged
()
}
}
\ No newline at end of file
video/app/src/main/java/com/duben/happyplaylet/ui/fragment/MainFragment.kt
View file @
cda8590c
...
...
@@ -11,10 +11,6 @@ import androidx.core.content.ContextCompat
import
androidx.recyclerview.widget.LinearLayoutManager
import
androidx.recyclerview.widget.RecyclerView
import
androidx.viewpager2.widget.ViewPager2
import
com.google.android.material.tabs.TabLayout
import
com.google.android.material.tabs.TabLayoutMediator
import
com.scwang.smartrefresh.layout.api.RefreshLayout
import
com.scwang.smartrefresh.layout.listener.OnRefreshListener
import
com.duben.happyplaylet.R
import
com.duben.happyplaylet.ad.AdManager
import
com.duben.happyplaylet.ad.banner.BannerManager
...
...
@@ -27,11 +23,11 @@ import com.duben.happyplaylet.mvp.model.*
import
com.duben.happyplaylet.mvp.presenters.HomePresenter
import
com.duben.happyplaylet.mvp.views.HomeView
import
com.duben.happyplaylet.ui.activitys.NineActivity
import
com.duben.happyplaylet.ui.activitys.NinePayActivity
import
com.duben.happyplaylet.ui.activitys.RecommendActivity
import
com.duben.happyplaylet.ui.activitys.VipActivity
import
com.duben.happyplaylet.ui.adapter.HomeVideoPageAdapter
import
com.duben.happyplaylet.ui.adapter.ImageTitleAdapter
import
com.duben.happyplaylet.ui.adapter.MainTypeAdapter
import
com.duben.happyplaylet.ui.adapter.TopAdapter
import
com.duben.happyplaylet.ui.fragment.base.LazyLoadBaseFragment
import
com.duben.happyplaylet.utils.AppPreferencesManager
...
...
@@ -39,6 +35,10 @@ import com.duben.happyplaylet.utils.SpanUtils
import
com.duben.library.utils.GlideUtils
import
com.duben.library.utils.json.JsonUtil
import
com.duben.library.utils.nodoubleclick.AntiShake
import
com.framework.tagflow.interfac.OnTagClickListener
import
com.google.android.material.tabs.TabLayout
import
com.scwang.smartrefresh.layout.api.RefreshLayout
import
com.scwang.smartrefresh.layout.listener.OnRefreshListener
import
kotlinx.android.synthetic.main.fragment_main.*
import
java.lang.reflect.Field
import
java.util.*
...
...
@@ -52,7 +52,7 @@ import kotlin.concurrent.schedule
class
MainFragment
:
LazyLoadBaseFragment
(),
HomeView
,
View
.
OnClickListener
,
OnRefreshListener
{
companion
object
{
var
mSelectTabIndex
=
-
1
var
mSelectTabIndex
=
0
}
private
val
tabsData
=
mutableListOf
<
HotStyleTypesBean
>()
...
...
@@ -201,45 +201,10 @@ class MainFragment : LazyLoadBaseFragment(), HomeView, View.OnClickListener, OnR
vpAdapter
=
HomeVideoPageAdapter
(
tabsData
,
this
)
vp2
.
adapter
=
vpAdapter
vp2
.
desensitization
()
TabLayoutMediator
(
tablayout
,
vp2
)
{
tab
,
position
->
// 初始化Tab
tab
.
id
=
position
if
(
tabsData
.
size
>
0
)
{
tab
.
customView
=
getTabView
(
tabsData
[
position
].
type
)
}
}.
attach
()
tablayout
.
addOnTabSelectedListener
(
object
:
TabLayout
.
OnTabSelectedListener
{
override
fun
onTabSelected
(
tab
:
TabLayout
.
Tab
?)
{
updateTab
(
tab
,
true
)
mSelectTabIndex
=
tab
!!
.
id
}
override
fun
onTabUnselected
(
tab
:
TabLayout
.
Tab
?)
{
updateTab
(
tab
,
false
)
}
override
fun
onTabReselected
(
tab
:
TabLayout
.
Tab
?)
{
}
})
vp2
.
offscreenPageLimit
=
100
}
private
fun
updateTab
(
tab
:
TabLayout
.
Tab
?,
isSelected
:
Boolean
)
{
tab
?.
customView
?.
let
{
val
text
=
it
.
findViewById
<
TextView
>(
R
.
id
.
item_tv
)
if
(
isSelected
)
{
text
.
setTextColor
(
ContextCompat
.
getColor
(
requireContext
(),
R
.
color
.
red
))
}
else
{
text
.
setTextColor
(
ContextCompat
.
getColor
(
requireContext
(),
R
.
color
.
color_8D8F90
))
}
}
}
private
fun
getTabView
(
text
:
String
):
View
{
val
view
=
LayoutInflater
.
from
(
requireContext
()).
inflate
(
R
.
layout
.
item_video_tab
,
null
)
view
.
findViewById
<
TextView
>(
R
.
id
.
item_tv
).
text
=
text
return
view
vp2
.
isUserInputEnabled
=
false
}
override
fun
onRefresh
(
refreshLayout
:
RefreshLayout
)
{
...
...
@@ -287,6 +252,24 @@ class MainFragment : LazyLoadBaseFragment(), HomeView, View.OnClickListener, OnR
mSelectTabIndex
=
0
vpAdapter
?.
notifyDataSetChanged
()
}
val
mainTypeAdapter
=
MainTypeAdapter
(
requireActivity
())
if
(
tabsData
.
size
>
0
)
{
for
(
index
in
0
..
tabsData
.
size
-
1
)
{
mainTypeAdapter
.
addData
(
tabsData
.
get
(
index
))
}
}
multiFlowTagSelf
.
setAdapter
(
mainTypeAdapter
)
multiFlowTagSelf
.
setOnTagClickListener
(
object
:
OnTagClickListener
{
override
fun
onClick
(
view
:
View
?,
position
:
Int
)
{
mSelectTabIndex
=
position
vp2
.
setCurrentItem
(
mSelectTabIndex
,
false
)
mainTypeAdapter
.
setCheck
(
position
)
}
override
fun
onLongClick
(
view
:
View
?,
position
:
Int
)
{
}
})
}
override
fun
topTabsSuc
(
data
:
BannerList
?)
{
...
...
video/app/src/main/res/layout/fragment_main.xml
View file @
cda8590c
...
...
@@ -121,21 +121,16 @@
</com.google.android.material.appbar.CollapsingToolbarLayout>
<com.google.android.material.tabs.TabLayout
android:id=
"@+id/tablayout"
android:layout_width=
"wrap_content"
android:layout_height=
"38dp"
android:layout_marginLeft=
"10dp"
android:layout_marginRight=
"10dp"
android:paddingTop=
"-10dp"
app:tabBackground=
"@null"
app:tabIndicatorHeight=
"0dp"
app:tabMaxWidth=
"200dp"
app:tabMinWidth=
"20dp"
app:tabMode=
"scrollable"
app:tabPaddingEnd=
"6dp"
app:tabPaddingStart=
"6dp"
app:tabRippleColor=
"@null"
/>
<com.framework.tagflow.MultiTagFlowLayout
android:layout_marginLeft=
"16dp"
android:layout_marginRight=
"16dp"
android:id=
"@+id/multiFlowTagSelf"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
app:hasMore=
"true"
app:layout_type=
"FlowLayout"
app:tagsHorizontalSpace=
"@dimen/dp_5"
app:tagsVerticalSpace=
"@dimen/dp_5"
/>
</com.google.android.material.appbar.AppBarLayout>
...
...
@@ -159,6 +154,7 @@
</LinearLayout>
<LinearLayout
android:visibility=
"gone"
android:id=
"@+id/ll_main_watching_root"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
...
...
video/app/src/main/res/layout/item_video_tab.xml
View file @
cda8590c
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:tools=
"http://schemas.android.com/tools"
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
android:id=
"@+id/constraint_layout"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:orientation=
"vertical"
>
android:layout_gravity=
"center_vertical|center_horizontal"
android:layout_margin=
"@dimen/dp_8"
android:background=
"@drawable/common_bg_radius_15_white"
android:paddingLeft=
"16dp"
android:paddingTop=
"4dp"
android:paddingRight=
"16dp"
android:paddingBottom=
"4dp"
>
<TextView
android:id=
"@+id/item_tv"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:paddingLeft=
"2dp"
android:paddingTop=
"6dp"
android:paddingRight=
"5dp"
android:paddingBottom=
"6dp"
android:textColor=
"@color/color_8D8F90"
android:textSize=
"16sp"
android:textStyle=
"bold"
/>
android:ellipsize=
"end"
android:text=
"香港"
android:textColor=
"@color/color_333333"
android:textSize=
"@dimen/sp_13"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
/>
</LinearLayout>
\ No newline at end of file
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
video/gradle.properties
View file @
cda8590c
...
...
@@ -44,7 +44,7 @@ WEIXIN_APP_SECRET =9eff885315f5f74fc9d6980e2bb1714a
RELEASE_UMENG_KEY
=
64d214b2a1a164591b65956b
#TalkingData
RELEASE_TALKING_DATA_KEY
=
"
E91735A7978140A8ABD1BB32D337CCAB
"
RELEASE_TALKING_DATA_KEY
=
"
C4092984E50144DD802C4AC32DD40F74
"
GROMORE_APP_ID="5423447"
GROMORE_SPLASH_CODE
=
"102416580"
...
...
video/library_tagflow/build.gradle
0 → 100755
View file @
cda8590c
plugins
{
id
'com.android.library'
id
'org.jetbrains.kotlin.android'
}
version
=
'1.0'
android
{
namespace
'com.framework.tagflow'
compileSdk
31
defaultConfig
{
minSdk
21
targetSdk
31
testInstrumentationRunner
"androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles
"consumer-rules.pro"
}
buildTypes
{
release
{
minifyEnabled
false
proguardFiles
getDefaultProguardFile
(
'proguard-android-optimize.txt'
),
'proguard-rules.pro'
}
}
compileOptions
{
sourceCompatibility
JavaVersion
.
VERSION_1_8
targetCompatibility
JavaVersion
.
VERSION_1_8
}
kotlinOptions
{
jvmTarget
=
'1.8'
}
}
dependencies
{
implementation
'androidx.core:core-ktx:1.3.2'
implementation
'androidx.appcompat:appcompat:1.2.0'
implementation
'com.google.android.material:material:1.2.1'
implementation
'androidx.constraintlayout:constraintlayout:2.0.4'
}
\ No newline at end of file
video/library_tagflow/consumer-rules.pro
0 → 100755
View file @
cda8590c
video/library_tagflow/proguard-rules.pro
0 → 100755
View file @
cda8590c
# 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
\ No newline at end of file
video/library_tagflow/src/main/AndroidManifest.xml
0 → 100755
View file @
cda8590c
<?xml version="1.0" encoding="utf-8"?>
<manifest>
</manifest>
\ No newline at end of file
video/library_tagflow/src/main/java/com/framework/tagflow/GridLayoutItemDecoration.kt
0 → 100755
View file @
cda8590c
package
com.framework.tagflow
import
android.graphics.Rect
import
android.view.View
import
androidx.recyclerview.widget.RecyclerView
/**
* @author: xiaxueyi
* @date: 2022-10-25
* @time: 13:55
* @说明:
*/
class
GridLayoutItemDecoration
(
private
val
spanCount
:
Int
,
private
val
spacing
:
Int
,
private
val
includeEdge
:
Boolean
=
false
)
:
RecyclerView
.
ItemDecoration
()
{
override
fun
getItemOffsets
(
outRect
:
Rect
,
view
:
View
,
parent
:
RecyclerView
,
state
:
RecyclerView
.
State
)
{
val
position
=
parent
.
getChildAdapterPosition
(
view
)
// item position
val
column
=
position
%
spanCount
// item column
if
(
includeEdge
)
{
outRect
.
left
=
spacing
-
column
*
spacing
/
spanCount
// spacing - column * ((1f / spanCount) * spacing)
outRect
.
right
=
(
column
+
1
)
*
spacing
/
spanCount
// (column + 1) * ((1f / spanCount) * spacing)
if
(
position
<
spanCount
)
{
// top edge
outRect
.
top
=
spacing
}
outRect
.
bottom
=
spacing
// item bottom
}
else
{
outRect
.
left
=
column
*
spacing
/
spanCount
// column * ((1f / spanCount) * spacing)
outRect
.
right
=
spacing
-
(
column
+
1
)
*
spacing
/
spanCount
// spacing - (column + 1) * ((1f / spanCount) * spacing)
if
(
position
>=
spanCount
)
{
outRect
.
top
=
spacing
// item top
}
}
}
/**
* 获取分割线的高度
* @return Int
*/
fun
getSpaceHeight
():
Int
{
return
spacing
}
/**
*
* @return Int
*/
fun
getSpaceCount
():
Int
{
return
spanCount
}
/**
*
* @return Boolean
*/
fun
getIncludeEdge
():
Boolean
{
return
includeEdge
}
}
\ No newline at end of file
video/library_tagflow/src/main/java/com/framework/tagflow/MultiTagFlowLayout.kt
0 → 100755
View file @
cda8590c
package
com.framework.tagflow
import
android.animation.ObjectAnimator
import
android.animation.ValueAnimator
import
android.content.Context
import
android.content.res.TypedArray
import
android.database.DataSetObserver
import
android.util.AttributeSet
import
android.view.LayoutInflater
import
android.view.View
import
android.view.ViewGroup
import
android.view.ViewTreeObserver
import
android.view.animation.AccelerateDecelerateInterpolator
import
android.widget.*
import
androidx.annotation.IntDef
import
androidx.core.view.marginBottom
import
androidx.core.view.marginTop
import
androidx.core.widget.NestedScrollView
import
androidx.recyclerview.widget.*
import
androidx.recyclerview.widget.RecyclerView.ItemDecoration
import
com.framework.tagflow.adapter.BaseTagAdapter
import
com.framework.tagflow.bean.BaseTagBean
import
com.framework.tagflow.interfac.OnTagClickListener
import
com.framework.tagflow.interfac.OnTagSelectedListener
import
com.framework.tagflow.tags.MutSelectedTagView
import
com.framework.tagflow.utils.DensityUtils
import
com.framework.tagflow.view.ControlScrollView
import
com.framework.tagflow.view.FlowLayout
import
kotlin.math.ceil
/**
* @author: xiaxueyi
* @date: 2022-09-27
* @time: 09:54
* @说明:多样 可折叠和展开的标签控件 流式布局,(RecyclerView和FlowLayout)
*/
open
class
MultiTagFlowLayout
@JvmOverloads
constructor
(
private
val
mContext
:
Context
,
attrs
:
AttributeSet
?
=
null
,
defStyleAttr
:
Int
=
0
)
:
NestedScrollView
(
mContext
,
attrs
,
defStyleAttr
)
{
private
lateinit
var
mControlScrollView
:
ControlScrollView
//标签容器
private
lateinit
var
mIvArrowMore
:
ImageView
//箭头
private
lateinit
var
mTvMoreHint
:
TextView
//提示文本
private
lateinit
var
mRlShowMore
:
LinearLayout
//展开收起布局
private
lateinit
var
mEmptyViewContainer
:
FrameLayout
;
//是否折叠起来
//true:折叠起来了
//false:展开了
private
var
isFolded
=
false
private
var
isInit
=
false
private
var
foldHint
=
""
//展开后显示的提示文字
private
var
expandHint
=
""
//折叠起来后显示的提示文字
private
var
animationDuration
=
0
//展开和折叠动画持续时间
private
var
mHasMore
=
false
//是否有展开的布局,查看更多
private
var
mRecyclerViewAdapterDataSetObserver
:
RecyclerViewAdapterDataSetObserver
?
=
null
private
var
mRecyclerViewAdapter
:
RecyclerView
.
Adapter
<*>?
=
null
private
lateinit
var
mRecyclerView
:
RecyclerView
private
var
defaultRows
:
Int
=
2
//默认行数三行
private
var
defaultColumn
:
Int
=
3
;
//默认列数三列
private
var
isNotifyData
:
Boolean
=
false
//是否刷新了数据
@IntDef
(
ITEM_MODEL_CLICK
,
ITEM_MODEL_SELECT
)
@Retention
(
AnnotationRetention
.
SOURCE
)
annotation
class
ItemMode
//标签模式,点击模式(默认),选中模式
@ItemMode
private
var
itemModel
=
0
private
var
mOnTagClickListener
:
OnTagClickListener
?
=
null
private
var
mSelectedListener
:
OnTagSelectedListener
?
=
null
private
var
mLayoutType
:
Int
=
0
//布局类型 0:RecyclerView,1:FlowLayout
private
var
mAdapterDataSetObserver
:
AdapterDataSetObserver
?
=
null
//FlowLayout 适配器监听
private
var
mTagAdapter
:
BaseTagAdapter
<*>?
=
null
//FlowLayout 适配器
private
lateinit
var
mFlowLayout
:
FlowLayout
private
var
tagsHorizontalSpace
=
0
//标签之间的横向间距
private
var
tagsVerticalSpace
=
0
//标签之间的纵向间距
private
var
mLayoutManagerMode
:
Int
=
0
private
lateinit
var
mEmptyView
:
View
;
companion
object
{
//默认标签之间的间距
private
const
val
DEFAULT_TAGS_SPACE
=
8f
//默认展开动画执行时间(毫秒)
private
const
val
DEFAULT_ANIMATION_DURATION
=
400
const
val
ITEM_MODEL_CLICK
=
100000
const
val
ITEM_MODEL_SELECT
=
100001
}
/**
* 列表布局只支持垂直列表模式
* @property index Int
* @constructor
*/
enum
class
LayoutManagerMode
(
val
index
:
Int
)
{
LinearLayoutManager
(
0
),
GridLayoutManager
(
1
),
}
/**
* 布局类型
* @property index Int
* @constructor
*/
enum
class
LayoutTypeMode
(
val
index
:
Int
)
{
RecyclerView
(
0
),
FlowLayout
(
1
),
}
init
{
val
typedArray
:
TypedArray
=
mContext
.
obtainStyledAttributes
(
attrs
,
R
.
styleable
.
TagFlowLayout
)
tagsHorizontalSpace
=
typedArray
.
getDimension
(
R
.
styleable
.
TagFlowLayout_tagsHorizontalSpace
,
DensityUtils
.
dp2px
(
mContext
,
DEFAULT_TAGS_SPACE
).
toFloat
()
).
toInt
()
tagsVerticalSpace
=
typedArray
.
getDimension
(
R
.
styleable
.
TagFlowLayout_tagsVerticalSpace
,
DensityUtils
.
dp2px
(
mContext
,
DEFAULT_TAGS_SPACE
).
toFloat
()
).
toInt
()
animationDuration
=
typedArray
.
getInt
(
R
.
styleable
.
TagFlowLayout_animationDuration
,
DEFAULT_ANIMATION_DURATION
)
mHasMore
=
typedArray
.
getBoolean
(
R
.
styleable
.
TagFlowLayout_hasMore
,
false
)
mLayoutType
=
typedArray
.
getInt
(
R
.
styleable
.
TagFlowLayout_layout_type
,
0
)
mLayoutManagerMode
=
typedArray
.
getInt
(
R
.
styleable
.
TagFlowLayout_layoutManager_Mode
,
0
)
foldHint
=
formatString
(
typedArray
.
getString
(
R
.
styleable
.
TagFlowLayout_foldHint
),
resources
.
getString
(
R
.
string
.
foldHint
)
)
expandHint
=
formatString
(
typedArray
.
getString
(
R
.
styleable
.
TagFlowLayout_expandHint
),
resources
.
getString
(
R
.
string
.
expandHint
)
)
itemModel
=
ITEM_MODEL_CLICK
typedArray
.
recycle
()
/**
* 实例化组件
*/
initWidget
()
/**
* 实例化组件类型
*/
initLayoutType
();
/**
*
*/
initLayoutManage
()
}
/**
* 初始化组件
*/
private
fun
initWidget
()
{
View
.
inflate
(
mContext
,
R
.
layout
.
tag_flow_layout
,
this
)
mControlScrollView
=
findViewById
(
R
.
id
.
hsv_tag_content
)
mIvArrowMore
=
findViewById
(
R
.
id
.
iv_arrow_more
)
mTvMoreHint
=
findViewById
(
R
.
id
.
tv_more_hint
)
mRlShowMore
=
findViewById
(
R
.
id
.
rl_show_more
)
mEmptyViewContainer
=
findViewById
(
R
.
id
.
fl_empty
)
mEmptyView
=
LayoutInflater
.
from
(
context
).
inflate
(
R
.
layout
.
layout_empty_not_data
,
this
,
false
)
mControlScrollView
.
isFillViewport
=
true
this
.
isFillViewport
=
true
mRlShowMore
.
setOnClickListener
(
View
.
OnClickListener
{
var
maxLine
:
Double
=
0.0
//最大行数
//真实数量
var
realCount
=
0
;
var
finalLine
:
Int
=
0
var
animateStart
:
Int
=
0
//记录动画开始位置
var
animateEnd
:
Int
=
0
//记录动画结束位置
when
(
mLayoutType
)
{
LayoutTypeMode
.
RecyclerView
.
index
->
{
realCount
=
mRecyclerViewAdapter
?.
itemCount
?:
0
;
if
(
mRecyclerView
.
layoutManager
is
GridLayoutManager
)
{
val
gridLayoutManager
:
GridLayoutManager
=
mRecyclerView
.
layoutManager
as
GridLayoutManager
if
(
gridLayoutManager
.
orientation
==
GridLayoutManager
.
VERTICAL
)
{
//计算列表中有多少行
maxLine
=
(
realCount
.
toDouble
()
/
defaultColumn
.
toDouble
())
//最大行数
}
}
else
{
maxLine
=
realCount
.
toDouble
();
}
//最终行数,向上取整,
finalLine
=
ceil
(
maxLine
).
toInt
()
}
LayoutTypeMode
.
FlowLayout
.
index
->
{
realCount
=
mFlowLayout
.
getLineSize
()
if
(
realCount
>=
6
)
{
realCount
=
6
}
}
else
->
{
realCount
=
0
}
}
//展开容器
if
(!
isFolded
)
{
ObjectAnimator
.
ofFloat
(
mIvArrowMore
,
"rotation"
,
0f
,
180f
).
start
()
if
(
mLayoutType
==
LayoutTypeMode
.
RecyclerView
.
index
)
{
animateStart
=
getLineHeight
()
*
defaultRows
animateEnd
=
getLineHeight
()
*
finalLine
}
else
{
animateStart
=
getLineHeight
()
*
2
animateEnd
=
getLineHeight
()
*
realCount
}
animate
(
animateStart
,
animateEnd
)
mTvMoreHint
.
text
=
foldHint
//点击收回
mControlScrollView
.
setCanScroll
(
false
)
//设置不可滑动
}
else
{
ObjectAnimator
.
ofFloat
(
mIvArrowMore
,
"rotation"
,
-
180f
,
0f
).
start
()
if
(
mLayoutType
==
LayoutTypeMode
.
RecyclerView
.
index
)
{
animateStart
=
getLineHeight
()
*
finalLine
animateEnd
=
getLineHeight
()
*
defaultRows
}
else
{
animateStart
=
getLineHeight
()
*
realCount
animateEnd
=
getLineHeight
()
*
2
}
animate
(
animateStart
,
animateEnd
)
mTvMoreHint
.
text
=
expandHint
//点击展开
mControlScrollView
.
setCanScroll
(
false
)
//设置不可滑动
}
isFolded
=
!
isFolded
})
}
/**
*动画
* @param animateStart Int
* @param animateEnd Int
*/
private
fun
animate
(
animateStart
:
Int
,
animateEnd
:
Int
)
{
var
start
:
Int
=
animateStart
var
end
=
animateEnd
when
(
mLayoutType
)
{
LayoutTypeMode
.
RecyclerView
.
index
->
{
if
(
start
<
0
)
{
start
=
mRecyclerView
.
measuredHeight
}
if
(
end
<
0
)
{
end
=
mRecyclerView
.
measuredHeight
}
}
LayoutTypeMode
.
FlowLayout
.
index
->
{
if
(
start
<
0
)
{
start
=
mFlowLayout
.
measuredHeight
}
if
(
end
<
0
)
{
end
=
mFlowLayout
.
measuredHeight
}
}
else
->
{
}
}
val
animator
:
ValueAnimator
=
ValueAnimator
.
ofInt
(
start
,
end
)
animator
.
duration
=
animationDuration
.
toLong
()
animator
.
addUpdateListener
{
animation
->
val
value
=
animation
.
animatedValue
as
Int
val
layoutParams
:
ViewGroup
.
LayoutParams
=
mControlScrollView
.
layoutParams
layoutParams
.
height
=
value
mControlScrollView
.
layoutParams
=
layoutParams
}
animator
.
interpolator
=
AccelerateDecelerateInterpolator
()
animator
.
start
()
}
/**
* 重新设置数据
*/
private
fun
reloadData
()
{
var
lines
:
Int
=
0
;
when
(
mLayoutType
)
{
LayoutTypeMode
.
RecyclerView
.
index
->
{
//RecyclerView
mRecyclerView
.
removeAllViews
()
lines
=
mRecyclerViewAdapter
?.
itemCount
?:
0
}
LayoutTypeMode
.
FlowLayout
.
index
->
{
//FlowLayout
mFlowLayout
.
removeAllViews
()
lines
=
mTagAdapter
?.
count
?:
0
}
else
->
{
lines
=
0
;
}
}
/**
* 如果行数为0,重新渲染布局
*/
if
(
lines
==
0
)
{
val
params
:
ViewGroup
.
LayoutParams
=
this
.
layoutParams
layoutParams
.
height
=
ViewGroup
.
LayoutParams
.
MATCH_PARENT
this
.
layoutParams
=
params
val
layoutParams
:
ViewGroup
.
LayoutParams
=
mControlScrollView
.
layoutParams
layoutParams
.
height
=
0
mControlScrollView
.
layoutParams
=
layoutParams
/**
* 增加空布局
*/
mEmptyViewContainer
.
removeAllViews
()
mEmptyViewContainer
.
addView
(
mEmptyView
)
mEmptyViewContainer
.
visibility
=
View
.
VISIBLE
mRlShowMore
.
visibility
=
View
.
GONE
return
}
val
childCount
:
Int
=
mEmptyViewContainer
.
childCount
if
(
childCount
>
0
)
{
mEmptyViewContainer
.
removeAllViews
()
mEmptyViewContainer
.
visibility
=
GONE
}
when
(
mLayoutType
)
{
LayoutTypeMode
.
RecyclerView
.
index
->
{
//RecyclerView
// if(getAdapter() is BaseQuickAdapter<*,*>){
// (getAdapter() as BaseQuickAdapter<*,*>).setOnItemClickListener { adapter, view, position ->
// mOnItemClickListener?.onItemClick(position)
// }
// }
mRecyclerView
.
viewTreeObserver
.
addOnGlobalLayoutListener
(
object
:
ViewTreeObserver
.
OnGlobalLayoutListener
{
override
fun
onGlobalLayout
()
{
val
itemCount
:
Int
=
mRecyclerViewAdapter
?.
itemCount
?:
0
var
realCount
:
Int
=
mRecyclerViewAdapter
?.
itemCount
?:
0
;
var
maxLine
=
0.0
//最大行数
if
(
mRecyclerView
.
layoutManager
is
GridLayoutManager
)
{
val
gridLayoutManager
:
GridLayoutManager
=
mRecyclerView
.
layoutManager
as
GridLayoutManager
if
(
gridLayoutManager
.
orientation
==
GridLayoutManager
.
VERTICAL
)
{
//计算列表中有多少行
maxLine
=
(
realCount
.
toDouble
()
/
defaultColumn
.
toDouble
())
//最大行数
}
}
else
{
maxLine
=
realCount
.
toDouble
();
}
//最终行数,向上取整,
val
finalLine
=
ceil
(
maxLine
).
toInt
()
if
(
mHasMore
)
{
//有展开更多的布局
val
layoutParams
:
ViewGroup
.
LayoutParams
=
mControlScrollView
.
layoutParams
/**
1.如果已經在爆開的情況下
update Data 的話就不用再次收起來
2.但如果是在收起的情況下
update Data 就保持收起
3. 如果在爆開的情況下 按"取消"返回上一頁
下一次進來要收起
首次进入也是收起
true 标识已经刷新数据了,特殊判断
*/
if
(
isNotifyData
)
{
if
(
finalLine
<=
2
)
{
layoutParams
.
height
=
getLineHeight
()
*
finalLine
mRlShowMore
.
visibility
=
View
.
GONE
}
else
{
mRlShowMore
.
visibility
=
View
.
VISIBLE
//表示已经展开了
if
(
isFolded
)
{
layoutParams
.
height
=
getLineHeight
()
*
finalLine
}
else
{
//设置默认展开高度(一个item 高度*多少行)
layoutParams
.
height
=
getLineHeight
()
*
defaultRows
}
}
mControlScrollView
.
layoutParams
=
layoutParams
}
else
{
if
(
finalLine
<=
2
)
{
layoutParams
.
height
=
getLineHeight
()
*
finalLine
mRlShowMore
.
visibility
=
View
.
GONE
}
else
{
//设置默认展开高度(一个item 高度*多少行)
layoutParams
.
height
=
getLineHeight
()
*
defaultRows
mRlShowMore
.
visibility
=
View
.
VISIBLE
}
mControlScrollView
.
layoutParams
=
layoutParams
}
}
else
{
//没有展开更多的布局
mRlShowMore
.
visibility
=
View
.
GONE
val
layoutParams
:
ViewGroup
.
LayoutParams
?
=
mControlScrollView
.
layoutParams
if
(
layoutParams
!=
null
)
{
layoutParams
.
height
=
getLineHeight
()
*
itemCount
}
mControlScrollView
.
layoutParams
=
layoutParams
}
mRecyclerView
.
viewTreeObserver
.
removeOnGlobalLayoutListener
(
this
)
}
})
}
LayoutTypeMode
.
FlowLayout
.
index
->
{
//FlowLayout
mFlowLayout
.
clearAllView
()
mFlowLayout
.
removeAllViews
()
for
(
i
in
0
until
mTagAdapter
!!
.
count
)
{
val
view
=
mTagAdapter
?.
getView
(
i
,
convertView
=
null
,
mFlowLayout
)
var
position
:
Int
=
i
;
if
(
itemModel
==
ITEM_MODEL_CLICK
&&
mOnTagClickListener
!=
null
)
{
view
?.
setOnClickListener
{
v
->
mOnTagClickListener
?.
onClick
(
v
,
position
)
}
view
?.
setOnLongClickListener
(
object
:
OnLongClickListener
{
override
fun
onLongClick
(
v
:
View
):
Boolean
{
mOnTagClickListener
?.
onLongClick
(
v
,
position
)
return
true
}
})
}
else
if
(
itemModel
==
ITEM_MODEL_SELECT
&&
mSelectedListener
!=
null
)
{
view
?.
setOnClickListener
{
v
->
if
(
v
is
MutSelectedTagView
)
{
if
(!
v
.
isSelected
)
{
mTagAdapter
!!
.
select
(
position
)
mSelectedListener
!!
.
selected
(
v
,
position
,
mTagAdapter
!!
.
getData
()
as
List
<
BaseTagBean
?>
)
}
else
{
mTagAdapter
!!
.
unSelect
(
position
)
mSelectedListener
!!
.
unSelected
(
v
,
position
,
mTagAdapter
!!
.
getData
()
as
List
<
BaseTagBean
?>
)
}
v
.
toggle
()
}
}
}
mFlowLayout
.
addView
(
view
)
}
mFlowLayout
.
viewTreeObserver
.
addOnGlobalLayoutListener
(
object
:
ViewTreeObserver
.
OnGlobalLayoutListener
{
override
fun
onGlobalLayout
()
{
if
(!
isInit
)
{
if
(
mHasMore
)
{
//有展开更多的布局
val
lines
:
Int
=
mFlowLayout
.
getLineSize
()
val
layoutParams
:
ViewGroup
.
LayoutParams
=
mControlScrollView
.
layoutParams
if
(
lines
<=
2
)
{
layoutParams
.
height
=
getLineHeight
()
*
lines
mRlShowMore
.
visibility
=
View
.
GONE
}
else
{
layoutParams
.
height
=
getLineHeight
()
*
2
mRlShowMore
.
visibility
=
View
.
VISIBLE
}
mControlScrollView
.
layoutParams
=
layoutParams
}
else
{
//没有展开更多的布局
mRlShowMore
.
visibility
=
View
.
GONE
var
layoutParams
:
ViewGroup
.
LayoutParams
?
=
mControlScrollView
.
layoutParams
val
lines
:
Int
=
mFlowLayout
.
getLineSize
()
if
(
layoutParams
!=
null
)
{
layoutParams
.
height
=
getLineHeight
()
*
lines
}
mControlScrollView
.
layoutParams
=
layoutParams
}
mFlowLayout
.
viewTreeObserver
.
removeOnGlobalLayoutListener
(
this
)
isInit
=
true
}
}
})
}
else
->
{
}
}
}
/**
* 初始化列表的布局管理模式
*/
private
fun
initLayoutManage
()
{
if
(
mLayoutType
==
LayoutTypeMode
.
RecyclerView
.
index
)
{
when
(
mLayoutManagerMode
)
{
LayoutManagerMode
.
LinearLayoutManager
.
index
->
{
val
linearLayoutManager
:
LinearLayoutManager
=
LinearLayoutManager
(
context
)
linearLayoutManager
.
orientation
=
LinearLayoutManager
.
VERTICAL
mRecyclerView
.
setHasFixedSize
(
true
)
mRecyclerView
.
layoutManager
=
linearLayoutManager
;
mRecyclerView
.
itemAnimator
=
DefaultItemAnimator
()
}
LayoutManagerMode
.
GridLayoutManager
.
index
->
{
val
gridLayoutManager
:
GridLayoutManager
=
GridLayoutManager
(
context
,
3
)
gridLayoutManager
.
orientation
=
GridLayoutManager
.
VERTICAL
mRecyclerView
.
setHasFixedSize
(
true
)
mRecyclerView
.
layoutManager
=
gridLayoutManager
;
mRecyclerView
.
itemAnimator
=
DefaultItemAnimator
()
}
else
->
{
Toast
.
makeText
(
context
,
"un know"
,
Toast
.
LENGTH_SHORT
).
show
()
}
}
}
}
/**
* RecyclerView监听
*/
internal
inner
class
RecyclerViewAdapterDataSetObserver
:
RecyclerView
.
AdapterDataObserver
()
{
override
fun
onChanged
()
{
super
.
onChanged
()
reloadData
()
}
}
/**
* Flowlayout监听
*/
internal
inner
class
AdapterDataSetObserver
:
DataSetObserver
()
{
override
fun
onChanged
()
{
super
.
onChanged
()
reloadData
()
}
override
fun
onInvalidated
()
{
super
.
onInvalidated
()
}
}
/**
* 实例化布局类型
*/
private
fun
initLayoutType
()
{
when
(
mLayoutType
)
{
LayoutTypeMode
.
RecyclerView
.
index
->
{
mControlScrollView
.
removeAllViews
()
mRecyclerView
=
RecyclerView
(
mContext
)
mControlScrollView
.
addView
(
mRecyclerView
)
}
LayoutTypeMode
.
FlowLayout
.
index
->
{
mControlScrollView
.
removeAllViews
()
mFlowLayout
=
FlowLayout
(
mContext
)
mControlScrollView
.
addView
(
mFlowLayout
)
mFlowLayout
.
setSpace
(
tagsHorizontalSpace
,
tagsVerticalSpace
)
}
else
->
{
Toast
.
makeText
(
mContext
,
"Un know "
,
Toast
.
LENGTH_SHORT
).
show
()
}
}
}
/**
*
* @return Int
*/
private
fun
getLineHeight
():
Int
{
var
itemHeight
:
Int
=
0
//每一个item 的高度
var
spaceHeight
:
Int
=
0
;
//间隔间距
var
spacing
:
Int
=
0
//分割线高度,如果设置了分割线,计算item 的高度需要加上
when
(
mLayoutType
)
{
LayoutTypeMode
.
RecyclerView
.
index
->
{
val
childCount
:
Int
=
mRecyclerView
.
childCount
println
(
childCount
)
val
childView
=
mRecyclerView
.
getChildAt
(
0
)
println
(
childView
)
val
itemDecorationCount
:
Int
=
mRecyclerView
.
itemDecorationCount
if
(
itemDecorationCount
>
0
)
{
if
(
mRecyclerView
.
layoutManager
is
GridLayoutManager
)
{
val
itemDecoration
:
ItemDecoration
=
mRecyclerView
.
getItemDecorationAt
(
0
)
val
gridLayoutManager
:
GridLayoutManager
=
mRecyclerView
.
layoutManager
as
GridLayoutManager
if
(
gridLayoutManager
.
orientation
==
GridLayoutManager
.
VERTICAL
)
{
if
(
itemDecoration
is
GridLayoutItemDecoration
)
{
val
gridLayoutItemDecoration
:
GridLayoutItemDecoration
=
itemDecoration
as
GridLayoutItemDecoration
spacing
=
gridLayoutItemDecoration
.
getSpaceHeight
()
}
else
{
spacing
=
0
}
}
}
}
if
(
childView
!=
null
)
{
//子view 的高度
itemHeight
=
childView
.
measuredHeight
//获取设置子view 内外间距的尺寸
spaceHeight
=
childView
.
marginTop
+
childView
.
marginBottom
//计算整个item 的高度
itemHeight
=
(
itemHeight
+
spaceHeight
+
spacing
)
println
(
itemHeight
)
}
}
LayoutTypeMode
.
FlowLayout
.
index
->
{
itemHeight
=
mFlowLayout
.
getLineHeight
()
+
tagsVerticalSpace
}
else
->
{
itemHeight
=
0
}
}
return
itemHeight
}
/**
*
* @param adapter Any
*/
fun
setAdapter
(
adapter
:
Any
)
{
when
(
mLayoutType
)
{
LayoutTypeMode
.
RecyclerView
.
index
->
{
if
(
adapter
is
RecyclerView
.
Adapter
<*>)
{
this
.
mRecyclerViewAdapter
=
adapter
as
RecyclerView
.
Adapter
<*>
mRecyclerView
.
adapter
=
mRecyclerViewAdapter
if
(
mRecyclerViewAdapter
!=
null
&&
mRecyclerViewAdapterDataSetObserver
!=
null
)
{
this
.
mRecyclerViewAdapter
!!
.
unregisterAdapterDataObserver
(
mRecyclerViewAdapterDataSetObserver
!!
)
}
if
(
this
.
mRecyclerViewAdapter
!=
null
)
{
mRecyclerViewAdapterDataSetObserver
=
RecyclerViewAdapterDataSetObserver
()
this
.
mRecyclerViewAdapter
!!
.
registerAdapterDataObserver
(
mRecyclerViewAdapterDataSetObserver
!!
)
reloadData
()
}
}
}
LayoutTypeMode
.
FlowLayout
.
index
->
{
if
(
adapter
is
BaseTagAdapter
<*>)
{
this
.
mTagAdapter
=
adapter
as
BaseTagAdapter
<*>
if
(
mTagAdapter
!=
null
&&
mAdapterDataSetObserver
!=
null
)
{
this
.
mTagAdapter
?.
unregisterDataSetObserver
(
mAdapterDataSetObserver
)
}
if
(
this
.
mTagAdapter
!=
null
)
{
mAdapterDataSetObserver
=
AdapterDataSetObserver
()
this
.
mTagAdapter
!!
.
registerDataSetObserver
(
mAdapterDataSetObserver
)
reloadData
()
}
}
}
else
->
{
}
}
}
/**
* 获取适配器
*/
private
fun
getAdapter
():
Any
?
{
when
(
mLayoutType
)
{
LayoutTypeMode
.
RecyclerView
.
index
->
{
return
mRecyclerViewAdapter
as
Any
}
LayoutTypeMode
.
FlowLayout
.
index
->
{
return
mTagAdapter
as
Any
}
else
->
{
return
null
}
}
}
/**
* 刷新数据
*/
fun
notifyDataSetChanged
()
{
when
(
mLayoutType
)
{
LayoutTypeMode
.
RecyclerView
.
index
->
{
mRecyclerViewAdapter
?.
notifyDataSetChanged
()
}
LayoutTypeMode
.
FlowLayout
.
index
->
{
mTagAdapter
?.
notifyDataSetChanged
()
}
else
->
{
}
}
//标识:刷新数据 isNotifyData=true
isNotifyData
=
true
}
/**
* 获取列表对象
* @return RecyclerView
*/
fun
getRecyclerView
():
RecyclerView
{
return
mRecyclerView
}
/**
* 获取流逝布局对象
* @return FlowLayout
*/
fun
getFlowLayout
():
FlowLayout
{
return
mFlowLayout
}
/**
* 获取展开后显示的提示文字
* @return String
*/
fun
getFoldHint
():
String
{
return
foldHint
}
/**
* 设置展开后显示的提示文字
* @param foldHint String
*/
fun
setFoldHint
(
foldHint
:
String
)
{
this
.
foldHint
=
foldHint
if
(
isFolded
)
{
mTvMoreHint
.
text
=
foldHint
}
}
/**
* 获取展开文字
* @return String
*/
fun
getExpandHint
():
String
{
return
expandHint
}
/**
* 设置展开后的文字
* @param expandHint String
*/
fun
setExpandHint
(
expandHint
:
String
)
{
this
.
expandHint
=
expandHint
if
(!
isFolded
)
{
mTvMoreHint
.
text
=
expandHint
}
}
/**
* 获取动画时间
* @return Int
*/
fun
getAnimationDuration
():
Int
{
return
animationDuration
}
/**
* 设置动画时间
* @param animationDuration Int
*/
fun
setAnimationDuration
(
animationDuration
:
Int
)
{
this
.
animationDuration
=
animationDuration
}
/**
*
* @return Boolean
*/
fun
isCanScroll
():
Boolean
{
return
mControlScrollView
.
isCanScroll
()
}
/**
* 设置是否退出内部标签容器
* @param can Boolean
*/
fun
setCanScroll
(
can
:
Boolean
)
{
mControlScrollView
.
setCanScroll
(
can
)
}
fun
setForceFixed
(
fixed
:
Boolean
)
{
mControlScrollView
.
setForceFixed
(
fixed
)
}
/**
* 获取FlowLayout 点击模式
* @return Int
*/
fun
getItemModel
():
Int
{
return
itemModel
}
/**
* 设置FlowLayout 点击模式,作为点击的标识
* @param itemModel Int
*/
fun
setItemModel
(
@ItemMode
itemModel
:
Int
)
{
this
.
itemModel
=
itemModel
reloadData
()
}
/**
* 获取水平间距
* @return Int
*/
fun
getTagsHorizontalSpace
():
Int
{
return
tagsHorizontalSpace
}
/**
* 设置水平间距
* @param tagsHorizontalSpace Int
*/
fun
setTagsHorizontalSpace
(
tagsHorizontalSpace
:
Int
)
{
this
.
tagsHorizontalSpace
=
tagsHorizontalSpace
}
/**
* 获取垂直间距
* @return Int
*/
fun
getTagsVerticalSpace
():
Int
{
return
tagsVerticalSpace
}
/**
* 设置垂直间距
* @param tagsVerticalSpace Int
*/
fun
setTagsVerticalSpace
(
tagsVerticalSpace
:
Int
)
{
this
.
tagsVerticalSpace
=
tagsVerticalSpace
}
/**
* 格式化字符
* @param str
* @param defaultString
* @return
*/
private
fun
formatString
(
str
:
String
?,
defaultString
:
String
):
String
{
return
if
(
str
.
isNullOrEmpty
())
{
defaultString
}
else
{
str
}
}
/******************************************************* set listener *********************************************************************/
fun
setOnTagClickListener
(
onTagClickListener
:
OnTagClickListener
)
=
apply
{
this
.
mOnTagClickListener
=
onTagClickListener
if
(
mTagAdapter
!=
null
)
{
reloadData
()
}
}
open
fun
setSelectedListener
(
selectedListener
:
OnTagSelectedListener
?)
{
this
.
mSelectedListener
=
selectedListener
if
(
mTagAdapter
!=
null
)
{
reloadData
()
}
}
}
\ No newline at end of file
video/library_tagflow/src/main/java/com/framework/tagflow/adapter/BaseTagAdapter.kt
0 → 100755
View file @
cda8590c
package
com.framework.tagflow.adapter
import
android.view.View
import
android.view.ViewGroup
import
android.widget.BaseAdapter
import
com.framework.tagflow.bean.BaseTagBean
abstract
class
BaseTagAdapter
<
T
>
:
BaseAdapter
()
{
private
var
dataList
:
MutableList
<
T
>
=
mutableListOf
()
override
fun
getCount
():
Int
{
return
dataList
.
size
}
override
fun
getItem
(
position
:
Int
):
T
{
return
dataList
[
position
]
}
override
fun
getItemId
(
position
:
Int
):
Long
{
return
position
.
toLong
()
}
abstract
override
fun
getView
(
position
:
Int
,
convertView
:
View
?,
parent
:
ViewGroup
):
View
fun
getData
():
List
<
T
>
{
return
dataList
}
/**
* 增加一条数据
* @param dataList T
*/
fun
addData
(
dataList
:
T
)
{
this
.
dataList
.
add
(
dataList
)
notifyDataSetChanged
()
}
/**
* 增加列表
* @param dataList List<T>?
*/
fun
addAllList
(
dataList
:
List
<
T
>?)
{
this
.
dataList
.
clear
()
if
(
null
!=
dataList
)
{
this
.
dataList
.
addAll
(
dataList
)
}
notifyDataSetChanged
()
}
/**
*
*/
open
fun
select
(
position
:
Int
)
{
if
(
position
<
0
||
position
>=
dataList
.
size
)
{
return
}
if
(
dataList
[
position
]
is
BaseTagBean
){
(
dataList
[
position
]
as
BaseTagBean
).
setIsSelected
(
true
)
}
}
/**
*
*/
open
fun
unSelect
(
position
:
Int
)
{
if
(
position
<
0
||
position
>=
dataList
.
size
)
{
return
}
if
(
dataList
[
position
]
is
BaseTagBean
){
(
dataList
[
position
]
as
BaseTagBean
).
setIsSelected
(
false
)
}
}
}
\ No newline at end of file
video/library_tagflow/src/main/java/com/framework/tagflow/bean/BaseTagBean.kt
0 → 100755
View file @
cda8590c
package
com.framework.tagflow.bean
/**
* @author: xiaxueyi
* @date: 2022-09-16
* @time: 16:02
* @说明:
*/
open
class
BaseTagBean
{
private
var
id
=
0
private
var
title
:
String
?
=
null
private
var
isSelected
=
false
//是否选中
private
var
tag
:
Any
?
=
null
//标签额外信息
fun
getId
():
Int
{
return
id
}
fun
setId
(
id
:
Int
)
{
this
.
id
=
id
}
fun
getTitle
():
String
?
{
return
title
}
fun
setTitle
(
title
:
String
?)
{
this
.
title
=
title
}
fun
getTag
():
Any
?
{
return
tag
}
fun
setTag
(
tag
:
Any
?)
{
this
.
tag
=
tag
}
fun
isSelected
():
Boolean
{
return
isSelected
}
fun
setIsSelected
(
selected
:
Boolean
)
{
this
.
isSelected
=
selected
}
}
\ No newline at end of file
video/library_tagflow/src/main/java/com/framework/tagflow/interfac/OnTagClickListener.kt
0 → 100755
View file @
cda8590c
package
com.framework.tagflow.interfac
import
android.view.View
/**
* @author: xiaxueyi
* @date: 2022-09-13
* @time: 15:30
* @说明:
*/
interface
OnTagClickListener
{
fun
onClick
(
view
:
View
?,
position
:
Int
)
fun
onLongClick
(
view
:
View
?,
position
:
Int
)
}
\ No newline at end of file
video/library_tagflow/src/main/java/com/framework/tagflow/interfac/OnTagSelectedListener.kt
0 → 100755
View file @
cda8590c
package
com.framework.tagflow.interfac
import
android.view.View
import
com.framework.tagflow.bean.BaseTagBean
/**
* @author: xiaxueyi
* @date: 2022-09-13
* @time: 15:30
* @说明:标签被选中或取消选中监听
*/
interface
OnTagSelectedListener
{
fun
selected
(
view
:
View
?,
position
:
Int
,
selected
:
List
<
BaseTagBean
?
>?)
fun
unSelected
(
view
:
View
?,
position
:
Int
,
selected
:
List
<
BaseTagBean
?
>?)
}
\ No newline at end of file
video/library_tagflow/src/main/java/com/framework/tagflow/tags/ColorfulStrokeTagView.kt
0 → 100755
View file @
cda8590c
package
com.framework.tagflow.tags
import
android.content.Context
import
android.util.AttributeSet
/**
* @author: xiaxueyi
* @date: 2022-09-19
* @time: 16:02
* @说明:
*/
class
ColorfulStrokeTagView
:
ColorfulTagView
{
constructor
(
context
:
Context
)
:
super
(
context
)
{}
constructor
(
context
:
Context
,
attrs
:
AttributeSet
?)
:
super
(
context
,
attrs
)
{}
constructor
(
context
:
Context
,
attrs
:
AttributeSet
?,
defStyleAttr
:
Int
)
:
super
(
context
,
attrs
,
defStyleAttr
)
{
}
override
fun
isSolid
():
Boolean
{
return
false
}
override
fun
getStrokeWidth
():
Float
{
return
1F
}
}
\ No newline at end of file
video/library_tagflow/src/main/java/com/framework/tagflow/tags/ColorfulTagView.kt
0 → 100755
View file @
cda8590c
package
com.framework.tagflow.tags
import
android.content.Context
import
android.graphics.Color
import
android.util.AttributeSet
import
java.util.*
/**
* @author: xiaxueyi
* @date: 2022-09-16
* @time: 16:02
* @说明:
*/
open
class
ColorfulTagView
:
DefaultTagView
{
constructor
(
context
:
Context
)
:
super
(
context
)
{}
constructor
(
context
:
Context
,
attrs
:
AttributeSet
?)
:
super
(
context
,
attrs
)
{}
constructor
(
context
:
Context
,
attrs
:
AttributeSet
?,
defStyleAttr
:
Int
)
:
super
(
context
,
attrs
,
defStyleAttr
)
{
}
override
fun
getNormalBackgroundColor
():
Int
{
val
random
=
Random
()
val
red
=
random
.
nextInt
(
200
)
+
50
val
green
=
random
.
nextInt
(
200
)
+
50
val
blue
=
random
.
nextInt
(
200
)
+
50
return
Color
.
rgb
(
red
,
green
,
blue
)
}
}
\ No newline at end of file
video/library_tagflow/src/main/java/com/framework/tagflow/tags/DefaultTagView.kt
0 → 100755
View file @
cda8590c
package
com.framework.tagflow.tags
import
android.content.Context
import
android.graphics.drawable.Drawable
import
android.graphics.drawable.GradientDrawable
import
android.graphics.drawable.StateListDrawable
import
android.util.AttributeSet
import
android.view.Gravity
import
androidx.annotation.ColorInt
import
androidx.appcompat.widget.AppCompatTextView
import
androidx.core.content.ContextCompat
import
com.framework.tagflow.R
import
com.framework.tagflow.utils.DensityUtils
/**
* @author: xiaxueyi
* @date: 2022-09-16
* @time: 16:02
* @说明:
*/
open
class
DefaultTagView
@JvmOverloads
constructor
(
protected
var
mContext
:
Context
,
attrs
:
AttributeSet
?
=
null
,
defStyleAttr
:
Int
=
0
)
:
AppCompatTextView
(
mContext
,
attrs
,
defStyleAttr
)
{
//默认标签内间距
private
val
DEFAULT_TAG_PADDING
=
5f
//默认标签背景圆角大小
private
val
DEFAULT_TAG_CORNER
=
3f
//默认边框宽度(仅在非实心背景有效),单位dp
private
val
DEFAULT_TAG_STROKE
=
1f
//默认标签背景正常颜色
private
val
DEFAULT_TAG_BACKGROUND_COLOR
=
-
0
x1
//默认标签背景按下颜色
private
val
DEFAULT_TAG_BACKGROUND_PRESSED_COLOR
=
-
0
x68bba4
private
fun
init
()
{
val
padding
:
Int
=
DensityUtils
.
dp2px
(
mContext
,
getTagPadding
())
setPadding
(
padding
,
padding
,
padding
,
padding
)
gravity
=
Gravity
.
CENTER
setBackgroundDrawable
(
getBackgroundDrawable
())
}
//设置字体颜色的选择器
//完全自定义tag的样式请重写此方法
//返回一个Drawable背景样式
protected
open
fun
getBackgroundDrawable
():
Drawable
?
{
//设置字体颜色的选择器
val
colorSateList
=
ContextCompat
.
getColorStateList
(
context
,
R
.
color
.
secondary_text
)
setTextColor
(
colorSateList
)
val
normal
=
GradientDrawable
()
normal
.
shape
=
GradientDrawable
.
RECTANGLE
normal
.
cornerRadius
=
DensityUtils
.
dp2px
(
mContext
,
getTagRadius
()).
toFloat
()
if
(
isSolid
())
{
normal
.
setColor
(
getNormalBackgroundColor
())
}
else
{
normal
.
setStroke
(
DensityUtils
.
dp2px
(
mContext
,
getStrokeWidth
()),
getNormalBackgroundColor
()
)
normal
.
setColor
(
getBackgroundColor
())
}
val
pressed
=
GradientDrawable
()
pressed
.
shape
=
GradientDrawable
.
RECTANGLE
pressed
.
cornerRadius
=
DensityUtils
.
dp2px
(
mContext
,
getTagRadius
()).
toFloat
()
if
(
isSolid
())
{
pressed
.
setColor
(
getPressedBackgroundColor
())
}
else
{
pressed
.
setStroke
(
DensityUtils
.
dp2px
(
mContext
,
getStrokeWidth
()),
getPressedBackgroundColor
()
)
pressed
.
setColor
(
getPressedBackgroundColor
())
}
val
selector
=
StateListDrawable
()
selector
.
addState
(
intArrayOf
(
android
.
R
.
attr
.
state_pressed
),
pressed
)
selector
.
addState
(
intArrayOf
(),
normal
)
return
selector
}
//默认tag背景颜色
@ColorInt
protected
open
fun
getNormalBackgroundColor
():
Int
{
return
DEFAULT_TAG_BACKGROUND_COLOR
}
//按下tag时背景颜色
@ColorInt
protected
open
fun
getPressedBackgroundColor
():
Int
{
return
DEFAULT_TAG_BACKGROUND_PRESSED_COLOR
}
//tag的圆角角度
protected
open
fun
getTagRadius
():
Float
{
return
DEFAULT_TAG_CORNER
}
//tag内间距
protected
open
fun
getTagPadding
():
Float
{
return
DEFAULT_TAG_PADDING
}
/***
* 是否为实心背景
*
* @return true:实心的,false:空心,可通过[.getStrokeWidth]设置边框宽度
*/
protected
open
fun
isSolid
():
Boolean
{
return
true
}
//设置边框的宽度,单位dp
protected
open
fun
getStrokeWidth
():
Float
{
return
DEFAULT_TAG_STROKE
}
//当设置了空心加边框的tag时给tag加一个背景,
//防止在透明背景上无法显示点击颜色
@ColorInt
protected
open
fun
getBackgroundColor
():
Int
{
return
DEFAULT_TAG_BACKGROUND_COLOR
}
init
{
init
()
}
}
\ No newline at end of file
video/library_tagflow/src/main/java/com/framework/tagflow/tags/MutSelectedTagView.kt
0 → 100755
View file @
cda8590c
package
com.framework.tagflow.tags
import
android.content.Context
import
android.graphics.drawable.Drawable
import
android.graphics.drawable.GradientDrawable
import
android.graphics.drawable.StateListDrawable
import
android.util.AttributeSet
import
androidx.core.content.ContextCompat
import
com.framework.tagflow.R
import
com.framework.tagflow.utils.DensityUtils
/**
* @author: xiaxueyi
* @date: 2022-09-16
* @time: 15:02
* @说明:
*/
class
MutSelectedTagView
:
DefaultTagView
{
constructor
(
context
:
Context
)
:
super
(
context
)
{}
constructor
(
context
:
Context
,
attrs
:
AttributeSet
?)
:
super
(
context
,
attrs
)
{}
constructor
(
context
:
Context
,
attrs
:
AttributeSet
?,
defStyleAttr
:
Int
)
:
super
(
context
,
attrs
,
defStyleAttr
)
{
}
override
fun
getBackgroundDrawable
():
Drawable
?
{
//设置字体颜色的选择器
val
colorSateList
=
ContextCompat
.
getColorStateList
(
context
,
R
.
color
.
secondary_text
)
setTextColor
(
colorSateList
)
val
normal
=
GradientDrawable
()
normal
.
shape
=
GradientDrawable
.
RECTANGLE
normal
.
cornerRadius
=
DensityUtils
.
dp2px
(
mContext
,
getTagRadius
()).
toFloat
()
if
(
isSolid
())
{
normal
.
setColor
(
getNormalBackgroundColor
())
}
else
{
normal
.
setStroke
(
DensityUtils
.
dp2px
(
mContext
,
getStrokeWidth
()),
getNormalBackgroundColor
()
)
normal
.
setColor
(
getBackgroundColor
())
}
val
pressed
=
GradientDrawable
()
pressed
.
shape
=
GradientDrawable
.
RECTANGLE
pressed
.
cornerRadius
=
DensityUtils
.
dp2px
(
mContext
,
getTagRadius
()).
toFloat
()
if
(
isSolid
())
{
pressed
.
setColor
(
getPressedBackgroundColor
())
}
else
{
pressed
.
setStroke
(
DensityUtils
.
dp2px
(
mContext
,
getStrokeWidth
()),
getPressedBackgroundColor
()
)
pressed
.
setColor
(
getPressedBackgroundColor
())
}
val
selector
=
StateListDrawable
()
selector
.
addState
(
intArrayOf
(
android
.
R
.
attr
.
state_pressed
),
pressed
)
selector
.
addState
(
intArrayOf
(
android
.
R
.
attr
.
state_selected
),
pressed
)
selector
.
addState
(
intArrayOf
(),
normal
)
return
selector
}
fun
toggle
()
{
this
.
isSelected
=
!
isSelected
}
}
\ No newline at end of file
video/library_tagflow/src/main/java/com/framework/tagflow/tags/StrokeTagView.kt
0 → 100755
View file @
cda8590c
package
com.aa.cat.ui.view.tagFlow.tags
import
android.content.Context
import
android.graphics.Color
import
android.util.AttributeSet
import
com.framework.tagflow.tags.DefaultTagView
/**
* @author: xiaxueyi
* @date: 2022-09-16
* @time: 11:02
* @说明:
*/
class
StrokeTagView
:
DefaultTagView
{
constructor
(
context
:
Context
)
:
super
(
context
)
{}
constructor
(
context
:
Context
,
attrs
:
AttributeSet
?)
:
super
(
context
,
attrs
)
{}
constructor
(
context
:
Context
,
attrs
:
AttributeSet
?,
defStyleAttr
:
Int
)
:
super
(
context
,
attrs
,
defStyleAttr
)
{
}
override
fun
isSolid
():
Boolean
{
return
false
}
override
fun
getStrokeWidth
():
Float
{
return
1F
}
override
fun
getNormalBackgroundColor
():
Int
{
return
Color
.
parseColor
(
"#000000"
)
}
override
fun
getPressedBackgroundColor
():
Int
{
return
Color
.
parseColor
(
"#aa666666"
)
}
}
\ No newline at end of file
video/library_tagflow/src/main/java/com/framework/tagflow/utils/DensityUtils.kt
0 → 100755
View file @
cda8590c
package
com.framework.tagflow.utils
import
android.content.Context
import
android.util.TypedValue
/**
* @author: xiaxueyi
* @date: 2022-09-19
* @time: 13:02
* @说明:
*/
class
DensityUtils
private
constructor
()
{
companion
object
{
/**
* dp转px
*
* @param context 上下文
* @param dpVal dp值
* @return result in px
*/
fun
dp2px
(
context
:
Context
,
dpVal
:
Float
):
Int
{
return
TypedValue
.
applyDimension
(
TypedValue
.
COMPLEX_UNIT_DIP
,
dpVal
,
context
.
resources
.
displayMetrics
).
toInt
()
}
/**
* sp转px
*
* @param context 上下文
* @param spVal sp值
* @return result in px
*/
fun
sp2px
(
context
:
Context
,
spVal
:
Float
):
Int
{
return
TypedValue
.
applyDimension
(
TypedValue
.
COMPLEX_UNIT_SP
,
spVal
,
context
.
resources
.
displayMetrics
).
toInt
()
}
/**
* px转dp
*
* @param context 上下文
* @param pxVal px值
* @return result in dp
*/
fun
px2dp
(
context
:
Context
,
pxVal
:
Float
):
Float
{
val
scale
=
context
.
resources
.
displayMetrics
.
density
return
pxVal
/
scale
}
/**
* px转sp
*
* @param context 上下文
* @param pxVal px值
* @return result in sp
*/
fun
px2sp
(
context
:
Context
,
pxVal
:
Float
):
Float
{
return
pxVal
/
context
.
resources
.
displayMetrics
.
scaledDensity
}
}
init
{
/* cannot be instantiated */
throw
UnsupportedOperationException
(
"cannot be instantiated"
)
}
}
\ No newline at end of file
video/library_tagflow/src/main/java/com/framework/tagflow/view/ControlScrollView.kt
0 → 100755
View file @
cda8590c
package
com.framework.tagflow.view
import
android.content.Context
import
android.util.AttributeSet
import
android.view.MotionEvent
import
android.widget.ScrollView
/**
* 可控制滑动,可控制固定
*/
class
ControlScrollView
:
ScrollView
{
private
var
forceFixed
=
false
//强制固定
private
var
canScroll
=
false
constructor
(
context
:
Context
?)
:
super
(
context
)
{}
constructor
(
context
:
Context
?,
attrs
:
AttributeSet
?)
:
super
(
context
,
attrs
)
{}
/**
* 是否可以滑动
* @return
*/
fun
isCanScroll
():
Boolean
{
return
canScroll
}
/**
* 设置是否可以滑动
* @param isCan
*/
fun
setCanScroll
(
isCan
:
Boolean
)
{
canScroll
=
isCan
}
/**
* 是否强制固定
* @return
*/
fun
isForceFixed
():
Boolean
{
return
forceFixed
}
/**
* 设置是否强制固定
* @param forceFixed
*/
fun
setForceFixed
(
forceFixed
:
Boolean
)
{
this
.
forceFixed
=
forceFixed
}
override
fun
dispatchTouchEvent
(
event
:
MotionEvent
):
Boolean
{
if
(!
forceFixed
&&
canScroll
)
{
parent
.
requestDisallowInterceptTouchEvent
(
true
)
}
return
super
.
dispatchTouchEvent
(
event
)
}
}
\ No newline at end of file
video/library_tagflow/src/main/java/com/framework/tagflow/view/FlowLayout.kt
0 → 100755
View file @
cda8590c
package
com.framework.tagflow.view
import
android.annotation.SuppressLint
import
android.content.Context
import
android.util.AttributeSet
import
android.view.View
import
android.view.ViewGroup
import
com.framework.tagflow.utils.DensityUtils
open
class
FlowLayout
:
ViewGroup
{
private
var
mContext
:
Context
?
=
null
private
var
mLines
:
MutableList
<
Line
>
=
ArrayList
()
// 记录当前有多少行
private
var
horizontalSpace
=
0
private
var
verticalSpace
=
0
private
var
mDefaultViewMaxWidth
:
Int
=
100
//子view默认宽度的最大值
private
var
mDefaultColumn
:
Int
=
3
;
//默认列数三列
private
var
mAverageWidth
:
Int
=
0
// 存储屏幕的1/3宽度
private
var
isNeedMinimumWidth
:
Boolean
=
true
//是否需要最小宽度值
/**
*
* @param context Context?
* @constructor
*/
constructor
(
context
:
Context
?)
:
super
(
context
)
{
mContext
=
context
}
/**
*
* @param context Context?
* @param attrs AttributeSet?
* @constructor
*/
constructor
(
context
:
Context
?,
attrs
:
AttributeSet
?)
:
super
(
context
,
attrs
)
{}
/**
*
* @param horizontalSpace Int
* @param verticalSpace Int
*/
fun
setSpace
(
horizontalSpace
:
Int
,
verticalSpace
:
Int
)
{
this
.
horizontalSpace
=
horizontalSpace
this
.
verticalSpace
=
verticalSpace
}
/**
* 获取单行的高度
* @return
*/
fun
getLineHeight
():
Int
{
return
if
(
mLines
.
size
>
0
)
{
mLines
[
0
].
height
}
else
{
0
}
}
/**
* 获取行数
* @return
*/
fun
getLineSize
():
Int
{
return
if
(
mLines
.
size
>
0
)
{
mLines
.
size
}
else
{
0
}
}
override
fun
onLayout
(
changed
:
Boolean
,
l
:
Int
,
t
:
Int
,
r
:
Int
,
b
:
Int
)
{
var
top
=
this
.
paddingTop
for
(
i
in
mLines
.
indices
)
{
val
line
=
mLines
[
i
]
// 自己布局
line
.
layout
(
top
,
this
.
paddingStart
)
top
+=
line
.
height
if
(
i
!=
mLines
.
size
-
1
)
{
top
+=
verticalSpace
}
}
}
@SuppressLint
(
"DrawAllocation"
)
override
fun
onMeasure
(
widthMeasureSpec
:
Int
,
heightMeasureSpec
:
Int
)
{
// 清空
mLines
.
clear
()
var
mCurrentLine
:
Line
?
=
null
// 获得容器的宽度
val
widthSize
=
MeasureSpec
.
getSize
(
widthMeasureSpec
)
//获取最大的宽
val
maxWidth
=
widthSize
-
this
.
paddingStart
-
this
.
paddingEnd
//子类的数量
val
childCount
=
this
.
childCount
//计算屏幕的三分之一宽度
mAverageWidth
=
maxWidth
/
mDefaultColumn
for
(
i
in
0
until
childCount
)
{
val
view
=
getChildAt
(
i
)
if
(
view
.
visibility
==
GONE
)
{
continue
}
if
(
isNeedMinimumWidth
){
val
min
=
widthSize
.
coerceAtMost
(
DensityUtils
.
dp2px
(
context
,
mDefaultViewMaxWidth
.
toFloat
()))
view
.
minimumWidth
=
min
}
// 测量孩子
measureChild
(
view
,
widthMeasureSpec
,
heightMeasureSpec
)
// 将孩子记录到行中
if
(
mCurrentLine
==
null
)
{
// 新建行
mCurrentLine
=
Line
(
maxWidth
,
horizontalSpace
)
// 记录行
mLines
.
add
(
mCurrentLine
)
// 给行添加孩子
mCurrentLine
.
addView
(
view
)
}
else
{
// 判断是否可以添加
if
(
mCurrentLine
.
canAdd
(
view
))
{
// 可以添加
mCurrentLine
.
addView
(
view
)
}
else
{
// 不可以添加
// 新建一行
mCurrentLine
=
Line
(
maxWidth
,
horizontalSpace
)
// 记录行
mLines
.
add
(
mCurrentLine
)
// 给行添加孩子
mCurrentLine
.
addView
(
view
)
}
}
}
// 设置自己的宽度和高度
var
measuredHeight
=
this
.
paddingTop
+
this
.
paddingBottom
// 添加行的高度
for
(
i
in
mLines
.
indices
)
{
measuredHeight
+=
mLines
[
i
].
height
}
// 间距
measuredHeight
+=
(
mLines
.
size
-
1
)
*
verticalSpace
// 设置自己的宽度和高度
setMeasuredDimension
(
widthSize
,
measuredHeight
)
}
private
inner
class
Line
(
private
var
maxWidth
:
Int
,
// 行最大宽度
private
var
space
:
Int
// view和view之间的间隔
)
{
// 属性,方法,构造
// 行中的控件
private
val
mViews
:
MutableList
<
View
>
=
ArrayList
()
private
var
usedWidth
=
0
// 已经使用的宽度
var
height
=
0
// 行的高度
/**
*
* @param top Int
* @param left Int
*/
fun
layout
(
top
:
Int
,
left
:
Int
)
{
// 给view布局
var
mleft
=
left
for
(
i
in
mViews
.
indices
)
{
val
view
=
mViews
[
i
]
var
viewWidth
=
view
.
measuredWidth
var
viewHeight
=
view
.
measuredHeight
view
.
measure
(
MeasureSpec
.
makeMeasureSpec
(
viewWidth
,
MeasureSpec
.
EXACTLY
),
MeasureSpec
.
makeMeasureSpec
(
viewHeight
,
MeasureSpec
.
EXACTLY
))
viewWidth
=
view
.
measuredWidth
viewHeight
=
view
.
measuredHeight
val
avgHeight
=
((
height
-
viewHeight
)
/
2f
+
0.5f
).
toInt
()
val
vLeft
=
mleft
val
vTop
=
top
+
avgHeight
val
vRight
=
vLeft
+
viewWidth
val
vBottom
=
vTop
+
viewHeight
view
.
layout
(
vLeft
,
vTop
,
vRight
,
vBottom
)
mleft
+=
space
+
viewWidth
}
}
/**
* 添加view的方法
*
* @param view
*/
fun
addView
(
view
:
View
)
{
val
viewWidth
=
view
.
measuredWidth
val
viewHeight
=
view
.
measuredHeight
if
(
mViews
.
size
==
0
)
{
if
(
viewWidth
>
maxWidth
)
{
usedWidth
=
maxWidth
height
=
viewHeight
}
else
{
usedWidth
=
viewWidth
height
=
viewHeight
}
}
else
{
usedWidth
+=
space
+
viewWidth
height
=
if
(
height
>
viewHeight
)
height
else
viewHeight
// 选择大的高度
}
mViews
.
add
(
view
)
}
/**
* 判断是否可以往行中添加控件
*
* @param view
*/
fun
canAdd
(
view
:
View
):
Boolean
{
if
(
mViews
.
size
==
0
)
{
return
true
}
// 已经使用的 + 间距+ 要加的view的宽度 > maxWidth ,添加不进来
// return usedWidth + space + view.measuredWidth <= maxWidth
return
usedWidth
+
view
.
measuredWidth
<=
maxWidth
}
}
fun
clearAllView
()
{
mLines
=
ArrayList
()
this
.
invalidate
()
}
}
\ No newline at end of file
video/library_tagflow/src/main/res/drawable-xhdpi/common_icon_down_arrow.png
0 → 100755
View file @
cda8590c
487 Bytes
video/library_tagflow/src/main/res/drawable-xhdpi/tag_flow_layout_arrow_bg.xml
0 → 100755
View file @
cda8590c
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:shape=
"rectangle"
>
<solid
android:color=
"@color/color_F5F3F0"
/>
<stroke
android:width=
"@dimen/dp_1"
android:color=
"@color/color_CCC8C2"
/>
<corners
android:radius=
"@dimen/dp_30"
/>
</shape>
\ No newline at end of file
video/library_tagflow/src/main/res/drawable-xhdpi/toast_background.xml
0 → 100755
View file @
cda8590c
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<corners
android:radius=
"@dimen/dp_8"
/>
<solid
android:color=
"#80000000"
/>
</shape>
\ No newline at end of file
video/library_tagflow/src/main/res/drawable/common_bg_radius_15_white.xml
0 → 100755
View file @
cda8590c
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:shape=
"rectangle"
>
<solid
android:color=
"@color/white"
/>
<corners
android:radius=
"@dimen/dp_15"
/>
</shape>
\ No newline at end of file
video/library_tagflow/src/main/res/drawable/common_bg_radius_white.xml
0 → 100755
View file @
cda8590c
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:shape=
"rectangle"
>
<solid
android:color=
"@color/white"
/>
<corners
android:radius=
"@dimen/dp_0"
/>
</shape>
\ No newline at end of file
video/library_tagflow/src/main/res/drawable/common_icon_down_arrow.png
0 → 100755
View file @
cda8590c
487 Bytes
video/library_tagflow/src/main/res/drawable/tag_flow_layout_arrow_bg.xml
0 → 100755
View file @
cda8590c
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:shape=
"rectangle"
>
<solid
android:color=
"@color/color_F5F3F0"
/>
<stroke
android:width=
"@dimen/dp_1"
android:color=
"@color/color_CCC8C2"
/>
<corners
android:radius=
"@dimen/dp_30"
/>
</shape>
\ No newline at end of file
video/library_tagflow/src/main/res/drawable/toast_background.xml
0 → 100755
View file @
cda8590c
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<corners
android:radius=
"@dimen/dp_8"
/>
<solid
android:color=
"#80000000"
/>
</shape>
\ No newline at end of file
video/library_tagflow/src/main/res/layout/custom_toast.xml
0 → 100755
View file @
cda8590c
<?xml version="1.0" encoding="utf-8"?>
<!--toast Textview-->
<TextView
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:tools=
"http://schemas.android.com/tools"
android:id=
"@+id/ad_hoc_toast_textview"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:paddingStart=
"@dimen/dp_15"
android:paddingEnd=
"@dimen/dp_15"
android:paddingTop=
"@dimen/dp_12"
android:paddingBottom=
"@dimen/dp_12"
android:layout_margin=
"@dimen/dp_20"
android:background=
"@drawable/toast_background"
android:textColor=
"#1e1e1e"
android:gravity=
"center"
android:visibility=
"visible"
android:layout_alignParentBottom=
"true"
tools:text=
"message ..."
/>
\ No newline at end of file
video/library_tagflow/src/main/res/layout/layout_empty_not_data.xml
0 → 100755
View file @
cda8590c
<?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:id=
"@+id/empty_view"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:gravity=
"center"
android:background=
"@color/color_transparent"
android:orientation=
"vertical"
>
<TextView
android:id=
"@+id/title"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:layout_gravity=
"center"
android:gravity=
"center"
android:textColor=
"@color/color_333333"
android:textSize=
"@dimen/sp_15"
android:textStyle=
"normal"
android:text=
"暂无数据"
app:layout_constraintTop_toTopOf=
"parent"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
video/library_tagflow/src/main/res/layout/tag_flow_layout.xml
0 → 100755
View file @
cda8590c
<?xml version="1.0" encoding="utf-8"?>
<merge
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
>
<LinearLayout
android:id=
"@+id/ll_tag_layout"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:orientation=
"vertical"
>
<FrameLayout
android:id=
"@+id/fl_empty"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:layout_gravity=
"center"
android:visibility=
"gone"
/>
<com.framework.tagflow.view.ControlScrollView
android:id=
"@+id/hsv_tag_content"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:scrollbars=
"none"
/>
<LinearLayout
android:id=
"@+id/rl_show_more"
android:orientation=
"vertical"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center"
android:padding=
"@dimen/dp_3"
>
<LinearLayout
android:orientation=
"horizontal"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center"
android:focusable=
"auto"
android:gravity=
"center"
android:layout_margin=
"@dimen/dp_2"
android:paddingStart=
"@dimen/dp_5"
android:paddingEnd=
"@dimen/dp_5"
>
<TextView
android:id=
"@+id/tv_more_hint"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:text=
"@string/expandHint"
android:textStyle=
"bold"
android:textColor=
"#262626"
android:textSize=
"@dimen/sp_14"
android:layout_gravity=
"center"
android:layout_marginStart=
"@dimen/dp_5"
android:layout_marginEnd=
"@dimen/dp_5"
android:gravity=
"center"
android:visibility=
"visible"
/>
<ImageView
android:id=
"@+id/iv_arrow_more"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center"
android:src=
"@drawable/common_icon_down_arrow"
/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</merge>
\ No newline at end of file
video/library_tagflow/src/main/res/values/attrs.xml
0 → 100755
View file @
cda8590c
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--流布局-->
<declare-styleable
name=
"TagFlowLayout"
>
<attr
name=
"tagsHorizontalSpace"
format=
"dimension"
/>
<attr
name=
"tagsVerticalSpace"
format=
"dimension"
/>
<attr
name=
"animationDuration"
format=
"integer"
/>
<attr
name=
"hasMore"
format=
"boolean"
/>
<attr
name=
"foldHint"
format=
"reference|string"
/>
<attr
name=
"expandHint"
format=
"reference|string"
/>
<!--布局类型,列表或者-->
<attr
name=
"layout_type"
format=
"reference"
>
<enum
name=
"RecyclerView"
value=
"0"
/>
<enum
name=
"FlowLayout"
value=
"1"
/>
</attr>
<!--LayoutManager 模式-->
<attr
name=
"layoutManager_Mode"
format=
"reference"
>
<enum
name=
"LinearLayoutManager"
value=
"0"
/>
<enum
name=
"GridLayoutManager"
value=
"1"
/>
</attr>
</declare-styleable>
</resources>
\ No newline at end of file
video/library_tagflow/src/main/res/values/colors.xml
0 → 100755
View file @
cda8590c
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- text color -->
<color
name=
"color_4D4D4D"
>
#4D4D4D
</color>
<color
name=
"color_333333"
>
#333333
</color>
<color
name=
"color_FCFCFC"
>
#FCFCFC
</color>
<color
name=
"color_808080"
>
#808080
</color>
<!-- image color -->
<color
name=
"color_D6D0C7"
>
#D6D0C7
</color>
<color
name=
"color_E8E4DF"
>
#E8E4DF
</color>
<color
name=
"color_F5B95F"
>
#F5B95F
</color>
<color
name=
"color_F8E49E"
>
#F8E49E
</color>
<color
name=
"color_959595"
>
#959595
</color>
<!-- bg color -->
<color
name=
"color_F2FFFFFF"
>
#F2FFFFFF
</color>
<color
name=
"color_11AB9B"
>
#11AB9B
</color>
<color
name=
"color_EF6A39"
>
#EF6A39
</color>
<color
name=
"color_F0E4D3"
>
#F0E4D3
</color>
<color
name=
"color_F0EDE9"
>
#F0EDE9
</color>
<color
name=
"color_F0E8DE"
>
#F0E8DE
</color>
<color
name=
"color_f6Ce7e"
>
#f6Ce7e
</color>
<color
name=
"color_FFFDFA"
>
#FFFDFA
</color>
<color
name=
"color_FFFFFF"
>
#FFFFFF
</color>
<color
name=
"color_FAF9F7"
>
#FAF9F7
</color>
<color
name=
"color_F5A05F"
>
#f5a05f
</color>
<!-- shadow color-->
<color
name=
"color_F5F3F0"
>
#F5F3F0
</color>
<color
name=
"white"
>
#FFFFFF
</color>
<color
name=
"color_8C8B89"
>
#8C8B89
</color>
<!--Line-->
<color
name=
"color_CCC8C2"
>
#33CCC8C2
</color>
<color
name=
"color_8A8A8A"
>
#8a8a8a
</color>
<color
name=
"color_EAEAEA"
>
#EAEAEA
</color>
<!--tagflow-->
<color
name=
"secondary_text"
>
#8a000000
</color>
<color
name=
"tag_layout_bg"
>
#def2f2f2
</color>
<color
name=
"dividers"
>
#1f000000
</color>
<!--标题搜索框背景颜色-->
<color
name=
"common_toolbar_search_bg_color"
>
#208C8B89
</color>
<!--标题搜索框说明性文字颜色-->
<color
name=
"common_toolbar_search_title_hint_text_color"
>
#7f7f7f
</color>
<color
name=
"color_transparent"
>
#00000000
</color>
<!-- 彈窗 -->
<color
name=
"list_line_color"
>
#ccc8c2
</color>
<color
name=
"color_8a8894"
>
#8a8894
</color>
</resources>
\ No newline at end of file
video/library_tagflow/src/main/res/values/dimens.xml
0 → 100755
View file @
cda8590c
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen
name=
"text_size_15_sp"
>
15sp
</dimen>
<dimen
name=
"dp_0"
>
0dp
</dimen>
<dimen
name=
"dp_0_1"
>
0.1dp
</dimen>
<dimen
name=
"dp_0_5"
>
0.5dp
</dimen>
<dimen
name=
"dp_1"
>
1dp
</dimen>
<dimen
name=
"dp_1_5"
>
1.5dp
</dimen>
<dimen
name=
"dp_2"
>
2dp
</dimen>
<dimen
name=
"dp_2_5"
>
2.5dp
</dimen>
<dimen
name=
"dp_3"
>
3dp
</dimen>
<dimen
name=
"dp_3_5"
>
3.5dp
</dimen>
<dimen
name=
"dp_4"
>
4dp
</dimen>
<dimen
name=
"dp_4_5"
>
4.5dp
</dimen>
<dimen
name=
"dp_5"
>
5dp
</dimen>
<dimen
name=
"dp_6"
>
6dp
</dimen>
<dimen
name=
"dp_7"
>
7dp
</dimen>
<dimen
name=
"dp_7_5"
>
7.5dp
</dimen>
<dimen
name=
"dp_8"
>
8dp
</dimen>
<dimen
name=
"dp_9"
>
9dp
</dimen>
<dimen
name=
"dp_10"
>
10dp
</dimen>
<dimen
name=
"dp_11"
>
11dp
</dimen>
<dimen
name=
"dp_12"
>
12dp
</dimen>
<dimen
name=
"dp_13"
>
13dp
</dimen>
<dimen
name=
"dp_14"
>
14dp
</dimen>
<dimen
name=
"dp_15"
>
15dp
</dimen>
<dimen
name=
"dp_16"
>
16dp
</dimen>
<dimen
name=
"dp_17"
>
17dp
</dimen>
<dimen
name=
"dp_18"
>
18dp
</dimen>
<dimen
name=
"dp_19"
>
19dp
</dimen>
<dimen
name=
"dp_20"
>
20dp
</dimen>
<dimen
name=
"dp_21"
>
21dp
</dimen>
<dimen
name=
"dp_22"
>
22dp
</dimen>
<dimen
name=
"dp_23"
>
23dp
</dimen>
<dimen
name=
"dp_24"
>
24dp
</dimen>
<dimen
name=
"dp_25"
>
25dp
</dimen>
<dimen
name=
"dp_26"
>
26dp
</dimen>
<dimen
name=
"dp_27"
>
27dp
</dimen>
<dimen
name=
"dp_28"
>
28dp
</dimen>
<dimen
name=
"dp_29"
>
29dp
</dimen>
<dimen
name=
"dp_30"
>
30dp
</dimen>
<dimen
name=
"dp_31"
>
31dp
</dimen>
<dimen
name=
"dp_32"
>
32dp
</dimen>
<dimen
name=
"dp_33"
>
33dp
</dimen>
<dimen
name=
"dp_34"
>
34dp
</dimen>
<dimen
name=
"dp_35"
>
35dp
</dimen>
<dimen
name=
"dp_36"
>
36dp
</dimen>
<dimen
name=
"dp_37"
>
37dp
</dimen>
<dimen
name=
"dp_38"
>
38dp
</dimen>
<dimen
name=
"dp_39"
>
39dp
</dimen>
<dimen
name=
"dp_40"
>
40dp
</dimen>
<dimen
name=
"dp_41"
>
41dp
</dimen>
<dimen
name=
"dp_42"
>
42dp
</dimen>
<dimen
name=
"dp_43"
>
43dp
</dimen>
<dimen
name=
"dp_44"
>
44dp
</dimen>
<dimen
name=
"dp_45"
>
45dp
</dimen>
<dimen
name=
"dp_46"
>
46dp
</dimen>
<dimen
name=
"dp_47"
>
47dp
</dimen>
<dimen
name=
"dp_48"
>
48dp
</dimen>
<dimen
name=
"dp_49"
>
49dp
</dimen>
<dimen
name=
"dp_50"
>
50dp
</dimen>
<dimen
name=
"dp_51"
>
51dp
</dimen>
<dimen
name=
"dp_52"
>
52dp
</dimen>
<dimen
name=
"dp_53"
>
53dp
</dimen>
<dimen
name=
"dp_54"
>
54dp
</dimen>
<dimen
name=
"dp_55"
>
55dp
</dimen>
<dimen
name=
"dp_56"
>
56dp
</dimen>
<dimen
name=
"dp_57"
>
57dp
</dimen>
<dimen
name=
"dp_58"
>
58dp
</dimen>
<dimen
name=
"dp_59"
>
59dp
</dimen>
<dimen
name=
"dp_60"
>
60dp
</dimen>
<dimen
name=
"dp_61"
>
61dp
</dimen>
<dimen
name=
"dp_62"
>
62dp
</dimen>
<dimen
name=
"dp_63"
>
63dp
</dimen>
<dimen
name=
"dp_64"
>
64dp
</dimen>
<dimen
name=
"dp_65"
>
65dp
</dimen>
<dimen
name=
"dp_66"
>
66dp
</dimen>
<dimen
name=
"dp_67"
>
67dp
</dimen>
<dimen
name=
"dp_68"
>
68dp
</dimen>
<dimen
name=
"dp_69"
>
69dp
</dimen>
<dimen
name=
"dp_70"
>
70dp
</dimen>
<dimen
name=
"dp_71"
>
71dp
</dimen>
<dimen
name=
"dp_72"
>
72dp
</dimen>
<dimen
name=
"dp_73"
>
73dp
</dimen>
<dimen
name=
"dp_74"
>
74dp
</dimen>
<dimen
name=
"dp_75"
>
75dp
</dimen>
<dimen
name=
"dp_76"
>
76dp
</dimen>
<dimen
name=
"dp_77"
>
77dp
</dimen>
<dimen
name=
"dp_78"
>
78dp
</dimen>
<dimen
name=
"dp_79"
>
79dp
</dimen>
<dimen
name=
"dp_80"
>
80dp
</dimen>
<dimen
name=
"dp_81"
>
81dp
</dimen>
<dimen
name=
"dp_82"
>
82dp
</dimen>
<dimen
name=
"dp_83"
>
83dp
</dimen>
<dimen
name=
"dp_84"
>
84dp
</dimen>
<dimen
name=
"dp_85"
>
85dp
</dimen>
<dimen
name=
"dp_86"
>
86dp
</dimen>
<dimen
name=
"dp_87"
>
87dp
</dimen>
<dimen
name=
"dp_88"
>
88dp
</dimen>
<dimen
name=
"dp_89"
>
89dp
</dimen>
<dimen
name=
"dp_90"
>
90dp
</dimen>
<dimen
name=
"dp_91"
>
91dp
</dimen>
<dimen
name=
"dp_92"
>
92dp
</dimen>
<dimen
name=
"dp_93"
>
93dp
</dimen>
<dimen
name=
"dp_94"
>
94dp
</dimen>
<dimen
name=
"dp_95"
>
95dp
</dimen>
<dimen
name=
"dp_96"
>
96dp
</dimen>
<dimen
name=
"dp_97"
>
97dp
</dimen>
<dimen
name=
"dp_98"
>
98dp
</dimen>
<dimen
name=
"dp_99"
>
99dp
</dimen>
<dimen
name=
"dp_100"
>
100dp
</dimen>
<dimen
name=
"dp_101"
>
101dp
</dimen>
<dimen
name=
"dp_102"
>
102dp
</dimen>
<dimen
name=
"dp_103"
>
103dp
</dimen>
<dimen
name=
"dp_104"
>
104dp
</dimen>
<dimen
name=
"dp_104_5"
>
104.5dp
</dimen>
<dimen
name=
"dp_105"
>
105dp
</dimen>
<dimen
name=
"dp_106"
>
106dp
</dimen>
<dimen
name=
"dp_107"
>
107dp
</dimen>
<dimen
name=
"dp_108"
>
108dp
</dimen>
<dimen
name=
"dp_109"
>
109dp
</dimen>
<dimen
name=
"dp_110"
>
110dp
</dimen>
<dimen
name=
"dp_111"
>
111dp
</dimen>
<dimen
name=
"dp_112"
>
112dp
</dimen>
<dimen
name=
"dp_113"
>
113dp
</dimen>
<dimen
name=
"dp_114"
>
114dp
</dimen>
<dimen
name=
"dp_115"
>
115dp
</dimen>
<dimen
name=
"dp_116"
>
116dp
</dimen>
<dimen
name=
"dp_117"
>
117dp
</dimen>
<dimen
name=
"dp_118"
>
118dp
</dimen>
<dimen
name=
"dp_119"
>
119dp
</dimen>
<dimen
name=
"dp_120"
>
120dp
</dimen>
<dimen
name=
"dp_121"
>
121dp
</dimen>
<dimen
name=
"dp_122"
>
122dp
</dimen>
<dimen
name=
"dp_123"
>
123dp
</dimen>
<dimen
name=
"dp_124"
>
124dp
</dimen>
<dimen
name=
"dp_125"
>
125dp
</dimen>
<dimen
name=
"dp_126"
>
126dp
</dimen>
<dimen
name=
"dp_127"
>
127dp
</dimen>
<dimen
name=
"dp_128"
>
128dp
</dimen>
<dimen
name=
"dp_129"
>
129dp
</dimen>
<dimen
name=
"dp_130"
>
130dp
</dimen>
<dimen
name=
"dp_131"
>
131dp
</dimen>
<dimen
name=
"dp_132"
>
132dp
</dimen>
<dimen
name=
"dp_133"
>
133dp
</dimen>
<dimen
name=
"dp_134"
>
134dp
</dimen>
<dimen
name=
"dp_134_5"
>
134.5dp
</dimen>
<dimen
name=
"dp_135"
>
135dp
</dimen>
<dimen
name=
"dp_136"
>
136dp
</dimen>
<dimen
name=
"dp_137"
>
137dp
</dimen>
<dimen
name=
"dp_138"
>
138dp
</dimen>
<dimen
name=
"dp_139"
>
139dp
</dimen>
<dimen
name=
"dp_140"
>
140dp
</dimen>
<dimen
name=
"dp_141"
>
141dp
</dimen>
<dimen
name=
"dp_142"
>
142dp
</dimen>
<dimen
name=
"dp_143"
>
143dp
</dimen>
<dimen
name=
"dp_144"
>
144dp
</dimen>
<dimen
name=
"dp_145"
>
145dp
</dimen>
<dimen
name=
"dp_146"
>
146dp
</dimen>
<dimen
name=
"dp_147"
>
147dp
</dimen>
<dimen
name=
"dp_148"
>
148dp
</dimen>
<dimen
name=
"dp_149"
>
149dp
</dimen>
<dimen
name=
"dp_150"
>
150dp
</dimen>
<dimen
name=
"dp_151"
>
151dp
</dimen>
<dimen
name=
"dp_152"
>
152dp
</dimen>
<dimen
name=
"dp_153"
>
153dp
</dimen>
<dimen
name=
"dp_154"
>
154dp
</dimen>
<dimen
name=
"dp_155"
>
155dp
</dimen>
<dimen
name=
"dp_156"
>
156dp
</dimen>
<dimen
name=
"dp_157"
>
157dp
</dimen>
<dimen
name=
"dp_158"
>
158dp
</dimen>
<dimen
name=
"dp_159"
>
159dp
</dimen>
<dimen
name=
"dp_160"
>
160dp
</dimen>
<dimen
name=
"dp_161"
>
161dp
</dimen>
<dimen
name=
"dp_162"
>
162dp
</dimen>
<dimen
name=
"dp_163"
>
163dp
</dimen>
<dimen
name=
"dp_164"
>
164dp
</dimen>
<dimen
name=
"dp_165"
>
165dp
</dimen>
<dimen
name=
"dp_166"
>
166dp
</dimen>
<dimen
name=
"dp_167"
>
167dp
</dimen>
<dimen
name=
"dp_168"
>
168dp
</dimen>
<dimen
name=
"dp_169"
>
169dp
</dimen>
<dimen
name=
"dp_170"
>
170dp
</dimen>
<dimen
name=
"dp_171"
>
171dp
</dimen>
<dimen
name=
"dp_172"
>
172dp
</dimen>
<dimen
name=
"dp_173"
>
173dp
</dimen>
<dimen
name=
"dp_174"
>
174dp
</dimen>
<dimen
name=
"dp_175"
>
175dp
</dimen>
<dimen
name=
"dp_176"
>
176dp
</dimen>
<dimen
name=
"dp_177"
>
177dp
</dimen>
<dimen
name=
"dp_178"
>
178dp
</dimen>
<dimen
name=
"dp_179"
>
179dp
</dimen>
<dimen
name=
"dp_180"
>
180dp
</dimen>
<dimen
name=
"dp_181"
>
181dp
</dimen>
<dimen
name=
"dp_182"
>
182dp
</dimen>
<dimen
name=
"dp_183"
>
183dp
</dimen>
<dimen
name=
"dp_184"
>
184dp
</dimen>
<dimen
name=
"dp_185"
>
185dp
</dimen>
<dimen
name=
"dp_186"
>
186dp
</dimen>
<dimen
name=
"dp_187"
>
187dp
</dimen>
<dimen
name=
"dp_188"
>
188dp
</dimen>
<dimen
name=
"dp_189"
>
189dp
</dimen>
<dimen
name=
"dp_190"
>
190dp
</dimen>
<dimen
name=
"dp_191"
>
191dp
</dimen>
<dimen
name=
"dp_191_25"
>
191.25dp
</dimen>
<dimen
name=
"dp_192"
>
192dp
</dimen>
<dimen
name=
"dp_193"
>
193dp
</dimen>
<dimen
name=
"dp_194"
>
194dp
</dimen>
<dimen
name=
"dp_195"
>
195dp
</dimen>
<dimen
name=
"dp_196"
>
196dp
</dimen>
<dimen
name=
"dp_197"
>
197dp
</dimen>
<dimen
name=
"dp_198"
>
198dp
</dimen>
<dimen
name=
"dp_199"
>
199dp
</dimen>
<dimen
name=
"dp_200"
>
200dp
</dimen>
<dimen
name=
"dp_201"
>
201dp
</dimen>
<dimen
name=
"dp_202"
>
202dp
</dimen>
<dimen
name=
"dp_203"
>
203dp
</dimen>
<dimen
name=
"dp_204"
>
204dp
</dimen>
<dimen
name=
"dp_205"
>
205dp
</dimen>
<dimen
name=
"dp_206"
>
206dp
</dimen>
<dimen
name=
"dp_207"
>
207dp
</dimen>
<dimen
name=
"dp_208"
>
208dp
</dimen>
<dimen
name=
"dp_209"
>
209dp
</dimen>
<dimen
name=
"dp_210"
>
210dp
</dimen>
<dimen
name=
"dp_211"
>
211dp
</dimen>
<dimen
name=
"dp_212"
>
212dp
</dimen>
<dimen
name=
"dp_213"
>
213dp
</dimen>
<dimen
name=
"dp_214"
>
214dp
</dimen>
<dimen
name=
"dp_215"
>
215dp
</dimen>
<dimen
name=
"dp_216"
>
216dp
</dimen>
<dimen
name=
"dp_217"
>
217dp
</dimen>
<dimen
name=
"dp_218"
>
218dp
</dimen>
<dimen
name=
"dp_219"
>
219dp
</dimen>
<dimen
name=
"dp_220"
>
220dp
</dimen>
<dimen
name=
"dp_221"
>
221dp
</dimen>
<dimen
name=
"dp_222"
>
222dp
</dimen>
<dimen
name=
"dp_223"
>
223dp
</dimen>
<dimen
name=
"dp_224"
>
224dp
</dimen>
<dimen
name=
"dp_225"
>
225dp
</dimen>
<dimen
name=
"dp_226"
>
226dp
</dimen>
<dimen
name=
"dp_227"
>
227dp
</dimen>
<dimen
name=
"dp_228"
>
228dp
</dimen>
<dimen
name=
"dp_229"
>
229dp
</dimen>
<dimen
name=
"dp_230"
>
230dp
</dimen>
<dimen
name=
"dp_231"
>
231dp
</dimen>
<dimen
name=
"dp_232"
>
232dp
</dimen>
<dimen
name=
"dp_233"
>
233dp
</dimen>
<dimen
name=
"dp_234"
>
234dp
</dimen>
<dimen
name=
"dp_235"
>
235dp
</dimen>
<dimen
name=
"dp_236"
>
236dp
</dimen>
<dimen
name=
"dp_237"
>
237dp
</dimen>
<dimen
name=
"dp_238"
>
238dp
</dimen>
<dimen
name=
"dp_239"
>
239dp
</dimen>
<dimen
name=
"dp_240"
>
240dp
</dimen>
<dimen
name=
"dp_241"
>
241dp
</dimen>
<dimen
name=
"dp_242"
>
242dp
</dimen>
<dimen
name=
"dp_243"
>
243dp
</dimen>
<dimen
name=
"dp_244"
>
244dp
</dimen>
<dimen
name=
"dp_245"
>
245dp
</dimen>
<dimen
name=
"dp_246"
>
246dp
</dimen>
<dimen
name=
"dp_247"
>
247dp
</dimen>
<dimen
name=
"dp_248"
>
248dp
</dimen>
<dimen
name=
"dp_249"
>
249dp
</dimen>
<dimen
name=
"dp_250"
>
250dp
</dimen>
<dimen
name=
"dp_251"
>
251dp
</dimen>
<dimen
name=
"dp_252"
>
252dp
</dimen>
<dimen
name=
"dp_253"
>
253dp
</dimen>
<dimen
name=
"dp_254"
>
254dp
</dimen>
<dimen
name=
"dp_255"
>
255dp
</dimen>
<dimen
name=
"dp_256"
>
256dp
</dimen>
<dimen
name=
"dp_257"
>
257dp
</dimen>
<dimen
name=
"dp_258"
>
258dp
</dimen>
<dimen
name=
"dp_259"
>
259dp
</dimen>
<dimen
name=
"dp_260"
>
260dp
</dimen>
<dimen
name=
"dp_261"
>
261dp
</dimen>
<dimen
name=
"dp_262"
>
262dp
</dimen>
<dimen
name=
"dp_263"
>
263dp
</dimen>
<dimen
name=
"dp_264"
>
264dp
</dimen>
<dimen
name=
"dp_265"
>
265dp
</dimen>
<dimen
name=
"dp_266"
>
266dp
</dimen>
<dimen
name=
"dp_267"
>
267dp
</dimen>
<dimen
name=
"dp_268"
>
268dp
</dimen>
<dimen
name=
"dp_269"
>
269dp
</dimen>
<dimen
name=
"dp_270"
>
270dp
</dimen>
<dimen
name=
"dp_271"
>
271dp
</dimen>
<dimen
name=
"dp_272"
>
272dp
</dimen>
<dimen
name=
"dp_273"
>
273dp
</dimen>
<dimen
name=
"dp_274"
>
274dp
</dimen>
<dimen
name=
"dp_275"
>
275dp
</dimen>
<dimen
name=
"dp_276"
>
276dp
</dimen>
<dimen
name=
"dp_277"
>
277dp
</dimen>
<dimen
name=
"dp_278"
>
278dp
</dimen>
<dimen
name=
"dp_279"
>
279dp
</dimen>
<dimen
name=
"dp_280"
>
280dp
</dimen>
<dimen
name=
"dp_281"
>
281dp
</dimen>
<dimen
name=
"dp_282"
>
282dp
</dimen>
<dimen
name=
"dp_283"
>
283dp
</dimen>
<dimen
name=
"dp_284"
>
284dp
</dimen>
<dimen
name=
"dp_285"
>
285dp
</dimen>
<dimen
name=
"dp_286"
>
286dp
</dimen>
<dimen
name=
"dp_287"
>
287dp
</dimen>
<dimen
name=
"dp_288"
>
288dp
</dimen>
<dimen
name=
"dp_289"
>
289dp
</dimen>
<dimen
name=
"dp_290"
>
290dp
</dimen>
<dimen
name=
"dp_291"
>
291dp
</dimen>
<dimen
name=
"dp_292"
>
292dp
</dimen>
<dimen
name=
"dp_293"
>
293dp
</dimen>
<dimen
name=
"dp_294"
>
294dp
</dimen>
<dimen
name=
"dp_295"
>
295dp
</dimen>
<dimen
name=
"dp_296"
>
296dp
</dimen>
<dimen
name=
"dp_297"
>
297dp
</dimen>
<dimen
name=
"dp_298"
>
298dp
</dimen>
<dimen
name=
"dp_299"
>
299dp
</dimen>
<dimen
name=
"dp_300"
>
300dp
</dimen>
<dimen
name=
"dp_301"
>
301dp
</dimen>
<dimen
name=
"dp_302"
>
302dp
</dimen>
<dimen
name=
"dp_303"
>
303dp
</dimen>
<dimen
name=
"dp_304"
>
304dp
</dimen>
<dimen
name=
"dp_305"
>
305dp
</dimen>
<dimen
name=
"dp_306"
>
306dp
</dimen>
<dimen
name=
"dp_307"
>
307dp
</dimen>
<dimen
name=
"dp_308"
>
308dp
</dimen>
<dimen
name=
"dp_309"
>
309dp
</dimen>
<dimen
name=
"dp_310"
>
310dp
</dimen>
<dimen
name=
"dp_311"
>
311dp
</dimen>
<dimen
name=
"dp_312"
>
312dp
</dimen>
<dimen
name=
"dp_313"
>
313dp
</dimen>
<dimen
name=
"dp_314"
>
314dp
</dimen>
<dimen
name=
"dp_315"
>
315dp
</dimen>
<dimen
name=
"dp_316"
>
316dp
</dimen>
<dimen
name=
"dp_317"
>
317dp
</dimen>
<dimen
name=
"dp_318"
>
318dp
</dimen>
<dimen
name=
"dp_319"
>
319dp
</dimen>
<dimen
name=
"dp_320"
>
320dp
</dimen>
<dimen
name=
"dp_321"
>
321dp
</dimen>
<dimen
name=
"dp_322"
>
322dp
</dimen>
<dimen
name=
"dp_323"
>
323dp
</dimen>
<dimen
name=
"dp_324"
>
324dp
</dimen>
<dimen
name=
"dp_325"
>
325dp
</dimen>
<dimen
name=
"dp_326"
>
326dp
</dimen>
<dimen
name=
"dp_327"
>
327dp
</dimen>
<dimen
name=
"dp_328"
>
328dp
</dimen>
<dimen
name=
"dp_329"
>
329dp
</dimen>
<dimen
name=
"dp_330"
>
330dp
</dimen>
<dimen
name=
"dp_331"
>
331dp
</dimen>
<dimen
name=
"dp_332"
>
332dp
</dimen>
<dimen
name=
"dp_333"
>
333dp
</dimen>
<dimen
name=
"dp_334"
>
334dp
</dimen>
<dimen
name=
"dp_335"
>
335dp
</dimen>
<dimen
name=
"dp_336"
>
336dp
</dimen>
<dimen
name=
"dp_337"
>
337dp
</dimen>
<dimen
name=
"dp_338"
>
338dp
</dimen>
<dimen
name=
"dp_339"
>
339dp
</dimen>
<dimen
name=
"dp_340"
>
340dp
</dimen>
<dimen
name=
"dp_341"
>
341dp
</dimen>
<dimen
name=
"dp_342"
>
342dp
</dimen>
<dimen
name=
"dp_343"
>
343dp
</dimen>
<dimen
name=
"dp_344"
>
344dp
</dimen>
<dimen
name=
"dp_345"
>
345dp
</dimen>
<dimen
name=
"dp_346"
>
346dp
</dimen>
<dimen
name=
"dp_347"
>
347dp
</dimen>
<dimen
name=
"dp_348"
>
348dp
</dimen>
<dimen
name=
"dp_349"
>
349dp
</dimen>
<dimen
name=
"dp_350"
>
350dp
</dimen>
<dimen
name=
"dp_351"
>
351dp
</dimen>
<dimen
name=
"dp_352"
>
352dp
</dimen>
<dimen
name=
"dp_353"
>
353dp
</dimen>
<dimen
name=
"dp_354"
>
354dp
</dimen>
<dimen
name=
"dp_355"
>
355dp
</dimen>
<dimen
name=
"dp_356"
>
356dp
</dimen>
<dimen
name=
"dp_357"
>
357dp
</dimen>
<dimen
name=
"dp_358"
>
358dp
</dimen>
<dimen
name=
"dp_359"
>
359dp
</dimen>
<dimen
name=
"dp_360"
>
360dp
</dimen>
<dimen
name=
"dp_365"
>
365dp
</dimen>
<dimen
name=
"dp_370"
>
370dp
</dimen>
<dimen
name=
"dp_400"
>
400dp
</dimen>
<dimen
name=
"dp_410"
>
410dp
</dimen>
<dimen
name=
"dp_422"
>
422dp
</dimen>
<dimen
name=
"dp_472"
>
472dp
</dimen>
<dimen
name=
"dp_500"
>
500dp
</dimen>
<dimen
name=
"dp_600"
>
600dp
</dimen>
<dimen
name=
"dp_640"
>
640dp
</dimen>
<dimen
name=
"dp_720"
>
720dp
</dimen>
<!-- font size,you can add if there is no one -->
<dimen
name=
"sp_6"
>
6sp
</dimen>
<dimen
name=
"sp_7"
>
7sp
</dimen>
<dimen
name=
"sp_8"
>
8sp
</dimen>
<dimen
name=
"sp_9"
>
9sp
</dimen>
<dimen
name=
"sp_10"
>
10sp
</dimen>
<dimen
name=
"sp_11"
>
11sp
</dimen>
<dimen
name=
"sp_12"
>
12sp
</dimen>
<dimen
name=
"sp_13"
>
13sp
</dimen>
<dimen
name=
"sp_14"
>
14sp
</dimen>
<dimen
name=
"sp_15"
>
15sp
</dimen>
<dimen
name=
"sp_16"
>
16sp
</dimen>
<dimen
name=
"sp_17"
>
17sp
</dimen>
<dimen
name=
"sp_18"
>
18sp
</dimen>
<dimen
name=
"sp_19"
>
19sp
</dimen>
<dimen
name=
"sp_20"
>
20sp
</dimen>
<dimen
name=
"sp_21"
>
21sp
</dimen>
<dimen
name=
"sp_22"
>
22sp
</dimen>
<dimen
name=
"sp_23"
>
23sp
</dimen>
<dimen
name=
"sp_24"
>
24sp
</dimen>
<dimen
name=
"sp_25"
>
25sp
</dimen>
<dimen
name=
"sp_28"
>
28sp
</dimen>
<dimen
name=
"sp_30"
>
30sp
</dimen>
<dimen
name=
"sp_32"
>
32sp
</dimen>
<dimen
name=
"sp_34"
>
34sp
</dimen>
<dimen
name=
"sp_36"
>
36sp
</dimen>
<dimen
name=
"sp_38"
>
38sp
</dimen>
<dimen
name=
"sp_40"
>
40sp
</dimen>
<dimen
name=
"sp_42"
>
42sp
</dimen>
<dimen
name=
"sp_48"
>
48sp
</dimen>
</resources>
\ No newline at end of file
video/library_tagflow/src/main/res/values/strings.xml
0 → 100755
View file @
cda8590c
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string
name=
"more"
>
更多
</string>
<string
name=
"cancel"
>
取消
</string>
<string
name=
"foldHint"
>
收起
</string>
<string
name=
"expandHint"
>
展开
</string>
</resources>
\ No newline at end of file
video/settings.gradle
View file @
cda8590c
...
...
@@ -3,3 +3,4 @@ include ':oaid'
include
':rxpay'
include
':alipay'
include
':wxpay'
include
':library_tagflow'
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment