Android仿IOS ViewPager滑动进度条
程序员文章站
2023-12-22 22:13:58
最近做项目,碰到如下的需求:viewpager分页,如果是6页(包括6页)就用圆点,如果是6页以上就用进度条来切换。前面一种交互方法最常见,用小圆点来表示当前选中的页面,这...
最近做项目,碰到如下的需求: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
效果如下:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。