Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Sign in / Register
Toggle navigation
S
Scan QR Code Barcode Reader
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
Scan QR Code Barcode Reader
Commits
c697848a
Commit
c697848a
authored
Dec 25, 2024
by
wanglei
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
...
parent
fd6e6cb5
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
613 additions
and
17 deletions
+613
-17
CameraUtils.kt
app/src/main/java/com/base/scanqr/qr/CameraUtils.kt
+7
-1
HistoryAdapter.kt
app/src/main/java/com/base/scanqr/ui/main/HistoryAdapter.kt
+14
-0
HistoryFragment.kt
app/src/main/java/com/base/scanqr/ui/main/HistoryFragment.kt
+72
-16
HistoryViewModel.kt
...src/main/java/com/base/scanqr/ui/main/HistoryViewModel.kt
+57
-0
DeleteQRDialog.kt
...src/main/java/com/base/scanqr/ui/widget/DeleteQRDialog.kt
+38
-0
HistoryMoreDialog.kt
.../main/java/com/base/scanqr/ui/widget/HistoryMoreDialog.kt
+63
-0
DateUtils.kt
app/src/main/java/com/base/scanqr/utils/DateUtils.kt
+168
-0
DialogUtils.kt
app/src/main/java/com/base/scanqr/utils/DialogUtils.kt
+41
-0
dialog_delete_qr.xml
app/src/main/res/layout/dialog_delete_qr.xml
+71
-0
dialog_history_more.xml
app/src/main/res/layout/dialog_history_more.xml
+51
-0
item_history.xml
app/src/main/res/layout/item_history.xml
+1
-0
dimens.xml
app/src/main/res/values/dimens.xml
+27
-0
strings.xml
app/src/main/res/values/strings.xml
+3
-0
No files found.
app/src/main/java/com/base/scanqr/qr/CameraUtils.kt
View file @
c697848a
...
...
@@ -11,6 +11,7 @@ import androidx.camera.lifecycle.ProcessCameraProvider
import
androidx.camera.view.PreviewView
import
androidx.core.content.ContextCompat
import
androidx.lifecycle.LiveData
import
com.base.scanqr.utils.LogEx
import
java.util.concurrent.ExecutorService
import
java.util.concurrent.Executors
import
kotlin.math.abs
...
...
@@ -21,6 +22,7 @@ import kotlin.math.min
class
CameraUtils
(
val
activity
:
AppCompatActivity
,
)
{
private
val
TAG
=
"CameraUtils"
private
var
cameraExecutor
:
ExecutorService
?
=
null
...
...
@@ -76,7 +78,11 @@ class CameraUtils(
previewView
.
width
,
previewView
.
height
)
val
rotation
=
previewView
.
display
.
rotation
val
display
=
previewView
.
display
LogEx
.
logDebug
(
TAG
,
"display=${display == null}"
)
val
rotation
=
display
.
rotation
// 选择相机
val
cameraSelector
=
CameraSelector
.
Builder
().
requireLensFacing
(
lensFacing
).
build
()
...
...
app/src/main/java/com/base/scanqr/ui/main/HistoryAdapter.kt
View file @
c697848a
package
com.base.scanqr.ui.main
import
android.content.Context
import
android.text.format.DateUtils
import
android.view.View
import
android.view.ViewGroup
import
com.base.scanqr.R
import
com.base.scanqr.bean.FunctionUIBean.Companion.KEY_CONTACT
...
...
@@ -16,17 +18,22 @@ import com.base.scanqr.bean.ScanBean
import
com.base.scanqr.bean.WifiUIBean
import
com.base.scanqr.databinding.ItemHistoryBinding
import
com.base.scanqr.ui.adapter.CommonViewHolder
import
com.base.scanqr.utils.DateUtils.formatTimeAgo
import
com.base.scanqr.utils.XmlEx.inflate
import
com.chad.library.adapter4.BaseQuickAdapter
class
HistoryAdapter
:
BaseQuickAdapter
<
ScanBean
,
CommonViewHolder
>()
{
var
moreAction
:
((
view
:
View
,
item
:
ScanBean
)
->
Unit
)?
=
null
var
itemClick
:
((
item
:
ScanBean
)
->
Unit
)?
=
null
override
fun
onBindViewHolder
(
holder
:
CommonViewHolder
,
position
:
Int
,
item
:
ScanBean
?)
{
item
?:
return
val
binding
=
ItemHistoryBinding
.
bind
(
holder
.
itemView
)
when
(
item
.
scanType
)
{
KEY_WIFI
->
{
if
(
item
is
WifiUIBean
)
{
binding
.
ivIcon
.
setImageResource
(
R
.
mipmap
.
h_wifi
)
binding
.
tvDesc
.
text
=
item
.
ssid
}
}
...
...
@@ -63,6 +70,13 @@ class HistoryAdapter : BaseQuickAdapter<ScanBean, CommonViewHolder>() {
}
binding
.
tvTime
.
text
=
formatTimeAgo
(
item
.
createTime
)
binding
.
flMore
.
setOnClickListener
{
moreAction
?.
invoke
(
it
,
item
)
}
binding
.
root
.
setOnClickListener
{
itemClick
?.
invoke
(
item
)
}
}
override
fun
onCreateViewHolder
(
context
:
Context
,
parent
:
ViewGroup
,
viewType
:
Int
):
CommonViewHolder
{
...
...
app/src/main/java/com/base/scanqr/ui/main/HistoryFragment.kt
View file @
c697848a
...
...
@@ -3,24 +3,46 @@ package com.base.scanqr.ui.main
import
android.graphics.Color
import
androidx.core.content.ContextCompat
import
androidx.core.view.updatePadding
import
androidx.lifecycle.ViewModelProvider
import
com.base.scanqr.R
import
com.base.scanqr.base.BaseFragment
import
com.base.scanqr.bean.EmailUIBean
import
com.base.scanqr.bean.FunctionUIBean
import
com.base.scanqr.bean.TextUIBean
import
com.base.scanqr.bean.WifiUIBean
import
com.base.scanqr.databinding.FragmentHistoryBinding
import
com.base.scanqr.ui.widget.DeleteQRDialog.showDeleteQRDialog
import
com.base.scanqr.ui.widget.HistoryMoreDialog.showHistoryMoreDialog
import
com.base.scanqr.utils.BarUtils
import
com.base.scanqr.utils.LogEx
import
com.base.scanqr.utils.SpJsonUtils
class
HistoryFragment
:
BaseFragment
<
FragmentHistoryBinding
>(
FragmentHistoryBinding
::
inflate
)
{
private
var
adapter
:
HistoryAdapter
?
=
null
private
val
viewModel
by
lazy
(
LazyThreadSafetyMode
.
NONE
)
{
ViewModelProvider
(
this
)[
HistoryViewModel
::
class
.
java
]
}
override
fun
initView
()
{
super
.
initView
()
binding
.
flTop
.
updatePadding
(
top
=
BarUtils
.
getStatusBarHeight
())
initAdapter
()
viewModel
.
initData
()
}
private
fun
initAdapter
()
{
adapter
=
HistoryAdapter
()
binding
.
rv
.
adapter
=
adapter
adapter
?.
moreAction
=
{
view
,
bean
->
requireContext
().
showHistoryMoreDialog
(
view
,
detailAction
=
{},
removeAction
=
{
viewModel
.
removeBean
(
bean
)
if
(
tab
==
0
)
{
scanUI
()
}
else
{
createUI
()
}
})
}
adapter
?.
itemClick
=
{}
}
override
fun
initListener
()
{
...
...
@@ -31,35 +53,69 @@ class HistoryFragment : BaseFragment<FragmentHistoryBinding>(FragmentHistoryBind
binding
.
tvCreate
.
setOnClickListener
{
createUI
()
}
binding
.
llRemove
.
setOnClickListener
{
requireContext
().
showDeleteQRDialog
{
val
wifiList
=
SpJsonUtils
.
getSpJsonList
<
WifiUIBean
>(
FunctionUIBean
.
KEY_WIFI
)
wifiList
.
forEach
{
LogEx
.
logDebug
(
TAG
,
"${it.scanType} ${it.ssid} ${it.password} ${it.createTime}"
)
viewModel
.
removeList
(
tab
)
if
(
tab
==
0
)
{
scanUI
()
}
else
{
createUI
()
}
val
textList
=
SpJsonUtils
.
getSpJsonList
<
TextUIBean
>(
FunctionUIBean
.
KEY_TEXT
)
textList
.
forEach
{
LogEx
.
logDebug
(
TAG
,
"${it.scanType} ${it.content} ${it.createTime}"
)
}
val
emailList
=
SpJsonUtils
.
getSpJsonList
<
EmailUIBean
>(
FunctionUIBean
.
KEY_EMAIL
)
emailList
.
forEach
{
LogEx
.
logDebug
(
TAG
,
"${it.scanType} ${it.address} ${it.createTime}"
)
}
if
(
tab
==
0
)
{
scanUI
()
}
else
{
createUI
()
}
}
private
fun
scanUI
()
{
tab
=
0
binding
.
tvScan
.
background
=
ContextCompat
.
getDrawable
(
requireContext
(),
R
.
drawable
.
bg_6473f8_10
)
binding
.
tvScan
.
setTextColor
(
Color
.
parseColor
(
"#FFFFFF"
))
binding
.
tvCreate
.
background
=
ContextCompat
.
getDrawable
(
requireContext
(),
R
.
drawable
.
bg_transparent
)
binding
.
tvCreate
.
setTextColor
(
Color
.
parseColor
(
"#666666"
))
changeRvData
(
false
)
}
private
fun
createUI
()
{
tab
=
1
binding
.
tvCreate
.
background
=
ContextCompat
.
getDrawable
(
requireContext
(),
R
.
drawable
.
bg_6473f8_10
)
binding
.
tvCreate
.
setTextColor
(
Color
.
parseColor
(
"#FFFFFF"
))
binding
.
tvScan
.
background
=
ContextCompat
.
getDrawable
(
requireContext
(),
R
.
drawable
.
bg_transparent
)
binding
.
tvScan
.
setTextColor
(
Color
.
parseColor
(
"#666666"
))
changeRvData
(
true
)
}
private
fun
changeRvData
(
isCreateOrScan
:
Boolean
)
{
val
uiRefresh
=
{
val
createList
=
viewModel
.
historyList
.
filter
{
it
.
isCreateOrScan
==
isCreateOrScan
}
adapter
?.
submitList
(
createList
)
}
if
(
viewModel
.
dataRefreshFinish
.
get
())
{
uiRefresh
.
invoke
()
}
else
{
viewModel
.
dataRefreshBack
=
{
requireActivity
().
runOnUiThread
{
uiRefresh
.
invoke
()
}
}
}
}
companion
object
{
var
tab
:
Int
=
0
//scan=0 create=1
var
sort
:
Int
=
0
}
}
\ No newline at end of file
app/src/main/java/com/base/scanqr/ui/main/HistoryViewModel.kt
0 → 100644
View file @
c697848a
package
com.base.scanqr.ui.main
import
androidx.lifecycle.ViewModel
import
androidx.lifecycle.viewModelScope
import
com.base.scanqr.bean.EmailUIBean
import
com.base.scanqr.bean.FunctionUIBean
import
com.base.scanqr.bean.ScanBean
import
com.base.scanqr.bean.TextUIBean
import
com.base.scanqr.bean.WifiUIBean
import
com.base.scanqr.utils.SpJsonUtils
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.launch
import
java.util.concurrent.atomic.AtomicBoolean
class
HistoryViewModel
()
:
ViewModel
()
{
var
historyList
=
arrayListOf
<
ScanBean
>()
var
dataRefreshFinish
=
AtomicBoolean
(
false
)
var
dataRefreshBack
:
(()
->
Unit
)?
=
null
fun
initData
()
=
viewModelScope
.
launch
(
Dispatchers
.
IO
)
{
historyList
.
clear
()
val
wifiList
=
SpJsonUtils
.
getSpJsonList
<
WifiUIBean
>(
FunctionUIBean
.
KEY_WIFI
)
val
textList
=
SpJsonUtils
.
getSpJsonList
<
TextUIBean
>(
FunctionUIBean
.
KEY_TEXT
)
val
emailList
=
SpJsonUtils
.
getSpJsonList
<
EmailUIBean
>(
FunctionUIBean
.
KEY_EMAIL
)
historyList
.
addAll
(
wifiList
)
historyList
.
addAll
(
textList
)
historyList
.
addAll
(
emailList
)
dataRefreshBack
?.
invoke
()
dataRefreshFinish
.
set
(
true
)
}
fun
removeList
(
tab
:
Int
)
{
val
removeList
=
historyList
.
filter
{
if
(
tab
==
0
)
!
it
.
isCreateOrScan
else
it
.
isCreateOrScan
}
removeList
.
forEach
{
removeBean
(
it
)
}
}
fun
removeBean
(
bean
:
ScanBean
)
{
val
scanBean
=
when
(
bean
.
scanType
)
{
FunctionUIBean
.
KEY_WIFI
->
bean
as
WifiUIBean
FunctionUIBean
.
KEY_TEXT
->
bean
as
TextUIBean
FunctionUIBean
.
KEY_EMAIL
->
bean
as
EmailUIBean
else
->
bean
}
SpJsonUtils
.
removeJsonBean
(
bean
.
scanType
,
scanBean
,
removeIf
=
{
it1
,
it2
->
it1
.
createTime
==
it2
.
createTime
})
historyList
.
removeIf
{
it
.
createTime
==
bean
.
createTime
}
}
}
\ No newline at end of file
app/src/main/java/com/base/scanqr/ui/widget/DeleteQRDialog.kt
0 → 100644
View file @
c697848a
package
com.base.scanqr.ui.widget
import
android.app.AlertDialog
import
android.content.Context
import
android.view.Gravity
import
android.view.LayoutInflater
import
com.base.scanqr.databinding.DialogDeleteQrBinding
object
DeleteQRDialog
{
fun
Context
.
showDeleteQRDialog
(
removeAction
:
(()
->
Unit
)?
=
null
,
)
{
val
dialog
=
AlertDialog
.
Builder
(
this
).
create
()
val
binding
=
DialogDeleteQrBinding
.
inflate
(
LayoutInflater
.
from
(
this
))
dialog
.
setView
(
binding
.
root
)
dialog
.
setCanceledOnTouchOutside
(
false
)
dialog
.
show
()
val
params
=
dialog
.
window
?.
attributes
// params?.width = resources.getDimensionPixelOffset(R.dimen.dp_320)
// params?.height = resources.getDimensionPixelOffset(R.dimen.dp_400)
params
?.
gravity
=
Gravity
.
CENTER
// params?.y = 50
dialog
.
window
?.
attributes
=
params
dialog
.
window
?.
setBackgroundDrawableResource
(
android
.
R
.
color
.
transparent
)
binding
.
tvCancel
.
setOnClickListener
{
dialog
.
dismiss
()
}
binding
.
tvRemove
.
setOnClickListener
{
dialog
.
dismiss
()
removeAction
?.
invoke
()
}
}
}
\ No newline at end of file
app/src/main/java/com/base/scanqr/ui/widget/HistoryMoreDialog.kt
0 → 100644
View file @
c697848a
package
com.base.scanqr.ui.widget
import
android.app.AlertDialog
import
android.content.Context
import
android.view.Gravity
import
android.view.LayoutInflater
import
android.view.View
import
android.widget.FrameLayout
import
com.base.scanqr.R
import
com.base.scanqr.databinding.DialogHistoryMoreBinding
import
com.base.scanqr.ui.widget.DeleteQRDialog.showDeleteQRDialog
import
com.base.scanqr.utils.DialogUtils.viewIsTopHalf
import
com.base.scanqr.utils.LogEx
object
HistoryMoreDialog
{
private
val
TAG
=
"HistoryMoreDialog"
fun
Context
.
showHistoryMoreDialog
(
anchorView
:
View
,
detailAction
:
(()
->
Unit
)?
=
null
,
removeAction
:
(()
->
Unit
)?
=
null
,
)
{
val
dialog
=
AlertDialog
.
Builder
(
this
).
create
()
val
binding
=
DialogHistoryMoreBinding
.
inflate
(
LayoutInflater
.
from
(
this
))
dialog
.
setView
(
binding
.
root
)
dialog
.
setCanceledOnTouchOutside
(
true
)
dialog
.
show
()
dialog
.
window
?.
setBackgroundDrawableResource
(
android
.
R
.
color
.
transparent
)
val
params
=
dialog
.
window
?.
attributes
params
?.
dimAmount
=
0f
params
?.
width
=
resources
.
getDimensionPixelOffset
(
R
.
dimen
.
dp_200
)
// params?.width = FrameLayout.LayoutParams.WRAP_CONTENT
params
?.
height
=
FrameLayout
.
LayoutParams
.
WRAP_CONTENT
params
?.
gravity
=
Gravity
.
TOP
val
location
=
IntArray
(
2
)
val
isTopHalf
=
viewIsTopHalf
(
anchorView
)
LogEx
.
logDebug
(
TAG
,
"isTopHalf=$isTopHalf"
)
anchorView
.
getLocationOnScreen
(
location
)
//减少宽度附近的值
val
x
=
location
[
0
]
-
resources
.
getDimensionPixelOffset
(
R
.
dimen
.
dp_256
)
val
y
=
if
(
isTopHalf
)
{
location
[
1
]
-
resources
.
getDimensionPixelOffset
(
R
.
dimen
.
dp_15
)
}
else
{
//减少高度附近的值
location
[
1
]
-
resources
.
getDimensionPixelOffset
(
R
.
dimen
.
dp_114
)
-
anchorView
.
height
}
params
?.
x
=
x
params
?.
y
=
y
dialog
.
window
?.
attributes
=
params
binding
.
tvDetail
.
setOnClickListener
{
dialog
.
dismiss
()
detailAction
?.
invoke
()
}
binding
.
tvRemove
.
setOnClickListener
{
dialog
.
dismiss
()
showDeleteQRDialog
(
removeAction
)
}
}
}
\ No newline at end of file
app/src/main/java/com/base/scanqr/utils/DateUtils.kt
0 → 100644
View file @
c697848a
package
com.base.scanqr.utils
import
android.annotation.SuppressLint
import
java.text.ParseException
import
java.text.SimpleDateFormat
import
java.util.Calendar
import
java.util.Date
import
kotlin.random.Random
object
DateUtils
{
fun
getDayOfWeek
(
timestamp
:
Long
):
String
{
val
days
=
arrayOf
(
"Sunday"
,
"Monday"
,
"Tuesday"
,
"Wednesday"
,
"Thursday"
,
"Friday"
,
"Saturday"
)
val
calendar
=
Calendar
.
getInstance
().
apply
{
timeInMillis
=
timestamp
}
return
days
[
calendar
.
get
(
Calendar
.
DAY_OF_WEEK
)
-
1
]
}
fun
getYearFromTimestamp
(
timestamp
:
Long
):
Int
{
val
calendar
:
Calendar
=
Calendar
.
getInstance
()
calendar
.
setTimeInMillis
(
timestamp
)
return
calendar
.
get
(
Calendar
.
YEAR
)
// 返回年份
}
fun
getMonthFromTimestamp
(
timestamp
:
Long
):
Int
{
val
calendar
=
Calendar
.
getInstance
()
calendar
.
timeInMillis
=
timestamp
return
calendar
[
Calendar
.
MONTH
]
+
1
// 返回月份,需要加1因为Calendar.MONTH是从0开始的
}
fun
getDayOfMonthFromTimestamp
(
timestamp
:
Long
):
Int
{
val
calendar
=
Calendar
.
getInstance
()
calendar
.
timeInMillis
=
timestamp
return
calendar
[
Calendar
.
DAY_OF_MONTH
]
// 返回当前是月份的第几天
}
fun
getDaySuffix
(
day
:
Int
):
String
{
return
when
(
day
)
{
1
,
21
,
31
->
"st"
2
,
22
->
"nd"
3
,
23
->
"rd"
else
->
"th"
}
}
fun
getHourOfDayFromTimestamp
(
timestamp
:
Long
):
Int
{
val
calendar
=
Calendar
.
getInstance
()
calendar
.
timeInMillis
=
timestamp
return
calendar
[
Calendar
.
HOUR_OF_DAY
]
// 返回当前小时(24小时制)
}
fun
getMinuteFromTimestamp
(
timestamp
:
Long
):
Int
{
val
calendar
=
Calendar
.
getInstance
()
calendar
.
timeInMillis
=
timestamp
return
calendar
[
Calendar
.
MINUTE
]
// 返回当前分钟
}
/**
* month是从1开的
*/
fun
getTimestampFromDateTime
(
year
:
Int
,
month
:
Int
,
day
:
Int
,
hour
:
Int
,
minute
:
Int
):
Long
{
val
calendar
=
Calendar
.
getInstance
()
calendar
[
year
,
month
-
1
,
day
,
hour
]
=
minute
return
calendar
.
timeInMillis
// 返回对应的时间戳
}
fun
daysInMonth
(
year
:
Int
,
month
:
Int
):
Int
{
// 每个月的天数,二月默认为28天
val
monthDays
=
arrayOf
(
31
,
28
,
31
,
30
,
31
,
30
,
31
,
31
,
30
,
31
,
30
,
31
)
// 检查是否是闰年
if
((
year
%
4
==
0
&&
year
%
100
!=
0
)
||
(
year
%
400
==
0
))
{
monthDays
[
1
]
=
29
// 如果是闰年,二月有29天
}
// 返回给定月份的天数
return
monthDays
[
month
-
1
]
}
@SuppressLint
(
"SimpleDateFormat"
)
fun
generateRandomBirthdayTimestamp
(
age
:
Int
):
Long
{
val
currentTimeMillis
=
System
.
currentTimeMillis
()
// 计算出生年份
val
birthYear
=
2024
-
age
// 随机选择一个月份
val
randomMonth
=
Random
.
nextInt
(
12
)
+
1
// 随机选择一个日期,确保是该月的有效日期
val
randomDay
=
Random
.
nextInt
(
28
)
+
1
// 简单起见,我们假设日期不会超过28
// 构建出生日期字符串,包括时间部分
val
birthDate
=
"$birthYear-${randomMonth.toString().padStart(2, '0')}-${randomDay.toString().padStart(2, '0')} 00:00:00"
// 将字符串转换为时间戳
return
try
{
// 尝试解析日期字符串
val
dateFormat
=
SimpleDateFormat
(
"yyyy-MM-dd HH:mm:ss"
)
dateFormat
.
parse
(
birthDate
)
?.
time
?:
currentTimeMillis
}
catch
(
e
:
ParseException
)
{
// 如果解析失败,返回当前时间戳
currentTimeMillis
}
}
fun
calculateAge
(
birthTimestamp
:
Long
):
Int
{
// 创建一个 Calendar 实例
val
birthCalendar
=
Calendar
.
getInstance
()
// 设置时间戳对应的日期
birthCalendar
.
timeInMillis
=
birthTimestamp
// 创建一个 Calendar 实例用于获取当前日期
val
currentCalendar
=
Calendar
.
getInstance
()
// 计算年龄
var
age
=
currentCalendar
.
get
(
Calendar
.
YEAR
)
-
birthCalendar
.
get
(
Calendar
.
YEAR
)
// 如果当前日期还没有到生日,则年龄减一
if
(
currentCalendar
.
get
(
Calendar
.
DAY_OF_YEAR
)
<
birthCalendar
.
get
(
Calendar
.
DAY_OF_YEAR
))
{
age
--
}
return
age
}
// fun formatTimeAgo(timestamp: Long): String {
// val instant = Instant.ofEpochMilli(timestamp)
// val now = LocalDateTime.now(ZoneId.systemDefault())
// val then = LocalDateTime.ofInstant(instant, ZoneId.systemDefault())
//
// val seconds = ChronoUnit.SECONDS.between(then, now)
// val minutes = ChronoUnit.MINUTES.between(then, now)
// val hours = ChronoUnit.HOURS.between(then, now)
// val days = ChronoUnit.DAYS.between(then, now)
//
// return when {
// days > 0 -> days.toString() + "day ago"
// hours > 0 -> hours.toString() + "H ago"
// minutes > 0 -> minutes.toString() + "Min ago"
// else -> seconds.toString() + "s ago"
// }
// }
fun
formatTimeAgo
(
timestamp
:
Long
):
String
{
val
then
=
Date
(
timestamp
)
val
now
=
Date
()
val
diff
=
now
.
time
-
then
.
time
if
(
diff
<
1000
*
60
)
{
// less than a minute
return
(
diff
/
1000
).
toString
()
+
" s ago"
}
else
if
(
diff
<
1000
*
60
*
60
)
{
// less than an hour
return
(
diff
/
(
1000
*
60
)).
toString
()
+
" minute ago"
}
else
if
(
diff
<
1000
*
60
*
60
*
24
)
{
// less than a day
return
(
diff
/
(
1000
*
60
*
60
)).
toString
()
+
" hour ago"
}
else
{
// more than a day
return
(
diff
/
(
1000
*
60
*
60
*
24
)).
toString
()
+
" day ago"
}
}
}
\ No newline at end of file
app/src/main/java/com/base/scanqr/utils/DialogUtils.kt
0 → 100644
View file @
c697848a
package
com.base.scanqr.utils
import
android.content.Context
import
android.content.Context.WINDOW_SERVICE
import
android.util.DisplayMetrics
import
android.view.View
import
android.view.WindowManager
object
DialogUtils
{
/**
* 判断视图在上半边还是下半边屏幕
*/
fun
Context
.
viewIsTopHalf
(
view
:
View
):
Boolean
{
val
location
=
IntArray
(
2
)
view
.
getLocationOnScreen
(
location
)
val
windowManager
=
getSystemService
(
WINDOW_SERVICE
)
as
WindowManager
val
dm
=
DisplayMetrics
()
windowManager
.
defaultDisplay
.
getMetrics
(
dm
)
val
screenHeight
=
dm
.
heightPixels
// 判断视图的顶部是否在屏幕的上半部分
val
isTopHalf
=
location
[
1
]
<
screenHeight
/
2
// 判断视图的底部是否在屏幕的上半部分
val
isBottomHalf
=
location
[
1
]
+
view
.
height
<
screenHeight
/
2
return
if
(
isTopHalf
)
{
// 视图的顶部在屏幕的上半部分
true
}
else
if
(
isBottomHalf
)
{
// 视图的底部在屏幕的上半部分
true
}
else
{
// 视图在屏幕的下半部分
false
}
}
}
\ No newline at end of file
app/src/main/res/layout/dialog_delete_qr.xml
0 → 100644
View file @
c697848a
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_margin=
"16dp"
app:cardBackgroundColor=
"@color/white"
app:cardCornerRadius=
"10dp"
>
<LinearLayout
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:orientation=
"vertical"
>
<TextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center_horizontal"
android:layout_marginTop=
"28dp"
android:text=
"@string/delete_qrcode"
android:textColor=
"@color/black"
android:textSize=
"19sp"
android:textStyle=
"bold"
/>
<TextView
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center_horizontal"
android:layout_marginTop=
"8dp"
android:gravity=
"center"
android:text=
"@string/do_you_want_delete_item"
android:textColor=
"#666666"
android:textSize=
"16sp"
/>
<LinearLayout
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center_horizontal"
android:layout_marginTop=
"24dp"
android:layout_marginBottom=
"24dp"
>
<TextView
android:id=
"@+id/tv_cancel"
android:layout_width=
"142dp"
android:layout_height=
"44dp"
android:layout_gravity=
"center_vertical"
android:background=
"@drawable/bg_f8f8fa_90"
android:gravity=
"center"
android:text=
"@string/cancel"
android:textColor=
"#333333"
android:textSize=
"18sp"
android:textStyle=
"bold"
/>
<TextView
android:id=
"@+id/tv_remove"
android:layout_width=
"142dp"
android:layout_height=
"44dp"
android:layout_gravity=
"center_vertical"
android:layout_marginStart=
"16dp"
android:background=
"@drawable/bg_6473f8_90"
android:gravity=
"center"
android:text=
"@string/remove"
android:textColor=
"@color/white"
android:textSize=
"18sp"
android:textStyle=
"bold"
/>
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
\ No newline at end of file
app/src/main/res/layout/dialog_history_more.xml
0 → 100644
View file @
c697848a
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
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=
"wrap_content"
android:layout_height=
"wrap_content"
>
<androidx.cardview.widget.CardView
android:layout_width=
"180dp"
android:layout_height=
"wrap_content"
android:layout_margin=
"10dp"
app:cardBackgroundColor=
"@color/white"
app:cardCornerRadius=
"10dp"
app:cardElevation=
"5dp"
>
<LinearLayout
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:orientation=
"vertical"
>
<TextView
android:id=
"@+id/tv_detail"
android:layout_width=
"match_parent"
android:layout_height=
"54dp"
android:background=
"?android:attr/selectableItemBackground"
android:gravity=
"center_vertical"
android:paddingStart=
"18dp"
android:text=
"@string/detail"
android:textColor=
"@color/black"
android:textSize=
"16sp"
tools:ignore=
"RtlSymmetry"
/>
<TextView
android:id=
"@+id/tv_remove"
android:layout_width=
"match_parent"
android:layout_height=
"54dp"
android:background=
"?android:attr/selectableItemBackground"
android:gravity=
"center_vertical"
android:paddingStart=
"18dp"
android:text=
"@string/remove"
android:textColor=
"@color/black"
android:textSize=
"16sp"
tools:ignore=
"RtlSymmetry"
/>
</LinearLayout>
</androidx.cardview.widget.CardView>
</FrameLayout>
\ No newline at end of file
app/src/main/res/layout/item_history.xml
View file @
c697848a
...
...
@@ -51,6 +51,7 @@
</LinearLayout>
<FrameLayout
android:id=
"@+id/fl_more"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center_vertical"
...
...
app/src/main/res/values/dimens.xml
View file @
c697848a
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen
name=
"dp_400"
>
400dp
</dimen>
<dimen
name=
"dp_106"
>
106dp
</dimen>
<dimen
name=
"dp_2"
>
2dp
</dimen>
<dimen
name=
"dp_180"
>
180dp
</dimen>
<dimen
name=
"dp_20"
>
20dp
</dimen>
<dimen
name=
"dp_108"
>
108dp
</dimen>
<dimen
name=
"dp_10"
>
10dp
</dimen>
<dimen
name=
"dp_190"
>
190dp
</dimen>
<dimen
name=
"dp_118"
>
118dp
</dimen>
<dimen
name=
"dp_200"
>
200dp
</dimen>
<dimen
name=
"dp_210"
>
210dp
</dimen>
<dimen
name=
"dp_220"
>
220dp
</dimen>
<dimen
name=
"dp_250"
>
250dp
</dimen>
<dimen
name=
"dp_240"
>
240dp
</dimen>
<dimen
name=
"dp_230"
>
230dp
</dimen>
<dimen
name=
"dp_235"
>
235dp
</dimen>
<dimen
name=
"dp_256"
>
256dp
</dimen>
<dimen
name=
"dp_30"
>
30dp
</dimen>
<dimen
name=
"dp_50"
>
50dp
</dimen>
<dimen
name=
"dp_25"
>
25dp
</dimen>
<dimen
name=
"dp_15"
>
15dp
</dimen>
<dimen
name=
"dp_128"
>
128dp
</dimen>
<dimen
name=
"dp_138"
>
138dp
</dimen>
<dimen
name=
"dp_102"
>
102dp
</dimen>
<dimen
name=
"dp_95"
>
95dp
</dimen>
<dimen
name=
"dp_110"
>
110dp
</dimen>
<dimen
name=
"dp_112"
>
112dp
</dimen>
<dimen
name=
"dp_114"
>
114dp
</dimen>
</resources>
\ No newline at end of file
app/src/main/res/values/strings.xml
View file @
c697848a
...
...
@@ -45,4 +45,7 @@
<string
name=
"sort"
>
Sort
</string>
<string
name=
"export"
>
Export
</string>
<string
name=
"remove"
>
Remove
</string>
<string
name=
"detail"
>
Detail
</string>
<string
name=
"delete_qrcode"
>
Delete QRCode
</string>
<string
name=
"do_you_want_delete_item"
>
Do you want delete item?
</string>
</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