仿淘宝详情页图片滑动至最后一张时仍能滑动并跳转详情页效果

189 阅读1分钟

“我正在参加「掘金·启航计划」”

仿淘宝客户端ViewPager滑动到最后一页,再拖动的时候跳到详情的功能. 效果如下:

0ydx9-jdmrg.gif

采用的方案是在ViewPager图片的后面再加一个view,然后滑动viewpager的时候去处理下就行了。

activity布局(ViewPager2来实现图片的滑动查看 更简洁):

<?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"
    tools:context=".viewpager2.MyActivity">
    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/vp"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:layout_marginTop="50dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>
    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginTop="300dp"
        android:layout_marginRight="20dp"
        android:textColor="#ff00ff"
        android:textSize="26sp"/>

</androidx.constraintlayout.widget.ConstraintLayout>

为ViewPager2创建一个适配器:

适配器布局:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <ImageView
            android:id="@+id/iv_datinghome_photo"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="centerCrop"/>
    </RelativeLayout>
    <LinearLayout
        android:id="@+id/ll_more_datinghome_photo"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        android:layout_alignParentRight="true"
        android:gravity="center_vertical"
        android:background="#000000"
        android:visibility="gone">
        <ImageView
            android:id="@+id/iv_more_datinghome_photo"
            android:layout_width="9dp"
            android:layout_height="12dp"
            android:src="@mipmap/ic_apply_recomm"
            android:layout_marginLeft="19dp"/>
        <TextView
            android:id="@+id/tv_more_datinghome_photo"
            android:layout_width="12dp"
            android:layout_height="wrap_content"
            android:textColor="#ffffff"
            android:textSize="12sp"
            android:text="滑动查看更多"/>
    </LinearLayout>
</FrameLayout>

适配器

package com.demo.cdh.cardswipedemo.viewpager2

import android.content.Context
import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.RelativeLayout
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.demo.cdh.cardswipedemo.R
import com.demo.cdh.cardswipedemo.bean.CardBean

class MyAdapter (mContext: Context, attaches:MutableList<CardBean>): RecyclerView.Adapter<MyAdapter.ViewHolder>() {
    var mContext: Context
    var attaches:MutableList<CardBean>
    var map:MutableMap<Int,MyAdapter.ViewHolder> = mutableMapOf()

    init {
        this.mContext=mContext
        this.attaches=attaches
    }
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(LayoutInflater.from(mContext).inflate(R.layout.item_vp,parent,false))
    }

    fun changeMore(position: Int,s:String){
        map.get(position)?.moreTv?.text="${s}查看更多"
        if (s.equals("释放")){
            map.get(position)?.moreIv?.setImageResource(R.mipmap.ic_remove)
        }else{
            map.get(position)?.moreIv?.setImageResource(R.mipmap.ic_apply_recomm)
        }
    }
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        map.put(position,holder)
        if (position!=itemCount-1){
            var bean=attaches?.get(position)
            holder.iv.setImageResource(bean.cover)
            holder.moreLl.visibility= View.GONE
        }else{
            holder.moreLl.visibility= View.VISIBLE
        }
    }

    override fun getItemCount(): Int {
        val size=attaches?.size?:0
        if(size==0){
            return 0
        }
        return size+1
    }
    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
        var iv: ImageView
        var moreLl: LinearLayout
        var moreIv: ImageView
        var moreTv: TextView

        init {
            iv=itemView.findViewById(R.id.iv_datinghome_photo)
            moreLl=itemView.findViewById(R.id.ll_more_datinghome_photo)
            moreIv=itemView.findViewById(R.id.iv_more_datinghome_photo)
            moreTv=itemView.findViewById(R.id.tv_more_datinghome_photo)
        }
    }
}

在activity中为ViewPager2设置适配器:

package com.demo.cdh.cardswipedemo.viewpager2

import android.content.Intent
import android.os.Bundle
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.viewpager2.widget.ViewPager2
import com.demo.cdh.cardswipedemo.MainActivity
import com.demo.cdh.cardswipedemo.R
import com.demo.cdh.cardswipedemo.bean.CardBean

class MyActivity : AppCompatActivity() {
    var needJump=false
    var lastOffset=0f

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_my)
        val vp=findViewById<ViewPager2>(R.id.vp)
        val tv=findViewById<TextView>(R.id.tv)

        val data: MutableList<CardBean> = ArrayList()
        data.add(CardBean(R.mipmap.tu15))
        data.add(CardBean(R.mipmap.tu16))
        data.add(CardBean(R.mipmap.tu17))

        tv.text="$1/${data.size}"
        val mAdapter=MyAdapter(this,data)
        vp.adapter=mAdapter

        vp.registerOnPageChangeCallback(object :ViewPager2.OnPageChangeCallback(){
            override fun onPageScrolled(
                position: Int,
                positionOffset: Float,
                positionOffsetPixels: Int
            ) {
                super.onPageScrolled(position, positionOffset, positionOffsetPixels)
                if (position==data.size-1){
                    if (positionOffsetPixels>300&&positionOffset>lastOffset){
                        needJump=true
                        mAdapter.changeMore(vp.currentItem+1,"释放")
                    }else{
                        needJump=false
                        mAdapter.changeMore(vp.currentItem+1, "滑动")
                    }
                    lastOffset=positionOffset
                }
            }
            override fun onPageScrollStateChanged(state: Int) {
                super.onPageScrollStateChanged(state)
//                1开始滑动 2滑动结束(最后一页再往下页方向滑不会走该状态) 0什么都没做
                if (state==2&&needJump) {
                    needJump=false
                    startActivity(Intent(this@MyActivity, MainActivity::class.java))
                }
            }
            override fun onPageSelected(position: Int) {
                super.onPageSelected(position)
                var cur=position+1
                tv.text="$cur/${data.size}"
                if (position==data.size){
                    mAdapter.changeMore(vp.currentItem, "滑动")
                    vp.currentItem=position-1
                }
            }
        })

    }

}

总结

ViewPager2多加了一个view但是又不能让其选择到这个多加的view,所以需要在onPageSelected方法中判断当选择的是最后一个view时手动将选择的view只为前一个。 当按住向左拖动不松达到进入下一页的临界值后依然不松向右放回,最后松开,此时不应该跳转详情页,所以需要在onPageScrolled和onPageScrollStateChanged方法中配合处理,用positionOffset>lastOffset判断滑动后是否又放回了,state==2判断滑动是否结束了,这样跳转就合理了。