Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
W
Widget
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 Widget
Widget
Commits
1bbf1180
Commit
1bbf1180
authored
Sep 03, 2019
by
王韦
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[new] 增加 bottomTab
parent
d7e5749a
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
533 additions
and
3 deletions
+533
-3
build.gradle
tools/build.gradle
+1
-1
BitmapExtention.kt
.../src/main/java/com/qimai/android/tools/BitmapExtention.kt
+24
-0
build.gradle
widgetlib/build.gradle
+1
-1
BottomBar.kt
...n/java/com/qimai/android/widgetlib/bottombar/BottomBar.kt
+290
-0
BottomBarTab.kt
...ava/com/qimai/android/widgetlib/bottombar/BottomBarTab.kt
+205
-0
QmAlertDialog.kt
...n/java/com/qimai/android/widgetlib/popup/QmAlertDialog.kt
+2
-1
segment_bg_msg_bubble.xml
widgetlib/src/main/res/drawable/segment_bg_msg_bubble.xml
+9
-0
segment_bottom_shadow.9.png
widgetlib/src/main/res/drawable/segment_bottom_shadow.9.png
+0
-0
colors.xml
widgetlib/src/main/res/values/colors.xml
+1
-0
No files found.
tools/build.gradle
View file @
1bbf1180
...
@@ -42,7 +42,7 @@ repositories {
...
@@ -42,7 +42,7 @@ repositories {
group
'com.qmai.android.tools'
group
'com.qmai.android.tools'
version
'1.1.
3
-SNAPSHOT'
version
'1.1.
4
-SNAPSHOT'
gradlePublish
{
gradlePublish
{
...
...
tools/src/main/java/com/qimai/android/tools/BitmapExtention.kt
0 → 100644
View file @
1bbf1180
package
com.qimai.android.tools
import
android.graphics.Bitmap
import
android.graphics.Matrix
/**
* created by wangwei ON 2019-09-03 email:wangwei_5521@163.com
* @version 1.1.1
* @Description
**/
fun
Bitmap
.
resize
(
w
:
Int
,
h
:
Int
):
Bitmap
{
val
width
=
width
val
height
=
height
val
scaleWight
=
w
.
toFloat
()
/
width
val
scaleHeight
=
h
.
toFloat
()
/
height
val
matrix
=
Matrix
()
matrix
.
postScale
(
scaleWight
,
scaleHeight
)
return
Bitmap
.
createBitmap
(
this
,
0
,
0
,
width
,
height
,
matrix
,
true
)
}
\ No newline at end of file
widgetlib/build.gradle
View file @
1bbf1180
...
@@ -45,7 +45,7 @@ repositories {
...
@@ -45,7 +45,7 @@ repositories {
group
'com.qmai.android.sdk'
group
'com.qmai.android.sdk'
version
'1.1.
6
-SNAPSHOT'
version
'1.1.
7
-SNAPSHOT'
gradlePublish
{
gradlePublish
{
...
...
widgetlib/src/main/java/com/qimai/android/widgetlib/bottombar/BottomBar.kt
0 → 100644
View file @
1bbf1180
package
com.qimai.android.widgetlib.bottombar
import
android.content.Context
import
android.graphics.Bitmap
import
android.graphics.BitmapFactory
import
android.graphics.Canvas
import
android.graphics.Paint
import
android.os.Parcel
import
android.os.Parcelable
import
android.util.AttributeSet
import
android.view.View
import
android.view.View.OnClickListener
import
android.view.ViewGroup
import
android.view.ViewTreeObserver
import
android.view.animation.AccelerateDecelerateInterpolator
import
android.widget.LinearLayout
import
androidx.core.content.ContextCompat
import
com.qimai.android.tools.dpTopx
import
com.qimai.android.tools.resize
import
com.qimai.android.widgetlib.R
import
java.util.*
@Suppress
(
"unused"
)
class
BottomBar
@JvmOverloads
constructor
(
context
:
Context
,
attrs
:
AttributeSet
?
=
null
,
defStyleAttr
:
Int
=
0
)
:
LinearLayout
(
context
,
attrs
,
defStyleAttr
)
{
private
val
TRANSLATE_DURATION_MILLIS
=
200
private
val
mInterpolator
=
AccelerateDecelerateInterpolator
()
private
var
mVisible
=
true
private
var
mTabs
:
MutableList
<
BottomBarTab
>
=
ArrayList
()
private
var
mTabLayout
:
LinearLayout
?
=
null
private
var
mTabParams
:
LayoutParams
?
=
null
private
var
mCurrentPosition
=
-
1
private
var
mListener
:
OnTabSelectedListener
?
=
null
private
var
mShadowBitmap
:
Bitmap
?
=
null
private
val
mPaint
=
Paint
(
Paint
.
ANTI_ALIAS_FLAG
)
init
{
initBottom
(
context
)
}
private
fun
initBottom
(
context
:
Context
)
{
clipChildren
=
false
setWillNotDraw
(
false
)
orientation
=
VERTICAL
mPaint
.
color
=
ContextCompat
.
getColor
(
context
,
R
.
color
.
segment_divider_dark
)
mPaint
.
strokeWidth
=
context
.
dpTopx
(
0.7F
).
toFloat
()
mTabLayout
=
LinearLayout
(
context
)
mTabLayout
!!
.
orientation
=
HORIZONTAL
this
.
addView
(
mTabLayout
,
LayoutParams
(
ViewGroup
.
LayoutParams
.
MATCH_PARENT
,
ViewGroup
.
LayoutParams
.
MATCH_PARENT
)
)
mTabLayout
!!
.
clipChildren
=
false
mTabParams
=
LayoutParams
(
0
,
ViewGroup
.
LayoutParams
.
MATCH_PARENT
)
mTabParams
!!
.
weight
=
1f
mShadowBitmap
=
BitmapFactory
.
decodeResource
(
resources
,
R
.
drawable
.
segment_bottom_shadow
)
mShadowBitmap
=
mShadowBitmap
!!
.
resize
(
resources
.
displayMetrics
.
widthPixels
,
mShadowBitmap
!!
.
height
/
2
)
}
override
fun
onDraw
(
canvas
:
Canvas
?)
{
canvas
!!
.
drawBitmap
(
mShadowBitmap
!!
,
0f
,
(-
mShadowBitmap
!!
.
height
).
toFloat
(),
mPaint
)
super
.
onDraw
(
canvas
)
}
override
fun
onAttachedToWindow
()
{
super
.
onAttachedToWindow
()
val
view
=
parent
as
View
if
(
view
is
ViewGroup
)
{
view
.
clipChildren
=
false
}
}
fun
addItem
(
tab
:
BottomBarTab
):
BottomBar
{
tab
.
setOnClickListener
(
OnClickListener
{
v
->
if
(
mListener
==
null
)
return
@OnClickListener
val
pos
=
mTabs
.
indexOf
(
v
)
if
(
pos
==
-
1
)
return
@OnClickListener
if
(
mCurrentPosition
==
-
1
)
{
mListener
!!
.
onTabSelected
(
pos
,
0
)
tab
.
isSelected
=
true
mCurrentPosition
=
pos
}
else
{
if
(
mCurrentPosition
==
pos
)
{
mListener
!!
.
onTabReselected
(
pos
)
}
else
{
//修复可能存在的数组越界情况
if
(
mCurrentPosition
>
mTabs
.
size
-
1
)
mCurrentPosition
=
mTabs
.
size
-
1
mListener
!!
.
onTabSelected
(
pos
,
mCurrentPosition
)
tab
.
isSelected
=
true
mListener
!!
.
onTabUnselected
(
mCurrentPosition
)
mTabs
[
mCurrentPosition
].
isSelected
=
false
mCurrentPosition
=
pos
}
}
})
tab
.
layoutParams
=
mTabParams
mTabLayout
!!
.
addView
(
tab
)
mTabs
.
add
(
tab
)
return
this
}
//获取BottomBarTab 的容器
fun
getTabLayout
():
LinearLayout
?
{
return
mTabLayout
}
//重置tabs 数量
fun
resetTabs
()
{
mTabs
=
ArrayList
()
}
fun
resetCurrentPosition
()
{
mCurrentPosition
=
-
1
}
/**
* 设置选择监听
*/
fun
setOnTabSelectedListener
(
onTabSelectedListener
:
OnTabSelectedListener
)
{
mListener
=
onTabSelectedListener
}
/**
* 设置当前 item
*/
fun
setCurrentItem
(
position
:
Int
)
{
mTabLayout
!!
.
post
{
mTabLayout
!!
.
getChildAt
(
position
).
performClick
()
}
}
/**
* 获取当前 选中index
*/
fun
getCurrentItemPosition
():
Int
{
return
mCurrentPosition
}
/**
* 获取 Tab
*/
fun
getItem
(
index
:
Int
):
BottomBarTab
?
{
return
if
(
mTabs
.
size
<
index
)
null
else
mTabs
[
index
]
}
interface
OnTabSelectedListener
{
fun
onTabSelected
(
position
:
Int
,
prePosition
:
Int
)
fun
onTabUnselected
(
position
:
Int
)
fun
onTabReselected
(
position
:
Int
)
}
override
fun
onSaveInstanceState
():
Parcelable
?
{
val
superState
=
super
.
onSaveInstanceState
()
return
SavedState
(
superState
!!
,
mCurrentPosition
)
}
override
fun
onRestoreInstanceState
(
state
:
Parcelable
)
{
val
ss
=
state
as
SavedState
super
.
onRestoreInstanceState
(
ss
.
superState
)
if
(
mCurrentPosition
!=
ss
.
position
)
{
if
(
mCurrentPosition
==
-
1
)
{
val
childAt
=
mTabLayout
!!
.
getChildAt
(
ss
.
position
)
if
(
childAt
!=
null
)
{
childAt
.
isSelected
=
true
}
mCurrentPosition
=
ss
.
position
return
}
val
currentView
=
mTabLayout
!!
.
getChildAt
(
mCurrentPosition
)
if
(
currentView
!=
null
)
{
currentView
.
isSelected
=
false
}
val
selectView
=
mTabLayout
!!
.
getChildAt
(
ss
.
position
)
if
(
selectView
!=
null
)
{
selectView
.
isSelected
=
true
}
}
mCurrentPosition
=
ss
.
position
}
internal
class
SavedState
:
BaseSavedState
{
var
position
:
Int
=
0
constructor
(
source
:
Parcel
)
:
super
(
source
)
{
position
=
source
.
readInt
()
}
constructor
(
superState
:
Parcelable
,
position
:
Int
)
:
super
(
superState
)
{
this
.
position
=
position
}
override
fun
writeToParcel
(
parcel
:
Parcel
,
flags
:
Int
)
{
parcel
.
writeInt
(
position
)
}
override
fun
describeContents
():
Int
{
return
0
}
companion
object
CREATOR
:
Parcelable
.
Creator
<
SavedState
>
{
override
fun
createFromParcel
(
parcel
:
Parcel
):
SavedState
{
return
SavedState
(
parcel
)
}
override
fun
newArray
(
size
:
Int
):
Array
<
SavedState
?
>
{
return
arrayOfNulls
(
size
)
}
}
}
fun
hide
()
{
hide
(
true
)
}
fun
show
()
{
show
(
true
)
}
fun
hide
(
anim
:
Boolean
)
{
toggle
(
false
,
anim
,
false
)
}
fun
show
(
anim
:
Boolean
)
{
toggle
(
true
,
anim
,
false
)
}
fun
isVisible
():
Boolean
{
return
mVisible
}
private
fun
toggle
(
visible
:
Boolean
,
animate
:
Boolean
,
force
:
Boolean
)
{
if
(
mVisible
!=
visible
||
force
)
{
mVisible
=
visible
val
height
=
height
if
(
height
==
0
&&
!
force
)
{
val
vto
=
viewTreeObserver
if
(
vto
.
isAlive
)
{
// view树完成测量并且分配空间而绘制过程还没有开始的时候播放动画。
vto
.
addOnPreDrawListener
(
object
:
ViewTreeObserver
.
OnPreDrawListener
{
override
fun
onPreDraw
():
Boolean
{
val
currentVto
=
viewTreeObserver
if
(
currentVto
.
isAlive
)
{
currentVto
.
removeOnPreDrawListener
(
this
)
}
toggle
(
visible
,
animate
,
true
)
return
true
}
})
return
}
}
val
translationY
=
if
(
visible
)
0
else
height
if
(
animate
)
{
animate
().
setInterpolator
(
mInterpolator
)
.
setDuration
(
TRANSLATE_DURATION_MILLIS
.
toLong
())
.
translationY
(
translationY
.
toFloat
())
}
else
{
this
.
translationY
=
translationY
.
toFloat
()
}
}
}
}
\ No newline at end of file
widgetlib/src/main/java/com/qimai/android/widgetlib/bottombar/BottomBarTab.kt
0 → 100644
View file @
1bbf1180
package
com.qimai.android.widgetlib.bottombar
import
android.content.Context
import
android.graphics.Color
import
android.os.Build
import
android.text.TextUtils
import
android.view.Gravity
import
android.view.View
import
android.view.ViewGroup
import
android.widget.FrameLayout
import
android.widget.ImageView
import
android.widget.LinearLayout
import
android.widget.TextView
import
androidx.annotation.DrawableRes
import
androidx.core.content.ContextCompat
import
com.qimai.android.tools.dpTopx
import
com.qimai.android.widgetlib.R
class
BottomBarTab
(
context
:
Context
,
title
:
CharSequence
,
tabTextColor
:
Int
,
selectedTabTextColor
:
Int
,
@DrawableRes
icon
:
Int
,
@DrawableRes
selectedIcon
:
Int
,
listener
:
OnSelectedTabListener
?
)
:
FrameLayout
(
context
)
{
private
var
mImg
:
ImageView
?
=
null
private
var
mTvTitle
:
TextView
?
=
null
private
var
mTvUnreadCount
:
TextView
?
=
null
private
var
mContext
:
Context
?
=
null
var
mTabTextColor
:
Int
=
0
var
mSelectedTabTextColor
:
Int
=
0
private
var
mIcon
:
Int
=
0
private
var
mSelectedIcon
:
Int
=
0
private
var
mOnSelectedTabListener
:
OnSelectedTabListener
?
=
null
/**
* 获取当前未读数量
*/
/**
* 设置未读数量
*/
var
unreadCount
:
Int
get
()
{
var
count
=
0
if
(
TextUtils
.
isEmpty
(
mTvUnreadCount
!!
.
text
))
{
return
count
}
if
(
mTvUnreadCount
!!
.
text
.
toString
()
==
"99+"
)
{
return
99
}
try
{
count
=
Integer
.
valueOf
(
mTvUnreadCount
!!
.
text
.
toString
())
}
catch
(
ignored
:
Exception
)
{
}
return
count
}
set
(
num
)
=
if
(
num
<=
0
)
{
mTvUnreadCount
!!
.
visibility
=
View
.
GONE
}
else
{
mTvUnreadCount
!!
.
text
=
""
mTvUnreadCount
!!
.
visibility
=
View
.
VISIBLE
}
init
{
init
(
context
,
title
,
tabTextColor
,
selectedTabTextColor
,
icon
,
selectedIcon
,
listener
!!
)
}
interface
OnSelectedTabListener
{
fun
onSelected
(
tabImageView
:
ImageView
?,
selected
:
Boolean
)
}
private
fun
init
(
context
:
Context
,
title
:
CharSequence
,
tabTextColor
:
Int
,
selectedTabTextColor
:
Int
,
icon
:
Int
,
selectedIcon
:
Int
,
listener
:
OnSelectedTabListener
)
{
this
.
mContext
=
context
this
.
mTabTextColor
=
tabTextColor
this
.
mIcon
=
icon
this
.
mSelectedIcon
=
selectedIcon
this
.
mOnSelectedTabListener
=
listener
this
.
mSelectedTabTextColor
=
selectedTabTextColor
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
LOLLIPOP
)
{
val
typedArray
=
context
.
obtainStyledAttributes
(
intArrayOf
(
android
.
R
.
attr
.
selectableItemBackgroundBorderless
))
val
drawable
=
typedArray
.
getDrawable
(
0
)
background
=
drawable
typedArray
.
recycle
()
}
val
lLContainer
=
LinearLayout
(
context
)
lLContainer
.
orientation
=
LinearLayout
.
VERTICAL
lLContainer
.
gravity
=
Gravity
.
CENTER
val
paramsContainer
=
LayoutParams
(
ViewGroup
.
LayoutParams
.
WRAP_CONTENT
,
ViewGroup
.
LayoutParams
.
WRAP_CONTENT
)
paramsContainer
.
gravity
=
Gravity
.
CENTER_HORIZONTAL
lLContainer
.
layoutParams
=
paramsContainer
mImg
=
ImageView
(
context
)
val
dp32
=
mContext
!!
.
dpTopx
(
32.0f
)
mImg
!!
.
layoutParams
=
ViewGroup
.
LayoutParams
(
dp32
,
dp32
)
lLContainer
.
addView
(
mImg
)
mTvTitle
=
TextView
(
context
)
mTvTitle
!!
.
text
=
title
val
tvTitleParams
=
LinearLayout
.
LayoutParams
(
ViewGroup
.
LayoutParams
.
WRAP_CONTENT
,
ViewGroup
.
LayoutParams
.
WRAP_CONTENT
)
// tvTitleParams.topMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, getResources().getDisplayMetrics());
mTvTitle
!!
.
textSize
=
10f
mTvTitle
!!
.
setTextColor
(
if
(
mTabTextColor
==
0
)
ContextCompat
.
getColor
(
context
,
R
.
color
.
QmTopBar_color_FFFFFFF
)
else
mTabTextColor
)
mTvTitle
!!
.
layoutParams
=
tvTitleParams
lLContainer
.
addView
(
mTvTitle
)
addView
(
lLContainer
)
val
min
=
context
.
dpTopx
(
12F
)
// int padding = SegmentUtil.dip2px(context, 5);
mTvUnreadCount
=
TextView
(
context
)
mTvUnreadCount
!!
.
setBackgroundResource
(
R
.
drawable
.
segment_bg_msg_bubble
)
mTvUnreadCount
!!
.
minWidth
=
min
mTvUnreadCount
!!
.
minHeight
=
min
mTvUnreadCount
!!
.
setTextColor
(
Color
.
WHITE
)
// mTvUnreadCount.setPadding(padding, 0, padding, 0);
mTvUnreadCount
!!
.
gravity
=
Gravity
.
CENTER
val
tvUnReadParams
=
LayoutParams
(
ViewGroup
.
LayoutParams
.
WRAP_CONTENT
,
min
)
tvUnReadParams
.
gravity
=
Gravity
.
CENTER
tvUnReadParams
.
leftMargin
=
context
.
dpTopx
(
17F
)
tvUnReadParams
.
bottomMargin
=
context
.
dpTopx
(
14F
)
mTvUnreadCount
!!
.
layoutParams
=
tvUnReadParams
mTvUnreadCount
!!
.
visibility
=
View
.
GONE
addView
(
mTvUnreadCount
)
isSelected
=
false
}
override
fun
setSelected
(
selected
:
Boolean
)
{
super
.
setSelected
(
selected
)
if
(
mSelectedTabTextColor
!=
0
)
{
mTvTitle
!!
.
setTextColor
(
if
(
selected
)
mSelectedTabTextColor
else
mTabTextColor
)
}
if
(
mOnSelectedTabListener
!=
null
&&
mSelectedIcon
==
0
&&
mIcon
==
0
)
{
mOnSelectedTabListener
!!
.
onSelected
(
mImg
,
selected
)
}
else
{
mImg
!!
.
setImageResource
(
if
(
selected
)
mSelectedIcon
else
mIcon
)
}
}
companion
object
{
fun
newTab
(
context
:
Context
,
title
:
CharSequence
,
tabTextColor
:
Int
,
icon
:
Int
,
selectedIcon
:
Int
):
BottomBarTab
{
return
BottomBarTab
(
context
,
title
,
tabTextColor
,
0
,
icon
,
selectedIcon
,
null
)
}
fun
newTab
(
context
:
Context
,
title
:
CharSequence
,
tabTextColor
:
Int
,
listener
:
OnSelectedTabListener
):
BottomBarTab
{
return
BottomBarTab
(
context
,
title
,
tabTextColor
,
0
,
0
,
0
,
listener
)
}
fun
newTab
(
context
:
Context
,
title
:
CharSequence
,
tabTextColor
:
Int
,
selectedTabTextColor
:
Int
,
listener
:
OnSelectedTabListener
):
BottomBarTab
{
return
BottomBarTab
(
context
,
title
,
tabTextColor
,
selectedTabTextColor
,
0
,
0
,
listener
)
}
}
}
widgetlib/src/main/java/com/qimai/android/widgetlib/popup/QmAlertDialog.kt
View file @
1bbf1180
package
com.qimai.android.widgetlib.popup
package
com.qimai.android.widgetlib.popup
import
android.content.Context
import
android.content.Context
import
android.graphics.drawable.ColorDrawable
import
android.graphics.drawable.Drawable
import
android.text.TextUtils
import
android.text.TextUtils
import
android.view.Gravity
import
android.view.Gravity
import
android.view.LayoutInflater
import
android.view.LayoutInflater
...
@@ -40,7 +42,6 @@ class QmAlertDialog private constructor(
...
@@ -40,7 +42,6 @@ class QmAlertDialog private constructor(
rightButtonClickListener
=
builder
.
rightButtonClick
,
rightButtonClickListener
=
builder
.
rightButtonClick
,
rootView
=
builder
.
rootView
,
rootView
=
builder
.
rootView
,
dismissListener
=
builder
.
dismissListener
dismissListener
=
builder
.
dismissListener
)
)
fun
show
()
{
fun
show
()
{
...
...
widgetlib/src/main/res/drawable/segment_bg_msg_bubble.xml
0 → 100644
View file @
1bbf1180
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<corners
android:radius=
"20dp"
/>
<solid
android:color=
"#FF4040"
/>
<stroke
android:width=
"1dp"
android:color=
"@android:color/white"
/>
</shape>
\ No newline at end of file
widgetlib/src/main/res/drawable/segment_bottom_shadow.9.png
0 → 100644
View file @
1bbf1180
156 Bytes
widgetlib/src/main/res/values/colors.xml
View file @
1bbf1180
...
@@ -6,6 +6,7 @@
...
@@ -6,6 +6,7 @@
<color
name=
"QmTopBar_color_000000"
>
#000000
</color>
<color
name=
"QmTopBar_color_000000"
>
#000000
</color>
<color
name=
"color_777777"
>
#777777
</color>
<color
name=
"color_777777"
>
#777777
</color>
<color
name=
"color_222222"
>
#222222
</color>
<color
name=
"color_222222"
>
#222222
</color>
<color
name=
"segment_divider_dark"
>
#d9d9d9
</color>
</resources>
</resources>
\ No newline at end of file
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