Android中的视差效应

1 篇文章 0 订阅

前言

最近,Android 中的每个应用程序都更加重视用户体验。具有良好用户体验的应用程序将具有良好的用户评分和受欢迎程度。为了给用户提供良好的体验,UI/UX 空间中提供了许多效果。一种这样的效果是视差。让我们了解这是关于什么的,以及一个应用程序示例以了解如何使用它。

本章涵盖了:

  • 什么是视差?
  • 在 Android App 中实现视差效果

什么是视差?

视差听起来像一个数学词。是的,这项技术源自数学原理本身。这是计算机图形和网页设计中的一种技术,其中背景图像在相机中的移动速度比前景图像慢,从而在 2D 场景中产生深度错觉并增加沉浸感。视差滚动是一种非常有趣的技术,可以让你的应用程序的某些部分更加生动和个性。它不仅限于 android/web-apps。大多数游戏应用程序都使用此效果来提供对象向后移动且仅聚焦一个对象的效果。

Android 中的视差将归于材料设计滚动动画。一些设计包括带有标题图像的视差滚动效果以及选项卡。
我们将在本文章中研究相同类型的视差示例。

在 Android App 中实现视差效果

我们先新建一个项目

  • 启动一个新的 Android 项目
  • 选择空活动和下一步
  • 名称:ParallaxAndroid
  • 包名:com.mindorks.example.parallax
  • 语言:kotlin
  • 完成

让我们添加所需的依赖项。

implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0"
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'com.google.android.material:material:1.2.0-alpha06'

现在,该项目已准备就绪。

在这里,我们将创建一个应用程序来显示具有视差滚动效果的书籍列表。让我们从 XML 布局开始。首先,我们需要有一个可折叠的工具栏布局,我们可以将其添加到主活动 XML 中。折叠工具栏布局类似于 FrameLayout。无论最后添加了什么元素,这些元素都将放置在顶部。这种定位对于使视差正常工作非常重要。

让我们看看activity_main.xml 的骨架,然后再添加所需的元素代码。

<androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.google.android.material.appbar.AppBarLayout>
    <com.google.android.material.appbar.CollapsingToolbarLayout>
        <ImageView/>
        <android.appcompat.widget.Toolbar />
        <com.google.android.material.tabs.TabLayout/>
    </com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

我们的 activity_main.xml 看起来像

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    tools:context=".MainActivity">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        android:fitsSystemWindows="true">

        <include layout="@layout/toolbar"/>

        <com.google.android.material.tabs.TabLayout
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:tabGravity="fill"
            app:tabTextAppearance="@style/TextAppearance.AppCompat.Medium"
            app:tabSelectedTextColor="@android:color/black"
            app:tabBackground="@android:color/holo_orange_dark"
            app:tabTextColor="@android:color/white"
            app:tabIndicatorColor="@android:color/white"
            app:tabMode="fixed" />

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"/>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

我已经toolbar单独添加了布局并包含在此处以提高可读性。

<?xml version="1.0" encoding="UTF-8"?>
<com.google.android.material.appbar.CollapsingToolbarLayout
    android:id="@+id/collapsing_toolbar"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    app:contentScrim="@android:color/holo_orange_dark"
    app:expandedTitleMarginEnd="64dp"
    app:expandedTitleMarginStart="48dp"
    app:layout_scrollFlags="scroll|exitUntilCollapsed"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <ImageView
        android:src="@drawable/books"
        app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"
        android:layout_width="wrap_content"
        android:layout_height="160dp"
        android:scaleType="centerCrop"
        app:layout_collapseMode="parallax"
        android:minHeight="50dp" />

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:contentDescription="@string/books"
        android:layout_width="match_parent"
        app:title="@string/app_name"
        app:titleTextAppearance="@style/TextAppearance.AppCompat.Medium"
        app:titleTextColor="@android:color/white"
        android:layout_height="?attr/actionBarSize"
        app:layout_scrollFlags="scroll|enterAlways" />
</com.google.android.material.appbar.CollapsingToolbarLayout>

**注意:**在上面的布局中,我们添加了这些属性:

对于 CollapsingToolbarLayout:
app:layout_scrollFlags="scroll|exitUntilCollapsed"
对于图像视图:
app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"
app:layout_collapseMode="parallax"
对于工具栏:
app:layout_scrollFlags="scroll|enterAlways"
我们的布局现在看起来像这样

我们将不得不在我们的MainActivity. 由于我们在布局中添加了选项卡,因此我们需要一个ViewPager它才能工作。此外,我们将设置一个加载项和一个加载项的适配器。在活动中,我负责设置视图分页器和选项卡,并为视图分页器加载片段。在这里,我正在加载 3 个选项卡并加载一个片段。我已经在. Fragment Recyclerview RecyclerView

ScreenSlidePagerAdapter

class MainActivity : FragmentActivity() {

    private lateinit var mPager: ViewPager
    private lateinit var tabLayout : TabLayout

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        mPager = findViewById(R.id.viewPager)
        tabLayout = findViewById(R.id.tabs)
        tabLayout.setupWithViewPager(mPager)

        val pagerAdapter = ScreenSlidePagerAdapter(supportFragmentManager)
        mPager.adapter = pagerAdapter
    }

    override fun onBackPressed() {
        if (mPager.currentItem == 0) {
            // If the user is currently looking at the first step, allow the system to handle the
            // Back button. This calls finish() on this activity and pops the back stack.
            super.onBackPressed()
        } else {
            // Otherwise, select the previous step.
            mPager.currentItem = mPager.currentItem - 1
        }
    }

    private inner class ScreenSlidePagerAdapter(fm: FragmentManager) :
        FragmentStatePagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
        override fun getCount(): Int = 3
        override fun getItem(position: Int): Fragment = BooksFragment().newInstance()
        override fun getPageTitle(position: Int): CharSequence? {
            var title  = ""
            when(position) {
                0 -> title ="Tech"
                1 -> title = "Novels"
                2 -> title = "Motivational"
            }
            return title
        }
    }
}

创建一个BooksFragment将加载Recyclerview

class BooksFragment : Fragment() {

    fun newInstance(): BooksFragment {
        return BooksFragment()
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view : View? = inflater.inflate(R.layout.books_fragment, container, false)
        val rvBooks : RecyclerView = view!!.findViewById(R.id.rvBooksList)
        rvBooks.layoutManager = LinearLayoutManager(activity);
        val recyclerAdapter = BooksRecyclerAdapter(Util().getBooks())
        rvBooks.adapter = recyclerAdapter
        return view
    }
}

我们需要一个用于 recyclerview 的适配器来加载每个项目。创建BooksRecyclerAdapter 并扩展类RecyclerView.Adaper<ViewHolder>,如下所示。

class BooksRecyclerAdapter(private val mBooks: List<Books>) : RecyclerView.Adapter<ViewHolder>() {

    inner class ViewHolder(listItemView: View) : RecyclerView.ViewHolder(listItemView) {
        val titleTextView: TextView = itemView.findViewById(R.id.text_title)
        val authorTextView: TextView = itemView.findViewById(R.id.text_author)
        val subTitleTextView: TextView = itemView.findViewById(R.id.text_subtitle)
    }

    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int): ViewHolder {
        val context: Context = parent.context
        val inflater = LayoutInflater.from(context)
        val booksView: View = inflater.inflate(R.layout.item_books, parent, false)
        return ViewHolder(booksView)
    }

    override fun onBindViewHolder(
        viewHolder: ViewHolder,
        position: Int) {
        val titleTextView: TextView = viewHolder.titleTextView
        titleTextView.text = mBooks[position].title
        val authorTextView: TextView = viewHolder.authorTextView
        authorTextView.text = mBooks[position].author
        val subTitleTextView: TextView = viewHolder.subTitleTextView
        subTitleTextView.text = mBooks[position].subtitle
    }

    override fun getItemCount(): Int {
        return mBooks.size
    }
}

这些是向您的应用程序添加视差效果所需的主要布局和 Kotlin 文件。这个应用程序的最终输出将如下所示。

ImageView您可以通过在工具栏布局中设置滚动速度和其他属性来自定义它们。结论是,Android 支持库有许多这样的实用程序,可以帮助我们在各个方面使我们的应用程序变得更好。我们需要探索它们并利用它们来制作更好的可用应用程序。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
立体匹配是计算机视觉的一个重要问题,它的目的是通过两个或多个视角的图像,计算出场景每个点的三维空间位置。其视差计算是立体匹配的一个关键步骤。 所谓视差,是指同一点在不同视角下的像素位置之差。它是由于视点的不同而导致的,因为视点的位置不同,同一点在不同视角下的投影位置也不同。 视差计算的目标是从两个或多个视角的图像计算出场景每个点的视差值。一般来说,视差计算可以分为以下几个步骤: 1. 特征提取:首先,对左右两张图像进行特征提取,提取出与场景深度相关的特征,如边缘、纹理等。 2. 匹配代价计算:针对左图像的每个特征点,在右图像搜索与之对应的特征点,并计算它们的代价值。代价值越小,说明匹配越好。 3. 匹配代价聚合:对于左图像的每个点,将其与右图像的所有点进行匹配代价计算,并将代价值进行聚合,得到一个视差图。 4. 视差优化:由于匹配过程可能存在误匹配或者遮挡等问题,因此需要进行视差优化,以提高匹配的精度和鲁棒性。 5. 三维重建:最后,通过视差图和摄像机参数,可以计算出场景每个点的三维坐标,完成立体匹配过程。 视差计算是立体匹配的一个复杂问题,需要考虑很多因素,如特征提取、匹配代价计算、匹配代价聚合等。近年来,深度学习等新技术的出现,为视差计算带来了更好的性能和效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值