Android粒子雨效果之音量条显示
学习自极客学院
* 主要的内容是关于自定义view的实现
* 线程的简单使用
首先要明白为什么要使用自定义view,自定义就是为了动态的获取view的宽高和view的样式。
我们可以如何实现自定义view呢?
自己定义一个class继承view
public abstract class BaseView extends View {
private MyThread thread;
private boolean running = true;
protected long sleepTime = 100;
public BaseView(Context context) {
super(context);
}
protected abstract void init();
protected abstract void drawSub(Canvas canvas);
protected abstract void logic();
public BaseView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onDraw(Canvas canvas) {
if(thread == null){
thread = new MyThread();
thread.start();
}else{
drawSub(canvas);
}
}
@Override
protected void onDetachedFromWindow() {
running = false;
super.onDetachedFromWindow();
}
class MyThread extends Thread{
@Override
public void run() {
init();
long workTime;
while(running){
workTime = System.currentTimeMillis();
postInvalidate();
logic();
workTime = System.currentTimeMillis() - workTime;
try {
if(workTime < sleepTime){
Thread.sleep(sleepTime - workTime);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
- 抽象了base类,且抽象了三个方法
- 线程绘制时间做个判断,停留的时间准确为等于绘制时间加上沉睡时间。
我这里定义了一个baseView,所以之后肯定会有自己要新建的classView来继承baseView,目的是为之后其他的view的创建更合适。
public class IrDisatanceView extends BaseView {
private ArrayList<IrDistanceItem> list = new ArrayList<IrDistanceItem>();
private IrDistanceItem irDistanceItem;
private final static int NUM = 8;
private int itemWidth = 20;
public IrDisatanceView(Context context) {
super(context);
}
public IrDisatanceView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void init() {
// irDistanceItem = new IrDistanceItem(getHeight());
for (int i = 0; i < NUM; i++) {
list.add(new IrDistanceItem(i * getWidth() / NUM, itemWidth, getHeight()));
}
}
@Override
protected void drawSub(Canvas canvas) {
for (IrDistanceItem item:list) {
item.draw(canvas);
}
}
@Override
protected void logic() {
for (IrDistanceItem item:list) {
item.move();
}
}
}
- 这里主要是传参数到IrDistanceItem 类中去,获得IrDistanceItem 对象,再执行方法。
所以就涉及到了IrDistanceItem 这个类
public class IrDistanceItem implements IAnimation{
private int itemHeight;
private Paint paint = new Paint();
private int maxHeight;
private Random random = new Random();
private int itemWidth;
private int x;
private int maxRectNum;
private int rectNum;
private int distance = 3;
public IrDistanceItem(int itemHeight){
this.maxHeight = itemHeight;
init();
}
public IrDistanceItem(int x,int itemWidth,int itemHeight){
this.maxHeight = itemHeight;
this.x = x;
this.itemWidth = itemWidth;
init();
}
private void init(){
paint.setColor(Color.RED);
maxRectNum = maxHeight / (itemWidth + distance);
}
@Override
public void draw(Canvas canvas) {
// canvas.drawRect(x,itemHeight,x+itemWidth,maxHeight,paint);
int num = maxRectNum - rectNum;
for (int i = 0; i < rectNum; i++) {
canvas.drawRect(x, (num + i) * (itemWidth + distance), x
+ itemWidth, (num + i + 1) * (itemWidth + distance)
- distance, paint);
}
}
@Override
public void move() {
// itemHeight = random.nextInt(maxHeight);
rectNum = 1 + random.nextInt(maxRectNum);
}
}
- 关键就在于这个类,构造方法有很多个,看需求需要哪些参数,就对应增加或者减少相应的参数。
- 主要看draw这个方法,调用了canvas这个类,
canvas.drawRect(x, (num + i) * (itemWidth + distance), x
+ itemWidth, (num + i + 1) * (itemWidth + distance)
- distance, paint); - drawRect(X1,Y1,X2,Y2,paint);五个参数,分别是左上右下,和paint对象。可以参考这个:[http://www.360doc.com/content/13/0703/16/8510389_297389451.shtml]
- random是一个随机函数
- maxRectNum 是通过计算得到的方块数
- num 是实际小方块的数目
还有一个简单的接口IAnimation类
public interface IAnimation {
public void draw(Canvas canvas);
public void move();
}
- 不需要解释吧
IrDistanceAct
public class IrDistanceAct extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ir_distance);
}
}
- 不需要做任何修改
最后就是layout文件了