Android自定义卡片切换效果

今天给大家实现一个自定义的卡片切换效果。

gallery

工程结构非常简单,就以下三个类:

一. 页面相关


        TestGalleryActivity

package com.openld.seniorui.testgallery

import android.os.Bundle
import android.os.Message
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.viewpager.widget.ViewPager
import com.openld.seniorui.R
import java.util.*

/**
 * 测试一下画廊效果
 */
class TestGalleryActivity : AppCompatActivity() {
    private val TAG = "Gallery"

    private var mCurrentIndex = 0

    private lateinit var mGallery: ViewPager

    private val mFruitList = mutableListOf<Int>()

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

        initData()

        initWidgets()

        addListeners()
    }

    private fun initData() {
        mFruitList.add(R.drawable.fruit_image1)
        mFruitList.add(R.drawable.fruit_image2)
        mFruitList.add(R.drawable.fruit_image3)
        mFruitList.add(R.drawable.fruit_image4)
        mFruitList.add(R.drawable.fruit_image5)
        mFruitList.add(R.drawable.fruit_image6)
        mFruitList.add(R.drawable.fruit_image7)
        mFruitList.add(R.drawable.fruit_image8)
        mFruitList.add(R.drawable.fruit_image9)
        mFruitList.add(R.drawable.fruit_image10)
        mFruitList.add(R.drawable.fruit_image11)
        mFruitList.add(R.drawable.fruit_image12)
        mFruitList.add(R.drawable.fruit_image13)
        mFruitList.add(R.drawable.fruit_image14)
        mFruitList.add(R.drawable.fruit_image15)
        mFruitList.add(R.drawable.fruit_image16)
        mFruitList.add(R.drawable.fruit_image17)
    }

    private fun addListeners() {
        mGallery.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
            override fun onPageScrolled(
                position: Int,
                positionOffset: Float,
                positionOffsetPixels: Int
            ) {
                Log.d(TAG, ">>> $position")
                mCurrentIndex = position
            }

            override fun onPageSelected(position: Int) {
            }

            override fun onPageScrollStateChanged(state: Int) {
            }
        })
    }

    private fun initWidgets() {
        Message.obtain()
        mGallery = findViewById(R.id.gallery)
        val adapter = GalleryAdapter(this, mFruitList)
        mGallery.offscreenPageLimit = mFruitList.size
        mGallery.adapter = adapter
        mGallery.currentItem = mFruitList.size - 1
        mGallery.setPageTransformer(false, GalleryTransformer())

        // 滑到第一个
        scrollToFirst()

        // 训话滑动轮播
        loopScroll()
    }

    /**
     * 循环滑动轮播
     */
    private fun loopScroll() {
        // 轮播
        mGallery.postDelayed({
            val timer = Timer()
            timer.schedule(object : TimerTask() {
                override fun run() {
                    if (mCurrentIndex == mFruitList.size) {
                        mCurrentIndex = 0
                    }
                    mGallery.currentItem = mCurrentIndex++
                }
            }, 0, 2000)
        }, 2200)
    }

    /**
     * 滑动到第一个
     */
    private fun scrollToFirst() {
        // 这鬼滑动速度不知道怎么控制
        mGallery.postDelayed({
            mGallery.setCurrentItem(0, true)
        }, 200)
    }
}

        页面布局activity_test_gallery.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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="match_parent"
    android:layout_height="match_parent"
    android:clipChildren="false"
    tools:context=".testgallery.TestGalleryActivity">

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/gallery"
        android:layout_width="200dp"
        android:layout_height="300dp"
        android:orientation="horizontal"
        android:overScrollMode="always"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

        页面中的图片资源自己替换下好了

二.适配器


        GalleryAdapter

package com.openld.seniorui.testgallery

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.annotation.NonNull
import androidx.appcompat.widget.AppCompatImageView
import androidx.viewpager.widget.PagerAdapter
import com.openld.seniorui.R

class GalleryAdapter(@NonNull context: Context, @NonNull fruitList: List<Int>) :
    PagerAdapter() {
    private val mContext = context
    private var mFruitList: List<Int> = fruitList

    override fun getCount(): Int {
        return mFruitList.size
    }

    override fun isViewFromObject(view: View, `object`: Any): Boolean {
        return view == `object`
    }

    override fun instantiateItem(container: ViewGroup, position: Int): Any {
        return LayoutInflater.from(mContext).inflate(R.layout.item_gallery, container, false)
            .apply {
                val imgFruit: AppCompatImageView = findViewById(R.id.img_fruit)
                imgFruit.setImageResource(mFruitList[position])
                imgFruit.setOnClickListener {
                    Toast.makeText(mContext, "点击了第${position}个图片", Toast.LENGTH_SHORT).show()
                }

                tag = "gallery_item_$position"
                container.addView(this)
            }
    }

    override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
        container.removeView(`object` as View)
    }
}

        适配器条目布局item_gallery.xml

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FCFCFC"
    android:elevation="10dp"
    app:cardCornerRadius="10dp"
    app:contentPadding="16dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent">

    <androidx.appcompat.widget.AppCompatImageView
        android:id="@+id/img_fruit"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        tools:src="@drawable/fruit_image1" />
</androidx.cardview.widget.CardView>

用到的图片资源自己换一下好了

三.转换器


        GalleryTransformer

        控制滑动时候的各种属性变化,达到自定义滑动切换时候的炫酷效果。

package com.openld.seniorui.testgallery

import android.view.View
import androidx.viewpager.widget.ViewPager

/**
 * author: lllddd
 * created on: 2022/6/10 11:14
 * description:
 */
class GalleryTransformer : ViewPager.PageTransformer {
    private val MIN_SCALE = 0.5F

    override fun transformPage(page: View, position: Float) {
        if (position < 0F) {
            page.scaleX = MIN_SCALE * position + 1.5F
            page.scaleY = MIN_SCALE * position + 1.5F
            page.alpha = MIN_SCALE * position + 1
//            page.rotationY = 30F * position
            page.rotation = 30 * position
        } else {
            page.scaleX = -MIN_SCALE * position + 1.5F
            page.scaleY = -MIN_SCALE * position + 1.5F
            page.alpha = -MIN_SCALE * position + 1
//            page.rotationY = 30F * position
            page.rotation = 30 * position
        }

        page.elevation = page.scaleX
    }
}

        这里效果的关键就是这个GalleryTransformer类,不明白原理的可以看下ViewPager.PageTransformer的相关源码或者解释。

        就是page滑到中间的时候position为0,page在左侧时position取值区间为(-1, 0),page在右侧时position取值区间为(0, 1),根据这个再结合一些诸如alpha、scaleX、scaleY、rotation等属性的设置就能实现你要的切换效果啦。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
原生JS实现卡牌翻牌效果可以通过以下步骤实现: 1. 创建一个Card对象,包含卡片的图像路径、状态(是否翻开)等属性。 2. 创建一个Card数组,用于存储所有的卡片对象。 3. 使用Array.sort()方法对卡片数组进行乱序处理,以实现随机分配卡片。 4. 将乱序后的卡片数组分配到不同的方格下,并隐藏卡片的图像。 5. 监听鼠标点击事件,并通过事件委托判断点击的单位是否为已经翻开的卡片。 6. 根据点击的卡片的id判断是否与上一张翻开的卡片的id相同,从而判断是否翻牌成功。 7. 如果翻牌成功,则保持卡片翻开状态;如果翻牌不成功,则在0.3秒后自动翻转回方格。 8. 当所有卡片都成功翻牌时,游戏胜利。 以上是实现卡牌翻牌效果的主要逻辑。你可以根据需要自行编写代码实现。\[3\] #### 引用[.reference_title] - *1* *2* [cocos2d-x 卡牌翻牌效果的实现](https://blog.csdn.net/yanghuiliu/article/details/9115833)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [原生JS记忆翻牌小游戏](https://blog.csdn.net/Y_qilin_/article/details/114292713)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值