Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Sign in / Register
Toggle navigation
S
scanqrwhitecopy
Project
Project
Details
Activity
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
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wanglei
scanqrwhitecopy
Commits
c3a7ed9e
Commit
c3a7ed9e
authored
Jan 23, 2025
by
wanglei
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
..
parent
901ea090
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
1517 additions
and
9 deletions
+1517
-9
CreateFragment.kt
.../main/java/com/base/scanqrclear/ui/main/CreateFragment.kt
+36
-0
MainActivity.kt
...rc/main/java/com/base/scanqrclear/ui/main/MainActivity.kt
+3
-1
ScanAc.kt
app/src/main/java/com/base/scanqrclear/ui/main/ScanAc.kt
+41
-0
ScanFragment.kt
...rc/main/java/com/base/scanqrclear/ui/main/ScanFragment.kt
+2
-1
BuildException.java
.../base/scanqrclear/ui/widget/guideview/BuildException.java
+25
-0
Common.java
...java/com/base/scanqrclear/ui/widget/guideview/Common.java
+42
-0
Component.java
...a/com/base/scanqrclear/ui/widget/guideview/Component.java
+86
-0
Configuration.java
...m/base/scanqrclear/ui/widget/guideview/Configuration.java
+140
-0
DimenUtil.java
...a/com/base/scanqrclear/ui/widget/guideview/DimenUtil.java
+35
-0
Guide.java
.../java/com/base/scanqrclear/ui/widget/guideview/Guide.java
+268
-0
GuideBuilder.java
...om/base/scanqrclear/ui/widget/guideview/GuideBuilder.java
+363
-0
LottieComponent.java
...base/scanqrclear/ui/widget/guideview/LottieComponent.java
+43
-0
MaskView.java
...va/com/base/scanqrclear/ui/widget/guideview/MaskView.java
+393
-0
fragment_create.xml
app/src/main/res/layout/fragment_create.xml
+21
-7
layout_lottie_guide.xml
app/src/main/res/layout/layout_lottie_guide.xml
+18
-0
guide_finger.json
app/src/main/res/raw/guide_finger.json
+1
-0
No files found.
app/src/main/java/com/base/scanqrclear/ui/main/CreateFragment.kt
View file @
c3a7ed9e
...
@@ -31,6 +31,9 @@ import com.base.scanqrclear.ui.telephone.TelephoneActivity
...
@@ -31,6 +31,9 @@ import com.base.scanqrclear.ui.telephone.TelephoneActivity
import
com.base.scanqrclear.ui.text.TextActivity
import
com.base.scanqrclear.ui.text.TextActivity
import
com.base.scanqrclear.ui.website.WebsiteActivity
import
com.base.scanqrclear.ui.website.WebsiteActivity
import
com.base.scanqrclear.ui.webview.WebBrowserActivity
import
com.base.scanqrclear.ui.webview.WebBrowserActivity
import
com.base.scanqrclear.ui.widget.guideview.Component
import
com.base.scanqrclear.ui.widget.guideview.GuideBuilder
import
com.base.scanqrclear.ui.widget.guideview.LottieComponent
import
com.base.scanqrclear.ui.wifi.WifiActivity
import
com.base.scanqrclear.ui.wifi.WifiActivity
import
com.base.scanqrclear.utils.AppPreferences
import
com.base.scanqrclear.utils.AppPreferences
import
com.base.scanqrclear.utils.BarUtils
import
com.base.scanqrclear.utils.BarUtils
...
@@ -181,6 +184,10 @@ class CreateFragment : BaseFragment<FragmentCreateBinding>(FragmentCreateBinding
...
@@ -181,6 +184,10 @@ class CreateFragment : BaseFragment<FragmentCreateBinding>(FragmentCreateBinding
override
fun
onResumeOneShoot
()
{
override
fun
onResumeOneShoot
()
{
super
.
onResumeOneShoot
()
super
.
onResumeOneShoot
()
adapter
?.
changeGuide
()
adapter
?.
changeGuide
()
binding
.
root
.
post
{
showGuideScan
()
}
}
}
override
fun
onResume
()
{
override
fun
onResume
()
{
...
@@ -189,6 +196,7 @@ class CreateFragment : BaseFragment<FragmentCreateBinding>(FragmentCreateBinding
...
@@ -189,6 +196,7 @@ class CreateFragment : BaseFragment<FragmentCreateBinding>(FragmentCreateBinding
statusBarColor
(
"#FFFFFFFF"
)
statusBarColor
(
"#FFFFFFFF"
)
statusBarDarkFont
(
true
)
statusBarDarkFont
(
true
)
}
}
setWeather
()
setWeather
()
}
}
...
@@ -220,6 +228,34 @@ class CreateFragment : BaseFragment<FragmentCreateBinding>(FragmentCreateBinding
...
@@ -220,6 +228,34 @@ class CreateFragment : BaseFragment<FragmentCreateBinding>(FragmentCreateBinding
// requireContext().showLogDialog(sb.toString())
// requireContext().showLogDialog(sb.toString())
// }
// }
// }
// }
}
private
fun
showGuideScan
()
{
val
isGuideScan
=
AppPreferences
.
getInstance
().
getBoolean
(
"isGuideScan"
,
false
)
if
(
isGuideScan
)
return
val
activity
=
requireActivity
()
as
MainActivity
?
activity
?:
return
val
builder
=
GuideBuilder
()
builder
.
setTargetView
(
binding
.
ivScan
)
.
setHighTargetGraphStyle
(
Component
.
CIRCLE
)
.
setAlpha
(
150
)
.
setHighTargetCorner
(
20
)
.
setHighTargetPadding
(
5
)
.
setExitAnimationId
(
android
.
R
.
anim
.
fade_out
)
builder
.
setOnVisibilityChangedListener
(
object
:
GuideBuilder
.
OnVisibilityChangedListener
{
override
fun
onShown
()
{
AppPreferences
.
getInstance
().
put
(
"isGuideScan"
,
true
)
}
override
fun
onDismiss
()
{
startActivity
(
Intent
(
activity
,
ScanAc
::
class
.
java
))
}
})
builder
.
addComponent
(
LottieComponent
())
val
guide
=
builder
.
createGuide
()
guide
.
setShouldCheckLocInWindow
(
false
)
guide
.
show
(
activity
)
}
}
}
}
\ No newline at end of file
app/src/main/java/com/base/scanqrclear/ui/main/MainActivity.kt
View file @
c3a7ed9e
...
@@ -28,6 +28,7 @@ import com.base.scanqrclear.luma.ActivityJumpHelps
...
@@ -28,6 +28,7 @@ import com.base.scanqrclear.luma.ActivityJumpHelps
import
com.base.scanqrclear.luma.HomeFragment
import
com.base.scanqrclear.luma.HomeFragment
import
com.base.scanqrclear.ui.widget.AppExitDialog.showAppExitDialog
import
com.base.scanqrclear.ui.widget.AppExitDialog.showAppExitDialog
import
com.base.scanqrclear.ui.widget.NotificationDialog.showNotificationTurnOn
import
com.base.scanqrclear.ui.widget.NotificationDialog.showNotificationTurnOn
import
com.base.scanqrclear.utils.AppPreferences
import
com.base.scanqrclear.utils.LogEx
import
com.base.scanqrclear.utils.LogEx
import
com.base.scanqrclear.utils.PermissionUtils.areNotificationsEnabled
import
com.base.scanqrclear.utils.PermissionUtils.areNotificationsEnabled
import
com.base.scanqrclear.utils.PermissionUtils.checkCameraPermission
import
com.base.scanqrclear.utils.PermissionUtils.checkCameraPermission
...
@@ -83,7 +84,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::infl
...
@@ -83,7 +84,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::infl
// if (checkCameraPermission()) {
// if (checkCameraPermission()) {
if
(!
bannerShowed
.
get
())
{
if
(!
bannerShowed
.
get
())
{
bannerShowed
.
set
(
true
)
bannerShowed
.
set
(
true
)
AdsMgr
.
showBanner
(
binding
.
flBanner
,
true
)
{
val
isGuideScan
=
AppPreferences
.
getInstance
().
getBoolean
(
"isGuideScan"
,
false
)
AdsMgr
.
showBanner
(
binding
.
flBanner
,
isGuideScan
)
{
showNotificationDialog
()
showNotificationDialog
()
}
}
}
else
{
}
else
{
...
...
app/src/main/java/com/base/scanqrclear/ui/main/ScanAc.kt
View file @
c3a7ed9e
package
com.base.scanqrclear.ui.main
package
com.base.scanqrclear.ui.main
import
androidx.activity.addCallback
import
com.base.scanqrclear.ads.AdsMgr
import
com.base.scanqrclear.ads.AdsShowCallBack
import
com.base.scanqrclear.base.BaseActivity
import
com.base.scanqrclear.base.BaseActivity
import
com.base.scanqrclear.bean.config.AdConfigBean
import
com.base.scanqrclear.databinding.ActivityScanBinding
import
com.base.scanqrclear.databinding.ActivityScanBinding
import
com.base.scanqrclear.qr.CameraUtils
import
com.base.scanqrclear.qr.CameraUtils
...
@@ -15,6 +19,43 @@ class ScanAc : BaseActivity<ActivityScanBinding>(ActivityScanBinding::inflate) {
...
@@ -15,6 +19,43 @@ class ScanAc : BaseActivity<ActivityScanBinding>(ActivityScanBinding::inflate) {
cameraUtils
=
CameraUtils
(
this
)
cameraUtils
=
CameraUtils
(
this
)
}
}
override
fun
onResumeOneShoot
()
{
super
.
onResumeOneShoot
()
if
(
AdConfigBean
.
adsConfigBean
.
functionInShowAd
)
{
AdsMgr
.
showInsert
(
this
,
false
,
object
:
AdsShowCallBack
()
{
override
fun
close
(
where
:
Int
)
{
}
override
fun
failed
(
where
:
Int
)
{
}
override
fun
googleFailed
(
where
:
Int
)
{
}
})
}
}
override
fun
initListener
()
{
super
.
initListener
()
onBackPressedDispatcher
.
addCallback
{
if
(
AdConfigBean
.
adsConfigBean
.
functionBackShowAd
)
{
AdsMgr
.
showInsert
(
this
@ScanAc
,
false
,
object
:
AdsShowCallBack
()
{
override
fun
close
(
where
:
Int
)
{
finishToMainTop
()
}
override
fun
failed
(
where
:
Int
)
{
finishToMainTop
()
}
override
fun
googleFailed
(
where
:
Int
)
{
finishToMainTop
()
}
})
}
}
}
override
fun
onDestroy
()
{
override
fun
onDestroy
()
{
super
.
onDestroy
()
super
.
onDestroy
()
cameraUtils
?.
unBind
()
cameraUtils
?.
unBind
()
...
...
app/src/main/java/com/base/scanqrclear/ui/main/ScanFragment.kt
View file @
c3a7ed9e
...
@@ -68,10 +68,11 @@ class ScanFragment : BaseFragment<FragmentScanBinding>(FragmentScanBinding::infl
...
@@ -68,10 +68,11 @@ class ScanFragment : BaseFragment<FragmentScanBinding>(FragmentScanBinding::infl
override
fun
onResumeOneShoot
()
{
override
fun
onResumeOneShoot
()
{
super
.
onResumeOneShoot
()
super
.
onResumeOneShoot
()
val
activity
=
requireActivity
()
as
ScanAc
?
if
(
requireContext
().
checkCameraPermission
())
{
if
(
requireContext
().
checkCameraPermission
())
{
initCamera
()
initCamera
()
}
else
{
}
else
{
val
activity
=
requireActivity
()
as
ScanAc
?
activity
?:
return
activity
?:
return
activity
.
launcher
.
launch
(
arrayOf
(
Manifest
.
permission
.
CAMERA
))
{
activity
.
launcher
.
launch
(
arrayOf
(
Manifest
.
permission
.
CAMERA
))
{
initCamera
()
initCamera
()
...
...
app/src/main/java/com/base/scanqrclear/ui/widget/guideview/BuildException.java
0 → 100644
View file @
c3a7ed9e
package
com
.
base
.
scanqrclear
.
ui
.
widget
.
guideview
;
/**
* 遮罩系统运行异常的封装
* Created by binIoter
*/
class
BuildException
extends
RuntimeException
{
private
static
final
long
serialVersionUID
=
6208777692136933357L
;
private
final
String
mDetailMessage
;
public
BuildException
()
{
mDetailMessage
=
"General error."
;
}
public
BuildException
(
String
detailMessage
)
{
mDetailMessage
=
detailMessage
;
}
@Override
public
String
getMessage
()
{
return
"Build GuideFragment failed: "
+
mDetailMessage
;
}
}
app/src/main/java/com/base/scanqrclear/ui/widget/guideview/Common.java
0 → 100644
View file @
c3a7ed9e
package
com
.
base
.
scanqrclear
.
ui
.
widget
.
guideview
;
import
android.graphics.Rect
;
import
android.view.LayoutInflater
;
import
android.view.View
;
import
android.view.ViewGroup
;
import
com.base.scanqrclear.utils.LogEx
;
/**
* Created by binIoter
*/
class
Common
{
/**
* 设置Component
*/
static
View
componentToView
(
LayoutInflater
inflater
,
Component
c
)
{
View
view
=
c
.
getView
(
inflater
);
final
MaskView
.
LayoutParams
lp
=
new
MaskView
.
LayoutParams
(
ViewGroup
.
LayoutParams
.
WRAP_CONTENT
,
ViewGroup
.
LayoutParams
.
WRAP_CONTENT
);
lp
.
offsetX
=
c
.
getXOffset
();
lp
.
offsetY
=
c
.
getYOffset
();
lp
.
targetAnchor
=
c
.
getAnchor
();
lp
.
targetParentPosition
=
c
.
getFitPosition
();
view
.
setLayoutParams
(
lp
);
return
view
;
}
/**
* Rect在屏幕上去掉状态栏高度的绝对位置
*/
static
Rect
getViewAbsRect
(
View
view
,
int
parentX
,
int
parentY
)
{
int
[]
loc
=
new
int
[
2
];
view
.
getLocationInWindow
(
loc
);
LogEx
.
INSTANCE
.
logDebug
(
"getViewAbsRect"
,
"x="
+
loc
[
0
]
+
"y="
+
loc
[
1
],
true
);
Rect
rect
=
new
Rect
();
rect
.
set
(
loc
[
0
],
loc
[
1
],
loc
[
0
]
+
view
.
getMeasuredWidth
(),
loc
[
1
]
+
view
.
getMeasuredHeight
());
rect
.
offset
(-
parentX
,
-
parentY
);
return
rect
;
}
}
app/src/main/java/com/base/scanqrclear/ui/widget/guideview/Component.java
0 → 100644
View file @
c3a7ed9e
package
com
.
base
.
scanqrclear
.
ui
.
widget
.
guideview
;
import
android.view.LayoutInflater
;
import
android.view.View
;
/**
* * 遮罩系统中相对于目标区域而绘制一些图片或者文字等view需要实现的接口. <br>
* * <br>
* * {@link #getView(LayoutInflater)} <br>
* * {@link #getAnchor()} <br>
* * {@link #getFitPosition()} <br>
* * {@link #getXOffset()} <br>
* * {@link #getYOffset()}
* * <br>
* * 具体创建遮罩的说明请参加{@link GuideBuilder}
* *
*
* Created by binIoter
*/
public
interface
Component
{
public
final
static
int
FIT_START
=
MaskView
.
LayoutParams
.
PARENT_START
;
public
final
static
int
FIT_END
=
MaskView
.
LayoutParams
.
PARENT_END
;
public
final
static
int
FIT_CENTER
=
MaskView
.
LayoutParams
.
PARENT_CENTER
;
public
final
static
int
ANCHOR_LEFT
=
MaskView
.
LayoutParams
.
ANCHOR_LEFT
;
public
final
static
int
ANCHOR_RIGHT
=
MaskView
.
LayoutParams
.
ANCHOR_RIGHT
;
public
final
static
int
ANCHOR_BOTTOM
=
MaskView
.
LayoutParams
.
ANCHOR_BOTTOM
;
public
final
static
int
ANCHOR_TOP
=
MaskView
.
LayoutParams
.
ANCHOR_TOP
;
public
final
static
int
ANCHOR_OVER
=
MaskView
.
LayoutParams
.
ANCHOR_OVER
;
/**
* 圆角矩形&矩形
*/
public
final
static
int
ROUNDRECT
=
0
;
/**
* 圆形
*/
public
final
static
int
CIRCLE
=
1
;
/**
* 需要显示的view
*
* @param inflater use to inflate xml resource file
* @return the component view
*/
View
getView
(
LayoutInflater
inflater
);
/**
* 相对目标View的锚点
*
* @return could be {@link #ANCHOR_LEFT}, {@link #ANCHOR_RIGHT},
* {@link #ANCHOR_TOP}, {@link #ANCHOR_BOTTOM}, {@link #ANCHOR_OVER}
*/
int
getAnchor
();
/**
* 相对目标View的对齐
*
* @return could be {@link #FIT_START}, {@link #FIT_END},
* {@link #FIT_CENTER}
*/
int
getFitPosition
();
/**
* 相对目标View的X轴位移,在计算锚点和对齐之后。
*
* @return X轴偏移量, 单位 dp
*/
int
getXOffset
();
/**
* 相对目标View的Y轴位移,在计算锚点和对齐之后。
*
* @return Y轴偏移量,单位 dp
*/
int
getYOffset
();
}
app/src/main/java/com/base/scanqrclear/ui/widget/guideview/Configuration.java
0 → 100644
View file @
c3a7ed9e
package
com
.
base
.
scanqrclear
.
ui
.
widget
.
guideview
;
import
android.os.Parcel
;
import
android.os.Parcelable
;
import
android.view.View
;
/**
* 遮罩系统创建时配置参数的封装 <br/>
* Created by binIoter
*/
class
Configuration
implements
Parcelable
{
/**
* 需要被找的View
*/
View
mTargetView
=
null
;
/**
* 高亮区域的padding
*/
int
mPadding
=
0
;
/**
* 高亮区域的左侧padding
*/
int
mPaddingLeft
=
0
;
/**
* 高亮区域的顶部padding
*/
int
mPaddingTop
=
0
;
/**
* 高亮区域的右侧padding
*/
int
mPaddingRight
=
0
;
/**
* 高亮区域的底部padding
*/
int
mPaddingBottom
=
0
;
/**
* 是否可以透过蒙层点击,默认不可以
*/
boolean
mOutsideTouchable
=
false
;
/**
* 遮罩透明度
*/
int
mAlpha
=
255
;
/**
* 遮罩覆盖区域控件Id
* <p/>
* 该控件的大小既该导航页面的大小
*/
int
mFullingViewId
=
-
1
;
/**
* 目标控件Id
*/
int
mTargetViewId
=
-
1
;
/**
* 高亮区域的圆角大小
*/
int
mCorner
=
0
;
/**
* 高亮区域的图形样式,默认为矩形
*/
int
mGraphStyle
=
Component
.
ROUNDRECT
;
/**
* 遮罩背景颜色id
*/
int
mFullingColorId
=
android
.
R
.
color
.
black
;
/**
* 是否在点击的时候自动退出导航
*/
boolean
mAutoDismiss
=
true
;
/**
* 是否覆盖目标控件
*/
boolean
mOverlayTarget
=
false
;
boolean
mShowCloseButton
=
false
;
int
mEnterAnimationId
=
-
1
;
int
mExitAnimationId
=
-
1
;
@Override
public
int
describeContents
()
{
return
0
;
}
@Override
public
void
writeToParcel
(
Parcel
dest
,
int
flags
)
{
dest
.
writeInt
(
mAlpha
);
dest
.
writeInt
(
mFullingViewId
);
dest
.
writeInt
(
mTargetViewId
);
dest
.
writeInt
(
mFullingColorId
);
dest
.
writeInt
(
mCorner
);
dest
.
writeInt
(
mPadding
);
dest
.
writeInt
(
mPaddingLeft
);
dest
.
writeInt
(
mPaddingTop
);
dest
.
writeInt
(
mPaddingRight
);
dest
.
writeInt
(
mPaddingBottom
);
dest
.
writeInt
(
mGraphStyle
);
dest
.
writeByte
((
byte
)
(
mAutoDismiss
?
1
:
0
));
dest
.
writeByte
((
byte
)
(
mOverlayTarget
?
1
:
0
));
}
public
static
final
Creator
<
Configuration
>
CREATOR
=
new
Creator
<
Configuration
>()
{
@Override
public
Configuration
createFromParcel
(
Parcel
source
)
{
Configuration
conf
=
new
Configuration
();
conf
.
mAlpha
=
source
.
readInt
();
conf
.
mFullingViewId
=
source
.
readInt
();
conf
.
mTargetViewId
=
source
.
readInt
();
conf
.
mFullingColorId
=
source
.
readInt
();
conf
.
mCorner
=
source
.
readInt
();
conf
.
mPadding
=
source
.
readInt
();
conf
.
mPaddingLeft
=
source
.
readInt
();
conf
.
mPaddingTop
=
source
.
readInt
();
conf
.
mPaddingRight
=
source
.
readInt
();
conf
.
mPaddingBottom
=
source
.
readInt
();
conf
.
mGraphStyle
=
source
.
readInt
();
conf
.
mAutoDismiss
=
source
.
readByte
()
==
1
;
conf
.
mOverlayTarget
=
source
.
readByte
()
==
1
;
return
conf
;
}
@Override
public
Configuration
[]
newArray
(
int
size
)
{
return
new
Configuration
[
size
];
}
};
}
app/src/main/java/com/base/scanqrclear/ui/widget/guideview/DimenUtil.java
0 → 100644
View file @
c3a7ed9e
package
com
.
base
.
scanqrclear
.
ui
.
widget
.
guideview
;
import
android.content.Context
;
/**
* Created by binIoter
*/
public
class
DimenUtil
{
/** sp转换成px */
public
static
int
sp2px
(
Context
context
,
float
spValue
)
{
float
fontScale
=
context
.
getApplicationContext
().
getResources
().
getDisplayMetrics
().
scaledDensity
;
return
(
int
)
(
spValue
*
fontScale
+
0.5f
);
}
/** px转换成sp */
public
static
int
px2sp
(
Context
context
,
float
pxValue
)
{
float
fontScale
=
context
.
getApplicationContext
().
getResources
().
getDisplayMetrics
().
density
;
return
(
int
)
(
pxValue
/
fontScale
+
0.5f
);
}
/** dip转换成px */
public
static
int
dp2px
(
Context
context
,
float
dipValue
)
{
float
scale
=
context
.
getApplicationContext
().
getResources
().
getDisplayMetrics
().
scaledDensity
;
return
(
int
)
(
dipValue
*
scale
+
0.5f
);
}
/** px转换成dip */
public
static
int
px2dp
(
Context
context
,
float
pxValue
)
{
float
scale
=
context
.
getApplicationContext
().
getResources
().
getDisplayMetrics
().
scaledDensity
;
return
(
int
)
(
pxValue
/
scale
+
0.5f
);
}
}
\ No newline at end of file
app/src/main/java/com/base/scanqrclear/ui/widget/guideview/Guide.java
0 → 100644
View file @
c3a7ed9e
package
com
.
base
.
scanqrclear
.
ui
.
widget
.
guideview
;
import
android.app.Activity
;
import
android.content.Context
;
import
android.view.KeyEvent
;
import
android.view.MotionEvent
;
import
android.view.View
;
import
android.view.ViewGroup
;
import
android.view.animation.Animation
;
import
android.view.animation.AnimationUtils
;
/**
* 遮罩系统的封装 <br>
* * 外部需要调用{@link GuideBuilder}来创建该实例,实例创建后调用
* * {@link #show(Activity)} 控制显示; 调用 {@link #dismiss()}让遮罩系统消失。 <br>
* <p>
* Created by binIoter
*/
public
class
Guide
implements
View
.
OnKeyListener
,
View
.
OnTouchListener
{
Guide
()
{
}
/**
* 滑动临界值
*/
private
static
final
int
SLIDE_THRESHOLD
=
30
;
private
Configuration
mConfiguration
;
private
MaskView
mMaskView
;
private
Component
[]
mComponents
;
// 根据locInwindow定位后,是否需要判断loc值非0
private
boolean
mShouldCheckLocInWindow
=
true
;
private
GuideBuilder
.
OnVisibilityChangedListener
mOnVisibilityChangedListener
;
private
GuideBuilder
.
OnSlideListener
mOnSlideListener
;
void
setConfiguration
(
Configuration
configuration
)
{
mConfiguration
=
configuration
;
}
void
setComponents
(
Component
[]
components
)
{
mComponents
=
components
;
}
void
setCallback
(
GuideBuilder
.
OnVisibilityChangedListener
listener
)
{
this
.
mOnVisibilityChangedListener
=
listener
;
}
public
void
setOnSlideListener
(
GuideBuilder
.
OnSlideListener
onSlideListener
)
{
this
.
mOnSlideListener
=
onSlideListener
;
}
/**
* 显示遮罩
*
* @param activity 目标Activity
*/
public
void
show
(
Activity
activity
)
{
show
(
activity
,
null
);
}
/**
* 显示遮罩
*
* @param activity 目标Activity
* @param overlay 遮罩层view
*/
public
void
show
(
Activity
activity
,
ViewGroup
overlay
)
{
mMaskView
=
onCreateView
(
activity
,
overlay
);
if
(
overlay
==
null
)
{
overlay
=
(
ViewGroup
)
activity
.
getWindow
().
getDecorView
();
}
if
(
mMaskView
.
getParent
()
==
null
&&
mConfiguration
.
mTargetView
!=
null
)
{
overlay
.
addView
(
mMaskView
);
if
(
mConfiguration
.
mEnterAnimationId
!=
-
1
)
{
Animation
anim
=
AnimationUtils
.
loadAnimation
(
activity
,
mConfiguration
.
mEnterAnimationId
);
assert
anim
!=
null
;
anim
.
setAnimationListener
(
new
Animation
.
AnimationListener
()
{
@Override
public
void
onAnimationStart
(
Animation
animation
)
{
}
@Override
public
void
onAnimationEnd
(
Animation
animation
)
{
if
(
mOnVisibilityChangedListener
!=
null
)
{
mOnVisibilityChangedListener
.
onShown
();
}
}
@Override
public
void
onAnimationRepeat
(
Animation
animation
)
{
}
});
mMaskView
.
startAnimation
(
anim
);
}
else
{
if
(
mOnVisibilityChangedListener
!=
null
)
{
mOnVisibilityChangedListener
.
onShown
();
}
}
}
}
public
void
clear
()
{
if
(
mMaskView
==
null
)
{
return
;
}
final
ViewGroup
vp
=
(
ViewGroup
)
mMaskView
.
getParent
();
if
(
vp
==
null
)
{
return
;
}
vp
.
removeView
(
mMaskView
);
onDestroy
();
}
/**
* 隐藏该遮罩并回收资源相关
*/
public
void
dismiss
()
{
if
(
mMaskView
==
null
)
{
return
;
}
final
ViewGroup
vp
=
(
ViewGroup
)
mMaskView
.
getParent
();
if
(
vp
==
null
)
{
return
;
}
if
(
mConfiguration
.
mExitAnimationId
!=
-
1
)
{
// mMaskView may leak if context is null
Context
context
=
mMaskView
.
getContext
();
assert
context
!=
null
;
Animation
anim
=
AnimationUtils
.
loadAnimation
(
context
,
mConfiguration
.
mExitAnimationId
);
assert
anim
!=
null
;
anim
.
setAnimationListener
(
new
Animation
.
AnimationListener
()
{
@Override
public
void
onAnimationStart
(
Animation
animation
)
{
}
@Override
public
void
onAnimationEnd
(
Animation
animation
)
{
vp
.
removeView
(
mMaskView
);
if
(
mOnVisibilityChangedListener
!=
null
)
{
mOnVisibilityChangedListener
.
onDismiss
();
}
onDestroy
();
}
@Override
public
void
onAnimationRepeat
(
Animation
animation
)
{
}
});
mMaskView
.
startAnimation
(
anim
);
}
else
{
vp
.
removeView
(
mMaskView
);
if
(
mOnVisibilityChangedListener
!=
null
)
{
mOnVisibilityChangedListener
.
onDismiss
();
}
onDestroy
();
}
}
/**
* 根据locInwindow定位后,是否需要判断loc值非0
*/
public
void
setShouldCheckLocInWindow
(
boolean
set
)
{
mShouldCheckLocInWindow
=
set
;
}
private
MaskView
onCreateView
(
Activity
activity
,
ViewGroup
overlay
)
{
if
(
overlay
==
null
)
{
overlay
=
(
ViewGroup
)
activity
.
getWindow
().
getDecorView
();
}
MaskView
maskView
=
new
MaskView
(
activity
);
maskView
.
setFullingColor
(
activity
.
getResources
().
getColor
(
mConfiguration
.
mFullingColorId
));
maskView
.
setFullingAlpha
(
mConfiguration
.
mAlpha
);
maskView
.
setHighTargetCorner
(
mConfiguration
.
mCorner
);
maskView
.
setPadding
(
mConfiguration
.
mPadding
);
maskView
.
setPaddingLeft
(
mConfiguration
.
mPaddingLeft
);
maskView
.
setPaddingTop
(
mConfiguration
.
mPaddingTop
);
maskView
.
setPaddingRight
(
mConfiguration
.
mPaddingRight
);
maskView
.
setPaddingBottom
(
mConfiguration
.
mPaddingBottom
);
maskView
.
setHighTargetGraphStyle
(
mConfiguration
.
mGraphStyle
);
maskView
.
setOverlayTarget
(
mConfiguration
.
mOverlayTarget
);
maskView
.
setOnKeyListener
(
this
);
// For removing the height of status bar we need the root content view's
// location on screen
int
parentX
=
0
;
int
parentY
=
0
;
if
(
overlay
!=
null
)
{
int
[]
loc
=
new
int
[
2
];
overlay
.
getLocationInWindow
(
loc
);
parentX
=
loc
[
0
];
parentY
=
loc
[
1
];
}
if
(
mConfiguration
.
mTargetView
!=
null
)
{
maskView
.
setTargetRect
(
Common
.
getViewAbsRect
(
mConfiguration
.
mTargetView
,
parentX
,
parentY
));
}
else
{
// Gets the target view's abs rect
View
target
=
activity
.
findViewById
(
mConfiguration
.
mTargetViewId
);
if
(
target
!=
null
)
{
maskView
.
setTargetRect
(
Common
.
getViewAbsRect
(
target
,
parentX
,
parentY
));
}
}
if
(
mConfiguration
.
mOutsideTouchable
)
{
maskView
.
setClickable
(
false
);
}
else
{
maskView
.
setOnTouchListener
(
this
);
}
// Adds the components to the mask view.
for
(
Component
c
:
mComponents
)
{
maskView
.
addView
(
Common
.
componentToView
(
activity
.
getLayoutInflater
(),
c
));
}
return
maskView
;
}
private
void
onDestroy
()
{
mConfiguration
=
null
;
mComponents
=
null
;
mOnVisibilityChangedListener
=
null
;
mOnSlideListener
=
null
;
mMaskView
.
removeAllViews
();
mMaskView
=
null
;
}
@Override
public
boolean
onKey
(
View
v
,
int
keyCode
,
KeyEvent
event
)
{
if
(
keyCode
==
KeyEvent
.
KEYCODE_BACK
&&
event
.
getAction
()
==
KeyEvent
.
ACTION_UP
)
{
if
(
mConfiguration
!=
null
&&
mConfiguration
.
mAutoDismiss
)
{
dismiss
();
return
true
;
}
else
{
return
false
;
}
}
return
false
;
}
float
startY
=
-
1
f
;
@Override
public
boolean
onTouch
(
View
view
,
MotionEvent
motionEvent
)
{
if
(
motionEvent
.
getAction
()
==
MotionEvent
.
ACTION_DOWN
)
{
startY
=
motionEvent
.
getY
();
}
else
if
(
motionEvent
.
getAction
()
==
MotionEvent
.
ACTION_UP
)
{
if
(
startY
-
motionEvent
.
getY
()
>
DimenUtil
.
dp2px
(
view
.
getContext
(),
SLIDE_THRESHOLD
))
{
if
(
mOnSlideListener
!=
null
)
{
mOnSlideListener
.
onSlideListener
(
GuideBuilder
.
SlideState
.
UP
);
}
}
else
if
(
motionEvent
.
getY
()
-
startY
>
DimenUtil
.
dp2px
(
view
.
getContext
(),
SLIDE_THRESHOLD
))
{
if
(
mOnSlideListener
!=
null
)
{
mOnSlideListener
.
onSlideListener
(
GuideBuilder
.
SlideState
.
DOWN
);
}
}
if
(
mConfiguration
!=
null
&&
mConfiguration
.
mAutoDismiss
)
{
dismiss
();
}
}
return
true
;
}
}
app/src/main/java/com/base/scanqrclear/ui/widget/guideview/GuideBuilder.java
0 → 100644
View file @
c3a7ed9e
package
com
.
base
.
scanqrclear
.
ui
.
widget
.
guideview
;
import
android.annotation.SuppressLint
;
import
android.view.View
;
import
androidx.annotation.AnimatorRes
;
import
androidx.annotation.IdRes
;
import
androidx.annotation.IntRange
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* <h1>遮罩系统构建器</h1>
* 本系统能够快速的为一个Activity里的任何一个View控件创建一个遮罩式的引导页。
* </p>
* <h3>工作原理</h3>
* 首先它需要一个目标View或者它的id,我们通过findViewById来得到这个View,计算它在屏幕上的区域targetRect,参见
* {@link #setTargetViewId(int)}与{@link #setTargetView(View)}通过这个区域,
* 开始绘制一个覆盖整个Activity的遮罩,可以定义蒙板的颜色{@link #setFullingColorId(int)}和透明度
* {@link #setAlpha(int)}。然而目标View的区域不会被绘制从而实现高亮的效果。
* </p>
* 接下来是在相对于这个targetRect的区域绘制一些图片或者文字。我们把这样一张图片或者文字抽象成一个Component接口
* {@link Component},设置文字或者图片等
* {@link Component#getView(android.view.LayoutInflater)}
* . 所有的图片文字都是相对于targetRect来定义的。可以设定额外的x,
* {@link Component#getXOffset()} ;y偏移量,
* {@link Component#getYOffset()}。
* </p>
* 可以对遮罩系统设置可见状态的发生变化时的监听回调
* {@link #setOnVisibilityChangedListener(OnVisibilityChangedListener)}
* </p>
* 可以对遮罩系统设置开始和结束时的动画效果 {@link #setEnterAnimationId(int)}
* {@link #setExitAnimationId(int)}
* </p>
* <p>
* Created by binIoter
**/
public
class
GuideBuilder
{
public
enum
SlideState
{
UP
,
DOWN
;
}
private
Configuration
mConfiguration
;
/**
* Builder被创建后,不允许在对它进行更改
*/
private
boolean
mBuilt
;
private
List
<
Component
>
mComponents
=
new
ArrayList
<
Component
>();
private
OnVisibilityChangedListener
mOnVisibilityChangedListener
;
private
OnSlideListener
mOnSlideListener
;
/**
* 构造函数
*/
public
GuideBuilder
()
{
mConfiguration
=
new
Configuration
();
}
/**
* 设置蒙板透明度
*
* @param alpha [0-255] 0 表示完全透明,255表示不透明
* @return GuideBuilder
*/
public
GuideBuilder
setAlpha
(
@IntRange
(
from
=
0
,
to
=
255
)
int
alpha
)
{
if
(
mBuilt
)
{
throw
new
BuildException
(
"Already created. rebuild a new one."
);
}
else
if
(
alpha
<
0
||
alpha
>
255
)
{
alpha
=
0
;
}
mConfiguration
.
mAlpha
=
alpha
;
return
this
;
}
/**
* 设置目标view
*/
public
GuideBuilder
setTargetView
(
View
v
)
{
if
(
mBuilt
)
{
throw
new
BuildException
(
"Already created. rebuild a new one."
);
}
mConfiguration
.
mTargetView
=
v
;
return
this
;
}
/**
* 设置目标View的id
*
* @param id 目标View的id
* @return GuideBuilder
*/
public
GuideBuilder
setTargetViewId
(
@IdRes
int
id
)
{
if
(
mBuilt
)
{
throw
new
BuildException
(
"Already created. rebuild a new one."
);
}
mConfiguration
.
mTargetViewId
=
id
;
return
this
;
}
/**
* 设置高亮区域的圆角大小
*
* @return GuideBuilder
*/
public
GuideBuilder
setHighTargetCorner
(
int
corner
)
{
if
(
mBuilt
)
{
throw
new
BuildException
(
"Already created. rebuild a new one."
);
}
else
if
(
corner
<
0
)
{
mConfiguration
.
mCorner
=
0
;
}
mConfiguration
.
mCorner
=
corner
;
return
this
;
}
/**
* 设置高亮区域的图形样式
*
* @return GuideBuilder
*/
public
GuideBuilder
setHighTargetGraphStyle
(
int
style
)
{
if
(
mBuilt
)
{
throw
new
BuildException
(
"Already created. rebuild a new one."
);
}
mConfiguration
.
mGraphStyle
=
style
;
return
this
;
}
/**
* 设置蒙板颜色的资源id
*
* @param id 资源id
* @return GuideBuilder
*/
@SuppressLint
(
"ResourceType"
)
public
GuideBuilder
setFullingColorId
(
@IdRes
int
id
)
{
if
(
mBuilt
)
{
throw
new
BuildException
(
"Already created. rebuild a new one."
);
}
mConfiguration
.
mFullingColorId
=
id
;
return
this
;
}
/**
* 是否在点击的时候自动退出蒙板
*
* @param b true if needed
* @return GuideBuilder
*/
public
GuideBuilder
setAutoDismiss
(
boolean
b
)
{
if
(
mBuilt
)
{
throw
new
BuildException
(
"Already created, rebuild a new one."
);
}
mConfiguration
.
mAutoDismiss
=
b
;
return
this
;
}
/**
* 是否覆盖目标
*
* @param b true 遮罩将会覆盖整个屏幕
* @return GuideBuilder
*/
public
GuideBuilder
setOverlayTarget
(
boolean
b
)
{
if
(
mBuilt
)
{
throw
new
BuildException
(
"Already created, rebuild a new one."
);
}
mConfiguration
.
mOverlayTarget
=
b
;
return
this
;
}
/**
* 设置进入动画
*
* @param id 进入动画的id
* @return GuideBuilder
*/
public
GuideBuilder
setEnterAnimationId
(
@AnimatorRes
int
id
)
{
if
(
mBuilt
)
{
throw
new
BuildException
(
"Already created. rebuild a new one."
);
}
mConfiguration
.
mEnterAnimationId
=
id
;
return
this
;
}
/**
* 设置退出动画
*
* @param id 退出动画的id @AnimatorRes
* @return GuideBuilder
*/
public
GuideBuilder
setExitAnimationId
(
int
id
)
{
if
(
mBuilt
)
{
throw
new
BuildException
(
"Already created. rebuild a new one."
);
}
mConfiguration
.
mExitAnimationId
=
id
;
return
this
;
}
/**
* 添加一个控件
*
* @param component 被添加的控件
* @return GuideBuilder
*/
public
GuideBuilder
addComponent
(
Component
component
)
{
if
(
mBuilt
)
{
throw
new
BuildException
(
"Already created, rebuild a new one."
);
}
mComponents
.
add
(
component
);
return
this
;
}
/**
* 设置遮罩可见状态变化时的监听回调
*/
public
GuideBuilder
setOnVisibilityChangedListener
(
OnVisibilityChangedListener
onVisibilityChangedListener
)
{
if
(
mBuilt
)
{
throw
new
BuildException
(
"Already created, rebuild a new one."
);
}
mOnVisibilityChangedListener
=
onVisibilityChangedListener
;
return
this
;
}
/**
* 设置手势滑动的监听回调
*/
public
GuideBuilder
setOnSlideListener
(
OnSlideListener
onSlideListener
)
{
if
(
mBuilt
)
{
throw
new
BuildException
(
"Already created, rebuild a new one."
);
}
mOnSlideListener
=
onSlideListener
;
return
this
;
}
/**
* 设置遮罩系统是否可点击并处理点击事件
*
* @param touchable true 遮罩不可点击,处于不可点击状态 false 可点击,遮罩自己可以处理自身点击事件
*/
public
GuideBuilder
setOutsideTouchable
(
boolean
touchable
)
{
mConfiguration
.
mOutsideTouchable
=
touchable
;
return
this
;
}
/**
* 设置高亮区域的padding
*
* @return GuideBuilder
*/
public
GuideBuilder
setHighTargetPadding
(
int
padding
)
{
if
(
mBuilt
)
{
throw
new
BuildException
(
"Already created. rebuild a new one."
);
}
else
if
(
padding
<
0
)
{
mConfiguration
.
mPadding
=
0
;
}
mConfiguration
.
mPadding
=
padding
;
return
this
;
}
/**
* 设置高亮区域的左侧padding
*
* @return GuideBuilder
*/
public
GuideBuilder
setHighTargetPaddingLeft
(
int
padding
)
{
if
(
mBuilt
)
{
throw
new
BuildException
(
"Already created. rebuild a new one."
);
}
else
if
(
padding
<
0
)
{
mConfiguration
.
mPaddingLeft
=
0
;
}
mConfiguration
.
mPaddingLeft
=
padding
;
return
this
;
}
/**
* 设置高亮区域的顶部padding
*
* @return GuideBuilder
*/
public
GuideBuilder
setHighTargetPaddingTop
(
int
padding
)
{
if
(
mBuilt
)
{
throw
new
BuildException
(
"Already created. rebuild a new one."
);
}
else
if
(
padding
<
0
)
{
mConfiguration
.
mPaddingTop
=
0
;
}
mConfiguration
.
mPaddingTop
=
padding
;
return
this
;
}
/**
* 设置高亮区域的右侧padding
*
* @return GuideBuilder
*/
public
GuideBuilder
setHighTargetPaddingRight
(
int
padding
)
{
if
(
mBuilt
)
{
throw
new
BuildException
(
"Already created. rebuild a new one."
);
}
else
if
(
padding
<
0
)
{
mConfiguration
.
mPaddingRight
=
0
;
}
mConfiguration
.
mPaddingRight
=
padding
;
return
this
;
}
/**
* 设置高亮区域的底部padding
*
* @return GuideBuilder
*/
public
GuideBuilder
setHighTargetPaddingBottom
(
int
padding
)
{
if
(
mBuilt
)
{
throw
new
BuildException
(
"Already created. rebuild a new one."
);
}
else
if
(
padding
<
0
)
{
mConfiguration
.
mPaddingBottom
=
0
;
}
mConfiguration
.
mPaddingBottom
=
padding
;
return
this
;
}
/**
* 创建Guide,非Fragment版本
*
* @return Guide
*/
public
Guide
createGuide
()
{
Guide
guide
=
new
Guide
();
Component
[]
components
=
new
Component
[
mComponents
.
size
()];
guide
.
setComponents
(
mComponents
.
toArray
(
components
));
guide
.
setConfiguration
(
mConfiguration
);
guide
.
setCallback
(
mOnVisibilityChangedListener
);
guide
.
setOnSlideListener
(
mOnSlideListener
);
mComponents
=
null
;
mConfiguration
=
null
;
mOnVisibilityChangedListener
=
null
;
mBuilt
=
true
;
return
guide
;
}
/**
* 手势滑动监听
*/
public
static
interface
OnSlideListener
{
void
onSlideListener
(
SlideState
state
);
}
/**
* 遮罩可见发生变化时的事件监听
*/
public
static
interface
OnVisibilityChangedListener
{
void
onShown
();
void
onDismiss
();
}
}
app/src/main/java/com/base/scanqrclear/ui/widget/guideview/LottieComponent.java
0 → 100644
View file @
c3a7ed9e
package
com
.
base
.
scanqrclear
.
ui
.
widget
.
guideview
;
import
android.view.LayoutInflater
;
import
android.view.View
;
import
android.widget.LinearLayout
;
import
android.widget.Toast
;
import
com.base.scanqrclear.R
;
/**
* Created by binIoter on 16/6/17.
*/
public
class
LottieComponent
implements
Component
{
@Override
public
View
getView
(
LayoutInflater
inflater
)
{
LinearLayout
ll
=
(
LinearLayout
)
inflater
.
inflate
(
R
.
layout
.
layout_lottie_guide
,
null
);
ll
.
setOnClickListener
(
view
->
Toast
.
makeText
(
view
.
getContext
(),
"引导层被点击了"
,
Toast
.
LENGTH_SHORT
).
show
());
return
ll
;
}
@Override
public
int
getAnchor
()
{
return
Component
.
ANCHOR_BOTTOM
;
}
@Override
public
int
getFitPosition
()
{
return
Component
.
FIT_CENTER
;
}
@Override
public
int
getXOffset
()
{
return
0
;
}
@Override
public
int
getYOffset
()
{
return
-
30
;
}
}
app/src/main/java/com/base/scanqrclear/ui/widget/guideview/MaskView.java
0 → 100644
View file @
c3a7ed9e
package
com
.
base
.
scanqrclear
.
ui
.
widget
.
guideview
;
import
static
android
.
view
.
ViewGroup
.
LayoutParams
.
WRAP_CONTENT
;
import
android.content.Context
;
import
android.graphics.Bitmap
;
import
android.graphics.Canvas
;
import
android.graphics.Color
;
import
android.graphics.Paint
;
import
android.graphics.PorterDuff
;
import
android.graphics.PorterDuffXfermode
;
import
android.graphics.Rect
;
import
android.graphics.RectF
;
import
android.util.AttributeSet
;
import
android.util.DisplayMetrics
;
import
android.view.View
;
import
android.view.ViewGroup
;
import
android.view.WindowManager
;
/**
* Created by binIoter
*/
class
MaskView
extends
ViewGroup
{
/**
* 高亮区域
*/
private
final
RectF
mTargetRect
=
new
RectF
();
/**
* 蒙层区域
*/
private
final
RectF
mOverlayRect
=
new
RectF
();
/**
* 中间变量
*/
private
final
RectF
mChildTmpRect
=
new
RectF
();
/**
* 蒙层背景画笔
*/
private
final
Paint
mFullingPaint
;
private
int
mPadding
=
0
;
private
int
mPaddingLeft
=
0
;
private
int
mPaddingTop
=
0
;
private
int
mPaddingRight
=
0
;
private
int
mPaddingBottom
=
0
;
/**
* 是否覆盖目标区域
*/
private
boolean
mOverlayTarget
=
false
;
/**
* 圆角大小
*/
private
int
mCorner
=
0
;
/**
* 目标区域样式,默认为矩形
*/
private
int
mStyle
=
Component
.
ROUNDRECT
;
/**
* 挖空画笔
*/
private
Paint
mEraser
;
/**
* 橡皮擦Bitmap
*/
private
Bitmap
mEraserBitmap
;
/**
* 橡皮擦Cavas
*/
private
Canvas
mEraserCanvas
;
private
boolean
ignoreRepadding
;
private
int
mInitHeight
;
private
int
mChangedHeight
=
0
;
private
boolean
mFirstFlag
=
true
;
public
MaskView
(
Context
context
)
{
this
(
context
,
null
,
0
);
}
public
MaskView
(
Context
context
,
AttributeSet
attrs
)
{
this
(
context
,
attrs
,
0
);
}
public
MaskView
(
Context
context
,
AttributeSet
attrs
,
int
defStyle
)
{
super
(
context
,
attrs
,
defStyle
);
//自我绘制
setWillNotDraw
(
false
);
WindowManager
wm
=
(
WindowManager
)
getContext
().
getSystemService
(
Context
.
WINDOW_SERVICE
);
DisplayMetrics
displayMetrics
=
new
DisplayMetrics
();
wm
.
getDefaultDisplay
().
getRealMetrics
(
displayMetrics
);
int
width
=
displayMetrics
.
widthPixels
;
int
height
=
displayMetrics
.
heightPixels
;
mOverlayRect
.
set
(
0
,
0
,
width
,
height
);
mEraserBitmap
=
Bitmap
.
createBitmap
(
width
,
height
,
Bitmap
.
Config
.
ARGB_8888
);
mEraserCanvas
=
new
Canvas
(
mEraserBitmap
);
mFullingPaint
=
new
Paint
();
mEraser
=
new
Paint
();
mEraser
.
setColor
(
0xFFFFFFFF
);
//图形重叠时的处理方式,擦除效果
mEraser
.
setXfermode
(
new
PorterDuffXfermode
(
PorterDuff
.
Mode
.
CLEAR
));
//位图抗锯齿设置
mEraser
.
setFlags
(
Paint
.
ANTI_ALIAS_FLAG
);
}
@Override
protected
void
onDetachedFromWindow
()
{
super
.
onDetachedFromWindow
();
try
{
clearFocus
();
mEraserCanvas
.
setBitmap
(
null
);
mEraserBitmap
=
null
;
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
@Override
protected
void
onMeasure
(
int
widthMeasureSpec
,
int
heightMeasureSpec
)
{
super
.
onMeasure
(
widthMeasureSpec
,
heightMeasureSpec
);
final
int
w
=
MeasureSpec
.
getSize
(
widthMeasureSpec
);
final
int
h
=
MeasureSpec
.
getSize
(
heightMeasureSpec
);
if
(
mFirstFlag
)
{
mInitHeight
=
h
;
mFirstFlag
=
false
;
}
if
(
mInitHeight
>
h
)
{
mChangedHeight
=
h
-
mInitHeight
;
}
else
if
(
mInitHeight
<
h
)
{
mChangedHeight
=
h
-
mInitHeight
;
}
else
{
mChangedHeight
=
0
;
}
setMeasuredDimension
(
w
,
h
);
mOverlayRect
.
set
(
0
,
0
,
w
,
h
);
resetOutPath
();
final
int
count
=
getChildCount
();
View
child
;
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
child
=
getChildAt
(
i
);
if
(
child
!=
null
)
{
measureChild
(
child
,
widthMeasureSpec
,
heightMeasureSpec
);
}
}
}
@Override
protected
void
onLayout
(
boolean
changed
,
int
l
,
int
t
,
int
r
,
int
b
)
{
final
int
count
=
getChildCount
();
final
float
density
=
getResources
().
getDisplayMetrics
().
density
;
View
child
;
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
child
=
getChildAt
(
i
);
if
(
child
==
null
)
{
continue
;
}
LayoutParams
lp
=
(
LayoutParams
)
child
.
getLayoutParams
();
if
(
lp
==
null
)
{
continue
;
}
switch
(
lp
.
targetAnchor
)
{
case
LayoutParams
.
ANCHOR_LEFT
:
//左
mChildTmpRect
.
right
=
mTargetRect
.
left
;
mChildTmpRect
.
left
=
mChildTmpRect
.
right
-
child
.
getMeasuredWidth
();
verticalChildPositionLayout
(
child
,
mChildTmpRect
,
lp
.
targetParentPosition
);
break
;
case
LayoutParams
.
ANCHOR_TOP
:
//上
mChildTmpRect
.
bottom
=
mTargetRect
.
top
;
mChildTmpRect
.
top
=
mChildTmpRect
.
bottom
-
child
.
getMeasuredHeight
();
horizontalChildPositionLayout
(
child
,
mChildTmpRect
,
lp
.
targetParentPosition
);
break
;
case
LayoutParams
.
ANCHOR_RIGHT
:
//右
mChildTmpRect
.
left
=
mTargetRect
.
right
;
mChildTmpRect
.
right
=
mChildTmpRect
.
left
+
child
.
getMeasuredWidth
();
verticalChildPositionLayout
(
child
,
mChildTmpRect
,
lp
.
targetParentPosition
);
break
;
case
LayoutParams
.
ANCHOR_BOTTOM
:
//下
mChildTmpRect
.
top
=
mTargetRect
.
bottom
;
mChildTmpRect
.
bottom
=
mChildTmpRect
.
top
+
child
.
getMeasuredHeight
();
horizontalChildPositionLayout
(
child
,
mChildTmpRect
,
lp
.
targetParentPosition
);
break
;
case
LayoutParams
.
ANCHOR_OVER
:
//中心
mChildTmpRect
.
left
=
((
int
)
mTargetRect
.
width
()
-
child
.
getMeasuredWidth
())
>>
1
;
mChildTmpRect
.
top
=
((
int
)
mTargetRect
.
height
()
-
child
.
getMeasuredHeight
())
>>
1
;
mChildTmpRect
.
right
=
((
int
)
mTargetRect
.
width
()
+
child
.
getMeasuredWidth
())
>>
1
;
mChildTmpRect
.
bottom
=
((
int
)
mTargetRect
.
height
()
+
child
.
getMeasuredHeight
())
>>
1
;
mChildTmpRect
.
offset
(
mTargetRect
.
left
,
mTargetRect
.
top
);
break
;
}
//额外的xy偏移
mChildTmpRect
.
offset
((
int
)
(
density
*
lp
.
offsetX
+
0.5f
),
(
int
)
(
density
*
lp
.
offsetY
+
0.5f
));
child
.
layout
((
int
)
mChildTmpRect
.
left
,
(
int
)
mChildTmpRect
.
top
,
(
int
)
mChildTmpRect
.
right
,
(
int
)
mChildTmpRect
.
bottom
);
}
}
private
void
horizontalChildPositionLayout
(
View
child
,
RectF
rect
,
int
targetParentPosition
)
{
switch
(
targetParentPosition
)
{
case
LayoutParams
.
PARENT_START
:
rect
.
left
=
mTargetRect
.
left
;
rect
.
right
=
rect
.
left
+
child
.
getMeasuredWidth
();
break
;
case
LayoutParams
.
PARENT_CENTER
:
rect
.
left
=
(
mTargetRect
.
width
()
-
child
.
getMeasuredWidth
())
/
2
;
rect
.
right
=
(
mTargetRect
.
width
()
+
child
.
getMeasuredWidth
())
/
2
;
rect
.
offset
(
mTargetRect
.
left
,
0
);
break
;
case
LayoutParams
.
PARENT_END
:
rect
.
right
=
mTargetRect
.
right
;
rect
.
left
=
rect
.
right
-
child
.
getMeasuredWidth
();
break
;
}
}
private
void
verticalChildPositionLayout
(
View
child
,
RectF
rect
,
int
targetParentPosition
)
{
switch
(
targetParentPosition
)
{
case
LayoutParams
.
PARENT_START
:
rect
.
top
=
mTargetRect
.
top
;
rect
.
bottom
=
rect
.
top
+
child
.
getMeasuredHeight
();
break
;
case
LayoutParams
.
PARENT_CENTER
:
rect
.
top
=
(
mTargetRect
.
width
()
-
child
.
getMeasuredHeight
())
/
2
;
rect
.
bottom
=
(
mTargetRect
.
width
()
+
child
.
getMeasuredHeight
())
/
2
;
rect
.
offset
(
0
,
mTargetRect
.
top
);
break
;
case
LayoutParams
.
PARENT_END
:
rect
.
bottom
=
mTargetRect
.
bottom
;
rect
.
top
=
mTargetRect
.
bottom
-
child
.
getMeasuredHeight
();
break
;
}
}
private
void
resetOutPath
()
{
resetPadding
();
}
/**
* 设置padding
*/
private
void
resetPadding
()
{
if
(!
ignoreRepadding
)
{
if
(
mPadding
!=
0
&&
mPaddingLeft
==
0
)
{
mTargetRect
.
left
-=
mPadding
;
}
if
(
mPadding
!=
0
&&
mPaddingTop
==
0
)
{
mTargetRect
.
top
-=
mPadding
;
}
if
(
mPadding
!=
0
&&
mPaddingRight
==
0
)
{
mTargetRect
.
right
+=
mPadding
;
}
if
(
mPadding
!=
0
&&
mPaddingBottom
==
0
)
{
mTargetRect
.
bottom
+=
mPadding
;
}
if
(
mPaddingLeft
!=
0
)
{
mTargetRect
.
left
-=
mPaddingLeft
;
}
if
(
mPaddingTop
!=
0
)
{
mTargetRect
.
top
-=
mPaddingTop
;
}
if
(
mPaddingRight
!=
0
)
{
mTargetRect
.
right
+=
mPaddingRight
;
}
if
(
mPaddingBottom
!=
0
)
{
mTargetRect
.
bottom
+=
mPaddingBottom
;
}
ignoreRepadding
=
true
;
}
}
@Override
protected
LayoutParams
generateDefaultLayoutParams
()
{
return
new
LayoutParams
(
WRAP_CONTENT
,
WRAP_CONTENT
);
}
@Override
protected
void
dispatchDraw
(
Canvas
canvas
)
{
final
long
drawingTime
=
getDrawingTime
();
try
{
View
child
;
for
(
int
i
=
0
;
i
<
getChildCount
();
i
++)
{
child
=
getChildAt
(
i
);
drawChild
(
canvas
,
child
,
drawingTime
);
}
}
catch
(
NullPointerException
e
)
{
}
}
@Override
protected
void
onDraw
(
Canvas
canvas
)
{
super
.
onDraw
(
canvas
);
if
(
mChangedHeight
!=
0
)
{
mTargetRect
.
offset
(
0
,
mChangedHeight
);
mInitHeight
=
mInitHeight
+
mChangedHeight
;
mChangedHeight
=
0
;
}
mEraserBitmap
.
eraseColor
(
Color
.
TRANSPARENT
);
mEraserCanvas
.
drawColor
(
mFullingPaint
.
getColor
());
if
(!
mOverlayTarget
)
{
switch
(
mStyle
)
{
case
Component
.
ROUNDRECT
:
mEraserCanvas
.
drawRoundRect
(
mTargetRect
,
mCorner
,
mCorner
,
mEraser
);
break
;
case
Component
.
CIRCLE
:
mEraserCanvas
.
drawCircle
(
mTargetRect
.
centerX
(),
mTargetRect
.
centerY
(),
mTargetRect
.
width
()
/
2
,
mEraser
);
break
;
default
:
mEraserCanvas
.
drawRoundRect
(
mTargetRect
,
mCorner
,
mCorner
,
mEraser
);
break
;
}
}
canvas
.
drawBitmap
(
mEraserBitmap
,
mOverlayRect
.
left
,
mOverlayRect
.
top
,
null
);
}
public
void
setTargetRect
(
Rect
rect
)
{
mTargetRect
.
set
(
rect
);
}
public
void
setFullingAlpha
(
int
alpha
)
{
mFullingPaint
.
setAlpha
(
alpha
);
}
public
void
setFullingColor
(
int
color
)
{
mFullingPaint
.
setColor
(
color
);
}
public
void
setHighTargetCorner
(
int
corner
)
{
this
.
mCorner
=
corner
;
}
public
void
setHighTargetGraphStyle
(
int
style
)
{
this
.
mStyle
=
style
;
}
public
void
setOverlayTarget
(
boolean
b
)
{
mOverlayTarget
=
b
;
}
public
void
setPadding
(
int
padding
)
{
this
.
mPadding
=
padding
;
}
public
void
setPaddingLeft
(
int
paddingLeft
)
{
this
.
mPaddingLeft
=
paddingLeft
;
}
public
void
setPaddingTop
(
int
paddingTop
)
{
this
.
mPaddingTop
=
paddingTop
;
}
public
void
setPaddingRight
(
int
paddingRight
)
{
this
.
mPaddingRight
=
paddingRight
;
}
public
void
setPaddingBottom
(
int
paddingBottom
)
{
this
.
mPaddingBottom
=
paddingBottom
;
}
static
class
LayoutParams
extends
ViewGroup
.
LayoutParams
{
public
static
final
int
ANCHOR_LEFT
=
0x01
;
public
static
final
int
ANCHOR_TOP
=
0x02
;
public
static
final
int
ANCHOR_RIGHT
=
0x03
;
public
static
final
int
ANCHOR_BOTTOM
=
0x04
;
public
static
final
int
ANCHOR_OVER
=
0x05
;
public
static
final
int
PARENT_START
=
0x10
;
public
static
final
int
PARENT_CENTER
=
0x20
;
public
static
final
int
PARENT_END
=
0x30
;
public
int
targetAnchor
=
ANCHOR_BOTTOM
;
public
int
targetParentPosition
=
PARENT_CENTER
;
public
int
offsetX
=
0
;
public
int
offsetY
=
0
;
public
LayoutParams
(
Context
c
,
AttributeSet
attrs
)
{
super
(
c
,
attrs
);
}
public
LayoutParams
(
int
width
,
int
height
)
{
super
(
width
,
height
);
}
public
LayoutParams
(
ViewGroup
.
LayoutParams
source
)
{
super
(
source
);
}
}
}
app/src/main/res/layout/fragment_create.xml
View file @
c3a7ed9e
...
@@ -47,18 +47,32 @@
...
@@ -47,18 +47,32 @@
app:layout_constraintRight_toRightOf=
"parent"
app:layout_constraintRight_toRightOf=
"parent"
app:layout_constraintTop_toTopOf=
"@id/tv_weather"
/>
app:layout_constraintTop_toTopOf=
"@id/tv_weather"
/>
<
TextView
<
LinearLayout
android:id=
"@+id/tv_logo"
android:id=
"@+id/tv_logo"
android:layout_width=
"wrap_content"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_height=
"wrap_content"
android:drawablePadding=
"13dp"
android:orientation=
"vertical"
android:text=
"@string/app_name"
android:textColor=
"@color/black"
android:textSize=
"19sp"
app:drawableTopCompat=
"@mipmap/codescan"
app:layout_constraintLeft_toLeftOf=
"parent"
app:layout_constraintLeft_toLeftOf=
"parent"
app:layout_constraintRight_toRightOf=
"parent"
app:layout_constraintRight_toRightOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@id/tv_zodiac"
/>
app:layout_constraintTop_toBottomOf=
"@id/tv_zodiac"
tools:ignore=
"UseCompoundDrawables"
>
<ImageView
android:id=
"@+id/ivScan"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center_horizontal"
android:src=
"@mipmap/codescan"
tools:ignore=
"ContentDescription"
/>
<TextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"13dp"
android:text=
"@string/app_name"
android:textColor=
"@color/black"
android:textSize=
"19sp"
/>
</LinearLayout>
<!-- <ImageView-->
<!-- <ImageView-->
<!-- android:id="@+id/ivVip"-->
<!-- android:id="@+id/ivVip"-->
...
...
app/src/main/res/layout/layout_lottie_guide.xml
0 → 100644
View file @
c3a7ed9e
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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=
"wrap_content"
android:orientation=
"vertical"
>
<com.airbnb.lottie.LottieAnimationView
android:layout_width=
"240dp"
android:layout_height=
"240dp"
android:layout_gravity=
"center_horizontal"
android:scaleType=
"centerCrop"
app:lottie_autoPlay=
"true"
app:lottie_loop=
"true"
app:lottie_rawRes=
"@raw/guide_finger"
/>
</LinearLayout>
\ No newline at end of file
app/src/main/res/raw/guide_finger.json
0 → 100644
View file @
c3a7ed9e
{
"nm"
:
"tap"
,
"ddd"
:
0
,
"h"
:
500
,
"w"
:
500
,
"meta"
:{
"g"
:
"@lottiefiles/toolkit-js 0.33.2"
},
"layers"
:[{
"ty"
:
4
,
"nm"
:
"Shape Layer 1"
,
"sr"
:
1
,
"st"
:
0
,
"op"
:
5000
,
"ip"
:
0
,
"hd"
:
false
,
"ddd"
:
0
,
"bm"
:
0
,
"hasMask"
:
false
,
"ao"
:
0
,
"ks"
:{
"a"
:{
"a"
:
0
,
"k"
:[
-27
,
-92
,
0
],
"ix"
:
1
},
"s"
:{
"a"
:
1
,
"k"
:[{
"o"
:{
"x"
:
0.333
,
"y"
:
0
},
"i"
:{
"x"
:
0
,
"y"
:
1
},
"s"
:[
0
,
0
,
100
],
"t"
:
61
},{
"s"
:[
263
,
263
,
100
],
"t"
:
88
}],
"ix"
:
6
},
"sk"
:{
"a"
:
0
,
"k"
:
0
},
"p"
:{
"a"
:
0
,
"k"
:[
246
,
197
,
0
],
"ix"
:
2
},
"r"
:{
"a"
:
0
,
"k"
:
0
,
"ix"
:
10
},
"sa"
:{
"a"
:
0
,
"k"
:
0
},
"o"
:{
"a"
:
1
,
"k"
:[{
"o"
:{
"x"
:
0.333
,
"y"
:
0
},
"i"
:{
"x"
:
0.667
,
"y"
:
1
},
"s"
:[
100
],
"t"
:
61
},{
"s"
:[
0
],
"t"
:
86
}],
"ix"
:
11
,
"x"
:
"var $bm_rt;
\n
$bm_rt = transform.opacity;"
}},
"ef"
:[],
"shapes"
:[{
"ty"
:
"gr"
,
"bm"
:
0
,
"hd"
:
false
,
"mn"
:
"ADBE Vector Group"
,
"nm"
:
"Ellipse 1"
,
"ix"
:
1
,
"cix"
:
2
,
"np"
:
3
,
"it"
:[{
"ty"
:
"el"
,
"bm"
:
0
,
"hd"
:
false
,
"mn"
:
"ADBE Vector Shape - Ellipse"
,
"nm"
:
"Ellipse Path 1"
,
"d"
:
1
,
"p"
:{
"a"
:
0
,
"k"
:[
0
,
0
],
"ix"
:
3
},
"s"
:{
"a"
:
0
,
"k"
:[
55.734
,
55.734
],
"ix"
:
2
}},{
"ty"
:
"st"
,
"bm"
:
0
,
"hd"
:
false
,
"mn"
:
"ADBE Vector Graphic - Stroke"
,
"nm"
:
"Stroke 1"
,
"lc"
:
1
,
"lj"
:
1
,
"ml"
:
4
,
"o"
:{
"a"
:
0
,
"k"
:
100
,
"ix"
:
4
},
"w"
:{
"a"
:
1
,
"k"
:[{
"o"
:{
"x"
:
0.333
,
"y"
:
0
},
"i"
:{
"x"
:
0.667
,
"y"
:
1
},
"s"
:[
5
],
"t"
:
61
},{
"s"
:[
0
],
"t"
:
92
}],
"ix"
:
5
},
"c"
:{
"a"
:
0
,
"k"
:[
1
,
0.7451
,
0.7451
],
"ix"
:
3
}},{
"ty"
:
"tr"
,
"a"
:{
"a"
:
0
,
"k"
:[
0
,
0
],
"ix"
:
1
},
"s"
:{
"a"
:
0
,
"k"
:[
100
,
100
],
"ix"
:
3
},
"sk"
:{
"a"
:
0
,
"k"
:
0
,
"ix"
:
4
},
"p"
:{
"a"
:
0
,
"k"
:[
-28.133
,
-94.133
],
"ix"
:
2
},
"r"
:{
"a"
:
0
,
"k"
:
0
,
"ix"
:
6
},
"sa"
:{
"a"
:
0
,
"k"
:
0
,
"ix"
:
5
},
"o"
:{
"a"
:
0
,
"k"
:
100
,
"ix"
:
7
}}]}],
"ind"
:
1
},{
"ty"
:
4
,
"nm"
:
"hand"
,
"sr"
:
1
,
"st"
:
0
,
"op"
:
5000
,
"ip"
:
0
,
"hd"
:
false
,
"ddd"
:
0
,
"bm"
:
0
,
"hasMask"
:
false
,
"ao"
:
0
,
"ks"
:{
"a"
:{
"a"
:
0
,
"k"
:[
10
,
14.5
,
0
],
"ix"
:
1
},
"s"
:{
"a"
:
0
,
"k"
:[
586
,
586
,
100
],
"ix"
:
6
},
"sk"
:{
"a"
:
0
,
"k"
:
0
},
"p"
:{
"a"
:
0
,
"k"
:[
264.319
,
272.606
,
0
],
"ix"
:
2
},
"r"
:{
"a"
:
0
,
"k"
:
-32
,
"ix"
:
10
},
"sa"
:{
"a"
:
0
,
"k"
:
0
},
"o"
:{
"a"
:
0
,
"k"
:
100
,
"ix"
:
11
}},
"ef"
:[],
"shapes"
:[{
"ty"
:
"gr"
,
"bm"
:
0
,
"hd"
:
false
,
"mn"
:
"ADBE Vector Group"
,
"nm"
:
"Group 1"
,
"ix"
:
1
,
"cix"
:
2
,
"np"
:
2
,
"it"
:[{
"ty"
:
"sh"
,
"bm"
:
0
,
"hd"
:
false
,
"mn"
:
"ADBE Vector Shape - Group"
,
"nm"
:
"Path 1"
,
"ix"
:
1
,
"d"
:
1
,
"ks"
:{
"a"
:
1
,
"k"
:[{
"o"
:{
"x"
:
0.333
,
"y"
:
0
},
"i"
:{
"x"
:
0.667
,
"y"
:
1
},
"s"
:[{
"c"
:
true
,
"i"
:[[
-0.988
,
2.4
],[
0.722
,
0.509
],[
0.006
,
0.278
],[
0.618
,
0.385
],[
0.272
,
0.057
],[
0.027
,
0.017
],[
-0.003
,
0.108
],[
0.662
,
0.412
],[
0.279
,
0.07
],[
0.023
,
0.015
],[
-0.084
,
0.136
],[
0
,
0
],[
0.834
,
0.519
],[
0.692
,
-1.112
],[
0
,
0
],[
0.414
,
0.257
],[
0.007
,
0.36
],[
0
,
0
],[
0.509
,
0.317
],[
0.022
,
-1.817
],[
0
,
0
],[
-0.089
,
-0.056
],[
-2.181
,
-1.312
],[
-0.045
,
0.063
],[
0
,
0
],[
-0.045
,
0.02
]],
"o"
:[[
1.029
,
-2.5
],[
-0.228
,
-0.161
],[
-0.028
,
-1.168
],[
-0.443
,
-0.276
],[
-0.035
,
-0.006
],[
-0.088
,
-0.054
],[
0.038
,
-1.29
],[
-0.385
,
-0.24
],[
-0.03
,
-0.007
],[
-0.127
,
-0.079
],[
0
,
0
],[
0.692
,
-1.112
],[
-0.835
,
-0.52
],[
0
,
0
],[
-0.313
,
0.503
],[
-0.252
,
-0.157
],[
0
,
0
],[
0.01
,
-0.804
],[
-1.15
,
-0.716
],[
0
,
0
],[
-0.007
,
0.104
],[
0
,
0
],[
2.393
,
1.439
],[
0
,
0
],[
0.028
,
-0.04
],[
4.267
,
-1.959
]],
"v"
:[[
9.386
,
4.737
],[
8.322
,
0.373
],[
7.943
,
-0.322
],[
6.705
,
-2.547
],[
5.532
,
-3.008
],[
5.438
,
-3.045
],[
5.298
,
-3.308
],[
4.041
,
-5.742
],[
2.981
,
-6.184
],[
2.901
,
-6.218
],[
2.811
,
-6.606
],[
5.84
,
-11.472
],[
5.216
,
-14.176
],[
2.514
,
-13.543
],[
-2.815
,
-4.983
],[
-4.147
,
-4.683
],[
-4.591
,
-5.474
],[
-4.628
,
-7.214
],[
-5.491
,
-8.897
],[
-8.559
,
-7.262
],[
-9.755
,
8.699
],[
-9.613
,
8.943
],[
-5.293
,
12.327
],[
-0.398
,
14.39
],[
2.063
,
10.93
],[
2.172
,
10.842
]]}],
"t"
:
50
},{
"o"
:{
"x"
:
0.333
,
"y"
:
0
},
"i"
:{
"x"
:
0.667
,
"y"
:
1
},
"s"
:[{
"c"
:
true
,
"i"
:[[
-0.988
,
2.4
],[
0.722
,
0.509
],[
0.006
,
0.278
],[
0.618
,
0.385
],[
0.272
,
0.057
],[
0.027
,
0.017
],[
-0.003
,
0.108
],[
0.662
,
0.412
],[
0.279
,
0.07
],[
0.023
,
0.015
],[
-0.084
,
0.136
],[
0
,
0
],[
0.834
,
0.519
],[
0.692
,
-1.112
],[
0
,
0
],[
0.414
,
0.257
],[
0.007
,
0.36
],[
0
,
0
],[
0.509
,
0.317
],[
0.022
,
-1.817
],[
0
,
0
],[
-0.089
,
-0.056
],[
-2.181
,
-1.312
],[
-0.045
,
0.063
],[
0
,
0
],[
-0.045
,
0.02
]],
"o"
:[[
1.029
,
-2.5
],[
-0.228
,
-0.161
],[
-0.028
,
-1.168
],[
-0.443
,
-0.276
],[
-0.035
,
-0.006
],[
-0.088
,
-0.054
],[
0.038
,
-1.29
],[
-0.385
,
-0.24
],[
-0.03
,
-0.007
],[
-0.127
,
-0.079
],[
0
,
0
],[
0.692
,
-1.112
],[
-0.835
,
-0.52
],[
0
,
0
],[
-0.313
,
0.503
],[
-0.252
,
-0.157
],[
0
,
0
],[
0.01
,
-0.804
],[
-1.15
,
-0.716
],[
0
,
0
],[
-0.007
,
0.104
],[
0
,
0
],[
2.393
,
1.439
],[
0
,
0
],[
0.028
,
-0.04
],[
4.267
,
-1.959
]],
"v"
:[[
9.386
,
4.737
],[
8.322
,
0.373
],[
7.943
,
-0.322
],[
6.705
,
-2.547
],[
5.532
,
-3.008
],[
5.438
,
-3.045
],[
5.298
,
-3.308
],[
4.041
,
-5.742
],[
2.981
,
-6.184
],[
2.901
,
-6.218
],[
2.811
,
-6.606
],[
4.646
,
-9.424
],[
4.022
,
-12.128
],[
1.32
,
-11.495
],[
-2.815
,
-4.983
],[
-4.147
,
-4.683
],[
-4.591
,
-5.474
],[
-4.628
,
-7.214
],[
-5.491
,
-8.897
],[
-8.559
,
-7.262
],[
-9.755
,
8.699
],[
-9.613
,
8.943
],[
-4.677
,
11.241
],[
-0.398
,
14.39
],[
2.063
,
10.93
],[
2.172
,
10.842
]]}],
"t"
:
61
},{
"o"
:{
"x"
:
0.333
,
"y"
:
0
},
"i"
:{
"x"
:
0.833
,
"y"
:
1
},
"s"
:[{
"c"
:
true
,
"i"
:[[
-0.988
,
2.4
],[
0.722
,
0.509
],[
0.006
,
0.278
],[
0.618
,
0.385
],[
0.272
,
0.057
],[
0.027
,
0.017
],[
-0.003
,
0.108
],[
0.662
,
0.412
],[
0.279
,
0.07
],[
0.023
,
0.015
],[
-0.084
,
0.136
],[
0
,
0
],[
0.834
,
0.519
],[
0.692
,
-1.112
],[
0
,
0
],[
0.414
,
0.257
],[
0.007
,
0.36
],[
0
,
0
],[
0.509
,
0.317
],[
0.022
,
-1.817
],[
0
,
0
],[
-0.089
,
-0.056
],[
-2.181
,
-1.312
],[
-0.045
,
0.063
],[
0
,
0
],[
-0.045
,
0.02
]],
"o"
:[[
1.029
,
-2.5
],[
-0.228
,
-0.161
],[
-0.028
,
-1.168
],[
-0.443
,
-0.276
],[
-0.035
,
-0.006
],[
-0.088
,
-0.054
],[
0.038
,
-1.29
],[
-0.385
,
-0.24
],[
-0.03
,
-0.007
],[
-0.127
,
-0.079
],[
0
,
0
],[
0.692
,
-1.112
],[
-0.835
,
-0.52
],[
0
,
0
],[
-0.313
,
0.503
],[
-0.252
,
-0.157
],[
0
,
0
],[
0.01
,
-0.804
],[
-1.15
,
-0.716
],[
0
,
0
],[
-0.007
,
0.104
],[
0
,
0
],[
2.393
,
1.439
],[
0
,
0
],[
0.028
,
-0.04
],[
4.267
,
-1.959
]],
"v"
:[[
9.386
,
4.737
],[
8.322
,
0.373
],[
7.943
,
-0.322
],[
6.705
,
-2.547
],[
5.532
,
-3.008
],[
5.438
,
-3.045
],[
5.298
,
-3.308
],[
4.041
,
-5.742
],[
2.981
,
-6.184
],[
2.901
,
-6.218
],[
2.811
,
-6.606
],[
5.84
,
-11.472
],[
5.216
,
-14.176
],[
2.514
,
-13.543
],[
-2.815
,
-4.983
],[
-4.147
,
-4.683
],[
-4.591
,
-5.474
],[
-4.628
,
-7.214
],[
-5.491
,
-8.897
],[
-8.559
,
-7.262
],[
-9.755
,
8.699
],[
-9.613
,
8.943
],[
-5.267
,
12.306
],[
-0.398
,
14.39
],[
2.063
,
10.93
],[
2.172
,
10.842
]]}],
"t"
:
72
},{
"s"
:[{
"c"
:
true
,
"i"
:[[
-0.988
,
2.4
],[
0.722
,
0.509
],[
0.006
,
0.278
],[
0.618
,
0.385
],[
0.272
,
0.057
],[
0.027
,
0.017
],[
-0.003
,
0.108
],[
0.662
,
0.412
],[
0.279
,
0.07
],[
0.023
,
0.015
],[
-0.084
,
0.136
],[
0
,
0
],[
0.834
,
0.519
],[
0.692
,
-1.112
],[
0
,
0
],[
0.414
,
0.257
],[
0.007
,
0.36
],[
0
,
0
],[
0.509
,
0.317
],[
0.022
,
-1.817
],[
0
,
0
],[
-0.089
,
-0.056
],[
-3.329
,
-1.925
],[
-0.044
,
0.062
],[
0
,
0
],[
-0.045
,
0.02
]],
"o"
:[[
1.029
,
-2.5
],[
-0.228
,
-0.161
],[
-0.028
,
-1.168
],[
-0.443
,
-0.276
],[
-0.035
,
-0.006
],[
-0.088
,
-0.054
],[
0.038
,
-1.29
],[
-0.385
,
-0.24
],[
-0.03
,
-0.007
],[
-0.127
,
-0.079
],[
0
,
0
],[
0.692
,
-1.112
],[
-0.835
,
-0.52
],[
0
,
0
],[
-0.313
,
0.503
],[
-0.252
,
-0.157
],[
0
,
0
],[
0.01
,
-0.804
],[
-1.15
,
-0.716
],[
0
,
0
],[
-0.007
,
0.104
],[
0
,
0
],[
3.323
,
1.921
],[
0
,
0
],[
0.028
,
-0.04
],[
4.267
,
-1.959
]],
"v"
:[[
9.386
,
4.737
],[
8.322
,
0.373
],[
7.943
,
-0.322
],[
6.705
,
-2.547
],[
5.532
,
-3.008
],[
5.438
,
-3.045
],[
5.298
,
-3.308
],[
4.041
,
-5.742
],[
2.981
,
-6.184
],[
2.901
,
-6.218
],[
2.811
,
-6.606
],[
5.84
,
-11.472
],[
5.216
,
-14.176
],[
2.514
,
-13.543
],[
-2.815
,
-4.983
],[
-4.147
,
-4.683
],[
-4.591
,
-5.474
],[
-4.628
,
-7.214
],[
-5.491
,
-8.897
],[
-8.559
,
-7.262
],[
-9.755
,
8.699
],[
-9.613
,
8.943
],[
-5.305
,
12.33
],[
-0.398
,
14.39
],[
2.063
,
10.93
],[
2.172
,
10.842
]]}],
"t"
:
85
}],
"ix"
:
2
}},{
"ty"
:
"fl"
,
"bm"
:
0
,
"hd"
:
false
,
"mn"
:
"ADBE Vector Graphic - Fill"
,
"nm"
:
"Fill 1"
,
"c"
:{
"a"
:
0
,
"k"
:[
1
,
1
,
1
],
"ix"
:
4
},
"r"
:
1
,
"o"
:{
"a"
:
0
,
"k"
:
100
,
"ix"
:
5
}},{
"ty"
:
"tr"
,
"a"
:{
"a"
:
0
,
"k"
:[
0
,
0
],
"ix"
:
1
},
"s"
:{
"a"
:
0
,
"k"
:[
100
,
100
],
"ix"
:
3
},
"sk"
:{
"a"
:
0
,
"k"
:
0
,
"ix"
:
4
},
"p"
:{
"a"
:
0
,
"k"
:[
9.755
,
14.498
],
"ix"
:
2
},
"r"
:{
"a"
:
0
,
"k"
:
0
,
"ix"
:
6
},
"sa"
:{
"a"
:
0
,
"k"
:
0
,
"ix"
:
5
},
"o"
:{
"a"
:
0
,
"k"
:
100
,
"ix"
:
7
}}]}],
"ind"
:
2
}],
"v"
:
"5.6.3"
,
"fr"
:
50
,
"op"
:
109
,
"ip"
:
50
,
"assets"
:[]}
\ 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