zoukankan      html  css  js  c++  java
  • 使用viewPage实现图片轮播

    概述

    图片循环播放这种效果,在许多的场合都能看到,只要一打开各大主流网站的首页几乎都有一个这样的组件,它可以很显目的提供给用户最近最火热的信息。因为它应用得如此之广泛,今天,我们就来写一下这个组件。

    前期准备

    首先,分析我们所看到的图片轮播效果,它有:
    1.若干张图片,一般为3-6张,不宜太多。
    2.一个承载图片的容器。
    3.一个线程,实现图片的自动轮播。
    4.表示当前图片位置的一个指示器,一般在图片的底部。
    以上,便是一个基本的图片轮播控件所需要具备的要素。接下来,我们来找找,安卓里都给我买提供了些什么:
    1.图片来源,很丰富。可以在本地,在网上,在项目里。归根结底,我们只要用到它们的url。因为url的变动很小,所以我们可以创建一个公共类来专门保存它们。(在此例子中是 Images.mgIds)
    2.容器。首先想到的便是imageView+fragment。通过查看API我们可以发现,一个叫做viewPageer的控件十分适合,它可以放置多张图片,并且可以自动回收那些没有显示出来的图片,十分的节省内存。
    3.Thread或Timer
    4.指示器当然是呀自己构造了,一个线性布局+对应图片数量的指示点。

    布局

    基本需要的东西已经分析完毕,接下来,我们便可以来搭载我们的布局了。
    同上面分析的一致,我们需要一个ViewPager 和一个LinearLayout 因为指示器的多少是和图片的数量有关的(动态的),因此我们需要在代码中动态的加载它,布局文件如下:
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
     
    <android.support.v4.view.ViewPager
    android:id="@+id/viewpage"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
     
    </android.support.v4.view.ViewPager>
     
    <RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom">
     
    <LinearLayout
    android:id="@+id/root"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:orientation="horizontal"></LinearLayout>
    </RelativeLayout>
    </FrameLayout>

    编码

    新建一个类,名为MyViewPager 继承你布局的根类,在这里,我们需要继承FrameLayout 并重写构造函数。这就是我们自定义view的第二种情况,组合已有的控件。

    初始化

    同在activity中的操作一样,我们需要先初始化我们布局中的控件。
    LayoutInflater.from(context).inflate(R.layout.activtity_viewpage,this);
    root = (LinearLayout) findViewById(R.id.root);
     
    viewPager= (ViewPager) findViewById(R.id.viewpage);
     
    adapter=new MyAdapter();
    viewPager.setAdapter(adapter);
    viewPager.addOnPageChangeListener(this);
    使用viewPager时,我们需要自定义一个adapter:
    @Override
    public int getCount() {
    return Images.mgIds.length;
    }
     
    @Override
    public boolean isViewFromObject(View view, Object object) {
    return object==view;
    }
     
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
    container.removeView(imageViews.get(position));
    }
     
    @Override
    public Object instantiateItem(ViewGroup container, int position) {
    container.addView(imageViews.get(position));
    return imageViews.get(position);
    }
    getCount 返回的是数量,这里的Images.mgIds 是我们的图片数据源数组(url)。destroyItem 需要移除当前imageview,而instantiateItem 需要加入imageview。因为imageview需要这么操作,因此我们用一个list来保存它们的引用。
    imageViews=new ArrayList<>();
    for (int i = 0; i< Images.mgIds.length; i++){
    ImageView img=new ImageView(context);
    img.setImageResource(Images.mgIds[i]);
    imageViews.add(img);
    }
    同样,因为指示器也需要后续使用,我们也用一个list进行保存
    points = new ArrayList<>();
    for (int i = 0; i < Images.mgIds.length; i++) {
    ImageView img = new ImageView(context);
    if (i == position) {
    img.setImageResource(R.drawable.page_indicator_focused);
    } else {
    img.setImageResource(R.drawable.page_indicator_unfocused);
    }
    root.addView(img);
    points.add(img);
    }
    此时,我们可以使用我们的控件了。但发现一个问题,那就是底部的指示器并没有动。因此,我们需实现viewPager的OnPageChangeListener接口
    /**
    * 当前展示的第position张图片
    * @param position
    */
    @Override
    public void onPageSelected(int position) {
    this.position=position;
    setImageBackGround(position);
    }

    增加 自动播放功能

     首先,创建一个timer 和timerTask,这里要先取消原先的任务,否则会报错。
    timer=new Timer();
    if (task!=null){
    task.cancel();
    }
    task=new viweTask();
    timer.schedule(task,2000,3000);
    /**
    * 自动播放任务
    */
    private class viweTask extends TimerTask{
     
    @Override
    public void run() {
    if (position == Images.mgIds.length - 1) {
    position = 0;
    } else {
    position++;
    }
    handler.sendEmptyMessage(1);
    }
    }
    我们通过hander来更新我们的图片和指示器
    private Handler handler=new Handler(){
    @Override
    public void handleMessage(Message msg) {
    super.handleMessage(msg);
    viewPager.setCurrentItem(position);
    setImageBackGround(position);
    }
    };
    我们还可以在onPageScrollStateChanged 中通过状态来判断用户是否想自己进行滑动
    /**
    *
    * @param state 1手指触摸屏幕;2 滑动;0 滑动完成
    */
    @Override
    public void onPageScrollStateChanged(int state) {
    if (state==1){
    playing=false;
    }else {
    playing=true;
    }
    }

    增加 每一项的点击事件回调

    直观的想,我们会直接覆盖诸如onclicklistener之类的方法。可是,我们用的是viewPager,每次图片进行切换时,都会销毁原来的图片,加载新的图片。因此,这个方法是没用的。我们应该在onPageSelected 中放置我们的钩子。
    在这之前,我们先定义好我们的回调接口:
    //设置回调接口
    private OnPageImageItemClick mOnPageImageItemClick;
    public interface OnPageImageItemClick{
    public void PageImageItemClick(ImageView imageItem,int position);
    }
     
    public void setOnPageImageItemClick(OnPageImageItemClick click){
    this.mOnPageImageItemClick=click;
    }
    之后,我们便可以放置好我们的接口
    final ImageView nowView=imageViews.get(position);
    nowView.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
    // Log.d(TAG, "position:" + position+" clicked!");
    mOnPageImageItemClick.PageImageItemClick(nowView,position);
    }
    });
    测试,在activity中调用
    viewPager.setOnPageImageItemClick(new MyViewPager.OnPageImageItemClick() {
    @Override
    public void PageImageItemClick(ImageView imageItem, int position) {
    Log.d("MainActivity", "position:" + position);
    }
    });
     
     
  • 相关阅读:
    通过具名 slot (插槽)来显示Dialog 的标题
    elementUI 中,table表格如何实现当某一行被点击时会触发该事件(row-click)
    switch循环
    CSS动画
    for循环
    Display
    修改页面标题前的图标
    from表单
    CSS3文字效果
    CSS颜色渐变
  • 原文地址:https://www.cnblogs.com/android-blogs/p/5724725.html
Copyright © 2011-2022 走看看