Android自定义View——仿滴滴出行十大司机评选活动说明

本文主要是介绍Android自定义View——仿滴滴出行十大司机评选活动说明,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


滴滴出行原版图                                                                           仿图

           


实现步骤


1、分析变量信息

    //圆的半径private int radius = 8;//圆之间的间距private int gap = 8;private Paint mPaint;//返回字体的高度private float textViewHeight = dp2px(55, getContext());//三角形的宽度private float triAngleWidth = 60;

    public static int dp2px(float dp, Context ctx) {float density = ctx.getResources().getDisplayMetrics().density;// 4.1->4, 4.9->4int px = (int) (dp * density + 0.5f);// 加0.5可以四舍五入return px;}
字体的高度:55dp是根据”返回“这个TextView的Padding的15dp (包括上下就等于30)和TextSize的25sp加上起来算出来的,这个高度可以用来画中间一排的圆。

三角形的宽度:以左三角形为例,图中的1、2、3都是这个宽度的值


2、初始化画笔
    public MyCardView(Context context) {super(context);init();}public MyCardView(Context context, AttributeSet attrs) {super(context, attrs);init();}public MyCardView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}private void init() {mPaint = new Paint();mPaint.setColor(Color.WHITE);mPaint.setStyle(Paint.Style.FILL);mPaint.setDither(true);}
3、绘制图形
    @Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//画上下圆int roundNum = getWidth() / (radius * 2 + gap * 2);for (int i = 1; i <= roundNum; i++) {canvas.drawCircle((gap + radius) * (2 * i - 1), 0, radius, mPaint);canvas.drawCircle((gap + radius) * (2 * i - 1), getHeight(), radius, mPaint);}//画中间的圆int roundNum2 = (int) ((getWidth() - (2 * triAngleWidth)) / (radius * 2 + gap * 2));for (int i = 1; i <= roundNum2; i++) {canvas.drawCircle((gap + radius) * (2 * i - 1) + triAngleWidth, getHeight() - textViewHeight, radius, mPaint);}//画三角形形Path path = new Path();path.moveTo(0, getHeight() - textViewHeight - triAngleWidth / 2);path.lineTo(0, getHeight() - textViewHeight + triAngleWidth / 2);path.lineTo(triAngleWidth, getHeight() - textViewHeight);path.close();canvas.drawPath(path, mPaint);//第二个三角形path.reset();path.moveTo(getWidth(), getHeight() - textViewHeight - triAngleWidth / 2);path.lineTo(getWidth(), getHeight() - textViewHeight + triAngleWidth / 2);path.lineTo(getWidth() - triAngleWidth, getHeight() - textViewHeight);path.close();canvas.drawPath(path, mPaint);}
4、布局使用
<?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"android:background="#ffffff"android:padding="60dp"><com.handsome.app2.View.Custom.MyCardViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:background="#D0C0A3"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:padding="15dp"android:text="Hensen博客有奖竞猜\n活动奖品说明"android:textColor="#7F3912"android:textSize="18sp" /></LinearLayout><!--中间的主体内容--><ScrollViewandroid:layout_weight="1"android:layout_width="match_parent"android:layout_height="match_parent"></ScrollView><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:padding="15dp"android:text="返回"android:textColor="#7F3912"android:textSize="22sp" /></LinearLayout></com.handsome.app2.View.Custom.MyCardView>
</RelativeLayout>

原理分析

1、画上下圆:可以看我上篇博客有分析,这里就不讲了,文章开头也有说明。
2、画中间圆:用原来算上下圆的个数的方法,只需要修改:整个View的宽度 — 两边三角形的宽度,再来计算个数。
3、画三角形:左三角形、先将Path移到点A,再lineTo到点B,再lineTo到点C,最后close自动从点C画到点A。同理,右三角形也如此。

这个类的源码
public class MyCardView extends LinearLayout {//圆的半径private int radius = 8;//圆之间的间距private int gap = 8;private Paint mPaint;//返回字体的高度private float textViewHeight = dp2px(55, getContext());//三角形的宽度private float triAngleWidth = 60;public MyCardView(Context context) {super(context);init();}public MyCardView(Context context, AttributeSet attrs) {super(context, attrs);init();}public MyCardView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}private void init() {mPaint = new Paint();mPaint.setColor(Color.WHITE);mPaint.setStyle(Paint.Style.FILL);mPaint.setDither(true);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//画上下圆int roundNum = getWidth() / (radius * 2 + gap * 2);for (int i = 1; i <= roundNum; i++) {canvas.drawCircle((gap + radius) * (2 * i - 1), 0, radius, mPaint);canvas.drawCircle((gap + radius) * (2 * i - 1), getHeight(), radius, mPaint);}//画中间的圆int roundNum2 = (int) ((getWidth() - (2 * triAngleWidth)) / (radius * 2 + gap * 2));for (int i = 1; i <= roundNum2; i++) {canvas.drawCircle((gap + radius) * (2 * i - 1) + triAngleWidth, getHeight() - textViewHeight, radius, mPaint);}//画三角形形Path path = new Path();path.moveTo(0, getHeight() - textViewHeight - triAngleWidth / 2);path.lineTo(0, getHeight() - textViewHeight + triAngleWidth / 2);path.lineTo(triAngleWidth, getHeight() - textViewHeight);path.close();canvas.drawPath(path, mPaint);//第二个三角形path.reset();path.moveTo(getWidth(), getHeight() - textViewHeight - triAngleWidth / 2);path.lineTo(getWidth(), getHeight() - textViewHeight + triAngleWidth / 2);path.lineTo(getWidth() - triAngleWidth, getHeight() - textViewHeight);path.close();canvas.drawPath(path, mPaint);}public static int dp2px(float dp, Context ctx) {float density = ctx.getResources().getDisplayMetrics().density;// 4.1->4, 4.9->4int px = (int) (dp * density + 0.5f);// 加0.5可以四舍五入return px;}
}






这篇关于Android自定义View——仿滴滴出行十大司机评选活动说明的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Vite 打包目录结构自定义配置小结

《Vite打包目录结构自定义配置小结》在Vite工程开发中,默认打包后的dist目录资源常集中在asset目录下,不利于资源管理,本文基于Rollup配置原理,本文就来介绍一下通过Vite配置自定义... 目录一、实现原理二、具体配置步骤1. 基础配置文件2. 配置说明(1)js 资源分离(2)非 JS 资

Android协程高级用法大全

《Android协程高级用法大全》这篇文章给大家介绍Android协程高级用法大全,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友跟随小编一起学习吧... 目录1️⃣ 协程作用域(CoroutineScope)与生命周期绑定Activity/Fragment 中手

Redis中哨兵机制和集群的区别及说明

《Redis中哨兵机制和集群的区别及说明》Redis哨兵通过主从复制实现高可用,适用于中小规模数据;集群采用分布式分片,支持动态扩展,适合大规模数据,哨兵管理简单但扩展性弱,集群性能更强但架构复杂,根... 目录一、架构设计与节点角色1. 哨兵机制(Sentinel)2. 集群(Cluster)二、数据分片

聊聊springboot中如何自定义消息转换器

《聊聊springboot中如何自定义消息转换器》SpringBoot通过HttpMessageConverter处理HTTP数据转换,支持多种媒体类型,接下来通过本文给大家介绍springboot中... 目录核心接口springboot默认提供的转换器如何自定义消息转换器Spring Boot 中的消息

Springboot项目构建时各种依赖详细介绍与依赖关系说明详解

《Springboot项目构建时各种依赖详细介绍与依赖关系说明详解》SpringBoot通过spring-boot-dependencies统一依赖版本管理,spring-boot-starter-w... 目录一、spring-boot-dependencies1.简介2. 内容概览3.核心内容结构4.

redis和redission分布式锁原理及区别说明

《redis和redission分布式锁原理及区别说明》文章对比了synchronized、乐观锁、Redis分布式锁及Redission锁的原理与区别,指出在集群环境下synchronized失效,... 目录Redis和redission分布式锁原理及区别1、有的同伴想到了synchronized关键字

MySQL 临时表创建与使用详细说明

《MySQL临时表创建与使用详细说明》MySQL临时表是存储在内存或磁盘的临时数据表,会话结束时自动销毁,适合存储中间计算结果或临时数据集,其名称以#开头(如#TempTable),本文给大家介绍M... 目录mysql 临时表详细说明1.定义2.核心特性3.创建与使用4.典型应用场景5.生命周期管理6.注

Android 缓存日志Logcat导出与分析最佳实践

《Android缓存日志Logcat导出与分析最佳实践》本文全面介绍AndroidLogcat缓存日志的导出与分析方法,涵盖按进程、缓冲区类型及日志级别过滤,自动化工具使用,常见问题解决方案和最佳实... 目录android 缓存日志(Logcat)导出与分析全攻略为什么要导出缓存日志?按需过滤导出1. 按

Python自定义异常的全面指南(入门到实践)

《Python自定义异常的全面指南(入门到实践)》想象你正在开发一个银行系统,用户转账时余额不足,如果直接抛出ValueError,调用方很难区分是金额格式错误还是余额不足,这正是Python自定义异... 目录引言:为什么需要自定义异常一、异常基础:先搞懂python的异常体系1.1 异常是什么?1.2

Java中数组与栈和堆之间的关系说明

《Java中数组与栈和堆之间的关系说明》文章讲解了Java数组的初始化方式、内存存储机制、引用传递特性及遍历、排序、拷贝技巧,强调引用数据类型方法调用时形参可能修改实参,但需注意引用指向单一对象的特性... 目录Java中数组与栈和堆的关系遍历数组接下来是一些编程小技巧总结Java中数组与栈和堆的关系关于