自定义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自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: 下拉选 ...
随机推荐
- FFmpeg 结构体学习(四): AVFrame 分析
在上文FFmpeg 结构体学习(三): AVPacket 分析我们学习了AVPacket结构体的相关内容.本文,我们将讲述一下AVFrame. AVFrame是包含码流参数较多的结构体.下面我们来分析 ...
- JDK 8 之 Stream sorted() 示例
原文链接:http://www.concretepage.com/java/jdk-8/java-8-stream-sorted-example 国外对Java8一系列总结的不错, 翻译过来给大家共享 ...
- [Swift]LeetCode23. 合并K个排序链表 | Merge k Sorted Lists
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. E ...
- [Swift]LeetCode35. 搜索插入位置 | Search Insert Position
Given a sorted array and a target value, return the index if the target is found. If not, return the ...
- [Swift]LeetCode93. 复原IP地址 | Restore IP Addresses
Given a string containing only digits, restore it by returning all possible valid IP address combina ...
- [Swift]LeetCode391. 完美矩形 | Perfect Rectangle
Given N axis-aligned rectangles where N > 0, determine if they all together form an exact cover o ...
- [Swift]LeetCode876. 链表的中间结点 | Middle of the Linked List
Given a non-empty, singly linked list with head node head, return a middle node of linked list. If t ...
- mysql 主主+ Keepalived 高可用
这是在mysql互为主从的基础上做的 yum -y install keepalived #两台机器上都装 配置Keepalived主从, vrrp_instance VI_1 { state ...
- MySQL面试必考知识点:揭秘亿级高并发数据库调优与最佳实践法则
做业务,要懂基本的SQL语句: 做性能优化,要懂索引,懂引擎: 做分库分表,要懂主从,懂读写分离... 数据库的使用,是开发人员的基本功,对它掌握越清晰越深入,你能做的事情就越多. 今天我们用10分钟 ...
- webdav 概览
webdav 概览 WebDav(Web Distributed Authoring and Versioning) 是一个控制远端Web资源的协议,它基于HTTP1.1.它的定义在RFC 4918( ...