自定义Progress小控件
progress各种各样的都有,自定义大多数也是简单的,根据业务需求来自己定义,记录一下,先上效果图

本来想找个第三方改改就上的,不过自己的业务需求有点不搭,一下子没找到合适的,也没这么多时间去找了,想想还是自己写个吧,因为也简单
主要就是需求就是椭圆进度,百分比跟随渐变背景,这样一想其实就是一个布局,然后控制里面的进度长度,或者移动,我这是控制长度,这样毕竟简单,而且扩展好,以后进度条有什么奇葩需求也好改
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.support.annotation.AttrRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.TextView; import com.app.commonlibrary.R; /**
* Created by LiuZhen on 2017/7/8.
*/ public class UpdateProgressBar extends FrameLayout { private TextView tv_progress;
private int width;
private ViewGroup.LayoutParams params;
/**
* The progress text offset.
*/
private int mOffset;
/**
* The progress text size.
*/
private float mTextSize;
/**
* The progress text color.
*/
private int mTextColor;
private float default_text_size;
/**
* The progress area bar color.
*/
private int mReachedBarColor;
/**
* The bar unreached area color.
*/
private int mUnreachedBarColor;
private final int default_reached_color = Color.rgb(66, 145, 241);
private final int default_unreached_color = Color.rgb(204, 204, 204);
private final int default_text_color = Color.rgb(66, 145, 241); public UpdateProgressBar(@NonNull Context context) {
this(context,null);
} public UpdateProgressBar(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
} public UpdateProgressBar(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs, defStyleAttr);
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int desiredWidth = 100;
int desiredHeight = 100; int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec); int height; //Measure Width
if (widthMode == MeasureSpec.EXACTLY) {
//Must be this size
width = widthSize;
} else if (widthMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
width = Math.min(desiredWidth, widthSize);
} else {
//Be whatever you want
width = desiredWidth;
} //Measure Height
if (heightMode == MeasureSpec.EXACTLY) {
//Must be this size
height = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
height = Math.min(desiredHeight, heightSize);
} else {
//Be whatever you want
height = desiredHeight;
} int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
ViewGroup.LayoutParams lp = child.getLayoutParams();
int childWidthSpec = getChildMeasureSpec(widthMeasureSpec, 0, lp.width);
int childHeightSpec = getChildMeasureSpec(heightMeasureSpec, 0, lp.height);
child.measure(childWidthSpec, childHeightSpec);
}
params = tv_progress.getLayoutParams();
params.width = ViewGroup.LayoutParams.WRAP_CONTENT;
params.height = ViewGroup.LayoutParams.MATCH_PARENT;
tv_progress.setLayoutParams(params);
height = tv_progress.getMeasuredHeight();
//MUST CALL THIS
setMeasuredDimension(width, height);
} private void init(AttributeSet attrs, int defStyleAttr){ default_text_size = 8;
//load styled attributes.
final TypedArray attributes = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.UpdateProgressBar,
defStyleAttr, 0); mTextSize = attributes.getDimension(R.styleable.UpdateProgressBar_update_text_size, default_text_size);
mReachedBarColor = attributes.getResourceId(R.styleable.UpdateProgressBar_update_reached_color, default_reached_color);
mUnreachedBarColor = attributes.getResourceId(R.styleable.UpdateProgressBar_update_unreached_color, default_unreached_color);
mTextColor = attributes.getColor(R.styleable.UpdateProgressBar_update_text_color, default_text_color); setDefaultProgressBar(); mOffset = px2dip(3); attributes.recycle();
} private void setDefaultProgressBar(){
setBackgroundResource(mUnreachedBarColor);
tv_progress = new TextView(getContext());
tv_progress.setTextSize(mTextSize);
tv_progress.setGravity(Gravity.RIGHT | Gravity.CENTER_VERTICAL);
tv_progress.setTextColor(mTextColor);
tv_progress.setLines(1);
tv_progress.setBackgroundResource(mReachedBarColor);
tv_progress.setPadding(dip2px(4),0,dip2px(8),0);
tv_progress.setText("0 %");
addView(tv_progress);
} public void setProgress(int progress){
tv_progress.setText(progress+"%");
int proWidth = width*progress/100;
if (tv_progress.getMeasuredWidth() < proWidth) {
//这里不能填充mOffset,因为是椭圆进度条,填充会导致椭圆宽度被进度条覆盖,导致不美观
// tv_progress.setLayoutParams(params);
tv_progress.setWidth(proWidth);
}
} /**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*/
public int dip2px(float dpValue) {
final float scale = getContext().getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
} /**
* 根据手机的分辨率从 px(像素) 的单位 转成为 dp
*/
public int px2dip(float pxValue) {
final float scale = getContext().getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
} /**
* 将px值转换为sp值,保证文字大小不变
*/
public int px2sp(float pxValue) {
final float fontScale = getContext().getResources().getDisplayMetrics().scaledDensity;
return (int) (pxValue / fontScale + 0.5f);
} /**
* 将sp值转换为px值,保证文字大小不变
*/
public int sp2px(float spValue) {
final float fontScale = getContext().getResources().getDisplayMetrics().scaledDensity;
return (int) (spValue * fontScale + 0.5f);
} }
UpdateProgressBar
用法布局文件
<com.progressbar.example.UpdateProgressBar
xmlns:pro="http://schemas.android.com/apk/res-auto"
android:id="@+id/progress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
pro:update_text_size="6sp"
pro:update_text_color="#FFFFFF"
pro:update_unreached_color="@drawable/shape_corner_progressbg"
pro:update_reached_color="@drawable/shape_corner_progressbar"/>
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast; import com.progressbar.NumberProgressBar; import java.util.Timer;
import java.util.TimerTask; public class MainActivity extends AppCompatActivity {
private Timer timer;
private UpdateProgressBar progressBar;
private int progress; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = (UpdateProgressBar)findViewById(R.id.progress); timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
runOnUiThread(new Runnable() {
@Override
public void run() {
progress++;
progressBar.setProgress(progress);
if(progress == 100) {
Toast.makeText(getApplicationContext(), getString(R.string.finish), Toast.LENGTH_SHORT).show();
// progress = 0;
// progressBar.setProgress(0);
timer.cancel();
}
}
});
}
}, 1000, 100);
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
} @Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
} @Override
protected void onDestroy() {
super.onDestroy();
timer.cancel();
}
}
MainActivity
渐变背景
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="#4984f2"/> <gradient
android:startColor="#4984f2"
android:endColor="#000" /> <corners
android:topLeftRadius="15dp"
android:topRightRadius="15dp"
android:bottomLeftRadius="15dp"
android:bottomRightRadius="15dp"/>
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="#dadada"/> <gradient
android:startColor="#FFF"
android:endColor="#000" /> <corners
android:topLeftRadius="15dp"
android:topRightRadius="15dp"
android:bottomLeftRadius="15dp"
android:bottomRightRadius="15dp"/>
</shape>
自定义Progress小控件的更多相关文章
- jquery和css自定义video播放控件
下面介绍一下通过jquery和css自定义video播放控件. Html5 Video是现在html5最流行的功能之一,得到了大多数最新版本的浏览器支持.包括IE9,也是如此.不同的浏览器提供了不同的 ...
- 在 Visual C++ 中开发自定义的绘图控件
本文讨论的重点介于两者 之间 — 公共控件赋予您想要的大部分功能,但控件的外观并不是您想要的.例如,列表视图控件提供在许多视图风格中显示数据列表的方式 — 小图标.大图标.列表和详细列表(报告).然而 ...
- jQ效果:jQuery和css自定义video播放控件
下面介绍一下通过jquery和css自定义video播放控件. Html5 Video是现在html5最流行的功能之一,得到了大多数最新版本的浏览器支持.包括IE9,也是如此.不同的浏览器提供了不同的 ...
- C#自定义Button按钮控件
C#自定义Button按钮控件 在实际项目开发中经常可以遇到.net自带控件并不一定可以满足需要,因此需要自定义开发一些新的控件,自定义控件的办法也有多种,可以自己绘制线条颜色图形等进行重绘,也可以采 ...
- C# WinForm自定义通用分页控件
大家好,前几天因工作需要要开发一个基于WinForm的小程序.其中要用到分页,最开始的想法找个第三方的dll用一下,但是后来想了想觉得不如自己写一个玩一下 之前的web开发中有各式各样的列表组件基本都 ...
- C# 根据BackgroundWoker异步模型和ProgressBar控件,自定义进度条控件
前言 程序开发过程中,难免会有的业务逻辑,或者算法之类产生让人能够感知的耗时操作,例如循环中对复杂逻辑处理;获取数据库百万乃至千万级数据;http请求的时候等...... 用户在使用UI操作并不知道程 ...
- kettle系列-[KettleUtil]kettle插件,类似kettle的自定义java类控件
该kettle插件功能类似kettle现有的定义java类插件,自定java类插件主要是支持在kettle中直接编写java代码实现自定特殊功能,而本控件主要是将自定义代码转移到jar包,就是说自定义 ...
- (转)sl简单自定义win窗体控件
sl简单自定义win窗体控件 相信大家接触过不少win窗体控件ChildWin子窗口就的sl自带的一个 而且网上也有很多类似的控件,而今天我和大家分享下自己制作个win窗体控件,希望对初学 ...
- WPF自定义控件与样式(8)-ComboBox与自定义多选控件MultComboBox
一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: 下拉选 ...
随机推荐
- 模仿bootstrap做的 js tooltip (添加鼠标跟随功能)
主要思路: 使用jquery hover方法,当进入时显示tooltip,移出时隐藏tooltip当设定为鼠标跟随时,使用mousemove事件显示tooltip根据tooltip显示位置设置,计算t ...
- [Swift]LeetCode503. 下一个更大元素 II | Next Greater Element II
Given a circular array (the next element of the last element is the first element of the array), pri ...
- [Swift]LeetCode563. 二叉树的坡度 | Binary Tree Tilt
Given a binary tree, return the tilt of the whole tree. The tilt of a tree node is defined as the ab ...
- [Swift]LeetCode878. 第 N 个神奇数字 | Nth Magical Number
A positive integer is magical if it is divisible by either A or B. Return the N-th magical number. ...
- python安装whl文件
在命令指示符下(cmd)的Python3安装命令为: pip3 install 文件名.whl 安装出错: matplotlib-2.0.0-cp34-cp34m-win_amd64.whl is n ...
- VueJs 源码分析 ---(一) 整体对 vuejs 框架的理解
vue-2.x SourceCode vue 2.x 源码解析 关于vue,以及为何要来写这份源码解析的原因 笔者从最开始接触到 vue 应该还是在 15年 10月份左右,当时听说 前端圈中发生很多的 ...
- 漫画:Linux中/etc/resolv.conf文件和puppet工具解析
今天办公室里来了一个程序员妹子飞鸟,小鱼是给她分配的导师,初次见面~ 午饭时间 Linux目录结构 resolv.conf文件 nameserver 唯一的必选关键字.表明DNS 服务器的IP 地址, ...
- JAVA实现接口监控报警系统
公司一内部系统需要添加一个接口和定时任务监控机制,针对了系统出现的定时任务没有执行,定时任务执行异常出错,对外传送的数据接口异常出错,对内的系统数据互传异常出错等问题进行设计,目的是为了能够让用户没发 ...
- 洛谷:P1182:数列分段`Section II`
题目描述 对于给定的一个长度为N的正整数数列 A-iA−i ,现要将其分成 M(M≤N)M(M≤N) 段,并要求每段连续,且每段和的最大值最小. 关于最大值最小: 例如一数列 4 2 4 5 1424 ...
- 如何发起、防御和测试XSS攻击,我们用DVWA来学习(下)
上一篇我们了解了XSS攻击的原理,并且利用DVWA尝试了简单的XSS攻击,这一篇我们来实现更复杂的攻击,然后探讨防御机制和测试理念. 前面我们通过脚本注入让网页弹出了用户cookie信息,可以光弹窗是 ...