全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

Android仿IOS ViewPager滑动进度条

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

这里就不作详细的讲解,大家可以参考我以前写过的博客:
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  # ViewPager滑动进度条  # Android滑动进度条  # ViewPager进度条  # 模仿iOS版微信的滑动View效果  # iOS使用pageViewController实现多视图滑动切换  # iOS中3DTouch预览导致TableView滑动卡顿问题解决的方法  # iOS开发上下滑动UIScrollview隐藏或者显示导航栏的实例  # ios scrollview嵌套tableview同向滑动的示例  # iOS基于UIScrollView实现滑动引导页  # IOS仿今日头条滑动导航栏  # iOS滑动解锁、滑动获取验证码效果的实现代码  # iOS 页面滑动与标题切换颜色渐变的联动效果实例  # iOS自定义View实现卡片滑动  # 滑块  # 就用  # 自己的  # 都是  # 进度条  # 小圆点  # 也很  # 弹出  # 分页  # 自定义  # 不作  # 来实现  # 没到  # 最常见  # 写过  # 大家多多  # 去把  # 很清晰  # 圆点  # 我以前 


相关文章: 个人网站制作流程图片大全,个人网站如何注销?  制作电商网页,电商供应链怎么做?  独立制作一个网站多少钱,建立网站需要花多少钱?  宿州网站制作公司兴策,安徽省低保查询网站?  零基础网站服务器架设实战:轻量应用与域名解析配置指南  Avalonia如何实现跨窗口通信 Avalonia窗口间数据传递  建站上传速度慢?如何优化加速网站加载效率?  如何高效利用200m空间完成建站?  网站广告牌制作方法,街上的广告牌,横幅,用PS还是其他软件做的?  如何获取PHP WAP自助建站系统源码?  网站网页制作电话怎么打,怎样安装和使用钉钉软件免费打电话?  c++23 std::expected怎么用 c++优雅处理函数错误返回【详解】  网站制作新手教程,新手建设一个网站需要注意些什么?  Python lxml的etree和ElementTree有什么区别  网站企业制作流程,用什么语言做企业网站比较好?  高性能网站服务器部署指南:稳定运行与安全配置优化方案  建站OpenVZ教程与优化策略:配置指南与性能提升  建站之星如何实现五合一智能建站与营销推广?  深圳网站制作设计招聘,关于服装设计的流行趋势,哪里的资料比较全面?  如何在香港服务器上快速搭建免备案网站?  如何用虚拟主机快速搭建网站?详细步骤解析  建站之星上传入口如何快速找到?  建站之星后台管理:高效配置与模板优化提升用户体验  岳西云建站教程与模板下载_一站式快速建站系统操作指南  如何通过山东自助建站平台快速注册域名?  网站制作公司哪里好做,成都网站制作公司哪家做得比较好,更正规?  自助网站制作软件,个人如何自助建网站?  小型网站制作HTML,*游戏网站怎么搭建?  手机网站制作平台,手机靓号代理商怎么制作属于自己的手机靓号网站?  怀化网站制作公司,怀化新生儿上户网上办理流程?  建站之星安装提示数据库无法连接如何解决?  想学网站制作怎么学,建立一个网站要花费多少?  如何在万网ECS上快速搭建专属网站?  金*站制作公司有哪些,金华教育集团官网?  制作证书网站有哪些,全国城建培训中心证书查询官网?  如何在Golang中使用replace替换模块_指定本地或远程路径  兔展官网 在线制作,怎样制作微信请帖?  高防服务器租用首荐平台,企业级优惠套餐快速部署  如何在Golang中处理模块冲突_解决依赖版本不兼容问题  如何在Windows服务器上快速搭建网站?  公司网站制作需要多少钱,找人做公司网站需要多少钱?  javascript中的try catch异常捕获机制用法分析  企业网站制作费用多少,企业网站空间一般需要多大,费用是多少?  如何在阿里云虚拟主机上快速搭建个人网站?  青岛网站建设如何选择本地服务器?  如何在阿里云虚拟机上搭建网站?步骤解析与避坑指南  建站之星免费模板:自助建站系统与智能响应式一键生成  整人网站在线制作软件,整蛊网站退不出去必须要打我是白痴才能出去?  定制建站是什么?如何实现个性化需求?  盘锦网站制作公司,盘锦大洼有多少5G网站? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。