欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android仿IOS ViewPager滑动进度条

程序员文章站 2024-02-20 11:12:46
最近做项目,碰到如下的需求:viewpager分页,如果是6页(包括6页)就用圆点,如果是6页以上就用进度条来切换。前面一种交互方法最常见,用小圆点来表示当前选中的页面,这...

最近做项目,碰到如下的需求:viewpager分页,如果是6页(包括6页)就用圆点,如果是6页以上就用进度条来切换。前面一种交互方法最常见,用小圆点来表示当前选中的页面,这些小圆点称为导航点,很多app都是这种实现方式。当用户第一次安装或升级应用时,都会利用导航页面告诉用户当前版本的主要亮点,一般情况下当行页面有三部分组成,背景图片,导航文字和滑动的原点,即下面的效果:

Android仿IOS ViewPager滑动进度条

这里就不作详细的讲解,大家可以参考我以前写过的博客:
viewpager实现图片轮翻效果
今天来实现viewpager进度条切换,主要逻辑如下:
mainactivity.java

package com.jackie.slidebarviewdemo.activity; 
 
import android.os.bundle; 
import android.support.v7.app.appcompatactivity; 
import android.widget.textview; 
 
import com.jackie.slidebarviewdemo.r; 
import com.jackie.slidebarviewdemo.widget.slidebarview; 
 
public class mainactivity extends appcompatactivity { 
  private slidebarview mslidebarview; 
  private textview mtextview; 
 
  @override 
  protected void oncreate(bundle savedinstancestate) { 
    super.oncreate(savedinstancestate); 
    setcontentview(r.layout.activity_main); 
 
    mslidebarview = (slidebarview) findviewbyid(r.id.slide_bar); 
    mtextview = (textview) findviewbyid(r.id.text_view); 
 
    mslidebarview.settotalpage(80); 
    mslidebarview.setonslidechangelistener(new slidebarview.onslidechangelistener() { 
      @override 
      public void onslidechange(int page) { 
        mtextview.settext("当前是第" + page + "页"); 
      } 
    }); 
  } 
} 

slidebarview.java

package com.jackie.slidebarviewdemo.widget; 
 
import android.content.context; 
import android.util.attributeset; 
import android.view.layoutinflater; 
import android.view.motionevent; 
import android.view.view; 
import android.widget.linearlayout; 
import android.widget.popupwindow; 
import android.widget.relativelayout; 
import android.widget.textview; 
 
import com.jackie.slidebarviewdemo.r; 
import com.jackie.slidebarviewdemo.utils.convertutils; 
 
/** 
 * created by jackie on 2017/1/17. 
 */ 
 
public class slidebarview extends relativelayout { 
  private layoutinflater minflater; 
 
  private relativelayout mslidebarview; 
  private view mslidebarblock; 
 
  private popupwindow mpopupwindow; 
  private textview mpopuptext; 
 
  private int mdp40; 
 
  private string mbound = "no"; // no表示没到边界,left为到左边界了,right表示到右边界了 
 
  public interface onslidechangelistener { 
    void onslidechange(int page); 
  } 
 
  private onslidechangelistener monslidechangelistener; 
  public void setonslidechangelistener(onslidechangelistener onslidechangelistener) { 
    this.monslidechangelistener = onslidechangelistener; 
  } 
 
  public slidebarview(context context) { 
    this(context, null); 
  } 
 
  public slidebarview(context context, attributeset attrs) { 
    this(context, attrs, 0); 
  } 
 
  public slidebarview(context context, attributeset attrs, int defstyleattr) { 
    super(context, attrs, defstyleattr); 
 
    init(context); 
    initevent(); 
  } 
 
  private void init(context context) { 
    minflater = layoutinflater.from(context); 
    view slidebar = minflater.inflate(r.layout.slide_bar, null); 
    layoutparams params = new layoutparams(layoutparams.match_parent, layoutparams.match_parent); 
    addview(slidebar, params); 
 
    mslidebarview = (relativelayout) slidebar.findviewbyid(r.id.slide_bar_view); 
    mslidebarblock = slidebar.findviewbyid(r.id.slide_bar_block); 
 
    mdp40 = convertutils.dip2px(context, 40); 
  } 
 
  private void initevent() { 
    mslidebarview.setontouchlistener(new ontouchlistener() { 
      int currentx = 0; 
      int startx = 0; 
 
      @override 
      public boolean ontouch(view v, motionevent event) { 
        switch (event.getaction()) { 
          case motionevent.action_down: 
            currentx = (int) event.getx(); 
            startx = (int) event.getx(); 
 
            // 设置滑块的滑动, 手指第一次点下去把滑块放到手指上 
            int downleft = currentx - mslidebarblock.getmeasuredwidth() / 2; 
            int downtop = mslidebarblock.gettop(); 
            int downright = downleft + mslidebarblock.getwidth(); 
            int downbottom = mslidebarblock.getbottom(); 
 
            //边界检测 
            if (downleft < 0) { 
              downleft = 0; 
              downright = mslidebarblock.getmeasuredwidth(); 
            } else if (downright > mslidebarview.getmeasuredwidth()) { 
              downleft = mslidebarview.getmeasuredwidth() - mslidebarblock.getmeasuredwidth(); 
              downright = mslidebarview.getmeasuredwidth(); 
            } 
 
            mslidebarblock.layout(downleft, downtop, downright, downbottom); 
            break; 
          case motionevent.action_move: 
            currentx = (int) event.getx(); 
            int currentpage = currentx * mtotalpage / mslidebarview.getmeasuredwidth(); 
            if (currentpage < 0) { 
              currentpage = 0; 
            } else if (currentpage > mtotalpage) { 
              currentpage = mtotalpage; 
            } 
 
            // 设置滑块的滑动 
            int moveleft = currentx - mslidebarblock.getmeasuredwidth() / 2; 
            int movetop = mslidebarblock.gettop(); 
            int moveright = moveleft + mslidebarblock.getmeasuredwidth(); 
            int movebottom = mslidebarblock.getbottom(); 
 
            //边界处理 
            if (moveleft < 0) { 
              mbound = "left"; 
 
              moveleft = 0; 
              moveright = mslidebarblock.getmeasuredwidth(); 
            } else if (moveright >= mslidebarview.getmeasuredwidth()) { 
              mbound = "right"; 
 
              moveleft = mslidebarview.getmeasuredwidth() - mslidebarblock.getmeasuredwidth(); 
              moveright = mslidebarview.getmeasuredwidth(); 
            } else { 
              mbound = "no"; 
            } 
 
            mslidebarblock.layout(moveleft, movetop, moveright, movebottom); 
            startx = currentx; 
 
            //设置popupwindow的弹出位置 
            if (monslidechangelistener != null) { 
              if (currentpage == mtotalpage) { 
                //防止viewpager越界 
                currentpage = mtotalpage - 1; 
              } 
 
              monslidechangelistener.onslidechange(currentpage); 
 
              if (mpopupwindow != null) { 
                mpopuptext.settext(currentpage + ""); 
 
                //设置popupwindow的滑动 
                if (!mpopupwindow.isshowing()) { 
                  int[] location = new int[2]; 
                  mslidebarview.getlocationinwindow(location); 
                  mpopupwindow.showasdropdown(mslidebarview, currentx, location[1] - mdp40); 
                } else { 
                  if ("no".equals(mbound)) { 
                    int[] location = new int[2] ; 
                    mslidebarview.getlocationinwindow(location); 
                    mpopupwindow.update(currentx, location[1] - mdp40, mpopupwindow.getwidth(), mpopupwindow.getheight(), true); 
                  } 
                } 
              } 
            } 
            break; 
          case motionevent.action_up: 
            currentx = 0; 
            startx = 0; 
            mpopupwindow.dismiss(); 
            break; 
        } 
 
        return true; 
      } 
    }); 
 
    // 初始化popupwindow 
    view contentview = minflater.inflate(r.layout.popup_window, null); 
    mpopuptext = (textview) contentview.findviewbyid(r.id.popup_text); 
    mpopupwindow = new popupwindow(linearlayout.layoutparams.wrap_content, linearlayout.layoutparams.wrap_content); 
    mpopupwindow.setcontentview(contentview); 
    mpopupwindow.setoutsidetouchable(true); 
    mpopupwindow.setbackgrounddrawable(getresources().getdrawable(r.mipmap.popup_window_bg)); 
    mpopupwindow.setanimationstyle(0); 
  } 
 
  int mtotalpage = 0; 
  public void settotalpage(int totalpage) { 
    this.mtotalpage = totalpage; 
  } 
} 

相关的单位转化工具,大家可以拷贝到自己的项目中直接使用。
convertutils.java

package com.jackie.slidebarviewdemo.utils; 
 
import android.content.context; 
 
public class convertutils { 
  public static int dip2px(context context, float dpvalue) { 
    final float scale = context.getresources().getdisplaymetrics().density; 
    return (int) (dpvalue * scale + 0.5f); 
  } 
 
  public static int px2dip(context context, float pxvalue) { 
    final float scale = context.getresources().getdisplaymetrics().density; 
    return (int) (pxvalue / scale + 0.5f); 
  } 
   
  public static int px2sp(context context, float pxvalue) { 
    final float fontscale = context.getresources().getdisplaymetrics().scaleddensity;  
    return (int) (pxvalue / fontscale + 0.5f);  
  }  
   
  public static int sp2px(context context, float spvalue) { 
    final float fontscale = context.getresources().getdisplaymetrics().scaleddensity;  
    return (int) (spvalue * fontscale + 0.5f);  
  } 
} 

自定义组合控件,然后实现相关的手势,思路很清晰,代码也很详细,这里就直接贴代码了。
activity_main.xml

<?xml version="1.0" encoding="utf-8"?> 
<relativelayout 
  xmlns:android="http://schemas.android.com/apk/res/android" 
  android:layout_width="match_parent" 
  android:layout_height="match_parent"> 
 
  <linearlayout 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:layout_centerinparent="true" 
    android:orientation="vertical"> 
 
    <com.jackie.slidebarviewdemo.widget.slidebarview 
      android:id="@+id/slide_bar" 
      android:layout_width="match_parent" 
      android:layout_height="50dp" 
      android:layout_marginleft="20dp" 
      android:layout_marginright="20dp"/> 
 
    <textview 
      android:id="@+id/text_view" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_gravity="center_horizontal" 
      android:layout_margintop="20dp" 
      android:textcolor="#000" 
      android:textsize="20dp" 
      android:text="当前是第0页"/> 
  </linearlayout> 
</relativelayout> 

activity_main.xml

<?xml version="1.0" encoding="utf-8"?> 
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" 
  android:layout_width="match_parent" 
  android:layout_height="match_parent"> 
 
  <relativelayout 
    android:id="@+id/slide_bar_view" 
    android:layout_width="match_parent" 
    android:layout_height="50dp"> 
 
    <view 
      android:layout_width="match_parent" 
      android:layout_height="5dp" 
      android:layout_centerinparent="true" 
      android:background="@drawable/shape_slide_bar_bg"/> 
 
    <view 
      android:id="@+id/slide_bar_block" 
      android:layout_width="20dp" 
      android:layout_height="14dp" 
      android:background="#b9b9b9" 
      android:layout_centervertical="true" /> 
  </relativelayout> 
</relativelayout> 

popup_window.xml

<?xml version="1.0" encoding="utf-8"?> 
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" 
  android:layout_width="match_parent" 
  android:layout_height="match_parent"> 
  <relativelayout 
    android:layout_width="30dp" 
    android:layout_height="30dp"> 
    <textview 
      android:id="@+id/popup_text" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:textcolor="#fff" 
      android:textsize="16dp" 
      android:gravity="center" 
      android:layout_centerinparent="true" /> 
  </relativelayout> 
</relativelayout> 

附上相关的资源文件:
shape_slide_bar_bg.xml

<?xml version="1.0" encoding="utf-8"?> 
<shape xmlns:android="http://schemas.android.com/apk/res/android" 
  android:shape="rectangle"> 
  <solid android:color="#dcdcdc" /> 
  <corners android:radius="1dp"/> 
</shape> 

popup_window_bg.9.png

Android仿IOS ViewPager滑动进度条

效果如下:

Android仿IOS ViewPager滑动进度条

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。