Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Room Park Android
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
Vladislav Bogdashkin
Room Park Android
Commits
23fc8814
Commit
23fc8814
authored
Mar 10, 2020
by
Vladislav Bogdashkin
🎣
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'feature/photo_scroller' into develop
parents
88c6ccf6
adfcf8c4
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
828 additions
and
67 deletions
+828
-67
Project.xml
.idea/codeStyles/Project.xml
+3
-0
build.gradle
app/build.gradle
+9
-0
ScreenController.kt
...l/roompark/presentation/screen/albums/ScreenController.kt
+34
-1
ScreenPresenter.kt
...al/roompark/presentation/screen/albums/ScreenPresenter.kt
+17
-7
ScreenViewState.kt
...al/roompark/presentation/screen/albums/ScreenViewState.kt
+1
-0
AlbumListAdapter.kt
...mpark/presentation/screen/albums/util/AlbumListAdapter.kt
+0
-2
ScreenController.kt
...al/roompark/presentation/screen/photo/ScreenController.kt
+29
-9
ScreenPresenter.kt
...ual/roompark/presentation/screen/photo/ScreenPresenter.kt
+7
-0
AlbumListAdapter.kt
...ompark/presentation/screen/photo/util/AlbumListAdapter.kt
+0
-43
PhotoPreviewSlider.kt
...park/presentation/screen/photo/util/PhotoPreviewSlider.kt
+192
-0
PhotoViewAdapter.kt
...ompark/presentation/screen/photo/util/PhotoViewAdapter.kt
+117
-0
Renderer.kt
...isual/roompark/presentation/screen/photo/util/Renderer.kt
+403
-0
photo_view_screen.xml
app/src/main/res/layout/photo_view_screen.xml
+14
-5
dependencies.gradle
dependencies.gradle
+2
-0
No files found.
.idea/codeStyles/Project.xml
View file @
23fc8814
<component
name=
"ProjectCodeStyleConfiguration"
>
<code_scheme
name=
"Project"
version=
"173"
>
<AndroidXmlCodeStyleSettings>
<option
name=
"ARRANGEMENT_SETTINGS_MIGRATED_TO_191"
value=
"true"
/>
</AndroidXmlCodeStyleSettings>
<JetCodeStyleSettings>
<option
name=
"CODE_STYLE_DEFAULTS"
value=
"KOTLIN_OFFICIAL"
/>
</JetCodeStyleSettings>
...
...
app/build.gradle
View file @
23fc8814
...
...
@@ -152,9 +152,18 @@ dependencies {
implementation
"com.google.android.exoplayer:exoplayer-hls:$exoPlayerVersion"
implementation
"com.google.android.exoplayer:extension-rtmp:$exoPlayerVersion"
//ViewPager2
implementation
"androidx.viewpager2:viewpager2:$viewPager2Version"
//Photo view
implementation
"com.github.chrisbanes:PhotoView:$photoViewVersion"
//Glide
implementation
"com.github.bumptech.glide:glide:$glideVersion"
annotationProcessor
"com.github.bumptech.glide:compiler:$glideVersion"
//Tests
testImplementation
'junit:junit:4.12'
androidTestImplementation
'androidx.test:runner:1.2.0'
...
...
app/src/main/java/com/biganto/visual/roompark/presentation/screen/albums/ScreenController.kt
View file @
23fc8814
...
...
@@ -22,6 +22,8 @@ import com.biganto.visual.roompark.presentation.screen.photo.PhotoScreenControll
import
com.biganto.visual.roompark.util.extensions.scaleCenterCrop
import
com.biganto.visual.roompark.util.view_utils.grid.CeilsDecoration
import
com.bluelinelabs.conductor.RouterTransaction
import
com.bluelinelabs.conductor.changehandler.FadeChangeHandler
import
com.bluelinelabs.conductor.changehandler.VerticalChangeHandler
import
com.google.android.material.textview.MaterialTextView
import
com.squareup.picasso.Picasso
import
io.reactivex.Observable
...
...
@@ -140,6 +142,7 @@ class AlbumsScreenController :
is
AlbumsScreenViewState
.
HeaderAlbumChoosed
->
render
(
viewState
)
is
AlbumsScreenViewState
.
PhotoSelected
->
render
(
viewState
)
is
AlbumsScreenViewState
.
SomeError
->
render
(
viewState
)
is
AlbumsScreenViewState
.
RestoreView
->
render
(
viewState
)
}
}
...
...
@@ -148,7 +151,11 @@ class AlbumsScreenController :
}
private
fun
render
(
viewState
:
AlbumsScreenViewState
.
PhotoSelected
){
router
.
pushController
(
RouterTransaction
.
with
(
PhotoScreenController
(
viewState
.
photoId
)))
router
.
pushController
(
RouterTransaction
.
with
(
PhotoScreenController
(
viewState
.
photoId
))
.
pushChangeHandler
(
VerticalChangeHandler
())
.
popChangeHandler
(
FadeChangeHandler
(
false
))
)
}
private
fun
render
(
viewState
:
AlbumsScreenViewState
.
SomeError
)
=
...
...
@@ -199,6 +206,32 @@ class AlbumsScreenController :
)
}
private
fun
render
(
viewState
:
AlbumsScreenViewState
.
RestoreView
){
(
albumsRecyclerView
.
adapter
as
AlbumListAdapter
).
setItems
(
viewState
.
restore
.
albumList
.
asSequence
().
sortedByDescending
{
it
.
published
}.
toList
()
)
(
headersRecyclerView
.
adapter
as
AlbumsHeaderAdapter
).
setItems
(
viewState
.
restore
.
albumsPreview
.
asSequence
().
sortedByDescending
{
it
.
published
}.
toList
()
)
headersRecyclerView
.
let
{
it
.
scrollToPosition
(
(
it
.
adapter
as
AlbumsHeaderAdapter
).
getItemPosition
(
viewState
.
restore
.
currentIndex
)
)
}
viewState
.
restore
.
albumsPreview
.
first
{
it
.
albumId
==
viewState
.
restore
.
currentIndex
}
.
let
{
currentAlbomTitle
.
text
=
it
.
title
picassoAsync
.
load
(
it
.
previewUrl
)
.
transform
(
BlurTransformation
(
activity
,
13
,
2
))
.
transform
(
ColorFilterTransformation
(
0
xCC000000
.
toInt
()))
.
into
(
photosBackgroundTarget
)
}
}
override
fun
onAlbumSelected
():
Observable
<
AlbumPreviewModel
>
=
(
headersRecyclerView
.
adapter
as
AlbumsHeaderAdapter
)
.
onItemClicked
...
...
app/src/main/java/com/biganto/visual/roompark/presentation/screen/albums/ScreenPresenter.kt
View file @
23fc8814
...
...
@@ -2,6 +2,8 @@ package com.biganto.visual.roompark.presentation.screen.albums
import
com.biganto.visual.roompark.conductor.BigantoBasePresenter
import
com.biganto.visual.roompark.domain.interactor.AlbumsInteractor
import
com.biganto.visual.roompark.domain.model.AlbumPreviewModel
import
com.biganto.visual.roompark.domain.model.AlbumSortedModel
import
com.biganto.visual.roompark.util.monades.ExceptionString
import
io.reactivex.Observable
import
io.reactivex.android.schedulers.AndroidSchedulers
...
...
@@ -13,32 +15,35 @@ import javax.inject.Named
* Created by Vladislav Bogdashkin on 30.09.2019.
*/
class
AlbumsScreenPresenter
@Inject
constructor
(
private
val
interactor
:
AlbumsInteractor
,
@Named
(
SELECTED_ALBUM_INDEX_KEY
)
private
var
selectedIndex
:
Int
)
:
BigantoBasePresenter
<
AlbumsScreen
,
AlbumsScreenViewState
>()
{
private
var
restoreModel
=
RestoreModel
(
listOf
(),
listOf
(),
selectedIndex
)
override
fun
defaultErrorViewStateHandler
()
=
{
e
:
ExceptionString
->
AlbumsScreenViewState
.
SomeError
(
e
)
}
private
fun
requestAlbum
(
id
:
Int
):
Observable
<
AlbumsScreenViewState
>
=
interactor
.
fetchAlbumPhotos
(
id
)
.
filter
{
!
it
.
isNullOrEmpty
()
}
.
map
{
AlbumsScreenViewState
.
AlbumsSelected
(
it
)}
.
doOnNext
{
restoreModel
.
albumList
=
it
}
.
map
{
AlbumsScreenViewState
.
AlbumsSelected
(
it
)}
override
fun
bindIntents
()
{
val
fetchParents
=
interactor
.
fetchHeaderAlbums
()
.
filter
{
!
it
.
isNullOrEmpty
()
}
.
doOnNext
{
restoreModel
.
albumsPreview
=
it
}
.
map
{
AlbumsScreenViewState
.
AlbumsListLoaded
(
it
,
selectedIndex
)
}
val
fetchSelected
=
requestAlbum
(
selectedIndex
)
val
headerItemSelected
=
intent
(
AlbumsScreen
::
onAlbumSelected
)
.
doOnNext
{
selectedIndex
=
it
.
albumId
}
.
doOnNext
{
restoreModel
.
currentIndex
=
it
.
albumId
}
.
flatMap
<
AlbumsScreenViewState
>
{
model
->
requestAlbum
(
model
.
albumId
)
.
startWith
(
Observable
.
just
(
AlbumsScreenViewState
.
HeaderAlbumChoosed
(
item
=
model
)))
...
...
@@ -47,9 +52,6 @@ class AlbumsScreenPresenter @Inject constructor(
val
photoSelected
=
intent
(
AlbumsScreen
::
onPhotoSelected
)
.
map
{
AlbumsScreenViewState
.
PhotoSelected
(
it
.
photoId
)
}
val
state
=
restoreStateObservable
.
mergeWith
(
fetchParents
)
.
mergeWith
(
fetchSelected
)
...
...
@@ -60,4 +62,12 @@ class AlbumsScreenPresenter @Inject constructor(
subscribeViewState
(
state
.
cast
(
AlbumsScreenViewState
::
class
.
java
),
AlbumsScreen
::
render
)
}
}
\ No newline at end of file
override
fun
detachView
()
{
super
.
detachView
()
restoreStateObservable
.
accept
(
AlbumsScreenViewState
.
RestoreView
(
restoreModel
))
}
}
data class
RestoreModel
(
var
albumList
:
List
<
AlbumSortedModel
>
,
var
albumsPreview
:
List
<
AlbumPreviewModel
>
,
var
currentIndex
:
Int
)
\ No newline at end of file
app/src/main/java/com/biganto/visual/roompark/presentation/screen/albums/ScreenViewState.kt
View file @
23fc8814
...
...
@@ -17,4 +17,5 @@ sealed class AlbumsScreenViewState : BigantoBaseViewState() {
class
HeaderAlbumChoosed
(
val
item
:
AlbumPreviewModel
)
:
AlbumsScreenViewState
()
class
PhotoSelected
(
val
photoId
:
Int
)
:
AlbumsScreenViewState
()
class
SomeError
(
val
exception
:
ExceptionString
)
:
AlbumsScreenViewState
()
class
RestoreView
(
val
restore
:
RestoreModel
)
:
AlbumsScreenViewState
()
}
\ No newline at end of file
app/src/main/java/com/biganto/visual/roompark/presentation/screen/albums/util/AlbumListAdapter.kt
View file @
23fc8814
...
...
@@ -10,8 +10,6 @@ import com.biganto.visual.roompark.base.RoomParkApplication
import
com.biganto.visual.roompark.domain.model.AlbumSortedModel
import
com.biganto.visual.roompark.domain.model.PhotoModel
import
com.biganto.visual.roompark.domain.model.PhotoResolutionModel
import
com.biganto.visual.roompark.presentation.screen.photo.util.PhotosAdapter
import
com.biganto.visual.roompark.presentation.screen.photo.util.PhotosViewHolder
import
com.biganto.visual.roompark.presentation.screen.settings.util.CommonRecyclerAdapter
import
com.biganto.visual.roompark.presentation.screen.settings.util.CommonViewHolder
import
com.biganto.visual.roompark.util.view_utils.image_view.RoundedImageView
...
...
app/src/main/java/com/biganto/visual/roompark/presentation/screen/photo/ScreenController.kt
View file @
23fc8814
...
...
@@ -9,7 +9,8 @@ import com.biganto.visual.roompark.R
import
com.biganto.visual.roompark.base.RoomParkApplication
import
com.biganto.visual.roompark.base.RoomParkMainActivity
import
com.biganto.visual.roompark.conductor.BigantoBaseController
import
com.biganto.visual.roompark.presentation.screen.photo.util.PhotoViewerAdapter
import
com.biganto.visual.roompark.presentation.screen.photo.util.PhotoPreviewSlider
import
com.biganto.visual.roompark.presentation.screen.photo.util.PhotosAdapter
import
com.google.android.material.textview.MaterialTextView
import
com.squareup.picasso.Picasso
import
timber.log.Timber
...
...
@@ -39,11 +40,26 @@ class PhotoScreenController :
@BindView
(
R
.
id
.
photo_frame
)
lateinit
var
photoViewPager
:
ViewPager2
@BindView
(
R
.
id
.
photosPreviewSlider
)
lateinit
var
slider
:
PhotoPreviewSlider
private
fun
bindRecycler
()
{
photoViewPager
.
isNestedScrollingEnabled
=
false
photoViewPager
.
offscreenPageLimit
=
2
photoViewPager
.
adapter
=
PhotoViewerAdapter
()
photoViewPager
.
adapter
=
PhotosAdapter
()
setVewPager
()
}
private
fun
setVewPager
(){
val
ap
=
PhotosAdapter
()
photoViewPager
.
adapter
=
ap
photoViewPager
.
orientation
=
ViewPager2
.
ORIENTATION_HORIZONTAL
photoViewPager
.
offscreenPageLimit
=
2
ap
.
notifyDataSetChanged
()
photoViewPager
.
invalidate
()
slider
.
setUpViewPager
(
photoViewPager
)
}
override
fun
onViewBound
(
v
:
View
)
{
...
...
@@ -68,8 +84,7 @@ class PhotoScreenController :
fun
getComponent
()
=
DaggerPhotoScreenComponent
.
factory
()
.
create
(
RoomParkApplication
.
component
,
activity
as
RoomParkMainActivity
,
args
.
getInt
(
SELECTED_PHOTO_KEY
))
.
inject
(
this
)
,
args
.
getInt
(
SELECTED_PHOTO_KEY
)).
inject
(
this
)
override
fun
render
(
viewState
:
PhotoScreenViewState
)
{
Timber
.
d
(
"render: $viewState"
)
...
...
@@ -94,11 +109,15 @@ class PhotoScreenController :
lateinit
var
picassoAsync
:
Picasso
private
fun
render
(
viewState
:
PhotoScreenViewState
.
PhotoListLoaded
)
{
(
photoViewPager
.
adapter
as
Photo
Viewer
Adapter
).
setItems
(
(
photoViewPager
.
adapter
as
Photo
s
Adapter
).
setItems
(
viewState
.
list
.
asSequence
().
sortedBy
{
it
.
sort
}.
toList
()
)
photoViewPager
.
currentItem
=
(
photoViewPager
.
adapter
as
PhotoViewerAdapter
)
.
getItemPosition
(
viewState
.
selectedId
)
slider
.
visibility
=
View
.
VISIBLE
slider
.
setUpViewPager
(
photoViewPager
)
photoViewPager
.
currentItem
=
(
photoViewPager
.
adapter
as
PhotosAdapter
).
indexById
(
viewState
.
selectedId
)
}
private
fun
render
(
viewState
:
PhotoScreenViewState
.
AldumFetched
)
{
...
...
@@ -107,13 +126,14 @@ class PhotoScreenController :
private
fun
render
(
viewState
:
PhotoScreenViewState
.
PhotoFetched
){
(
photoViewPager
.
adapter
as
Photo
Viewer
Adapter
).
setItems
(
arrayListOf
(
viewState
.
model
))
(
photoViewPager
.
adapter
as
Photo
s
Adapter
).
setItems
(
arrayListOf
(
viewState
.
model
))
}
private
fun
render
(
viewState
:
PhotoScreenViewState
.
PhotoSelected
){
// (photoViewPager.adapter as PhotoViewerAdapter).setItems(arrayListOf(viewState.model))
}
override
fun
handleBack
():
Boolean
{
router
.
popController
(
this
);
return
true
}
override
fun
getLayoutId
():
Int
=
R
.
layout
.
photo_view_screen
...
...
app/src/main/java/com/biganto/visual/roompark/presentation/screen/photo/ScreenPresenter.kt
View file @
23fc8814
...
...
@@ -45,4 +45,11 @@ class PhotoScreenPresenter @Inject constructor(
.
observeOn
(
AndroidSchedulers
.
mainThread
())
subscribeViewState
(
state
.
cast
(
PhotoScreenViewState
::
class
.
java
),
PhotoScreen
::
render
)
}
override
fun
detachView
()
{
super
.
detachView
()
restoreStateObservable
.
accept
(
PhotoScreenViewState
.
Idle
())
}
}
\ No newline at end of file
app/src/main/java/com/biganto/visual/roompark/presentation/screen/photo/util/AlbumListAdapter.kt
deleted
100644 → 0
View file @
88c6ccf6
package
com.biganto.visual.roompark.presentation.screen.photo.util
import
android.view.View
import
butterknife.BindView
import
com.biganto.visual.roompark.R
import
com.biganto.visual.roompark.base.RoomParkApplication
import
com.biganto.visual.roompark.domain.model.PhotoModel
import
com.biganto.visual.roompark.domain.model.PhotoResolutionModel
import
com.biganto.visual.roompark.presentation.screen.settings.util.CommonRecyclerAdapter
import
com.biganto.visual.roompark.presentation.screen.settings.util.CommonViewHolder
import
com.biganto.visual.roompark.util.view_utils.image_view.RoundedImageView
/**
* Created by Vladislav Bogdashkin on 16.10.2019.
*/
class
PhotosAdapter
:
CommonRecyclerAdapter
<
PhotosViewHolder
,
PhotoModel
>()
{
override
val
vhKlazz
=
PhotosViewHolder
::
class
override
fun
getVhLayout
():
Int
=
R
.
layout
.
photo_preview_viewholder
}
class
PhotosViewHolder
(
itemView
:
View
)
:
CommonViewHolder
<
PhotoModel
>(
itemView
)
{
@BindView
(
R
.
id
.
photo_preview_imageview
)
lateinit
var
photoPreview
:
RoundedImageView
private
val
picassoAsync
by
lazy
{
return
@lazy
RoomParkApplication
.
component
.
providePicassoAsync
()
}
override
fun
onViewBound
(
model
:
PhotoModel
)
{
model
.
resolutionList
.
lowelest
()
?.
let
{
picassoAsync
.
load
(
it
.
url
)
.
centerCrop
()
.
fit
()
.
into
(
photoPreview
)
}}
}
fun
List
<
PhotoResolutionModel
>.
lowelest
()
=
this
.
minBy
{
it
.
resWidth
*
it
.
resHeight
}
\ No newline at end of file
app/src/main/java/com/biganto/visual/roompark/presentation/screen/photo/util/PhotoPreviewSlider.kt
0 → 100644
View file @
23fc8814
package
com.biganto.visual.roompark.presentation.screen.photo.util
import
android.content.Context
import
android.graphics.SurfaceTexture
import
android.util.AttributeSet
import
android.view.GestureDetector
import
android.view.MotionEvent
import
android.view.TextureView
import
android.view.View
import
androidx.viewpager2.widget.ViewPager2
import
kotlinx.android.synthetic.main.photo_page_viewholder.view.*
import
timber.log.Timber
/**
* Created by Vladislav Bogdashkin on 22.12.2019.
*/
class
PhotoPreviewSlider
@JvmOverloads
constructor
(
context
:
Context
,
attrs
:
AttributeSet
?
=
null
,
defStyleAttr
:
Int
=
0
)
:
TextureView
(
context
,
attrs
,
defStyleAttr
)
,
TextureView
.
SurfaceTextureListener
{
private
var
texThread
:
RendererThread
?=
null
private
var
adapter
:
PhotosAdapter
?
=
null
private
var
vp
:
ViewPager2
?
=
null
fun
setUpViewPager
(
viewpager
:
ViewPager2
)
{
this
.
adapter
=
viewpager
.
adapter
as
PhotosAdapter
with
(
viewpager
)
{
setPageTransformer
{
page
,
position
->
setParallaxTransformation
(
page
,
position
)
}
registerOnPageChangeCallback
(
object
:
ViewPager2
.
OnPageChangeCallback
()
{
var
actualPosition
=
0
override
fun
onPageScrolled
(
position
:
Int
,
positionOffset
:
Float
,
positionOffsetPixels
:
Int
)
{
if
(
position
==
actualPosition
){
processSliding
(
positionOffset
)
}
else
{
processSliding
(
positionOffset
-
1
)
}
super
.
onPageScrolled
(
position
,
positionOffset
,
positionOffsetPixels
)
}
override
fun
onPageSelected
(
position
:
Int
)
{
actualPosition
=
position
texThread
?.
setIndex
(
position
)
super
.
onPageSelected
(
position
)
}
})
}
vp
=
viewpager
}
private
fun
setParallaxTransformation
(
page
:
View
,
position
:
Float
)
{
page
.
apply
{
when
{
position
<
-
1
->
// [-Infinity,-1)
// This page is way off-screen to the left.
alpha
=
1f
position
<
-
1
->
// [-1,0){
{
}
position
<=
1
->
{
// [-1,1]
photo_view
.
translationX
=
-
position
*
(
width
/
2
)
// slider.processSliding(position)
}
else
->
// (1,+Infinity]
{
// This page is way off-screen to the right.
alpha
=
1f
}
}
}
}
fun
processSliding
(
_position
:
Float
){
texThread
?.
setSlidePosition
(
_position
)
}
val
gestureDetector
=
GestureDetector
(
context
,
object
:
GestureDetector
.
SimpleOnGestureListener
(){
override
fun
onDoubleTap
(
e
:
MotionEvent
?):
Boolean
{
Timber
.
d
(
"double tap"
)
return
true
}
override
fun
onScroll
(
e1
:
MotionEvent
?,
e2
:
MotionEvent
?,
distanceX
:
Float
,
distanceY
:
Float
):
Boolean
{
mIsScrolling
=
true
Timber
.
d
(
"scroll"
)
texThread
?.
perfomDrag
(
distanceX
)
return
true
}
override
fun
onDown
(
e
:
MotionEvent
?):
Boolean
{
Timber
.
d
(
"down"
)
return
true
}
})
private
var
mIsScrolling
=
false
init
{
surfaceTextureListener
=
this
val
gestureListener
=
object
:
OnTouchListener
{
private
var
gesture
:
GestureDetector
=
gestureDetector
override
fun
onTouch
(
v
:
View
,
event
:
MotionEvent
):
Boolean
{
Timber
.
w
(
" ON TOUCH EVENT!"
)
val
performTouch
=
gesture
.
onTouchEvent
(
event
)
if
(
performTouch
)
return
true
if
(
event
.
action
==
MotionEvent
.
ACTION_UP
)
{
if
(
mIsScrolling
)
{
Timber
.
d
(
"OnTouchListener --> onTouch ACTION_UP"
)
mIsScrolling
=
false
texThread
?.
perfomDrag
(
null
,
mIsScrolling
)
}
}
if
(
event
.
action
==
MotionEvent
.
ACTION_BUTTON_PRESS
)
performClick
()
return
false
}
}
setOnTouchListener
(
gestureListener
)
}
override
fun
onSizeChanged
(
w
:
Int
,
h
:
Int
,
oldw
:
Int
,
oldh
:
Int
)
{
Timber
.
d
(
"On Size Chagned"
)
super
.
onSizeChanged
(
w
,
h
,
oldw
,
oldh
)
}
override
fun
onSurfaceTextureSizeChanged
(
surface
:
SurfaceTexture
?,
width
:
Int
,
height
:
Int
)
{
print
(
" onSurfaceTextureSizeChanged"
)
texThread
?.
setSize
(
width
,
height
)
//Ignored
}
override
fun
onSurfaceTextureUpdated
(
surface
:
SurfaceTexture
?)
{
print
(
" onSurfaceTextureUpdated"
)
//Ignored
}
override
fun
onSurfaceTextureDestroyed
(
surface
:
SurfaceTexture
?):
Boolean
{
texThread
?.
isStopped
=
true
return
true
}
override
fun
onSurfaceTextureAvailable
(
surface
:
SurfaceTexture
?,
width
:
Int
,
height
:
Int
)
{
Timber
.
d
(
"avaliable surf: $surface"
)
surface
?.
let
{
if
(
texThread
?.
isAlive
==
true
)
return
texThread
=
RendererThread
(
context
,
it
)
texThread
?.
setSize
(
width
,
height
)
texThread
?.
onChangePage
=
{
ind
->
vp
?.
setCurrentItem
(
ind
,
false
)}
texThread
?.
start
()
adapter
?.
let
{
adapter
->
texThread
?.
setAdapter
(
adapter
.
photosPreviewList
)
texThread
?.
setIndex
(
vp
?.
currentItem
?:
0
)
// texThread?.setIndex(min(_l.size,2))
}
?:
error
(
"adapter not ready!"
)
}
}
override
fun
onDetachedFromWindow
()
{
super
.
onDetachedFromWindow
()
texThread
?.
isStopped
=
true
}
}
app/src/main/java/com/biganto/visual/roompark/presentation/screen/photo/util/PhotoViewAdapter.kt
0 → 100644
View file @
23fc8814
package
com.biganto.visual.roompark.presentation.screen.photo.util
import
android.content.Context
import
android.graphics.Point
import
android.view.View
import
android.view.WindowManager
import
butterknife.BindView
import
com.biganto.visual.roompark.R
import
com.biganto.visual.roompark.base.RoomParkApplication
import
com.biganto.visual.roompark.domain.model.PhotoModel
import
com.biganto.visual.roompark.domain.model.PhotoResolutionModel
import
com.biganto.visual.roompark.presentation.screen.settings.util.CommonRecyclerAdapter
import
com.biganto.visual.roompark.presentation.screen.settings.util.CommonViewHolder
import
com.github.chrisbanes.photoview.PhotoView
import
com.google.android.material.textview.MaterialTextView
import
timber.log.Timber
import
javax.security.auth.callback.Callback
import
kotlin.math.absoluteValue
/**
* Created by Vladislav Bogdashkin on 16.10.2019.
*/
class
PhotosAdapter
:
CommonRecyclerAdapter
<
PhotosViewHolder
,
PhotoModel
>()
{
val
photosPreviewList
:
List
<
String
>
get
()
{
val
ret
=
list
.
map
{
it
.
resolutionList
.
lowelest
()
?.
url
?:
error
(
"No res urls!"
)}.
toList
()
Timber
.
d
(
"$ret"
)
return
ret
}
fun
indexById
(
id
:
Int
):
Int
=
list
.
indexOfFirst
{
it
.
photoId
==
id
}
override
val
vhKlazz
=
PhotosViewHolder
::
class
override
fun
getVhLayout
():
Int
=
R
.
layout
.
photo_page_viewholder
}
class
PhotosViewHolder
(
itemView
:
View
)
:
CommonViewHolder
<
PhotoModel
>(
itemView
)
{
@BindView
(
R
.
id
.
photo_view
)
lateinit
var
photoPreview
:
PhotoView
@BindView
(
R
.
id
.
photo_description
)
lateinit
var
description
:
MaterialTextView
private
val
picassoAsync
by
lazy
{
return
@lazy
RoomParkApplication
.
component
.
providePicassoAsync
()
}
private
val
windowSize
by
lazy
{
val
pSize
:
Point
=
Point
()
(
itemView
.
context
.
getSystemService
(
Context
.
WINDOW_SERVICE
)
as
WindowManager
)
.
defaultDisplay
.
getSize
(
pSize
)
pSize
}
override
fun
onViewBound
(
model
:
PhotoModel
)
{
description
.
visibility
=
if
(
model
.
description
!=
null
)
View
.
VISIBLE
else
View
.
GONE
model
.
description
?.
let
{
description
.
text
=
it
}
model
.
resolutionList
.
lowelest
()
?.
let
{
picassoAsync
.
load
(
it
.
url
)
.
centerCrop
()
.
fit
()
.
into
(
photoPreview
,
object
:
Callback
,
com
.
squareup
.
picasso
.
Callback
{
override
fun
onSuccess
()
{
model
.
resolutionList
.
onEach
{
Timber
.
d
(
"val ensure: ${it.resWidth} : ${it.resHeight}"
)
}
.
minBy
{
((
windowSize
.
x
-
it
.
resWidth
+
.
1f
).
absoluteValue
+
(
windowSize
.
y
-
it
.
resHeight
+
.
1f
).
absoluteValue
)
}
?.
let
{
photo
->
Timber
.
d
(
"val: ${photo.resWidth} : ${photo.resHeight}"
)
picassoAsync
.
load
(
photo
.
url
)
.
centerCrop
()
.
fit
()
.
into
(
photoPreview
)
}
}
override
fun
onError
(
e
:
Exception
?)
{
model
.
resolutionList
.
onEach
{
Timber
.
d
(
"val ensure: ${it.resWidth} : ${it.resHeight}"
)
}
.
minBy
{
((
windowSize
.
x
-
it
.
resWidth
+
.
1f
).
absoluteValue
+
(
windowSize
.
y
-
it
.
resHeight
+
.
1f
).
absoluteValue
)
}
?.
let
{
Timber
.
d
(
"val: ${it.resWidth} : ${it.resHeight}"
)
picassoAsync
.
load
(
it
.
url
)
.
centerCrop
()
.
fit
()
.
into
(
photoPreview
)
}
}
})
}
}
}
private
fun
List
<
PhotoResolutionModel
>.
lowelest
()
=
this
.
minBy
{
it
.
resWidth
*
it
.
resHeight
}
\ No newline at end of file
app/src/main/java/com/biganto/visual/roompark/presentation/screen/photo/util/Renderer.kt
0 → 100644
View file @
23fc8814
package
com.biganto.visual.roompark.presentation.screen.photo.util
import
android.content.Context
import
android.graphics.*
import
android.graphics.drawable.Drawable
import
android.view.Surface
import
com.bumptech.glide.Glide
import
com.bumptech.glide.load.engine.DiskCacheStrategy
import
com.bumptech.glide.request.RequestOptions
import
com.bumptech.glide.request.target.CustomTarget
import
com.bumptech.glide.request.transition.Transition
import
timber.log.Timber
import
kotlin.math.abs
import
kotlin.math.absoluteValue
import
kotlin.math.sign
import
kotlin.math.sin
/**
* Created by Vladislav Bogdashkin on 18.07.2019.
*/
private
const
val
CONST_SLEEP_THRESHOLD
=
8L
private
const
val
CONST_CENTER_PHOTO_BORDER_PX
=
8
private
const
val
CONST_CENTER_HEIGHT_DIFF_PX
=
0
private
const
val
CONST_HEIGHT_MARGIN_BORDER_PX
=
8
private
const
val
CONST_DIFF_BORDER_PX
=
1
private
const
val
CONST_DECAY_TIMER
=
500L
class
RendererThread
(
val
context
:
Context
,
val
surface
:
SurfaceTexture
)
:
Thread
(){
private
val
dens
:
Float
by
lazy
{
context
.
resources
.
displayMetrics
.
density
}
private
val
SLEEP_THRESHOLD
get
()
=
CONST_SLEEP_THRESHOLD
private
val
CENTER_PHOTO_BORDER_PX
get
()
=
(
CONST_CENTER_PHOTO_BORDER_PX
*
dens
).
int
private
val
CENTER_HEIGHT_DIFF_PX
get
()
=
(
CONST_CENTER_HEIGHT_DIFF_PX
*
dens
).
int
private
val
HEIGHT_MARGIN_BORDER_PX
get
()
=
(
CONST_HEIGHT_MARGIN_BORDER_PX
*
dens
).
int
private
val
DIFF_BORDER_PX
get
()
=
(
CONST_DIFF_BORDER_PX
*
dens
).
int
private
val
DECAY_TIMER
get
()
=
CONST_DECAY_TIMER
private
var
isDirty
=
true
var
isStopped
=
false
private
var
width
=
0
private
var
height
=
0
private
var
bmpCache
:
MutableList
<
Bitmap
?>
=
mutableListOf
()
private
var
holdIndex
=
0
get
()
=
if
(
isDragging
)
field
else
currentIndex
private
var
currentIndex
:
Int
=
0
set
(
value
)
{
Timber
.
w
(
"currentIndex to: $value"
);
field
=
value
}
private
var
bmpCacheUrls
:
List
<
String
>
=
arrayListOf
()
fun
setAdapter
(
urls
:
List
<
String
>
)
{
bmpCacheUrls
=
urls
bmpCache
=
MutableList
(
bmpCacheUrls
.
size
)
{
null
}
bmpCacheUrls
.
fetchUrls
()
bordersArray
=
IntArray
(
bmpCacheUrls
.
size
*
4
)
cropArray
=
IntArray
(
bmpCacheUrls
.
size
*
4
)
}
private
fun
List
<
String
>.
fetchUrls
(){
this
.
forEachIndexed
{
index
,
s
->
if
(
bmpCache
.
getOrNull
(
index
)
==
null
){
Timber
.
d
(
"loading: $s"
)
Glide
.
with
(
context
)
.
asBitmap
()
.
load
(
bmpCacheUrls
[
index
])
.
apply
(
RequestOptions
().
override
(
width
/
bmpCache
.
size
,
height
))
.
diskCacheStrategy
(
DiskCacheStrategy
.
ALL
)
.
into
(
object
:
CustomTarget
<
Bitmap
>(){
override
fun
onLoadCleared
(
placeholder
:
Drawable
?)
{
Timber
.
d
(
" onLoadCleared "
)
bmpCache
[
index
]
=
null
}
override
fun
onResourceReady
(
resource
:
Bitmap
,
transition
:
Transition
<
in
Bitmap
>?
)
{
Timber
.
d
(
" onResourceReady $resource"
)
bmpCache
[
index
]
=
resource
isDirty
=
true
}
})
}
}
}
fun
setIndex
(
index
:
Int
){
if
(!
isDragging
)
holdIndex
=
index
currentIndex
=
index
isDirty
=
true
}
private
var
bordersArray
:
IntArray
?
=
null
private
var
cropArray
:
IntArray
?
=
null
private
fun
IntArray
.
getPosition
(
dir
:
Float
):
Int
{
if
(
dir
<
0
&&
this
.
getX
(
currentIndex
)
>
width
/
2f
)
return
(
currentIndex
-
1
).
coerceIn
(
0
,
this
.
size
/
4
-
1
)
if
(
dir
>
0
&&
this
.
getRight
(
currentIndex
)
<
width
/
2f
)
return
(
currentIndex
+
1
).
coerceIn
(
0
,
this
.
size
/
4
-
1
)
return
currentIndex
}
private
fun
IntArray
.
getX
(
index
:
Int
)
=
if
(
index
>=
0
)
this
[
index
*
4
+
0
]
else
0
private
fun
IntArray
.
getY
(
index
:
Int
)
=
this
[
index
*
4
+
1
]
private
fun
IntArray
.
getRight
(
index
:
Int
)
=
if
(
index
>=
0
)
this
[
index
*
4
+
2
]
else
0
private
fun
IntArray
.
getBottom
(
index
:
Int
)
=
this
[
index
*
4
+
3
]
private
fun
IntArray
.
getWidth
(
index
:
Int
)
=
this
[
index
*
4
+
2
]
-
this
[
index
*
4
+
0
]
private
fun
IntArray
.
getHeight
(
index
:
Int
)
=
this
[
index
*
4
+
3
]
-
this
[
index
*
4
+
1
]
private
fun
IntArray
.
aspect
(
index
:
Int
)
=
this
.
getWidth
(
index
).
toFloat
()/
this
.
getHeight
(
index
).
toFloat
()
private
fun
IntArray
.
setX
(
index
:
Int
,
block
:()->
Int
){
this
[
index
*
4
+
0
]
=
block
.
invoke
()
}
private
fun
IntArray
.
setY
(
index
:
Int
,
block
:()->
Int
){
this
[
index
*
4
+
1
]
=
block
.
invoke
()
}
private
fun
IntArray
.
setRight
(
index
:
Int
,
block
:()->
Int
){
this
[
index
*
4
+
2
]
=
block
.
invoke
()
}
private
fun
IntArray
.
setBottom
(
index
:
Int
,
block
:()->
Int
){
this
[
index
*
4
+
3
]
=
block
.
invoke
()
}
private
val
Bitmap
.
aspect
:
Float
get
()
=
this
.
width
.
toFloat
()/
this
.
height
.
toFloat
()
private
fun
calcBorders
()
{
val
centerX
=
width
/
2f
-
scrollOffset
val
adjWidth
=
height
*
.
6f
bmpCache
.
forEachIndexed
{
index
,
bitmap
->
val
limit
=
(
2
-
(
index
-
currentIndex
).
absoluteValue
).
coerceIn
(
0
,
1
)
val
direction
=
(
index
-
currentIndex
).
sign
//cos(((index-currentIndex).sign)*1.57f)
val
ch2
=
limit
*
(
(
slidePosition
*
direction
).
coerceIn
(
0f
,
1f
)
+
(
1f
-
direction
.
absoluteValue
)
*
(
1f
-
slidePosition
.
absoluteValue
)
)
bordersArray
?.
let
{
arr
->
val
wDiff
=
height
*
(
bitmap
?.
aspect
?:
0f
)
val
_width
=
adjWidth
+
dragKoef
*((
wDiff
-
adjWidth
)
/
2f
+
CENTER_PHOTO_BORDER_PX
)
*
ch2
arr
.
setX
(
index
)
{
arr
.
getRight
(
index
-
1
)
}
arr
.
setRight
(
index
)
{(
arr
.
getX
(
index
)
+
_width
).
int
}
arr
.
setY
(
index
)
{(
HEIGHT_MARGIN_BORDER_PX
+
CENTER_HEIGHT_DIFF_PX
*
(
1f
-
ch2
)).
int
}
arr
.
setBottom
(
index
)
{
height
-
(
HEIGHT_MARGIN_BORDER_PX
+
CENTER_HEIGHT_DIFF_PX
*
(
1f
-
ch2
)).
int
}
}
cropArray
?.
let
{
arr
->
val
asp
=
bordersArray
?.
aspect
(
index
)
?:
0f
bitmap
?.
let
{
if
(
asp
>=
it
.
aspect
)
{
arr
.
setX
(
index
)
{
0
}
arr
.
setRight
(
index
)
{
it
.
width
}
val
hKef
=
it
.
aspect
/
asp
val
marg
=
it
.
height
*
(
1f
-
hKef
)
/
2f
arr
.
setY
(
index
)
{
marg
.
int
}
arr
.
setBottom
(
index
)
{
it
.
height
-
marg
.
int
}
}
else
{
arr
.
setY
(
index
)
{
0
}
arr
.
setBottom
(
index
)
{
it
.
height
}
val
hKef
=
asp
/
it
.
aspect
val
marg
=
it
.
width
*
(
1f
-
hKef
)
/
2f
arr
.
setX
(
index
)
{
marg
.
int
}
arr
.
setRight
(
index
)
{
it
.
width
-
marg
.
int
}
}
}
}
}
bordersArray
?.
let
{
arr
->
val
halfW
=
arr
.
getWidth
(
currentIndex
)
/
2f
val
minusW
=
arr
.
getX
(
holdIndex
)
-
centerX
+
halfW
*
(
1f
+
2f
*
slidePosition
)
bmpCache
.
forEachIndexed
{
index
,
bitmap
->
val
limit
=
(
2
-
(
index
-
currentIndex
).
absoluteValue
).
coerceIn
(
0
,
1
)
val
direction
=
(
index
-
currentIndex
).
sign
val
cBorder
=
(
CENTER_PHOTO_BORDER_PX
)
val
borderKoef
=
(
direction
+
1f
-
limit
*
sin
((
direction
+
slidePosition
.
sign
).
coerceIn
(-
1f
,
1f
)
*
1.57f
)
*
slidePosition
.
absoluteValue
)
val
borderSize
=
dragKoef
*
cBorder
*
borderKoef
arr
.
setX
(
index
)
{(
arr
.
getX
(
index
)
-
minusW
.
int
+
borderSize
+
DIFF_BORDER_PX
).
int
}
arr
.
setRight
(
index
)
{
(
arr
.
getRight
(
index
)
-
minusW
.
int
+
borderSize
-
DIFF_BORDER_PX
).
int
}
}
}
}
private
val
Float
.
int
:
Int
get
()
{
return
this
.
toInt
()}
fun
perfomDrag
(
distanceX
:
Float
?,
dragging
:
Boolean
=
true
){
isDragging
=
dragging
if
(
isDragging
)
distanceX
?.
let
{
perfomScroll
(
it
)}
else
{
holdIndex
=
currentIndex
scrollOffset
=
0f
touchOffset
=
0f
}
isDirty
=
true
}
private
fun
perfomScroll
(
distanceX
:
Float
)
{
touchOffset
+=
distanceX
*
scrollScaleFactor
val
p
=
bordersArray
?.
getPosition
(
distanceX
.
sign
)
?:
0
if
(
p
!=
currentIndex
)
{
setIndex
(
p
)
onChangePage
?.
invoke
(
p
)
}
isDirty
=
true
}
var
onChangePage
:
((
newPage
:
Int
)->
Unit
)?
=
null
private
var
scrollScaleFactor
=
1f
private
var
touchOffset
=
0f
private
var
scrollOffset
=
0f
private
var
isDragging
=
false
private
var
slidePosition
=
0f
private
var
dragKoef
=
1f
fun
setSlidePosition
(
newPosition
:
Float
){
slidePosition
=
newPosition
isDirty
=
true
}
private
var
decayFraction
=
0f
private
fun
timerDecay
(
mills
:
Long
){
isDirty
=
true
decayFraction
+=
mills
animateBorders
()
scrollOffset
=
scrollOffset
.
smoothLerp
(
touchOffset
-
scrollOffset
,.
2f
)
if
(
touchOffset
>
0
&&
scrollOffset
>=
touchOffset
)
{
scrollOffset
=
touchOffset
isDirty
=
false
}
else
if
(
touchOffset
<
0
&&
scrollOffset
<=
touchOffset
)
{
scrollOffset
=
touchOffset
isDirty
=
false
}
if
(
decayFraction
>
DECAY_TIMER
)
isDirty
=
false
val
dirty
=
animateBorders
()
if
(!
isDirty
)
isDirty
=
dirty
}
private
fun
animateBorders
():
Boolean
{
if
(
isDragging
&&
dragKoef
>
0
){
dragKoef
=
dragKoef
.
smoothLerp
(-
dragKoef
,.
12f
)
if
(
dragKoef
<.
1f
)
dragKoef
=
0f
return
dragKoef
>
0
}
if
(!
isDragging
&&
dragKoef
<
1f
)
{
dragKoef
=
dragKoef
.
smoothLerp
(
1f
-
dragKoef
,.
03f
)
if
(
dragKoef
>.
99f
)
dragKoef
=
1f
return
dragKoef
<
1f
}
return
false
}
private
fun
Float
.
smoothLerp
(
delta
:
Float
,
fraction
:
Float
=.
4f
):
Float
{
return
this
+
fraction
*
(
delta
)
}
fun
setSize
(
w
:
Int
,
h
:
Int
){
width
=
w
height
=
h
}
override
fun
run
()
{
super
.
run
()
Timber
.
w
(
"isStopped: $isStopped"
)
Timber
.
w
(
"isDirty: $isDirty"
)
isDirty
=
true
while
(!
isStopped
)
{
while
(!
isDirty
)
sleep
(
SLEEP_THRESHOLD
)
// in real life this sleep is more complicated
isDirty
=
false
val
surf
=
Surface
(
surface
)
val
dRect
=
Rect
(
width
.
div
(
4
)
+
width
.
div
(
2
)
,
HEIGHT_MARGIN_BORDER_PX
,
width
-
width
.
div
(
4
)
,
height
.
minus
(
HEIGHT_MARGIN_BORDER_PX
)
)
val
c
=
surf
.
lockCanvas
(
dRect
)
c
.
drawColor
(
Color
.
BLACK
)
timerDecay
(
SLEEP_THRESHOLD
)
if
(
bmpCache
.
size
>
0
)
calcBorders
()
bmpCache
.
forEachIndexed
{
index
,
bitmap
->
// Timber.d("bitmap ${bitmap} / $index")
bitmap
?.
let
{
val
bmpX
=
cropArray
?.
getX
(
index
)
?:
0
val
bmpY
=
cropArray
?.
getY
(
index
)
?:
0
val
bmpRight
=
cropArray
?.
getRight
(
index
)
?:
0
val
bmpBottom
=
cropArray
?.
getBottom
(
index
)
?:
0
val
dstX
=
bordersArray
?.
getX
(
index
)
?:
0
val
dstY
=
bordersArray
?.
getY
(
index
)
?:
0
val
dstRight
=
bordersArray
?.
getRight
(
index
)
?:
0
val
dstBottom
=
bordersArray
?.
getBottom
(
index
)
?:
0
c
.
drawBitmap
(
it
,
Rect
(
bmpX
,
bmpY
,
bmpRight
,
bmpBottom
)
,
Rect
(
dstX
,
dstY
,
dstRight
,
dstBottom
)
,
null
)
}
}
surf
.
unlockCanvasAndPost
(
c
)
surf
.
release
()
// isDirty = false
}
Timber
.
w
(
"STOPPED; $isStopped"
)
Timber
.
w
(
"STOPPED; $isDirty"
)
isDirty
=
false
}
private
fun
calcHeightPixel
(
index
:
Int
,
selectedIndex
:
Int
):
Int
{
return
height
}
private
fun
calcWidthPixel
(
index
:
Int
,
selectedIndex
:
Int
):
Int
{
val
dist
=
abs
(
index
-
selectedIndex
)
val
bled
=
index
-
selectedIndex
// Timber.d("gonna calc: $bled")
try
{
var
bled_res
=
100
;
// Timber.d("res is : $bled_res")
if
(
bled
==
0
)
bled_res
=
calcHeightPixel
(
index
,
selectedIndex
)
else
bled_res
=
(
calcHeightPixel
(
index
,
selectedIndex
)*
(
1f
-
.
05f
*
dist
)).
int
bled_res
=
when
(
bled
)
{
0
->
calcHeightPixel
(
index
,
selectedIndex
)
in
-
1
downTo
Int
.
MIN_VALUE
->
(
calcHeightPixel
(
index
,
selectedIndex
)*
(
1f
-
.
05f
*
dist
)).
int
in
1
..
Int
.
MAX_VALUE
->
(
calcHeightPixel
(
index
,
selectedIndex
)*
(
1f
-
.
05f
*
dist
)).
int
else
->
error
(
"Unexeptable value"
)
}
// Timber.d("res is : $bled_res")
return
bled_res
}
catch
(
e
:
Exception
){
Timber
.
e
(
e
)}
return
-
1
}
private
fun
Bitmap
.
flip
():
Bitmap
{
val
flip
=
Matrix
()
flip
.
postScale
(
1f
,
-
1f
)
return
Bitmap
.
createBitmap
(
this
,
0
,
0
,
this
.
width
,
this
.
height
,
flip
,
true
)
}
}
app/src/main/res/layout/photo_view_screen.xml
View file @
23fc8814
...
...
@@ -5,7 +5,7 @@
android:id=
"@+id/linearLayout6"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:background=
"
@color/colorOpacityBackground
"
>
android:background=
"
#000000
"
>
<com.google.android.material.textview.MaterialTextView
android:id=
"@+id/photoTitle"
...
...
@@ -53,29 +53,38 @@
android:layout_height=
"24dp"
android:layout_marginStart=
"16dp"
android:layout_marginTop=
"16dp"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"@+id/guideline2"
app:layout_constraintVertical_bias=
"0.0"
app:srcCompat=
"@drawable/iic_full_view"
/>
<ImageView
android:id=
"@+id/change_size_button"
android:layout_width=
"24dp"
android:layout_height=
"24dp"
android:layout_marginEnd=
"16dp"
android:layout_marginTop=
"16dp"
android:layout_marginEnd=
"16dp"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintTop_toTopOf=
"@+id/guideline2"
app:layout_constraintVertical_bias=
"0.0"
app:srcCompat=
"@drawable/iic_full_view"
/>
<androidx.recyclerview.widget.RecyclerView
<com.biganto.visual.roompark.presentation.screen.photo.util.PhotoPreviewSlider
android:id=
"@+id/photosPreviewSlider"
android:layout_width=
"0dp"
android:layout_height=
"0dp"
android:layout_height=
"48dp"
android:layout_marginStart=
"16dp"
android:layout_marginTop=
"8dp"
android:layout_marginEnd=
"16dp"
android:layout_marginBottom=
"16dp"
android:orientation=
"horizontal"
android:visibility=
"invisible"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toStartOf=
"@+id/change_size_button"
app:layout_constraintStart_toEndOf=
"@+id/show_full_button"
app:layout_constraintTop_toTopOf=
"@+id/guideline2"
/>
app:layout_constraintTop_toTopOf=
"@+id/guideline2"
app:layout_constraintVertical_bias=
"0.0"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
dependencies.gradle
View file @
23fc8814
...
...
@@ -25,4 +25,6 @@ ext {
rxRelayVersion
=
'2.1.1'
exoPlayerVersion
=
"2.10.8"
photoViewVersion
=
"2.0.0"
viewPager2Version
=
"1.0.0"
glideVersion
=
"4.11.0"
}
\ 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