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
a60ca88a
Commit
a60ca88a
authored
Sep 01, 2019
by
王韦
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[new] tip 初步完成
parent
00646619
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
552 additions
and
59 deletions
+552
-59
AndroidManifest.xml
app/src/main/AndroidManifest.xml
+2
-1
AlertDialogActivity.java
...in/java/com/qimai/android/widget/AlertDialogActivity.java
+0
-27
MainActivity.kt
app/src/main/java/com/qimai/android/widget/MainActivity.kt
+5
-0
TipActivity.kt
app/src/main/java/com/qimai/android/widget/TipActivity.kt
+38
-0
activity_main.xml
app/src/main/res/layout/activity_main.xml
+5
-0
activity_tip.xml
app/src/main/res/layout/activity_tip.xml
+43
-0
tip.xml
app/src/main/res/layout/tip.xml
+14
-0
SharedPreferencesTools.kt
...in/java/com/qimai/android/tools/SharedPreferencesTools.kt
+16
-5
TestDrawable.kt
...src/main/java/com/qimai/android/widgetlib/TestDrawable.kt
+55
-6
QmTipOverlayDrawable.kt
...com/qimai/android/widgetlib/popup/QmTipOverlayDrawable.kt
+150
-14
QmToolTip.kt
.../main/java/com/qimai/android/widgetlib/popup/QmToolTip.kt
+221
-3
styles.xml
widgetlib/src/main/res/values/styles.xml
+3
-3
No files found.
app/src/main/AndroidManifest.xml
View file @
a60ca88a
...
@@ -9,7 +9,8 @@
...
@@ -9,7 +9,8 @@
android:roundIcon=
"@mipmap/ic_launcher_round"
android:roundIcon=
"@mipmap/ic_launcher_round"
android:supportsRtl=
"true"
android:supportsRtl=
"true"
android:theme=
"@style/AppTheme"
>
android:theme=
"@style/AppTheme"
>
<activity
android:name=
".CommomPopActivity"
></activity>
<activity
android:name=
".TipActivity"
></activity>
<activity
android:name=
".CommomPopActivity"
/>
<activity
android:name=
".TopBarActivity"
/>
<activity
android:name=
".TopBarActivity"
/>
<activity
android:name=
".MainActivity"
>
<activity
android:name=
".MainActivity"
>
<intent-filter>
<intent-filter>
...
...
app/src/main/java/com/qimai/android/widget/AlertDialogActivity.java
deleted
100644 → 0
View file @
00646619
package
com
.
qimai
.
android
.
widget
;
import
android.os.Bundle
;
import
androidx.annotation.Nullable
;
import
androidx.appcompat.app.AppCompatActivity
;
import
com.qimai.android.widgetlib.popup.QmAlertDialog
;
import
kotlin.jvm.functions.Function1
;
/**
* created by wangwei ON 2019-08-28 email:wangwei_5521@163.com
*
* @version 1.1.1
* @Description
**/
public
class
AlertDialogActivity
extends
AppCompatActivity
{
@Override
protected
void
onCreate
(
@Nullable
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
);
}
}
app/src/main/java/com/qimai/android/widget/MainActivity.kt
View file @
a60ca88a
...
@@ -18,5 +18,10 @@ class MainActivity : AppCompatActivity() {
...
@@ -18,5 +18,10 @@ class MainActivity : AppCompatActivity() {
startActivity
(
Intent
(
MainActivity
@
this
,
CommomPopActivity
::
class
.
java
))
startActivity
(
Intent
(
MainActivity
@
this
,
CommomPopActivity
::
class
.
java
))
}
}
findViewById
<
Button
>(
R
.
id
.
tip
).
setOnClickListener
{
startActivity
(
Intent
(
MainActivity
@
this
,
TipActivity
::
class
.
java
))
}
}
}
}
}
app/src/main/java/com/qimai/android/widget/TipActivity.kt
0 → 100644
View file @
a60ca88a
package
com.qimai.android.widget
import
android.os.Bundle
import
android.view.Gravity
import
android.view.LayoutInflater
import
android.widget.Button
import
androidx.appcompat.app.AppCompatActivity
import
com.qimai.android.widgetlib.popup.QmToolTip
class
TipActivity
:
AppCompatActivity
()
{
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
super
.
onCreate
(
savedInstanceState
)
setContentView
(
R
.
layout
.
activity_tip
)
findViewById
<
Button
>(
R
.
id
.
top
).
setOnClickListener
{
val
view
=
LayoutInflater
.
from
(
TipActivity
@
this
).
inflate
(
R
.
layout
.
tip
,
null
)
QmToolTip
.
Builder
()
.
withAttachedView
(
findViewById
(
R
.
id
.
top
))
.
withContentView
(
view
)
.
withGravity
(
Gravity
.
TOP
)
.
build
().
show
()
}
findViewById
<
Button
>(
R
.
id
.
bottom
).
setOnClickListener
{
val
view
=
LayoutInflater
.
from
(
TipActivity
@
this
).
inflate
(
R
.
layout
.
tip
,
null
)
QmToolTip
.
Builder
()
.
withAttachedView
(
findViewById
<
Button
>(
R
.
id
.
bottom
))
.
withContentView
(
view
)
.
withGravity
(
Gravity
.
BOTTOM
)
.
build
().
show
()
}
}
}
app/src/main/res/layout/activity_main.xml
View file @
a60ca88a
...
@@ -24,6 +24,11 @@
...
@@ -24,6 +24,11 @@
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"50dp"
/>
android:layout_height=
"50dp"
/>
<Button
android:id=
"@+id/tip"
android:text=
"Tip"
android:layout_width=
"match_parent"
android:layout_height=
"50dp"
/>
</LinearLayout>
</LinearLayout>
...
...
app/src/main/res/layout/activity_tip.xml
0 → 100644
View file @
a60ca88a
<?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"
xmlns:tools=
"http://schemas.android.com/tools"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
tools:context=
".TipActivity"
>
<Button
android:id=
"@+id/top"
android:layout_width=
"150dp"
android:layout_height=
"50dp"
android:layout_marginTop=
"140dp"
android:text=
"top"
app:layout_constraintRight_toRightOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
/>
<Button
android:id=
"@+id/bottom"
android:layout_width=
"150dp"
android:layout_height=
"50dp"
android:layout_marginTop=
"140dp"
android:text=
"bottom"
app:layout_constraintEnd_toStartOf=
"@+id/top"
app:layout_constraintHorizontal_bias=
"0.144"
app:layout_constraintRight_toRightOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
/>
<TextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:text=
"测试测试测试\n 测试测试测试"
android:textColor=
"#C02F14"
android:textSize=
"10sp"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
app/src/main/res/layout/tip.xml
0 → 100644
View file @
a60ca88a
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:orientation=
"vertical"
>
<TextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:text=
"测试测试测试\n 测试测试测试"
android:textColor=
"#C02F14"
android:textSize=
"10sp"
/>
</LinearLayout>
\ No newline at end of file
tools/src/main/java/com/qimai/android/tools/SharedPreferencesTools.kt
View file @
a60ca88a
...
@@ -2,6 +2,7 @@ package com.qimai.android.tools
...
@@ -2,6 +2,7 @@ package com.qimai.android.tools
import
android.content.Context
import
android.content.Context
import
android.content.SharedPreferences
import
android.content.SharedPreferences
import
androidx.core.content.edit
import
java.util.concurrent.ConcurrentHashMap
import
java.util.concurrent.ConcurrentHashMap
/**
/**
...
@@ -41,27 +42,37 @@ class SharedPreferencesTools {
...
@@ -41,27 +42,37 @@ class SharedPreferencesTools {
fun
putString
(
key
:
String
,
value
:
String
)
{
fun
putString
(
key
:
String
,
value
:
String
)
{
check
()
check
()
sp
!!
.
edit
().
putString
(
key
,
value
).
apply
()
sp
?.
edit
{
putString
(
key
,
value
)
}
}
}
fun
putInt
(
key
:
String
,
value
:
Int
)
{
fun
putInt
(
key
:
String
,
value
:
Int
)
{
check
()
check
()
sp
!!
.
edit
().
putInt
(
key
,
value
).
apply
()
sp
?.
edit
{
putInt
(
key
,
value
).
apply
()
}
}
}
fun
putBoolean
(
key
:
String
,
value
:
Boolean
)
{
fun
putBoolean
(
key
:
String
,
value
:
Boolean
)
{
check
()
check
()
sp
!!
.
edit
().
putBoolean
(
key
,
value
).
apply
()
sp
?.
edit
{
putBoolean
(
key
,
value
)
}
}
}
fun
remove
(
key
:
String
)
{
fun
remove
(
key
:
String
)
{
check
()
check
()
sp
!!
.
edit
().
remove
(
key
).
apply
()
sp
?.
edit
{
remove
(
key
)
}
}
}
fun
clear
()
{
fun
clear
()
{
check
()
check
()
sp
!!
.
edit
().
clear
().
apply
()
sp
?.
edit
{
clear
()
}
}
}
private
fun
check
()
{
private
fun
check
()
{
...
...
widgetlib/src/main/java/com/qimai/android/widgetlib/TestDrawable.kt
View file @
a60ca88a
package
com.qimai.android.widgetlib
package
com.qimai.android.widgetlib
import
android.graphics.Canvas
import
android.graphics.*
import
android.graphics.ColorFilter
import
android.graphics.PixelFormat
import
android.graphics.Rect
import
android.graphics.drawable.Drawable
import
android.graphics.drawable.Drawable
import
android.
util.Log
import
android.
os.Build
/**
/**
* created by wangwei ON 2019-08-29 email:wangwei_5521@163.com
* created by wangwei ON 2019-08-29 email:wangwei_5521@163.com
...
@@ -13,7 +10,33 @@ import android.util.Log
...
@@ -13,7 +10,33 @@ import android.util.Log
* @Description
* @Description
**/
**/
class
TestDrawable
:
Drawable
()
{
class
TestDrawable
:
Drawable
()
{
val
rectF
:
RectF
val
arrowHeight
=
20.0f
var
arrowPath
=
Path
()
var
path
=
Path
()
val
radius
=
10.0f
var
borderPaint
=
Paint
()
val
outlineRect
=
Rect
()
init
{
borderPaint
=
Paint
(
Paint
.
ANTI_ALIAS_FLAG
)
borderPaint
.
style
=
Paint
.
Style
.
STROKE
borderPaint
.
strokeJoin
=
Paint
.
Join
.
ROUND
borderPaint
.
strokeWidth
=
2.0f
borderPaint
.
color
=
Color
.
BLACK
path
=
Path
()
arrowPath
=
Path
()
rectF
=
RectF
()
}
override
fun
draw
(
canvas
:
Canvas
)
{
override
fun
draw
(
canvas
:
Canvas
)
{
borderPaint
?.
let
{
canvas
.
drawPath
(
arrowPath
,
it
)
}
borderPaint
?.
let
{
canvas
.
drawPath
(
path
,
it
)
}
}
}
override
fun
setAlpha
(
alpha
:
Int
)
{
override
fun
setAlpha
(
alpha
:
Int
)
{
...
@@ -24,12 +47,38 @@ class TestDrawable : Drawable() {
...
@@ -24,12 +47,38 @@ class TestDrawable : Drawable() {
}
}
override
fun
getOutline
(
outline
:
Outline
)
{
super
.
getOutline
(
outline
)
copyBounds
(
outlineRect
)
outlineRect
.
inset
(
10
,
10
)
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
LOLLIPOP
)
{
outline
.
setRoundRect
(
outlineRect
,
radius
)
}
else
{
// 5.0以下
}
}
override
fun
setColorFilter
(
colorFilter
:
ColorFilter
?)
{
override
fun
setColorFilter
(
colorFilter
:
ColorFilter
?)
{
}
}
override
fun
onBoundsChange
(
bounds
:
Rect
?)
{
override
fun
onBoundsChange
(
bounds
:
Rect
?)
{
super
.
onBoundsChange
(
bounds
)
super
.
onBoundsChange
(
bounds
)
Log
.
v
(
"drawableT"
,
"${bounds!!.right},${bounds!!.bottom}"
)
val
left
=
bounds
!!
.
left
val
right
=
bounds
!!
.
right
var
top
=
bounds
?.
top
var
bottom
=
bounds
.
bottom
rectF
.
set
(
left
.
toFloat
()
+
arrowHeight
+
20
,
top
.
toFloat
()+
10
,
right
.
toFloat
(),
bottom
.
toFloat
())
path
.
addRoundRect
(
rectF
,
radius
,
radius
,
Path
.
Direction
.
CW
)
val
radioHeight
=
(
bottom
-
top
)
*
0.5f
arrowPath
.
moveTo
(
left
+
arrowHeight
+
20
,
top
+
radioHeight
+
arrowHeight
)
arrowPath
.
lineTo
(
left
.
toFloat
()+
20
,
top
+
radioHeight
)
arrowPath
.
lineTo
(
left
+
arrowHeight
+
20
,
top
+
radioHeight
-
arrowHeight
)
arrowPath
.
close
()
}
}
}
}
\ No newline at end of file
widgetlib/src/main/java/com/qimai/android/widgetlib/popup/QmTipOverlayDrawable.kt
View file @
a60ca88a
package
com.qimai.android.widgetlib.popup
package
com.qimai.android.widgetlib.popup
import
android.content.Context
import
android.graphics.*
import
android.graphics.*
import
android.graphics.drawable.Drawable
import
android.graphics.drawable.Drawable
import
android.os.Build
import
android.os.Build
import
android.view.Gravity
import
com.qimai.android.tools.dpTopx
import
com.qimai.android.widgetlib.R
import
com.qimai.android.widgetlib.R
/**
/**
...
@@ -11,22 +12,23 @@ import com.qimai.android.widgetlib.R
...
@@ -11,22 +12,23 @@ import com.qimai.android.widgetlib.R
* @version 1.1.1
* @version 1.1.1
* @Description
* @Description
**/
**/
internal
class
QmTipOverlayDrawable
(
context
:
Context
,
builder
:
QmToolTip
.
Builder
)
:
Drawable
()
{
internal
class
QmTipOverlayDrawable
(
builder
:
QmToolTip
.
Builder
)
:
Drawable
()
{
private
val
outlineRect
=
Rect
()
private
val
outlineRect
=
Rect
()
private
val
radius
:
Float
private
val
radius
:
Float
private
val
bgColor
:
Int
private
val
bgColor
:
Int
private
va
l
borderWidth
:
Int
private
va
r
borderWidth
:
Int
private
va
l
borderColor
:
Int
private
va
r
borderColor
:
Int
private
val
bgPaint
:
Paint
?
private
val
bgPaint
:
Paint
?
private
val
borderPaint
:
Paint
?
private
val
borderPaint
:
Paint
?
private
val
path
:
Path
private
val
path
:
Path
private
val
arrowPath
:
Path
private
var
padding
=
0
private
var
padding
=
0
private
var
gravity
=
0
private
var
gravity
=
builder
.
gravity
private
var
showArrow
=
true
private
val
rectF
:
RectF
private
val
rectF
:
RectF
private
val
arrowHeight
=
20f
/**
/**
* 0-1
* 0-1
...
@@ -34,6 +36,7 @@ internal class QmTipOverlayDrawable(context: Context, builder: QmToolTip.Builder
...
@@ -34,6 +36,7 @@ internal class QmTipOverlayDrawable(context: Context, builder: QmToolTip.Builder
private
var
arrowWeight
=
0.5f
private
var
arrowWeight
=
0.5f
init
{
init
{
val
context
=
builder
.
contentView
!!
.
context
val
theme
=
context
.
theme
.
obtainStyledAttributes
(
val
theme
=
context
.
theme
.
obtainStyledAttributes
(
null
,
null
,
R
.
styleable
.
QmToolTipOverlay
,
R
.
styleable
.
QmToolTipOverlay
,
...
@@ -41,13 +44,19 @@ internal class QmTipOverlayDrawable(context: Context, builder: QmToolTip.Builder
...
@@ -41,13 +44,19 @@ internal class QmTipOverlayDrawable(context: Context, builder: QmToolTip.Builder
0
0
)
)
this
.
radius
=
this
.
radius
=
theme
.
getDimensionPixelSize
(
R
.
styleable
.
QmToolTipOverlay_overlay_radius
,
4
).
toFloat
()
theme
.
getDimensionPixelSize
(
R
.
styleable
.
QmToolTipOverlay_overlay_radius
,
context
.
dpTopx
(
5f
)
).
toFloat
()
this
.
bgColor
=
theme
.
getColor
(
this
.
bgColor
=
theme
.
getColor
(
R
.
styleable
.
QmToolTipOverlay_overlay_bgColor
,
R
.
styleable
.
QmToolTipOverlay_overlay_bgColor
,
context
.
resources
.
getColor
(
R
.
color
.
QmTopBar_color_FFFFFFF
)
context
.
resources
.
getColor
(
R
.
color
.
QmTopBar_color_FFFFFFF
)
)
)
this
.
borderWidth
=
this
.
borderWidth
=
theme
.
getDimensionPixelOffset
(
R
.
styleable
.
QmToolTipOverlay_overlay_borderWidth
,
1
)
theme
.
getDimensionPixelOffset
(
R
.
styleable
.
QmToolTipOverlay_overlay_borderWidth
,
context
.
dpTopx
(
1f
)
)
this
.
borderColor
=
theme
.
getColor
(
this
.
borderColor
=
theme
.
getColor
(
R
.
styleable
.
QmToolTipOverlay_overlay_borderColor
,
R
.
styleable
.
QmToolTipOverlay_overlay_borderColor
,
context
.
resources
.
getColor
(
R
.
color
.
QmTopBar_color_FFFFFFF
)
context
.
resources
.
getColor
(
R
.
color
.
QmTopBar_color_FFFFFFF
)
...
@@ -62,22 +71,28 @@ internal class QmTipOverlayDrawable(context: Context, builder: QmToolTip.Builder
...
@@ -62,22 +71,28 @@ internal class QmTipOverlayDrawable(context: Context, builder: QmToolTip.Builder
borderPaint
=
Paint
(
Paint
.
ANTI_ALIAS_FLAG
)
borderPaint
=
Paint
(
Paint
.
ANTI_ALIAS_FLAG
)
bgPaint
.
color
=
borderColor
bgPaint
.
color
=
borderColor
borderPaint
.
style
=
Paint
.
Style
.
STROKE
borderPaint
.
style
=
Paint
.
Style
.
STROKE
borderPaint
.
strokeJoin
=
Paint
.
Join
.
ROUND
borderPaint
.
strokeWidth
=
borderWidth
.
toFloat
()
borderPaint
.
strokeWidth
=
borderWidth
.
toFloat
()
}
else
{
}
else
{
borderPaint
=
null
borderPaint
=
null
}
}
path
=
Path
()
path
=
Path
()
arrowPath
=
Path
()
}
}
override
fun
draw
(
canvas
:
Canvas
)
{
override
fun
draw
(
canvas
:
Canvas
)
{
bgPaint
?.
let
{
path
.
op
(
arrowPath
,
Path
.
Op
.
XOR
)
canvas
.
drawPath
(
path
,
it
)
}
borderPaint
?.
let
{
borderPaint
?.
let
{
canvas
.
drawPath
(
path
,
it
)
canvas
.
drawPath
(
path
,
it
)
}
}
// borderPaint?.let {
// canvas.drawPath(arrowPath,it)
// }
// borderPaint?.let {
// canvas.drawPath(path, it)
// }
}
}
...
@@ -125,7 +140,7 @@ internal class QmTipOverlayDrawable(context: Context, builder: QmToolTip.Builder
...
@@ -125,7 +140,7 @@ internal class QmTipOverlayDrawable(context: Context, builder: QmToolTip.Builder
val
minY
=
top
+
radius
val
minY
=
top
+
radius
val
minX
=
left
+
radius
val
minX
=
left
+
radius
if
(
showArrow
)
{
if
(
gravity
!=
Gravity
.
NO_GRAVITY
)
{
calculatePathWithGravity
(
calculatePathWithGravity
(
outBounds
=
outBounds
,
outBounds
=
outBounds
,
left
=
left
,
left
=
left
,
...
@@ -157,14 +172,135 @@ internal class QmTipOverlayDrawable(context: Context, builder: QmToolTip.Builder
...
@@ -157,14 +172,135 @@ internal class QmTipOverlayDrawable(context: Context, builder: QmToolTip.Builder
minX
:
Float
minX
:
Float
)
{
)
{
when
(
gravity
)
{
Gravity
.
TOP
->
{
drawArrowTopWithRect
(
left
,
top
,
right
,
bottom
)
}
Gravity
.
BOTTOM
->
{
drawArrowBottomWithRect
(
left
,
top
,
right
,
bottom
)
}
}
}
/**
* 箭头朝上
*/
private
fun
drawArrowTopWithRect
(
left
:
Int
,
top
:
Int
,
right
:
Int
,
bottom
:
Int
)
{
rectF
.
set
(
left
.
toFloat
()
+
borderWidth
,
top
.
toFloat
()
+
borderWidth
,
right
.
toFloat
()
-
borderWidth
,
bottom
.
toFloat
()
-
arrowHeight
-
borderWidth
)
path
.
addRoundRect
(
rectF
,
radius
,
radius
,
Path
.
Direction
.
CW
)
val
radioHeight
=
(
right
-
left
)
*
arrowWeight
arrowPath
.
moveTo
(
left
+
radioHeight
+
borderWidth
-
arrowHeight
,
bottom
-
arrowHeight
-
borderWidth
)
arrowPath
.
lineTo
(
left
.
toFloat
()
+
radioHeight
+
borderWidth
,
(
bottom
-
borderWidth
).
toFloat
()
)
arrowPath
.
lineTo
(
left
+
radioHeight
+
arrowHeight
+
borderWidth
,
bottom
-
arrowHeight
-
borderWidth
)
arrowPath
.
close
()
}
private
fun
drawArrowBottomWithRect
(
left
:
Int
,
top
:
Int
,
right
:
Int
,
bottom
:
Int
)
{
rectF
.
set
(
left
.
toFloat
()
+
borderWidth
,
top
.
toFloat
()
+
borderWidth
+
arrowHeight
,
right
.
toFloat
()
-
borderWidth
,
bottom
.
toFloat
()
-
borderWidth
)
path
.
addRoundRect
(
rectF
,
radius
,
radius
,
Path
.
Direction
.
CW
)
val
radioHeight
=
(
right
-
left
)
*
arrowWeight
arrowPath
.
moveTo
(
left
+
borderWidth
+
radioHeight
-
arrowHeight
,
top
+
arrowHeight
+
borderWidth
)
arrowPath
.
lineTo
(
left
+
radioHeight
+
borderWidth
,
top
.
toFloat
()
+
borderWidth
)
arrowPath
.
lineTo
(
left
+
arrowHeight
+
borderWidth
+
radioHeight
,
top
+
arrowHeight
+
borderWidth
)
arrowPath
.
close
()
}
}
private
fun
drawLeftArrayWithRect
(
left
:
Int
,
top
:
Int
,
right
:
Int
,
bottom
:
Int
)
{
rectF
.
set
(
left
.
toFloat
()
+
arrowHeight
+
borderWidth
,
top
.
toFloat
()
+
borderWidth
,
right
.
toFloat
()
-
borderWidth
,
bottom
.
toFloat
()
-
borderWidth
)
path
.
addRoundRect
(
rectF
,
radius
,
radius
,
Path
.
Direction
.
CW
)
val
radioHeight
=
(
bottom
-
top
)
*
arrowWeight
arrowPath
.
moveTo
(
left
+
arrowHeight
+
borderWidth
,
top
+
radioHeight
+
arrowHeight
)
arrowPath
.
lineTo
(
left
.
toFloat
()
+
borderWidth
,
top
+
radioHeight
)
arrowPath
.
lineTo
(
left
+
arrowHeight
+
borderWidth
,
top
+
radioHeight
-
arrowHeight
)
arrowPath
.
close
()
// path.moveTo(left + arrowHeight, bottom - radius)
// val radioHeight = (bottom - top) * arrowWeight
// path.lineTo(left + arrowHeight, top + radioHeight + arrowHeight)
// path.lineTo(left.toFloat(), top + radioHeight)
// path.lineTo(left + arrowHeight, top + radioHeight - arrowHeight)
// path.lineTo(left + arrowHeight, top + radius)
//// // 话 左上的 圆弧
// path.addArc(
// RectF(
// left + arrowHeight,
// top.toFloat(),
// left + arrowHeight + 2 * radius,
// top + 2 * radius
// ),
// 180F,
// 90f
// )
// path.lineTo(right - radius, top.toFloat())
// path.addArc(
// RectF(right - 2 * radius, top.toFloat(), right.toFloat(), top + 2 * radius),
// 270F,
// 90f)
// path.lineTo(right.toFloat(), bottom - radius)
// path.addArc(
// RectF(
// right - 2 * radius,
// bottom - 2 * radius,
// right.toFloat(),
// bottom.toFloat()
// ), 0f, 90f
// )
// path.lineTo(left + arrowHeight + radius, bottom.toFloat())
// path.addArc(
// RectF(
// left + arrowHeight,
// bottom - radius,
// left + arrowHeight + 2 * radius,
// bottom.toFloat()
// ), 90f, 90f
// )
// path.close()
}
}
}
\ No newline at end of file
widgetlib/src/main/java/com/qimai/android/widgetlib/popup/QmToolTip.kt
View file @
a60ca88a
package
com.qimai.android.widgetlib.popup
package
com.qimai.android.widgetlib.popup
import
android.graphics.Color
import
android.graphics.Point
import
android.graphics.drawable.ColorDrawable
import
android.os.Build
import
android.view.Gravity
import
android.view.MotionEvent
import
android.view.View
import
android.view.View
import
android.view.ViewGroup
import
android.widget.FrameLayout
import
android.widget.PopupWindow
import
androidx.annotation.IntDef
import
androidx.core.view.ViewCompat
import
com.qimai.android.widgetlib.R
import
com.qimai.android.widgetlib.R
/**
/**
...
@@ -10,21 +21,214 @@ import com.qimai.android.widgetlib.R
...
@@ -10,21 +21,214 @@ import com.qimai.android.widgetlib.R
**/
**/
class
QmToolTip
private
constructor
(
class
QmToolTip
private
constructor
(
var
attachedView
:
View
?,
var
attachedView
:
View
?,
var
defaultOverlayStyle
:
Int
var
defaultOverlayStyle
:
Int
,
var
gravity
:
Int
)
{
)
{
private
val
mWindow
=
PopupWindow
()
private
val
attachedViewLocation
=
IntArray
(
2
)
/**
* 箭头离 anchor的距离
*/
private
val
arrowOffsetOfAnchor
=
20
/**
* 弹框边框离屏幕的距离
* 只有Tip 超过 最大高度和宽度的时候才会使用
*/
private
val
tipFrameOffsetOfScreenFrame
=
20
private
val
containerPaddingBig
=
30
private
val
containerPaddingSmall
=
10
var
containerMeasureWidth
=
0
var
containerMeasureHeight
=
0
private
constructor
(
builder
:
Builder
)
:
this
(
private
constructor
(
builder
:
Builder
)
:
this
(
builder
.
attachedView
,
builder
.
attachedView
,
builder
.
defaultOverlayStyle
builder
.
defaultOverlayStyle
,
builder
.
gravity
)
{
)
{
checkMustParams
(
builder
)
mWindow
.
width
=
ViewGroup
.
LayoutParams
.
WRAP_CONTENT
mWindow
.
height
=
ViewGroup
.
LayoutParams
.
WRAP_CONTENT
mWindow
.
isTouchable
=
true
mWindow
.
isFocusable
=
true
mWindow
.
isOutsideTouchable
=
true
gravity
=
builder
.
gravity
val
container
=
FrameLayout
(
builder
.
contentView
!!
.
context
)
when
(
builder
.
gravity
)
{
Gravity
.
TOP
->
{
container
.
setPadding
(
containerPaddingSmall
,
containerPaddingSmall
,
containerPaddingSmall
,
containerPaddingBig
)
}
Gravity
.
BOTTOM
->
{
container
.
setPadding
(
containerPaddingSmall
,
containerPaddingBig
,
containerPaddingSmall
,
containerPaddingSmall
)
}
}
container
.
addView
(
builder
.
contentView
,
ViewGroup
.
LayoutParams
.
WRAP_CONTENT
,
ViewGroup
.
LayoutParams
.
WRAP_CONTENT
)
container
.
measure
(
View
.
MeasureSpec
.
UNSPECIFIED
,
View
.
MeasureSpec
.
UNSPECIFIED
)
containerMeasureWidth
=
container
.
measuredWidth
containerMeasureHeight
=
container
.
measuredHeight
builder
.
attachedView
?.
getLocationOnScreen
(
attachedViewLocation
)
when
(
gravity
)
{
Gravity
.
TOP
->
{
if
(
containerMeasureHeight
>
attachedViewLocation
[
1
])
{
// view的上边放不下了
val
containerParams
=
container
.
layoutParams
containerParams
.
height
=
attachedViewLocation
[
1
]
-
2
*
arrowOffsetOfAnchor
container
.
layoutParams
=
containerParams
}
}
Gravity
.
BOTTOM
->
{
if
(
containerMeasureHeight
>
attachedViewLocation
[
1
])
{
// view的下边放不下了
val
containerParams
=
container
.
layoutParams
containerParams
.
height
=
attachedViewLocation
[
1
]
-
2
*
arrowOffsetOfAnchor
container
.
layoutParams
=
containerParams
}
}
}
container
.
background
=
QmTipOverlayDrawable
(
builder
=
builder
)
mWindow
.
contentView
=
container
mWindow
.
setBackgroundDrawable
(
ColorDrawable
(
Color
.
TRANSPARENT
))
mWindow
.
setTouchInterceptor
(
View
.
OnTouchListener
{
v
,
event
->
if
(
event
.
action
==
MotionEvent
.
ACTION_OUTSIDE
)
{
mWindow
.
dismiss
()
return
@OnTouchListener
false
}
false
})
mWindow
.
setOnDismissListener
{
// this@QMBasePopup.onDismiss()
// if (mDismissListener != null) {
// mDismissListener!!.onDismiss()
// }
}
builder
.
attachedView
?.
addOnAttachStateChangeListener
(
object
:
View
.
OnAttachStateChangeListener
{
override
fun
onViewAttachedToWindow
(
v
:
View
)
{
}
override
fun
onViewDetachedFromWindow
(
v
:
View
)
{
if
(
hasShowing
())
{
dismiss
()
}
}
})
}
fun
hasShowing
():
Boolean
{
return
mWindow
.
isShowing
}
fun
dismiss
()
{
mWindow
.
dismiss
()
}
fun
show
()
{
if
(
attachedView
!=
null
&&
!
ViewCompat
.
isAttachedToWindow
(
attachedView
!!
))
{
return
}
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
LOLLIPOP_MR1
)
{
mWindow
.
isAttachedInDecor
=
false
}
val
point
=
calculateLocation
(
attachedView
!!
)
// showAsDropDown anchorView 的左下角 为原点 偏移 x, y
mWindow
.
showAtLocation
(
attachedView
,
Gravity
.
NO_GRAVITY
,
point
.
x
,
point
.
y
)
}
private
fun
checkMustParams
(
builder
:
Builder
)
{
checkNotNull
(
builder
.
attachedView
)
{
"attachedView must not to be null "
}
}
private
fun
calculateLocation
(
anchorView
:
View
):
Point
{
anchorView
?.
getLocationOnScreen
(
attachedViewLocation
)
var
point
=
Point
()
when
(
gravity
)
{
Gravity
.
TOP
->
{
point
=
calculateTopOffset
(
anchorView
)
}
Gravity
.
BOTTOM
->
{
point
=
calculateBottomOffset
(
anchorView
)
}
}
return
point
}
private
fun
calculateTopOffset
(
anchorView
:
View
):
Point
{
val
point
=
Point
()
point
.
x
=
(
attachedViewLocation
[
0
]
+
anchorView
.
measuredWidth
/
2
)
-
containerMeasureWidth
/
2
point
.
y
=
attachedViewLocation
[
1
]
-
arrowOffsetOfAnchor
-
anchorView
.
measuredHeight
/
2
return
point
}
private
fun
calculateBottomOffset
(
anchorView
:
View
):
Point
{
val
point
=
Point
()
val
anchorViewHeight
=
anchorView
.
measuredWidth
point
.
x
=
attachedViewLocation
[
0
]
+
containerMeasureWidth
/
2
point
.
y
=
attachedViewLocation
[
1
]
+
anchorView
.
measuredHeight
return
point
}
}
class
Builder
{
class
Builder
{
internal
var
attachedView
:
View
?
=
null
@IntDef
(
Gravity
.
TOP
,
Gravity
.
BOTTOM
,
Gravity
.
NO_GRAVITY
)
@Retention
(
AnnotationRetention
.
SOURCE
)
internal
annotation
class
GravityRange
internal
var
attachedView
:
View
?
=
null
internal
var
defaultOverlayStyle
:
Int
=
R
.
style
.
QmToolTipOverlayDefault
internal
var
defaultOverlayStyle
:
Int
=
R
.
style
.
QmToolTipOverlayDefault
@GravityRange
internal
var
gravity
=
Gravity
.
NO_GRAVITY
internal
var
contentView
:
View
?
=
null
fun
withAttachedView
(
attachedView
:
View
?)
=
apply
{
fun
withAttachedView
(
attachedView
:
View
?)
=
apply
{
...
@@ -32,11 +236,25 @@ class QmToolTip private constructor(
...
@@ -32,11 +236,25 @@ class QmToolTip private constructor(
}
}
fun
withGravity
(
@GravityRange
gravity
:
Int
)
=
apply
{
this
.
gravity
=
gravity
}
fun
withDefaultOverlayStyle
(
defaultOverlayStyle
:
Int
)
=
apply
{
fun
withDefaultOverlayStyle
(
defaultOverlayStyle
:
Int
)
=
apply
{
this
.
defaultOverlayStyle
=
defaultOverlayStyle
this
.
defaultOverlayStyle
=
defaultOverlayStyle
}
}
fun
withContentView
(
contentView
:
View
)
=
apply
{
this
.
contentView
=
contentView
}
fun
build
():
QmToolTip
{
val
tip
=
QmToolTip
(
this
)
return
tip
}
}
}
}
}
\ No newline at end of file
widgetlib/src/main/res/values/styles.xml
View file @
a60ca88a
...
@@ -2,10 +2,10 @@
...
@@ -2,10 +2,10 @@
<resources>
<resources>
<style
name=
"QmToolTipOverlayDefault"
>
<style
name=
"QmToolTipOverlayDefault"
>
<item
name=
"overlay_radius"
>
4
dp
</item>
<item
name=
"overlay_radius"
>
19
dp
</item>
<item
name=
"overlay_bgColor"
>
@color/QmTopBar_color_FFFFFFF
</item>
<item
name=
"overlay_bgColor"
>
@color/QmTopBar_color_FFFFFFF
</item>
<item
name=
"overlay_borderColor"
>
@color/
QmTopBar_color_FFFFFFF
</item>
<item
name=
"overlay_borderColor"
>
@color/
color_777777
</item>
<item
name=
"overlay_borderWidth"
>
1
dp
</item>
<item
name=
"overlay_borderWidth"
>
0.5
dp
</item>
</style>
</style>
</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