import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.view.View;
import com.example.googleplay.utils.UIUtils;
public class IndicatorView extends View {
private static final int POSITION_NONE = -1;
private Drawable mDrbIndicator;
private int mCount;
private int mSelection;
private int mInterval;
public IndicatorView(Context context) {
super(context);
init();
}
/** 初始化 */
private void init() {
mSelection = POSITION_NONE;
}
/** 设置数目 */
public void setCount(int count) {
count = count > 0 ? count : 0;
if (count != mCount) {
mCount = count;
requestLayoutInner();
requestInvalidate();
}
}
/** 设置选中项 */
public void setSelection(int selection) {
if (selection != mSelection) {
mSelection = selection;
requestInvalidate();
}
}
/** 设置选中项的图片 */
public void setIndicatorDrawable(Drawable drawable) {
mDrbIndicator = drawable;
requestLayoutInner();
requestInvalidate();
}
/** 设置item之间间隔 */
public void setInterval(int interval) {
if (interval != mInterval) {
mInterval = interval;
requestLayoutInner();
requestInvalidate();
}
}
/**
* invalidate:View本身调用迫使view重画。
*/
private void requestInvalidate() {
if (UIUtils.isRunInMainThread()) {
invalidate();
} else {
postInvalidate();
}
}
/**
* requestLayout:当view确定自身已经不再适合现有的区域时, 该view本身调用这个方法要求parent
* view重新调用他的onMeasure onLayout来对重新设置自己位置。
* 特别的当view的layoutparameter发生改变,并且它的值还没能应用到view上,这时候适合调用这个方法。
*/
private void requestLayoutInner() {
UIUtils.runInMainThread(new Runnable() {
@Override
public void run() {
requestLayout();
}
});
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width;
int height;
// 而是将模式和尺寸组合在一起的数值
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
// 计算高度
/*
* MeasureSpec.EXACTLY是精确尺寸,当我们将控件的
* layout_width或layout_height指定为具体数值时如andorid:layout_width="50dip",
* 或者为FILL_PARENT是,都是控件大小已经确定的情况,都是精确尺寸。
*/
if (widthMode == MeasureSpec.EXACTLY) {// 如果是精确的,就采用精确值
width = widthSize;
} else {// 否则就采用图片的宽度 获取资源文件中图片的大小,最简单的最直接的方法
int indicatorW = mDrbIndicator == null ? 0 : mDrbIndicator.getIntrinsicWidth();
int expectedW = indicatorW * mCount + mInterval * (mCount - 1) + getPaddingLeft()
+ getPaddingRight();
if (widthMode == MeasureSpec.AT_MOST) {
/**
* MeasureSpec.AT_MOST是最大尺寸,当控件的layout_width或layout_height指定为
* WRAP_CONTENT时,控件大小一般随着控件的子空间或内容进行变化,此时控件尺寸只要不超过
* 父控件允许的最大尺寸即可。因此,此时的mode是AT_MOST,size给出了父控件允许的最大尺寸。
*/
width = Math.min(expectedW, widthSize);
} else {
width = expectedW;
}
}
// 计算高度
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
} else {// 否则就采用图片的高度
int indicatorH = mDrbIndicator == null ? 0 : mDrbIndicator.getIntrinsicHeight();
int expectedH = indicatorH + getPaddingTop() + getPaddingBottom();
if (expectedH == MeasureSpec.AT_MOST) {
height = Math.min(expectedH, heightSize);
} else {
height = expectedH;
}
}
// 继承View,实现自己想要的组件,那么需要使用到setMeasuredDimension这个方法,这个方法决定了当前View的大小
setMeasuredDimension(width, height);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mDrbIndicator == null || mCount == 0) {
return;
}
int w = mDrbIndicator.getIntrinsicWidth();
int h = mDrbIndicator.getIntrinsicHeight();
int horizontalSideSpacing = (getWidth() - getPaddingLeft() - w * mCount - mInterval
* (mCount - 1)) / 2;
int verticalSideSpacing = (getHeight() - getPaddingTop() - getPaddingBottom() - h) / 2;
int l = getPaddingLeft() + horizontalSideSpacing;
int t = getPaddingTop() + verticalSideSpacing;
int rEdge = getRight() - getPaddingRight();
int bEdge = getBottom() - getPaddingBottom();
// 计算出间隙和范围,然后画图片,实际画的是同一张图片,只是改变图片的bounds
for (int i = 0; i < mCount; i++) {
mDrbIndicator.setBounds(l, t, Math.min(1 + w, rEdge), Math.min(t + h, bEdge));
if (i == mSelection) {
mDrbIndicator.setState(new int[] {
android.R.attr.state_selected
});
} else {
mDrbIndicator.setState(null);
}
mDrbIndicator.draw(canvas);
l += w + mInterval;
}
}
}相关推荐
HBuilderX实战:快速将网站打包成原生体验APP的完整指南
在移动开发领域,跨平台技术始终是平衡开发效率与应用性能的关键。其核心原理在于通过统一的代码库,利用中间层桥接技术,调用不同操作系统的原生能力,最终编译生成多端应用。这种方案的技术价值在于大幅降低了开发成本与维护复杂度,尤其适合需要快速验证或拥有成熟Web产品的团队。典型的应用场景包括内容展示、企业工具、电商及信息类应用。本文聚焦于使用HBuilderX与uni-app生态,将现有网站快速转化为功能完备的APP。通过其提供的增强型WebView与JS Bridge,开发者能便捷地调用摄像头、地理位置等原生模块
项目实战(应用市场)----FragmentFactory
import android.support.v4.app.Fragment; import java.util.HashMap; import java.util.Map; /** * Created by zlr on 2014/7/19. */ public class FragmentFactory { public static final int TAB_HOME = 0;
Unibest跨端开发实践:基于Vue3+Vite+TS的工程化方案详解
跨端开发是前端领域的高频需求,核心目标是一套代码同时运行于小程序、App和H5。其原理基于uni-app这类框架将Vue语法编译为多端可执行代码,而Vue3、Vite和TypeScript的组合则提供了更现代的响应式机制、极速构建与类型安全保障。Unibest正是构建在这一技术栈之上的上层工程化框架,它整合了请求封装、Pinia状态管理、标准目录结构等最佳实践,有效解决了原生uni-app在工程化层面的不足,显著降低多端平台差异带来的维护成本。无论是启动新项目、升级存量uni-app应用,还是规范多人协作流
Android实战进阶 - 通过Scheme和App Link响应外部调用
介绍了Android开发中实现外部调起App的两种主要方式:Deep Link和App Link,并分享了项目实战方案
Android开发实战:基于Eclipse的完整项目构建与核心技能解析
Android应用开发作为移动生态的基石,其核心在于理解四大组件(Activity、Service、BroadcastReceiver、ContentProvider)的协作机制与项目架构设计。从原理层面看,Android系统通过组件化模型管理应用生命周期,而开发者需掌握UI布局、事件处理、数据持久化及网络通信等关键技术模块。这些技能的价值在于能够构建稳定、高效且可维护的移动应用,满足从个人工具到商业平台等多种应用场景的需求。本文以经典的Eclipse开发环境为切入点,通过一个完整的“博学谷”项目实战,系统
仿小米应用市场APK开发实战项目
在Android应用开发中,界面交互的丰富性与性能表现往往取决于对核心UI组件的掌握程度。随着用户对视觉体验和操作流畅度的要求不断提升,标准控件已难以满足复杂业务场景的需求。因此,深入理解自定义View的底层机制,并掌握RecyclerView等高级列表组件的优化策略,成为构建高性能、可维护性强的应用的关键所在。本章将系统性地剖析自定义View的技术实现路径,从绘制流程到底层生命周期管理,再到属性解析与实际效果落地;
用 uni-app x 重构我们的 App:一套代码跑通 iOS、Android、鸿蒙!人力成本直降 60%
摘要: uni-app x通过Vue 3 + TypeScript实现iOS、Android、鸿蒙NEXT三端原生开发,大幅降低多端适配成本。其核心优势包括:编译时生成各平台原生代码(Swift/Kotlin/ArkTS),性能接近手写原生;支持鸿蒙NEXT原生上架;开发效率提升3倍,包体积缩减40%。已有携程、美图等企业落地案例,特别适合中小团队快速覆盖多端生态。开发者可通过HBuilderX一键生成三端应用,抢占鸿蒙生态红利。(150字)
【物联网原理与应用】实验三:RFID低频卡实验——门禁系统
【物联网原理与应用】实验三:RFID低频卡实验——门禁系统
智能手表App开发技术选型实战指南:RN、Flutter与原生深度对比
智能手表App开发本质是受硬件资源、系统沙盒和分发机制三重约束的嵌入式工程实践。其核心原理在于平衡渲染一致性、传感器直控能力与平台合规性——React Native擅长高频健康数据同步但受限于动态加载禁令;Flutter提供像素级UI控制却需手动调优GPU内存与ABI兼容;Kotlin/Swift则能直接对接HAL层与HealthKit等系统API,保障毫秒级响应与审核通过。技术价值体现在降低售后投诉率、提升表盘帧率稳定性及满足App Store/HarmonyOS上架要求。典型应用场景包括苹果Watch内
【项目实战】基于STM32单片机的智能小车设计(有代码)
【1】背景意义 近些年随着国民生活水平的提升,以小车为载体的轮式机器人进入了我们的生活,尤其是在一些布线复杂困难的安全生活区和需要监控的施工作业场合都必须依赖轮式机器人的视频监控技术。因此,基于嵌入式技术的无线通信视频监控轮式机器人应运而生。由于它们与人类工作相比具有成本低廉、安全稳定的优点,目前已经在许多危险作业以及工业场合得到了广泛应用而且轮式机器人不需要像人那样采取过多的保护措施,因此轮式机...
【实战指南】EC-Engineer中ESI配置与PDO Mapping全流程解析
本文详细解析了EC-Engineer中ESI配置与PDO Mapping的全流程操作,包括环境准备、ESI文件导入技巧、在线配置细节及故障处理。特别强调了WinPcap驱动的兼容性问题和PDO Mapping的最佳实践,帮助工程师高效完成EtherCAT总线配置,适用于工业自动化领域的伺服控制与运动协同场景。
app前后台交互php_现在学 PHP 没有发展?看到这个后台框架你还会这么想吗
最近在开发者群体中,「学 PHP 还有用吗」的讨论越来越多,在各种技术论坛上,曾经「PHP 是世界上最好的语言」的呼声似乎也没有以前那么强烈的。实际上,PHP 仍然在被大范围的使用,尤其是 Web 后端领域,PHP 的地位依然没有下滑。在 Gitee 上也有不少优秀的 PHP 开发者,今天就为大家推荐的是一款基于 ThinkPHP6 底层的极简极速后台开发框架:Kplphp,希望给使用 PHP 的...
嵌入式环境下XML配置文件解析实践
在资源受限的嵌入式环境中,如何轻量级地解析XML配置文件成为关键。通过简化语法结构与优化内存使用,实现快速读取和解析配置文件,提升系统启动效率与稳定性。
uni-app App升级踩坑实录:从5+原生弹窗到Vue组件化改造的完整心路
本文详细记录了uni-app应用升级方案从5+原生弹窗到Vue组件化改造的全过程。通过分析原生方案的技术债务,提出分层设计与服务封装策略,实现版本检测、弹窗组件和平台适配的模块化。重点解决了Android平台特殊权限处理和Vue弹窗组件的API设计问题,最终显著提升维护效率和用户体验。
从仿真到真机:如何将XTDrone的VINS-Fusion+RTABMap建图方案部署到真实无人机上?
本文详细介绍了如何将XTDrone的VINS-Fusion+RTABMap建图方案从仿真环境迁移到真实无人机上。内容涵盖硬件选型、传感器配置、VINS-Fusion调优、RTABMap性能优化以及系统集成等关键步骤,特别针对三维稠密重建在真实环境中的挑战提供了实用解决方案。
OGG工具实现MySQL同步到Oracle数据库
OGG工具实现MySQL同步数据到Oracle
东风汽车集团App开发岗面试全解析:从技术栈到车联网实战
在移动开发领域,从互联网应用转向车联网场景,需要理解的不只是界面与接口,更是软硬协同的完整链路。Android开发作为车主服务App的基础,其Kotlin/Java技术栈、自定义View、性能优化等能力尤为重要;而车联网的核心则在于云端与车载终端的消息交互机制。通过Android Studio构建贴近业务的车控Demo,是快速提升实战能力的有效路径。这类岗位不仅要求开发者具备扎实的移动端功底,还需掌握MQTT协议、T-Box通信、蓝牙钥匙等车联网技术,以应对远程控制、数据安全与合规审查等复杂场景。本文围绕东
《唤醒你的AI同事:WorkBuddy从零上手》000:介绍及目录
《唤醒你的AI同事:WorkBuddy从零上手》全书导览与总目录:000–043 共 44 篇,覆盖从环境搭建、对话基础到资料库、行业助手与多模态生成的入门实战。含完整篇目速查与编号直达,建议关注收藏。
Android 实战 版本更新(okhttp3、service、notification)
转发请注明出处:http://www.jianshu.com/p/b669940c9f3e 前言 整理功能,把这块拿出来单独做个demo,好和大家分享交流一下。 版本更新这个功能一般 app 都有实现,而用户获取新版本一般来源有两种: 一种是各种应用市场的新版本提醒 一种是打开app时拉取版本信息 (还要一种推送形式,热修复或打补丁包时用得多点) 这两区别就在于,市场的不能强制更新、不够及时、...
TPAMI 2024 | 面向大型城市场景的快速建筑实例代理重建
大规模城市场景(特别是建筑物)的数字化是一个长期存在的开放问题,这归因于数据获取方面的挑战,如场景覆盖不完整、缺乏语义、规划路径的效率和可靠性低。在本文中,我们针对从航拍图像中重建城市建筑的问题,提出了一个有效的工作流程和一些新颖的算法,用于大型城市场景中高效的3D建筑实例代理重建。具体来说,我们提出了一种基于学习的新型方法,用于从航拍图像中进行城市建筑的实例分割,然后通过基于投票的算法将多视图实例信息融合到稀疏点云中(使用标准结构从运动管道重建)。我们的方法实现了从点云中对建筑实例进行有效的实例分割。
STM32F407中文手册
STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。
Android 实战-版本更新(okhttp3、service、notification)
转发请注明出处:http://www.jianshu.com/p/b669940c9f3e前言整理功能,把这块拿出来单独做个demo,好和大家分享交流一下。 版本更新这个功能一般 app 都有实现,而用户获取新版本一般来源有两种: - 一种是各种应用市场的新版本提醒 - 一种是打开app时拉取版本信息 - (还要一种推送形式,热修复或打补丁包时用得多点)这两区别就在于,市场的不能强制更新、不
Statistics and Machine Learning Toolbox
Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具
鸿蒙版微信深度解析:原生通信、ArkUI与分布式数据库实战
微信作为最典型的超级App,其在HarmonyOS NEXT上的重构,本质是移动应用从‘兼容运行’迈向‘原生协同’的技术分水岭。它不再依赖Android虚拟机或WebView桥接,而是基于鸿蒙分布式软总线实现设备直连通信,依托ArkUI声明式框架重构渲染管线,并采用轻量级KV+图谱混合引擎替代SQLite完成数据存储范式升级。这种改造显著提升多端同步效率、降低功耗与延迟,同时强化隐私控制粒度。对开发者而言,理解鸿蒙版微信的协议栈重写、UI驱动模型切换与分布式数据访问机制,是掌握纯血鸿蒙原生应用开发的关键入口
jre9下载 jdk9
(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】
蓝牙模块HM-10手册
蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。
基于uni-app+Vue的校友房屋合租小程序开发实战
跨平台开发已成为移动应用降本增效的关键路径。uni-app作为一套代码多端编译的框架,凭借Vue语法生态和成熟的编译能力,让开发者能够同时输出微信小程序、H5及App。其核心原理在于统一的组件化开发模型与条件编译机制,配合Vue的响应式数据绑定和组件复用,可显著提升工程迭代效率。在校园服务场景中,利用uni-app构建校友房屋合租平台,不仅解决租房信息分散、信任缺失的痛点,还能通过校友认证、房源审核、站内聊天等模块实现业务闭环。从环境配置、页面架构到定位地图、上传审核,本文以实际项目为例,梳理了跨端小程序开
Web前端开发必不可少的10个开源框架
作为一名前端开发人员,持续学习是必备的技能之一。随着新技术的不断涌现,前端开发框架越来越多,各种框架现、版本的更新此起彼伏。 前端领域的技术不断更迭,让人眼花缭乱。面对这么多框架,我们应该如何选择?接下来就为你们一 一介绍! 1、Jquery库 AJAX(Asynchronous Javascript And XML)这一技术概念在2005年提出,用来描述与浏览器有关的一类技术,包括: HTML/XHTML, CSS, JavaScript, DOM, XML, XSLT, 以及最重要的XMLHt
Android WebView跳转浏览器下载或打开第三方应用
项目有个需求是跳转应用宝网页下载更新自己的APP,开始不知道怎么写,不过通过一番查找还是理顺了!这篇文章以此来记录加深印象! 通过这篇文章知道了该怎么写的,这是链接:https://blog.youkuaiyun.com/yyanjun/article/details/79861666 废话不多说.一开始我是直接传递了一个我们APP在应用宝上的网址的,但是在webView中加载完之后点击网页上的按钮没有...
436



被折叠的 条评论
为什么被折叠?



