Albums scrollable and CW with blurhash
This commit is contained in:
parent
7631e8c1f9
commit
1778f775b2
113
app/src/main/java/com/h/pixeldroid/posts/NestedScrollableHost.kt
Normal file
113
app/src/main/java/com/h/pixeldroid/posts/NestedScrollableHost.kt
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.h.pixeldroid.posts
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewConfiguration
|
||||||
|
import android.widget.FrameLayout
|
||||||
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
|
import androidx.viewpager2.widget.ViewPager2.ORIENTATION_HORIZONTAL
|
||||||
|
import kotlin.math.absoluteValue
|
||||||
|
import kotlin.math.sign
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Layout to wrap a scrollable component inside a ViewPager2. Provided as a solution to the problem
|
||||||
|
* where pages of ViewPager2 have nested scrollable elements that scroll in the same direction as
|
||||||
|
* ViewPager2. The scrollable element needs to be the immediate and only child of this host layout.
|
||||||
|
*
|
||||||
|
* This solution has limitations when using multiple levels of nested scrollable elements
|
||||||
|
* (e.g. a horizontal RecyclerView in a vertical RecyclerView in a horizontal ViewPager2).
|
||||||
|
*/
|
||||||
|
class NestedScrollableHost : ConstraintLayout {
|
||||||
|
constructor(context: Context) : super(context)
|
||||||
|
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
|
||||||
|
|
||||||
|
private var touchSlop = 0
|
||||||
|
private var initialX = 0f
|
||||||
|
private var initialY = 0f
|
||||||
|
private val parentViewPager: ViewPager2?
|
||||||
|
get() {
|
||||||
|
var v: View? = parent as? View
|
||||||
|
while (v != null && v !is ViewPager2) {
|
||||||
|
v = v.parent as? View
|
||||||
|
}
|
||||||
|
return v as? ViewPager2
|
||||||
|
}
|
||||||
|
|
||||||
|
private val child: View? get() = if (childCount > 0) getChildAt(0) else null
|
||||||
|
|
||||||
|
init {
|
||||||
|
touchSlop = ViewConfiguration.get(context).scaledTouchSlop
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun canChildScroll(orientation: Int, delta: Float): Boolean {
|
||||||
|
val direction = -delta.sign.toInt()
|
||||||
|
return when (orientation) {
|
||||||
|
0 -> child?.canScrollHorizontally(direction) ?: false
|
||||||
|
1 -> child?.canScrollVertically(direction) ?: false
|
||||||
|
else -> throw IllegalArgumentException()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onInterceptTouchEvent(e: MotionEvent): Boolean {
|
||||||
|
handleInterceptTouchEvent(e)
|
||||||
|
return super.onInterceptTouchEvent(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleInterceptTouchEvent(e: MotionEvent) {
|
||||||
|
val orientation = parentViewPager?.orientation ?: return
|
||||||
|
|
||||||
|
// Early return if child can't scroll in same direction as parent
|
||||||
|
if (!canChildScroll(orientation, -1f) && !canChildScroll(orientation, 1f)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.action == MotionEvent.ACTION_DOWN) {
|
||||||
|
initialX = e.x
|
||||||
|
initialY = e.y
|
||||||
|
parent.requestDisallowInterceptTouchEvent(true)
|
||||||
|
} else if (e.action == MotionEvent.ACTION_MOVE) {
|
||||||
|
val dx = e.x - initialX
|
||||||
|
val dy = e.y - initialY
|
||||||
|
val isVpHorizontal = orientation == ORIENTATION_HORIZONTAL
|
||||||
|
|
||||||
|
// assuming ViewPager2 touch-slop is 2x touch-slop of child
|
||||||
|
val scaledDx = dx.absoluteValue * if (isVpHorizontal) .5f else 1f
|
||||||
|
val scaledDy = dy.absoluteValue * if (isVpHorizontal) 1f else .5f
|
||||||
|
|
||||||
|
if (scaledDx > touchSlop || scaledDy > touchSlop) {
|
||||||
|
if (isVpHorizontal == (scaledDy > scaledDx)) {
|
||||||
|
// Gesture is perpendicular, allow all parents to intercept
|
||||||
|
parent.requestDisallowInterceptTouchEvent(false)
|
||||||
|
} else {
|
||||||
|
// Gesture is parallel, query child if movement in that direction is possible
|
||||||
|
if (canChildScroll(orientation, if (isVpHorizontal) dx else dy)) {
|
||||||
|
// Child can scroll, disallow all parents to intercept
|
||||||
|
parent.requestDisallowInterceptTouchEvent(true)
|
||||||
|
} else {
|
||||||
|
// Child cannot scroll, allow all parents to intercept
|
||||||
|
parent.requestDisallowInterceptTouchEvent(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -17,7 +17,6 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.bumptech.glide.RequestBuilder
|
import com.bumptech.glide.RequestBuilder
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.google.android.material.tabs.TabLayoutMediator
|
|
||||||
import com.h.pixeldroid.R
|
import com.h.pixeldroid.R
|
||||||
import com.h.pixeldroid.databinding.AlbumImageViewBinding
|
import com.h.pixeldroid.databinding.AlbumImageViewBinding
|
||||||
import com.h.pixeldroid.databinding.CommentBinding
|
import com.h.pixeldroid.databinding.CommentBinding
|
||||||
@ -28,7 +27,6 @@ import com.h.pixeldroid.utils.api.PixelfedAPI
|
|||||||
import com.h.pixeldroid.utils.api.objects.Attachment
|
import com.h.pixeldroid.utils.api.objects.Attachment
|
||||||
import com.h.pixeldroid.utils.api.objects.Status
|
import com.h.pixeldroid.utils.api.objects.Status
|
||||||
import com.h.pixeldroid.utils.db.AppDatabase
|
import com.h.pixeldroid.utils.db.AppDatabase
|
||||||
import com.h.pixeldroid.utils.displayDimensionsInPx
|
|
||||||
import com.karumi.dexter.Dexter
|
import com.karumi.dexter.Dexter
|
||||||
import com.karumi.dexter.listener.PermissionDeniedResponse
|
import com.karumi.dexter.listener.PermissionDeniedResponse
|
||||||
import com.karumi.dexter.listener.PermissionGrantedResponse
|
import com.karumi.dexter.listener.PermissionGrantedResponse
|
||||||
@ -60,12 +58,13 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
|
|||||||
}?.maxOrNull() ?: 1f
|
}?.maxOrNull() ?: 1f
|
||||||
|
|
||||||
val (displayWidth, displayHeight) = displayDimensionsInPx
|
val (displayWidth, displayHeight) = displayDimensionsInPx
|
||||||
val height = if (displayWidth / maxImageRatio > displayHeight * 3/4f) {
|
if (displayWidth / maxImageRatio > displayHeight * 3/4f) {
|
||||||
binding.postPicture.layoutParams.width = ((displayHeight * 3 / 4f) * maxImageRatio).roundToInt()
|
binding.postPager.layoutParams.width = ((displayHeight * 3 / 4f) * maxImageRatio).roundToInt()
|
||||||
displayHeight * 3 / 4f
|
binding.postPager.layoutParams.height = (displayHeight * 3 / 4f).toInt()
|
||||||
} else displayWidth / maxImageRatio
|
} else {
|
||||||
|
binding.postPager.layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
binding.postPicture.layoutParams.height = height.toInt()
|
binding.postPager.layoutParams.height = (displayWidth / maxImageRatio).toInt()
|
||||||
|
}
|
||||||
|
|
||||||
//Setup the post layout
|
//Setup the post layout
|
||||||
val picRequest = Glide.with(itemView)
|
val picRequest = Glide.with(itemView)
|
||||||
@ -128,12 +127,10 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
|
|||||||
if(!status?.media_attachments.isNullOrEmpty()) {
|
if(!status?.media_attachments.isNullOrEmpty()) {
|
||||||
setupPostPics(binding, request)
|
setupPostPics(binding, request)
|
||||||
} else {
|
} else {
|
||||||
binding.postPicture.visibility = View.GONE
|
|
||||||
binding.postPager.visibility = View.GONE
|
binding.postPager.visibility = View.GONE
|
||||||
binding.postTabs.visibility = View.GONE
|
binding.postIndicator.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//Set comment initial visibility
|
//Set comment initial visibility
|
||||||
binding.commentIn.visibility = View.GONE
|
binding.commentIn.visibility = View.GONE
|
||||||
binding.commentContainer.visibility = View.GONE
|
binding.commentContainer.visibility = View.GONE
|
||||||
@ -145,56 +142,41 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
// Standard layout
|
// Standard layout
|
||||||
binding.postPicture.visibility = View.VISIBLE
|
|
||||||
binding.postPager.visibility = View.GONE
|
|
||||||
binding.postTabs.visibility = View.GONE
|
|
||||||
|
|
||||||
|
|
||||||
if(status?.media_attachments?.size == 1) {
|
|
||||||
request.placeholder(
|
|
||||||
status?.media_attachments?.get(0).let {
|
|
||||||
it?.blurhash?.let { hash ->
|
|
||||||
BlurHashDecoder.blurHashBitmap(binding.root.resources,
|
|
||||||
hash,
|
|
||||||
it.meta?.original?.width,
|
|
||||||
it.meta?.original?.height
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
).load(status?.getPostUrl()).into(binding.postPicture)
|
|
||||||
val imgDescription = status?.media_attachments?.get(0)?.description.orEmpty().ifEmpty { binding.root.context.getString(
|
|
||||||
R.string.no_description) }
|
|
||||||
binding.postPicture.contentDescription = imgDescription
|
|
||||||
|
|
||||||
binding.postPicture.setOnLongClickListener {
|
|
||||||
Snackbar.make(it, imgDescription, Snackbar.LENGTH_SHORT).show()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if(status?.media_attachments?.size!! > 1) {
|
|
||||||
setupTabsLayout(binding, request)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status?.sensitive!!) {
|
|
||||||
status?.setupSensitiveLayout(binding)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setupTabsLayout(
|
|
||||||
binding: PostFragmentBinding,
|
|
||||||
request: RequestBuilder<Drawable>,
|
|
||||||
) {
|
|
||||||
//Only show the viewPager and tabs
|
|
||||||
binding.postPicture.visibility = View.GONE
|
|
||||||
binding.postPager.visibility = View.VISIBLE
|
binding.postPager.visibility = View.VISIBLE
|
||||||
binding.postTabs.visibility = View.VISIBLE
|
|
||||||
|
|
||||||
//Attach the given tabs to the view pager
|
//Attach the given tabs to the view pager
|
||||||
binding.postPager.adapter = AlbumViewPagerAdapter(status?.media_attachments ?: emptyList())
|
binding.postPager.adapter = AlbumViewPagerAdapter(status?.media_attachments ?: emptyList(), status?.sensitive)
|
||||||
|
|
||||||
TabLayoutMediator(binding.postTabs, binding.postPager) { tab, _ ->
|
if(status?.media_attachments?.size ?: 0 > 1) {
|
||||||
tab.icon = ContextCompat.getDrawable(binding.root.context, R.drawable.ic_dot_blue_12dp)
|
binding.postIndicator.setViewPager(binding.postPager)
|
||||||
}.attach()
|
binding.postIndicator.visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
binding.postIndicator.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status?.sensitive == true) {
|
||||||
|
setupSensitiveLayout()
|
||||||
|
} else {
|
||||||
|
// GONE is the default, but have to set it again because of how RecyclerViews work
|
||||||
|
binding.sensitiveWarning.visibility = View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun setupSensitiveLayout() {
|
||||||
|
|
||||||
|
// Set dark layout and warning message
|
||||||
|
binding.sensitiveWarning.visibility = View.VISIBLE
|
||||||
|
//binding.postPicture.colorFilter = ColorMatrixColorFilter(censorMatrix)
|
||||||
|
|
||||||
|
fun uncensorPicture(binding: PostFragmentBinding) {
|
||||||
|
binding.sensitiveWarning.visibility = View.GONE
|
||||||
|
(binding.postPager.adapter as AlbumViewPagerAdapter).uncensor()
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.sensitiveWarning.setOnClickListener {
|
||||||
|
uncensorPicture(binding)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setDescription(
|
private fun setDescription(
|
||||||
@ -459,7 +441,7 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
|
|||||||
|
|
||||||
//Activate double tap liking
|
//Activate double tap liking
|
||||||
var clicked = false
|
var clicked = false
|
||||||
binding.postPicture.setOnClickListener {
|
binding.postPager.setOnClickListener {
|
||||||
lifecycleScope.launchWhenCreated {
|
lifecycleScope.launchWhenCreated {
|
||||||
//Check that the post isn't hidden
|
//Check that the post isn't hidden
|
||||||
if(binding.sensitiveWarning.visibility == View.GONE) {
|
if(binding.sensitiveWarning.visibility == View.GONE) {
|
||||||
@ -479,7 +461,7 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
|
|||||||
clicked = true
|
clicked = true
|
||||||
|
|
||||||
//Reset clicked to false after 500ms
|
//Reset clicked to false after 500ms
|
||||||
binding.postPicture.handler.postDelayed(fun() { clicked = false }, 500)
|
binding.postPager.handler.postDelayed(fun() { clicked = false }, 500)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -696,7 +678,7 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AlbumViewPagerAdapter(private val media_attachments: List<Attachment>) :
|
private class AlbumViewPagerAdapter(private val media_attachments: List<Attachment>, private var sensitive: Boolean?) :
|
||||||
RecyclerView.Adapter<AlbumViewPagerAdapter.ViewHolder>() {
|
RecyclerView.Adapter<AlbumViewPagerAdapter.ViewHolder>() {
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
@ -708,20 +690,29 @@ class AlbumViewPagerAdapter(private val media_attachments: List<Attachment>) :
|
|||||||
|
|
||||||
override fun getItemCount() = media_attachments.size
|
override fun getItemCount() = media_attachments.size
|
||||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
Glide.with(holder.binding.root)
|
media_attachments[position].apply {
|
||||||
.asDrawable().fitCenter().placeholder(
|
val blurhashBitMap = blurhash?.let {
|
||||||
media_attachments[position].blurhash?.let {
|
|
||||||
BlurHashDecoder.blurHashBitmap(
|
BlurHashDecoder.blurHashBitmap(
|
||||||
holder.binding.root.resources,
|
holder.binding.root.resources,
|
||||||
it,
|
it,
|
||||||
media_attachments[position].meta?.original?.width,
|
meta?.original?.width,
|
||||||
media_attachments[position].meta?.original?.height)
|
meta?.original?.height
|
||||||
}
|
|
||||||
)
|
)
|
||||||
.load(media_attachments[position].url).into(holder.image)
|
}
|
||||||
|
if (sensitive == false) {
|
||||||
|
Glide.with(holder.binding.root)
|
||||||
|
.asDrawable().fitCenter()
|
||||||
|
.placeholder(blurhashBitMap)
|
||||||
|
.load(url).into(holder.image)
|
||||||
|
} else {
|
||||||
|
Glide.with(holder.binding.root)
|
||||||
|
.asDrawable().fitCenter()
|
||||||
|
.load(blurhashBitMap).into(holder.image)
|
||||||
|
}
|
||||||
|
|
||||||
val description = media_attachments[position].description
|
val description = description
|
||||||
.orEmpty().ifEmpty{ holder.binding.root.context.getString(R.string.no_description)}
|
.orEmpty()
|
||||||
|
.ifEmpty { holder.binding.root.context.getString(R.string.no_description) }
|
||||||
|
|
||||||
holder.image.setOnLongClickListener {
|
holder.image.setOnLongClickListener {
|
||||||
Snackbar.make(it, description, Snackbar.LENGTH_SHORT).show()
|
Snackbar.make(it, description, Snackbar.LENGTH_SHORT).show()
|
||||||
@ -730,6 +721,12 @@ class AlbumViewPagerAdapter(private val media_attachments: List<Attachment>) :
|
|||||||
|
|
||||||
holder.image.contentDescription = description
|
holder.image.contentDescription = description
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun uncensor(){
|
||||||
|
sensitive = false
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
class ViewHolder(val binding: AlbumImageViewBinding) : RecyclerView.ViewHolder(binding.root){
|
class ViewHolder(val binding: AlbumImageViewBinding) : RecyclerView.ViewHolder(binding.root){
|
||||||
val image: ImageView = binding.imageImageView
|
val image: ImageView = binding.imageImageView
|
||||||
|
@ -96,29 +96,6 @@ open class Status(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setupSensitiveLayout(binding: PostFragmentBinding) {
|
|
||||||
|
|
||||||
// Set dark layout and warning message
|
|
||||||
binding.sensitiveWarning.visibility = VISIBLE
|
|
||||||
val array = floatArrayOf(0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 1f, 0f)
|
|
||||||
val censorMatrix = ColorMatrix(array)
|
|
||||||
binding.postPicture.colorFilter = ColorMatrixColorFilter(censorMatrix)
|
|
||||||
|
|
||||||
fun uncensorPicture(binding: PostFragmentBinding) {
|
|
||||||
binding.sensitiveWarning.visibility = GONE
|
|
||||||
binding.postPicture.clearColorFilter()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
binding.sensitiveWarning.setOnClickListener {
|
|
||||||
uncensorPicture(binding)
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.postPicture.setOnClickListener {
|
|
||||||
uncensorPicture(binding)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun downloadImage(context: Context, url: String, view: View, share: Boolean = false) {
|
fun downloadImage(context: Context, url: String, view: View, share: Boolean = false) {
|
||||||
val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
|
val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
|
||||||
|
|
||||||
|
12
app/src/main/res/drawable/rounded_corner.xml
Normal file
12
app/src/main/res/drawable/rounded_corner.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<solid android:color="#BE505050" />
|
||||||
|
|
||||||
|
<padding
|
||||||
|
android:left="4dp"
|
||||||
|
android:right="4dp"
|
||||||
|
android:bottom="4dp"
|
||||||
|
android:top="4dp" />
|
||||||
|
|
||||||
|
<corners android:radius="5dp" />
|
||||||
|
</shape>
|
@ -8,8 +8,9 @@
|
|||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/imageImageView"
|
android:id="@+id/imageImageView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center"
|
||||||
android:adjustViewBounds="true"
|
android:adjustViewBounds="true"
|
||||||
tools:ignore="ContentDescription" />
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
|
@ -56,58 +56,59 @@
|
|||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/profilePic">
|
app:layout_constraintTop_toBottomOf="@+id/profilePic">
|
||||||
|
|
||||||
|
<com.h.pixeldroid.posts.NestedScrollableHost
|
||||||
|
android:id="@+id/postPagerHost"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
<androidx.viewpager2.widget.ViewPager2
|
<androidx.viewpager2.widget.ViewPager2
|
||||||
android:id="@+id/postPager"
|
android:id="@+id/postPager"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<com.google.android.material.tabs.TabLayout
|
|
||||||
android:id="@+id/postTabs"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/postPager"
|
|
||||||
app:tabMode="auto" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/postPicture"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="200dp"
|
android:layout_height="200dp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
tools:src="@color/browser_actions_bg_grey"
|
android:orientation="horizontal" />
|
||||||
tools:ignore="ContentDescription" />
|
|
||||||
|
</com.h.pixeldroid.posts.NestedScrollableHost>
|
||||||
|
|
||||||
|
<me.relex.circleindicator.CircleIndicator3
|
||||||
|
android:id="@+id/postIndicator"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/postPagerHost"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"/>
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/post_fragment_image_popup_menu_anchor"
|
android:id="@+id/post_fragment_image_popup_menu_anchor"
|
||||||
android:layout_width="1dp"
|
android:layout_width="1dp"
|
||||||
android:layout_height="1dp"
|
android:layout_height="1dp"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/postPicture"
|
app:layout_constraintBottom_toBottomOf="@+id/postPagerHost"
|
||||||
app:layout_constraintEnd_toEndOf="@+id/postPicture"
|
app:layout_constraintEnd_toEndOf="@+id/postPagerHost"
|
||||||
app:layout_constraintHorizontal_bias="0.1"
|
app:layout_constraintHorizontal_bias="0.1"
|
||||||
app:layout_constraintStart_toStartOf="@+id/postPicture"
|
app:layout_constraintStart_toStartOf="@+id/postPagerHost"
|
||||||
app:layout_constraintTop_toTopOf="@+id/postPicture"
|
app:layout_constraintTop_toTopOf="@+id/postPagerHost"
|
||||||
app:layout_constraintVertical_bias="0.1" />
|
app:layout_constraintVertical_bias="0.1" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/sensitiveWarning"
|
android:id="@+id/sensitiveWarning"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:adjustViewBounds="true"
|
android:adjustViewBounds="true"
|
||||||
|
android:background="@drawable/rounded_corner"
|
||||||
android:gravity="center|center_horizontal|center_vertical"
|
android:gravity="center|center_horizontal|center_vertical"
|
||||||
android:text="@string/cw_nsfw_hidden_media_n_click_to_show"
|
android:text="@string/cw_nsfw_hidden_media_n_click_to_show"
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
|
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
|
||||||
android:textColor="@color/ic_launcher_background"
|
android:textColor="@color/ic_launcher_background"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/postPicture"
|
app:layout_constraintBottom_toBottomOf="@+id/postPagerHost"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/postTabs"
|
app:layout_constraintTop_toTopOf="@+id/postPagerHost"
|
||||||
tools:src="@color/browser_actions_bg_grey" />
|
tools:src="@color/browser_actions_bg_grey" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user