引导页圆点指示器

2024-08-31 22:58
文章标签 指示器 引导 圆点

本文主要是介绍引导页圆点指示器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

这里写图片描述

布局代码

 <com.godinsec.privacy.guidepage.BezierViewPagerandroid:id="@+id/mViewPager"android:layout_width="fill_parent"android:layout_height="fill_parent" />...
...<com.godinsec.privacy.guidepage.BezierRoundViewandroid:id="@+id/bezRound"android:layout_marginBottom="33.333dp"android:layout_gravity="bottom|center"android:layout_width="90dp"android:layout_height="wrap_content"/>

attrs.xml

<resources><declare-styleable name="BezierRoundView"><attr name="color_bez" format="color"/><attr name="color_touch" format="color"/><attr name="color_stroke" format="color"/><attr name="time_animator" format="integer"/><attr name="round_count" format="integer"/><attr name="radius" format="dimension"/></declare-styleable>
</resources>


BezierRoundView bezRound = (BezierRoundView) findViewById(R.id.bezRound);
bezRound.attach2ViewPage(mViewPager);

BezierRoundView

package com.godinsec.privacy.guidepage;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Xfermode;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.WindowManager;public class BezierRoundView extends View implements ViewPager.OnPageChangeListener {public BezierRoundView(Context context) {this(context, null);}public BezierRoundView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public BezierRoundView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);mRadius = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getResources().getDisplayMetrics());  //默认设置15dpTypedArray array = context.getTheme().obtainStyledAttributes(attrs, R.styleable.BezierRoundView, defStyleAttr, 0);int n = array.getIndexCount();for (int i = 0; i < n; i++) {int attr = array.getIndex(i);if (attr == R.styleable.BezierRoundView_color_bez) {color_bez = array.getColor(i, color_bez);} else if (attr == R.styleable.BezierRoundView_color_touch) {color_touch = array.getColor(i, color_touch);} else if (attr == R.styleable.BezierRoundView_color_stroke) {color_stroke = array.getColor(i, color_stroke);} else if (attr == R.styleable.BezierRoundView_time_animator) {time_animator = array.getInteger(i, time_animator);} else if (attr == R.styleable.BezierRoundView_round_count) {default_round_count = array.getInteger(i, default_round_count);} else if (attr == R.styleable.BezierRoundView_radius) {mRadius = array.getDimensionPixelSize(attr, mRadius);}}array.recycle();init();}private final String TAG = "QDX";private int time_animator = 500;  //动画时间private Matrix matrix_bounceL;   //将向右弹的动画改为向左private int color_bez = 0xffffffff;private int color_touch = 0xffffffff;private int color_stroke = Color.parseColor("#393d56");private void init() {DEFAULT_HEIGHT = mRadius * 3;mBezPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mBezPaint.setColor(color_bez);//默认QQ糖的颜色为粉红色mBezPaint.setStyle(Paint.Style.FILL);mRoundStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);mRoundStrokePaint.setColor(color_stroke);mRoundStrokePaint.setStyle(Paint.Style.STROKE);mRoundStrokePaint.setStrokeWidth(2);mTouchPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mTouchPaint.setColor(color_touch);//默认触摸反馈颜色也为粉红色mTouchPaint.setStyle(Paint.Style.FILL);mTouchPaint.setXfermode(clearXfermode);mBezPath = new Path();//y轴一样p5 = new PointF(mRadius * bezFactor, mRadius);p6 = new PointF(0, mRadius);p7 = new PointF(-mRadius * bezFactor, mRadius);//y轴一样p0 = new PointF(0, -mRadius);p1 = new PointF(mRadius * bezFactor, -mRadius);p11 = new PointF(-mRadius * bezFactor, -mRadius);//x轴一样p2 = new PointF(mRadius, -mRadius * bezFactor);p3 = new PointF(mRadius, 0);p4 = new PointF(mRadius, mRadius * bezFactor);//x轴一样p8 = new PointF(-mRadius, mRadius * bezFactor);p9 = new PointF(-mRadius, 0);p10 = new PointF(-mRadius, -mRadius * bezFactor);matrix_bounceL = new Matrix();matrix_bounceL.preScale(-1, 1);}private int DEFAULT_WIDTH;private int DEFAULT_HEIGHT;private int default_round_count = 4;   //默认圆球的数量@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);if (DEFAULT_WIDTH == 0) {WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);DEFAULT_WIDTH = wm.getDefaultDisplay().getWidth();}int width = measureSize(1, DEFAULT_WIDTH, widthMeasureSpec);int height = measureSize(1, DEFAULT_HEIGHT, heightMeasureSpec);setMeasuredDimension(width, height);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);mWidth = w;mHeight = h;initCountPos();}/*** 测绘measure** @param specType    1为宽, 其他为高* @param contentSize 默认值*/private int measureSize(int specType, int contentSize, int measureSpec) {int result;//获取测量的模式和Sizeint specMode = MeasureSpec.getMode(measureSpec);int specSize = MeasureSpec.getSize(measureSpec);if (specMode == MeasureSpec.EXACTLY) {result = Math.min(contentSize, specSize);} else {result = contentSize;if (specType == 1) {// 根据传人方式计算宽result += (getPaddingLeft() + getPaddingRight());} else {// 根据传人方式计算高result += (getPaddingTop() + getPaddingBottom());}}return result;}private Paint mBezPaint;private Paint mRoundStrokePaint;private Paint mTouchPaint;private int mWidth;private int mHeight;private int mRadius;private final float bezFactor = 0.551915024494f;private Xfermode clearXfermode = new PorterDuffXfermode(PorterDuff.Mode.CLEAR);private Path mBezPath;private PointF p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11;private float rRadio = 1;  //P2,3,4 x轴倍数private float lRadio = 1;  //P8,9,10倍数private float tbRadio = 1;  //y轴缩放倍数private float boundRadio = 0.55f;  //进入另一个圆的回弹效果/*** 离开圆的阈值*/private float disL = 0.5f;/*** 最大值的阈值*/private float disM = 0.8f;/*** 到达下个圆的阈值*/private float disA = 0.9f;private float[] bezPos; //记录每一个圆心x轴的位置private float[] xPivotPos;  //根据圆心x轴+mRadius,划分成不同的区域 ,主要为了判断触摸x轴的位置private int curPos = 0;  //当前圆的位置private int nextPos = 0; //圆要到达的下一个位置private BezierViewPager mViewPage;/*** 关联ViewPager,监听scroll进行改变bezRound*/public void attach2ViewPage(BezierViewPager vPage) {vPage.addOnPageChangeListener(this);this.mViewPage = vPage;this.default_round_count = vPage.getAdapter().getCount();initCountPos();}private void initCountPos() {bezPos = new float[default_round_count];xPivotPos = new float[default_round_count];for (int i = 0; i < default_round_count; i++) {bezPos[i] = mWidth / (default_round_count + 1) * (i + 1);xPivotPos[i] = mWidth / (default_round_count + 1) * (i + 1) + mRadius;}}//展示QQ糖动画private float animatedValue;private boolean isAniming = false;@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.translate(0, mHeight / 2);mBezPath.reset();for (int i = 0; i < default_round_count; i++) {canvas.drawCircle(bezPos[i], 0, mRadius - 2, mRoundStrokePaint);   //绘制圆框}if (animatedValue == 1) {canvas.drawCircle(bezPos[nextPos], 0, mRadius, mBezPaint);return;}canvas.translate(bezPos[curPos], 0);if (0 < animatedValue && animatedValue <= disL) {rRadio = 1f + animatedValue * 2;                         //  [1,2]lRadio = 1f;tbRadio = 1f;}if (disL < animatedValue && animatedValue <= disM) {rRadio = 2 - range0Until1(disL, disM) * 0.5f;          //  [2,1.5]lRadio = 1 + range0Until1(disL, disM) * 0.5f;          // [1,1.5]tbRadio = 1 - range0Until1(disL, disM) / 3;           // [1 , 2/3]}if (disM < animatedValue && animatedValue <= disA) {rRadio = 1.5f - range0Until1(disM, disA) * 0.5f;     //  [1.5,1]lRadio = 1.5f - range0Until1(disM, disA) * (1.5f - boundRadio);      //反弹效果,进场 内弹boundRadiotbRadio = (range0Until1(disM, disA) + 2) / 3;        // [ 2/3,1]}if (disA < animatedValue && animatedValue <= 1f) {rRadio = 1;tbRadio = 1;lRadio = boundRadio + range0Until1(disA, 1) * (1 - boundRadio);     //反弹效果,饱和}if (animatedValue == 1 || animatedValue == 0) {  //防止极其粗暴的滑动rRadio = 1f;lRadio = 1f;tbRadio = 1f;}boolean isTrans = false;float transX = (nextPos - curPos) * (mWidth / (default_round_count + 1));if (disL <= animatedValue && animatedValue <= disA) {isTrans = true;transX = transX * (animatedValue - disL) / (disA - disL);}if (disA < animatedValue && animatedValue <= 1) {isTrans = true;}if (isTrans) {canvas.translate(transX, 0);}bounce2RightRound();if (!direction) {mBezPath.transform(matrix_bounceL);}canvas.drawPath(mBezPath, mBezPaint);if (isTrans) {canvas.save();}}/*** 通过 path 将向右弹射的动画绘制出来* 如果要绘制向左的动画,只要设置path的transform(matrix)即可*/private void bounce2RightRound() {mBezPath.moveTo(p0.x, p0.y * tbRadio);mBezPath.cubicTo(p1.x, p1.y * tbRadio, p2.x * rRadio, p2.y, p3.x * rRadio, p3.y);mBezPath.cubicTo(p4.x * rRadio, p4.y, p5.x, p5.y * tbRadio, p6.x, p6.y * tbRadio);mBezPath.cubicTo(p7.x, p7.y * tbRadio, p8.x * lRadio, p8.y, p9.x * lRadio, p9.y);mBezPath.cubicTo(p10.x * lRadio, p10.y, p11.x, p11.y * tbRadio, p0.x, p0.y * tbRadio);mBezPath.close();}/*** 将animatedValue值域转化为[0,1]** @param minValue 大于等于* @param maxValue 小于等于* @return 根据当前 animatedValue,返回 [0,1] 对应的数值*/private float range0Until1(float minValue, float maxValue) {return (animatedValue - minValue) / (maxValue - minValue);}private boolean direction; //方向 , true是位置向右(0->1)/*** @param position       当前cur位置,如果当前是1,手指右滑(vPage向左滑动)那就是0, 左滑至下一个位置才为2* @param positionOffset [0,1) ,到达下一个pos就置为0*/@Overridepublic void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {if (isAniming)     //如果是手动选择pos,就用animatorValue去计算 0-->3return;Log.w(TAG, "onPageScrolled positionOffset==" + positionOffset);animatedValue = positionOffset;direction = ((position + positionOffset) - curPos > 0);  //运动方向。 true为右边(手往左滑动)nextPos = direction ? curPos + 1 : curPos - 1;  //右 +1   左 -1if (!direction)   //如果是向左animatedValue = 1 - animatedValue;  //让 animatedValue 不管是左滑还是右滑,都从[0,1)开始计算if (positionOffset == 0) {curPos = position;nextPos = position;}//快速滑动的时候,positionOffset有可能不会置于0if (direction && position + positionOffset > nextPos) {  //向右,而且curPos = position;nextPos = position + 1;} else if (!direction && position + positionOffset < nextPos) {curPos = position;nextPos = position - 1;}invalidate();}@Overridepublic void onPageSelected(int position) {onPageSelected.onPageSelected(direction,position);}@Overridepublic void onPageScrollStateChanged(int state) {}OnPageSelected onPageSelected;public void setOnPageSelected(OnPageSelected onPageSelected){this.onPageSelected = onPageSelected;}public void setAnimDuration(int time) {time_animator = time;}/*** 设置圆的半径*/public void setRadius(int radius) {this.mRadius = radius;init();}/*** 设置bez 圆的数量,默认4个*/public void setRoundCount(int count) {this.default_round_count = count;initCountPos();}/*** 设置bez 圆的颜色,默认粉红色*/public void setBezRoundColor(int roundcolor) {color_bez = roundcolor;mBezPaint.setColor(roundcolor);}/*** 触摸效果颜色,默认粉红色*/public void setTouchColor(int touchColor) {color_touch = touchColor;mTouchPaint.setColor(touchColor);}/*** 圆框的颜色*/public void setStrokeColor(int strokeColor) {color_stroke = strokeColor;mRoundStrokePaint.setColor(strokeColor);}}

这篇关于引导页圆点指示器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1125235

相关文章

Android 引导图层、引导页

Android 引导图层(参考gith项目) Android 引导图层参考gith项目 简介不多说 先上图 部分代码说明 简介: 最最轻量级的新手引导图层库,支持单页,多个引导,支持设置不同的图形,支持动画等,例如:Activity 、fragment、各种对应View 皆可; 不多说 先上图: OK ;可以根据自己的需求重新定义 显示的效果;都

linux-5.6.6 内核引导

本文转自网络文章,内容均为非盈利,版权归原作者所有。 转载此文章仅为个人收藏,分享知识,如有侵权,马上删除。 原文作者:povcfe 原文地址:https://bbs.pediy.com/thread-261718.htm     本文详细讲解linux内核的加载过程,参考linux-insiders,并结合linux-5.6.6代码对原文的部分老旧内容做修改 引导 1.按

win10 gpt分区+uefi引导 卸载双系统ubuntu

1、首先暴力卸载ubuntu 在win10里面磁盘管理中找到对应的linux磁盘分区 删除卷OK 2、重启 出现下面(根据机型不同界面可能不一样 ) 3、exit 退出grub引导 进入uefi引导  选择win10引导项 (当然你要是一直按着进入bios boot的那个按键的话 也不用看第二步了 直接选择windows启动项进去 dell的话是F12) 4、进入

ViewPageIndctor,viewPage指示器效果

开发中我们很多时候遇到类似这种的效果 或者是这种三角形的该如何实现呢, 本篇介绍来源于慕课网的张鸿洋的自定义ViewPageIndctor,(视频中讲解的是三角形的那种) 我们看下项目的结构 主要的程序都已经封装在ViewPageIndctor中,我们来看下MainActivity中的调用就知道 public class MainActivity extends Fragment

简单的启动页滑动动画,下面带圆点的切换

一个简单实用的滑动页动画,开始之前我们先认识一个空间,ViewPager,他是google SDk中自带的一个类,可以用来实现屏幕之间的切换。 先上代码,一看就明了!! GlideActivity.ava import java.util.ArrayList;import android.app.Activity;import android.content.Intent

Learning Memory-guided Normality for Anomaly Detection——学习记忆引导的常态异常检测

又是一篇在自编码器框架中研究使用记忆模块的论文,可以看做19年的iccv的论文的衍生,在我的博客中对19年iccv这篇论文也做了简单介绍。韩国人写的,应该是吧,这名字听起来就像。 摘要abstract 我们解决异常检测的问题,即检测视频序列中的异常事件。基于卷积神经网络的异常检测方法通常利用代理任务(如重建输入视频帧)来学习描述正常情况的模型,而在训练时看不到异常样本,并在测试时使用重建误

基于中心引导判别学习的弱监督视频异常检测

WEAKLY SUPERVISED VIDEO ANOMALY DETECTION VIA CENTER-GUIDED DISCRIMINATIVE LEARNING 基于中心引导判别学习的弱监督视频异常检测 abstract 由于异常视频内容和时长的多样性,监控视频中的异常检测是一项具有挑战性的任务。在本文中,我们将视频异常检测看作是一个弱监督下视频片段异常分数的回归问题。因此,我们提出了

C1-2 ABB二次SDK开发——手把手教登录对应的机器人控制器(图片引导操作)登录机器人控制器和刷新机器人列表

1.完成配置后我们开始进行操作 C1-1 ABB二次SDK开发——C#Window窗体-环境配置(带ABB二次开发SDK资源包)-CSDN博客文章浏览阅读95次。3.记住路径,右键C#引用,然后导入ABB.Robotics.Controllers.PC.dll。2.安装资源文件PCABB二次开发的SDK,并打开安装路径。1.新建VSC#的windowfrom项目。4.在框架代码主界面代码中添加。

whose引导的定语从句,先行词是复数形式,从句里谓语动词用单数还是复数?

得看whose后面跟的名词,如果是复数,定语从句的谓语动词就用复数,如实单数就用单数。 比如说: we live in a house whose windows are broken. we live in a house whose door is destroyed. 先行词是复数形式, whose引导的定语从句, 请问,从句里谓语动词用单数还是复数?谢谢了先 - 雨露学习互助

ubuntu 引导修复,grub2多余选项删除

问题描述:ubuntu无法启动,进入了grub界面,修复后grub2界面选项太多,只想保留需要的。 修复引导: 借助Boot Repair这个神奇的软件,可以在软件界面中一键修复ubuntu启动项 使用方法: 1、首先你需要一张ubuntu的live CD或者自启动u盘(建议和安装的是相同版本),电脑也要连接到互联网(建议是路由器自动拨号的那种,从而无需手动联网)。既然你已经装了ubunt