自定义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自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: 下拉选 ...
随机推荐
- JavaWeb开发SSM框架搭建详解
1.需要用到的jar包:由于很多的jar包不好下载,我直接上传到百度网盘: 很多,而且不好下载,我已经整理好好了: 链接:https://pan.baidu.com/s/1iIFprmstp86uKz ...
- [Swift]LeetCode373. 查找和最小的K对数字 | Find K Pairs with Smallest Sums
You are given two integer arrays nums1 and nums2 sorted in ascending order and an integer k. Define ...
- iOS学习——Quartz2D学习之DrawRect
Quartz2D学习之DrawRect 本文以问答形式主要讲述Quartz2D的相关内容,参考内容是网上下载的学习视频资料. 1.什么是Quartz2D? 他是一个二维的绘图引擎,同时支持iOS和Ma ...
- 1、MySQL主从同步机制及同步中的问题处理
http://www.drupal001.com/2012/03/mysql-master-slave-troubles/ http://www.jb51.net/article/33052.htm
- .NET Core实战项目之CMS 第九章 设计篇-白话架构设计
前面两篇文章给大家介绍了我们实战的CMS系统的数据库设计,源码也已经上传到服务器上了.今天我们就好聊聊架构设计,在开始之前先给大家分享一下这几天我一直在听的<从零开始学架构>里面关于架构设 ...
- 『宝藏 状态压缩DP NOIP2017』
宝藏(NOIP2017) Description 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 n 个深埋在地下的宝藏屋, 也给出了这 n 个宝藏屋之间可供开发的m 条道路和它们的长度. 小明决 ...
- Hystrix是如何工作的
接上一篇:<Hystrix介绍> 流程图 下面这幅图相当重要 稍微解释一下上面的流程: Construct a HystrixCommand or HystrixObservableCom ...
- 并发编程(五)——AbstractQueuedSynchronizer 之 ReentrantLock源码分析
本文将从 ReentrantLock 的公平锁源码出发,分析下 AbstractQueuedSynchronizer 这个类是怎么工作的,希望能给大家提供一些简单的帮助. AQS 结构 先来看看 AQ ...
- 使用ML.NET实现情感分析[新手篇]后补
在<使用ML.NET实现情感分析[新手篇]>完成后,有热心的朋友建议说,为何例子不用中文的呢,其实大家是需要知道怎么预处理中文的数据集的.想想确实有道理,于是略微调整一些代码,权作示范. ...
- CentOS6.5下DNS服务器搭建与配置
一.安装机器情况 192.168.1.70(dns 主节点) 192.168.1.71(dns 从节点) 二.主节点DNS的安装及配置 1. DNS服务器所需的软件包安装 yum -y install ...