如何使 ScrollView 中的项目位于屏幕中央
How to make an item in a ScrollView be positioned in the center of the screen
我在一个 HorizontalScrollView
中有三个 CardView
,我希望中间的一个位于屏幕中央(就好像用户通过滑动来找到它一样)。我如何在 XML
中或以编程方式执行此操作?
XML布局:
<HorizontalScrollView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:scrollbars="none"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/culture_toolbar">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<androidx.cardview.widget.CardView
android:id="@+id/one"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_marginEnd="10dp"
app:cardCornerRadius="12dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
android:src="@drawable/beach_bg_placeholder" />
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:id="@+id/two"
android:layout_width="300dp"
android:layout_height="300dp"
app:cardCornerRadius="12dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
android:src="@drawable/beach_bg_placeholder" />
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:id="@+id/three"
android:layout_width="300dp"
android:layout_height="300dp"
app:cardCornerRadius="12dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
android:src="@drawable/beach_bg_placeholder" />
</androidx.cardview.widget.CardView>
</LinearLayout>
</HorizontalScrollView>
这是我想要的结果:
您是否尝试过在 LinearLayout
中使用 layout_gravity
?
android:layout_gravity="center"
添加前layout_gravity:center
查看结果(蓝图视图):
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
添加后layout_gravity:center
查看结果(蓝图视图):
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center">
How do i do that in xml preferably?
AFAIK 使用 XML
只有那是不可能的
How to make an item in a ScrollView be positioned in the center of the screen
我建议您使用 carousel layout
而不是 HorizontalScrollView
你可以carousel layout
using ViewPager
and using RecyclerView
查看以下 carousel layout
的好文章
- Carousel Layout with ViewPager in Android
Android ViewPager - Show preview of page on left and right
- Making Carousel Layout in Android
- CarouselLayoutManager for RecyclerView
所以我认为您无法在 xml 中完成。
我的建议是用代码来完成。因此,在 Activity 中的 setContentView() 或 Fragment 中的 onViewCreated() 之后,您可以测量整个滚动视图的宽度,将其除以 2,如果不这样做,则使用方法 smoothScrollBy(int dx, int dy) of your horizontalScrollView, or scrollBy(int dx, int dy)让它动起来。
要获得滚动视图的宽度,您可以按照此 answer。只需确保将正确的单位传递给方法,像素、dps 等。
如果您需要转换单位,那么您可以使用 this.
我和你有同样的任务,在滚动视图中将项目居中
如果只是改变布局滚动视图我就做了
尝试将滚动视图替换为
https://github.com/yarolegovich/DiscreteScrollView
<com.yarolegovich.discretescrollview.DiscreteScrollView
android:id="@+id/picker"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:dsv_orientation="horizontal|vertical" />
如果成功请告诉我
对于此行为,您应该使用 ViewPager
或 ViewPager2
(基本上是包含 SnapHelper
的 RecyclerView
)
我将展示如何使用常规 ViewPager
所以轮播的寻呼机设置应该是这样的
pager.apply{
// Set current item to the middle page so we can fling to both
// directions left and right
currentItem = 1
// Necessary or the pager will only have one extra page to show
// make this at least however many pages you can see
offscreenPageLimit = 3
// Set margin for pages as a negative number, so a part of next and
// previous pages will be showed
// Calculate here a value you need
pageMargin = -((3f / 4f) * App.screenWidth).toInt()
}
虽然改编应该实施ViewPager.PageTransformer
class CarouselPagerAdapter : PagerAdapter(), ViewPager.PageTransformer {
...
companion object {
val NO_SCALE = 1.0f
val SMALL_SCALE_DOWN = 0.1f
val DIFF_SCALE = NO_SCALE - SMALL_SCALE_DOWN
val FULL_OPACITY = 255
val LOW_OPACITY = 5
val DIFF_OPACITY = FULL_OPACITY - LOW_OPACITY
val NO_TRANSLATION = 0f
val TRANSLATION_Y = 100f
val DIFF_TRANSLATION_Y = TRANSLATION_Y - NO_TRANSLATION
}
override fun transformPage(page: View, position: Float) {
val scalableLayout = page.item_child_wrapper
val animatableLayout = page.child_name_wrapper
var scale = NO_SCALE
var opacity = FULL_OPACITY
var translationY = NO_TRANSLATION
if (position > 0) {
scale -= position * DIFF_SCALE
opacity -= (position * DIFF_OPACITY).toInt()
translationY -= (position * DIFF_TRANSLATION_Y)
} else {
scale += position * DIFF_SCALE
opacity += (position * DIFF_OPACITY).toInt()
translationY += (position * DIFF_TRANSLATION_Y)
}
if (scale < 0) scale = 0f
if (opacity < 0) opacity = 0
if (opacity > 255) opacity = 255
scalableLayout.setScale(scale)
scalableLayout.setOpacity(opacity)
animatableLayout.setScale(scale)
animatableLayout.setTranslation(0f, translationY)
}
}
这是我的旧代码,因此应该以某种方式对其进行现代化处理,它也适用于元素的不透明度和过渡 - 但我想您会想出如何使用它。
希望对您有所帮助。
我在一个 HorizontalScrollView
中有三个 CardView
,我希望中间的一个位于屏幕中央(就好像用户通过滑动来找到它一样)。我如何在 XML
中或以编程方式执行此操作?
XML布局:
<HorizontalScrollView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:scrollbars="none"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/culture_toolbar">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<androidx.cardview.widget.CardView
android:id="@+id/one"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_marginEnd="10dp"
app:cardCornerRadius="12dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
android:src="@drawable/beach_bg_placeholder" />
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:id="@+id/two"
android:layout_width="300dp"
android:layout_height="300dp"
app:cardCornerRadius="12dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
android:src="@drawable/beach_bg_placeholder" />
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:id="@+id/three"
android:layout_width="300dp"
android:layout_height="300dp"
app:cardCornerRadius="12dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
android:src="@drawable/beach_bg_placeholder" />
</androidx.cardview.widget.CardView>
</LinearLayout>
</HorizontalScrollView>
这是我想要的结果:
您是否尝试过在 LinearLayout
中使用 layout_gravity
?
android:layout_gravity="center"
添加前layout_gravity:center
查看结果(蓝图视图):
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
添加后layout_gravity:center
查看结果(蓝图视图):
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center">
How do i do that in xml preferably?
AFAIK 使用 XML
只有那是不可能的
How to make an item in a ScrollView be positioned in the center of the screen
我建议您使用 carousel layout
而不是 HorizontalScrollView
你可以carousel layout
using ViewPager
and using RecyclerView
查看以下 carousel layout
- Carousel Layout with ViewPager in Android
Android ViewPager - Show preview of page on left and right
- Making Carousel Layout in Android
- CarouselLayoutManager for RecyclerView
所以我认为您无法在 xml 中完成。
我的建议是用代码来完成。因此,在 Activity 中的 setContentView() 或 Fragment 中的 onViewCreated() 之后,您可以测量整个滚动视图的宽度,将其除以 2,如果不这样做,则使用方法 smoothScrollBy(int dx, int dy) of your horizontalScrollView, or scrollBy(int dx, int dy)让它动起来。
要获得滚动视图的宽度,您可以按照此 answer。只需确保将正确的单位传递给方法,像素、dps 等。
如果您需要转换单位,那么您可以使用 this.
我和你有同样的任务,在滚动视图中将项目居中
如果只是改变布局滚动视图我就做了
尝试将滚动视图替换为
https://github.com/yarolegovich/DiscreteScrollView
<com.yarolegovich.discretescrollview.DiscreteScrollView
android:id="@+id/picker"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:dsv_orientation="horizontal|vertical" />
如果成功请告诉我
对于此行为,您应该使用 ViewPager
或 ViewPager2
(基本上是包含 SnapHelper
的 RecyclerView
)
我将展示如何使用常规 ViewPager
所以轮播的寻呼机设置应该是这样的
pager.apply{
// Set current item to the middle page so we can fling to both
// directions left and right
currentItem = 1
// Necessary or the pager will only have one extra page to show
// make this at least however many pages you can see
offscreenPageLimit = 3
// Set margin for pages as a negative number, so a part of next and
// previous pages will be showed
// Calculate here a value you need
pageMargin = -((3f / 4f) * App.screenWidth).toInt()
}
虽然改编应该实施ViewPager.PageTransformer
class CarouselPagerAdapter : PagerAdapter(), ViewPager.PageTransformer {
...
companion object {
val NO_SCALE = 1.0f
val SMALL_SCALE_DOWN = 0.1f
val DIFF_SCALE = NO_SCALE - SMALL_SCALE_DOWN
val FULL_OPACITY = 255
val LOW_OPACITY = 5
val DIFF_OPACITY = FULL_OPACITY - LOW_OPACITY
val NO_TRANSLATION = 0f
val TRANSLATION_Y = 100f
val DIFF_TRANSLATION_Y = TRANSLATION_Y - NO_TRANSLATION
}
override fun transformPage(page: View, position: Float) {
val scalableLayout = page.item_child_wrapper
val animatableLayout = page.child_name_wrapper
var scale = NO_SCALE
var opacity = FULL_OPACITY
var translationY = NO_TRANSLATION
if (position > 0) {
scale -= position * DIFF_SCALE
opacity -= (position * DIFF_OPACITY).toInt()
translationY -= (position * DIFF_TRANSLATION_Y)
} else {
scale += position * DIFF_SCALE
opacity += (position * DIFF_OPACITY).toInt()
translationY += (position * DIFF_TRANSLATION_Y)
}
if (scale < 0) scale = 0f
if (opacity < 0) opacity = 0
if (opacity > 255) opacity = 255
scalableLayout.setScale(scale)
scalableLayout.setOpacity(opacity)
animatableLayout.setScale(scale)
animatableLayout.setTranslation(0f, translationY)
}
}
这是我的旧代码,因此应该以某种方式对其进行现代化处理,它也适用于元素的不透明度和过渡 - 但我想您会想出如何使用它。
希望对您有所帮助。