pageView使用(二)

本文深入探讨了Android中ViewPager组件的使用方法,包括如何通过PageAdapter实现页面切换,以及OnPageChangeListener接口的监听机制。提供了MainActivity的具体实现代码,展示了如何加载布局、设置页面标题和监听页面变化。

pageView使用(二)

注意看实现OnPageChangeListener的注释

mainActivity.java


import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.PagerTitleStrip;
import androidx.viewpager.widget.ViewPager;

import java.util.ArrayList;
import java.util.List;

import fengxing.primer.textlink.R;

public class Viewpage2Activity extends AppCompatActivity {

    private ViewPager vp_change_page_2;
    private PagerTitleStrip pts_page_title_2;//每一页标题
    private List<View> layoutList;//每一页的布局
    private List<String> titleList;//标题
    private LayoutInflater inflater = null;

    private static final String TAG ="Viewpage2Activity";
    private MyPageAdapter adapter = new MyPageAdapter();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_viewpage2);

        initView();
    }

    private void initView() {
        vp_change_page_2 = findViewById(R.id.vp_change_page_2);
        pts_page_title_2 = findViewById(R.id.pts_page_title_2);

        //加载布局
        inflater = LayoutInflater.from(Viewpage2Activity.this);
        //第一次被加载的布局对象
        View tab = inflater.inflate(R.layout.tab,null);

        layoutList = new ArrayList<View>();
        layoutList.add(tab);

        titleList = new ArrayList<String>();
        titleList.add("标题一");

        vp_change_page_2.setAdapter(adapter);
        //页面改变监听事件
        vp_change_page_2.addOnPageChangeListener(new MyOnPageChangeListener());
    }

    private class MyPageAdapter extends PagerAdapter {

        /**
         * 初始化每个页面
         * @param container
         * @param position
         * @return
         */
        @NonNull
        @Override
        public Object instantiateItem(@NonNull ViewGroup container, int position) {
            //获得页面(强转)
            ((ViewPager)container).addView(layoutList.get(position));
            return layoutList.get(position);
        }

        /**
         * 销毁页面
         * @param container
         * @param position
         * @param object
         */
        @Override
        public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
            //注释调用父类的方法,不然在滑动过程中报错
            //super.destroyItem(container, position, object);
            ((ViewPager)container).removeView(layoutList.get(position));
        }

        /**
         * 设置页面标题
         * @param position
         * @return
         */
        @Nullable
        @Override
        public CharSequence getPageTitle(int position) {
            return titleList.get(position);
        }

        /**
         * 返回当前集合的页面数量
         * @return
         */
        @Override
        public int getCount() {
            return layoutList.size();
        }

        /**
         * 判断当前对象是否是同一个对象
         * @param view
         * @param object
         * @return
         */
        @Override
        public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
            return view==object;
        }
    }

    private class MyOnPageChangeListener implements ViewPager.OnPageChangeListener {

        /**
         * 当前页面被滚动
         * @param position
         * @param positionOffset
         * @param positionOffsetPixels
         */
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            Log.d(TAG, "onPageScrolled: "+position+"  :  "+positionOffset+"  :  "+positionOffsetPixels);
            /**
             * 不合适在该方法中执行耗时操作(比如请求网络数据)
             * 为什么呢?:打印日志查看调用详情
             */
        }

        /**
         * 当前页面被选中
         * @param position
         */
        @Override
        public void onPageSelected(int position) {
            Log.d(TAG, "onPageSelected: "+position);
        }

        /**
         * 状态发生改变
         * @param state
         */
        @Override
        public void onPageScrollStateChanged(int state) {
            Log.d(TAG, "onPageScrollStateChanged: "+state);

            /**
             * 界面加载,一般在此执行
             */
            View view = inflater.inflate(R.layout.tab,null);
            layoutList.add(view);
            titleList.add("hello title");

            //刷新数据
            adapter.notifyDataSetChanged();

        }
    }
}

layout.xml

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!--添加网络数据: 图文混排   本地数据;-->

    <ProgressBar
        android:layout_marginTop="100dp"
        android:layout_gravity="center"
        android:layout_width="50dp"
        android:layout_height="50dp">
    </ProgressBar>


</LinearLayout>

<think> 我们正在讨论Android中的PageView使用指南。根据之前的对话历史,用户遇到了一个NullPointerException,但当前问题转向了PageView使用。注意,之前的引用内容可能与PageView相关,例如引用[1]提到PageIndicatorDots,引用[2]提到NestedScrollView和TabBarView,引用[3]提到轮播图组件。因此,在回答PageView时,我们可以适当结合这些内容。 PageView是Android中用于实现滑动页面的组件,通常与Fragment或View结合使用。以下是一个详细的使用指南: ### 1. **添加依赖** 在`build.gradle`中添加AndroidX支持(如果尚未添加): ```groovy dependencies { implementation 'androidx.viewpager2:viewpager2:1.0.0' } ``` ### 2. **在布局文件中添加PageView** ```xml <androidx.viewpager2.widget.ViewPager2 android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` ### 3. **创建适配器** 适配器用于提供页面内容。以下是一个使用Fragment的示例: ```kotlin class MyPagerAdapter(fragmentActivity: FragmentActivity) : FragmentStateAdapter(fragmentActivity) { override fun getItemCount(): Int = 3 // 页面总数 override fun createFragment(position: Int): Fragment { return when (position) { 0 -> FirstFragment() 1 -> SecondFragment() else -> ThirdFragment() } } } ``` ### 4. **设置适配器** 在Activity中: ```kotlin val pager: ViewPager2 = findViewById(R.id.pager) pager.adapter = MyPagerAdapter(this) ``` ### 5. **添加页面指示器(如引用[1]中的PageIndicatorDots)** ```xml <com.google.android.material.tabs.TabLayout android:id="@+id/tab_layout" android:layout_width="match_parent" android:layout_height="wrap_content" /> ``` 在Activity中关联: ```kotlin val tabLayout = findViewById<TabLayout>(R.id.tab_layout) TabLayoutMediator(tabLayout, pager) { tab, position -> tab.text = "Tab ${position + 1}" }.attach() ``` ### 6. **页面切换监听(如引用[3]中的回调)** ```kotlin pager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() { override fun onPageSelected(position: Int) { super.onPageSelected(position) // 更新指示器状态,例如引用[3]中的轮播图指示器 } }) ``` ### 7. **进阶使用** - **嵌套滚动**:如引用[2]中提到的`ExtendedNestedScrollView`,在需要嵌套滚动时调整滚动行为。 - **页面变换动画**: ```kotlin pager.setPageTransformer { page, position -> // 自定义动画效果 } ``` ### 8. **注意事项** - 使用`FragmentStateAdapter`适合大量页面(节省内存),少量页面可用`FragmentPagerAdapter`。 - 禁止在`ViewPager2`内嵌套另一个`ViewPager2`(可能导致滚动冲突)。 ### 9. **页面预加载** 默认预加载相邻页面,可通过以下方式调整: ```kotlin pager.offscreenPageLimit = 1 // 默认值,设为0可能不会预加载 ``` §§相关问题§§ 1. 如何处理ViewPager2中的嵌套滚动冲突? 2. 如何在ViewPager2中实现类似轮播图(Carousel)的无限滚动效果? 3. ViewPager2与旧版ViewPager的主要区别是什么? 4. 如何为ViewPager2的页面切换添加自定义动画? 以上指南基于Android官方文档和最佳实践[^1][^2][^3]。 </think> 以下是 Android 中 `PageView` 的详细使用指南,结合了视图分页、页面指示器和滑动交互的最佳实践: --- ### 一、基础使用 #### 1. XML 布局配置 ```xml <androidx.viewpager2.widget.ViewPager2 android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="300dp" /> <!-- 页面指示器(如引用[1]的修改方案) --> <com.google.android.material.tabs.TabLayout android:id="@+id/tabLayout" android:layout_width="match_parent" android:layout_height="wrap_content" app:tabIndicatorHeight="4dp" app:tabIndicatorColor="@color/blue"/> ``` #### 2. Adapter 实现 ```kotlin class ImagePagerAdapter : RecyclerView.Adapter<PagerViewHolder>() { private val images = listOf(R.drawable.img1, R.drawable.img2, R.drawable.img3) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PagerViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.item_page, parent, false) return PagerViewHolder(view) } override fun onBindViewHolder(holder: PagerViewHolder, position: Int) { holder.imageView.setImageResource(images[position]) } override fun getItemCount() = images.size inner class PagerViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val imageView: ImageView = itemView.findViewById(R.id.pageImage) } } ``` #### 3. 绑定与联动指示器 ```kotlin val viewPager: ViewPager2 = findViewById(R.id.viewPager) val tabLayout: TabLayout = findViewById(R.id.tabLayout) // 设置适配器 viewPager.adapter = ImagePagerAdapter() // 绑定指示器(如引用[3]的指示器实现) TabLayoutMediator(tabLayout, viewPager) { tab, position -> tab.text = "Page ${position+1}" }.attach() ``` --- ### 、进阶功能实现 #### 1. 页面切换监听 ```kotlin viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() { override fun onPageSelected(position: Int) { Toast.makeText(this@MainActivity, "当前页面: $position", Toast.LENGTH_SHORT).show() } }) ``` #### 2. 滑动动画定制(如引用[3]的轮播参数) ```kotlin viewPager.setPageTransformer { page, position -> // 实现放大效果(类似carousel_slider的enlargeCenterPage) val scale = if (position >= -1 && position <= 1) 1 - 0.2f * abs(position) else 0.8f page.scaleX = scale page.scaleY = scale } ``` #### 3. 嵌套滚动处理(参考引用[2]) ```xml <androidx.core.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout...> <!-- ViewPager2 放在可滚动容器内 --> <androidx.viewpager2.widget.ViewPager2.../> </LinearLayout> </androidx.core.widget.NestedScrollView> ``` --- ### 三、性能优化要点 1. **视图复用**: ```kotlin viewPager.offscreenPageLimit = 1 // 保留相邻页面避免重复创建 ``` 2. **Fragment 场景优化**: ```kotlin class ScreenSlideAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) { override fun createFragment(position: Int) = ScreenSlideFragment.newInstance() override fun getItemCount() = 3 } ``` 3. **禁止用户滑动**: ```kotlin viewPager.isUserInputEnabled = false // 程序控制翻页 ``` --- ### 四、常见问题解决 1. **Fragment 生命周期错乱**: ```kotlin // 在 Fragment 中使用 override fun onDestroyView() { super.onDestroyView() _binding = null // 避免视图泄漏 } ``` 2. **滚动冲突**: 实现自定义 `NestedScrollView`(参考引用[2]的 `ExtendedNestedScrollView`)并重写: ```kotlin override fun onNestedPreScroll(...) { // 自定义滚动优先级逻辑 } ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值