您的位置:首页 > 移动开发 > Android开发

Android动画特效之水波(地震波)报警动画

2015-06-04 10:51 549 查看
需求:

工作中有个项目需求:在GridView列表中展示水波(地震波)报警动画效果,显示所有区域的故障数量,以及故障的严重程度(故障数量越大表示越严重,水波扩散越快,状态越醒目),现将这一实现方式整理成文,给有需要的小伙伴一点帮助,同时希望,开源互助的精神能激励更多未来的大牛门前行在coding的道路上!

效果

实现的效果如下




效果比较简单,可根据需求自定义其他颜色的状态(比如***表示警告、绿色表示正常等)同时显示在GridView中的item中,是否出现波纹可进行控制,以作为对比效果,如下图所示:



附上源码地址:http://download.csdn.net/detail/daijin888888/8771873

(直接导入Eclipse ADT即可,出现乱码请调整项目编码,笔者的是UTF-8编码)

实现方式

首先说明涉及的主要知识点:

GridView+Adapter

自定义View

Handle

项目结构图如下:




MainActivity:主Activity,生成数据源

StateAdapter:适配器,适配GridView数据

StatePojo:数据实体

MyAlarmView:自定义视图,重要部分

我们先自定义视图,也是实现报警效果的主要组件,通常情况下,要在Android中绘图,需要先创建一个继承自View类的视图,并且在该类中重写它的onDraw方法,然后在显示绘图的Activity中添加该视图。这里主要用到了Paint类和Canvas类:

Paint类代表画笔,用来描述图形的颜色和风格,如线宽,颜色,透明度和填充效果等信息。使用Paint类时,需要先创建该类的对象,可以通过该类的构造函数实现,然后再通过该对象提供的方法对画笔的默认设置进行改变。

Canvas类代表画布,通过该类提供的构造方法,可以绘制各种图形。(具体使用方法本篇不再赘述)

MyAlarmView.java

[code]package com.test.widget;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

/**
 * @author daij 地震波效果,可根据故障严重程度调节闪烁速度
 */
public class MyAlarmView extends View {

    private Paint paint;
    private int maxWidth = 128;
    private boolean isStarting = false;
    private int delay;
    private List<String> alphaList = new ArrayList<String>();
    private List<String> startWidthList = new ArrayList<String>();

    public MyAlarmView(Context context) {
        super(context);
        init();
    }

    public MyAlarmView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MyAlarmView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        paint = new Paint();
        paint.setColor(Color.RED);// 此处颜色可以改为自己喜欢的
        alphaList.add("128");// 圆心的不透明度
        startWidthList.add("0");
    }

    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        setBackgroundColor(Color.TRANSPARENT);// 颜色:完全透明
        // 依次绘制 同心圆
        for (int i = 0; i < alphaList.size(); i++) {
            int alpha = Integer.parseInt(alphaList.get(i));
            int startWidth = Integer.parseInt(startWidthList.get(i));
            paint.setAlpha(alpha);// 设置透明度
            canvas.drawCircle(getWidth() / 2, getHeight() / 2, startWidth,
                    paint);
            // 同心圆扩散
            if (isStarting && alpha > 0 && startWidth < maxWidth) {
                alphaList.set(i, (alpha - 1) + "");
                startWidthList.set(i, (startWidth + 1) + "");
            }
        }
        if (isStarting
                && Integer
                        .parseInt(startWidthList.get(startWidthList.size() - 1)) == maxWidth / 5) {
            alphaList.add("128");
            startWidthList.add("0");
        }
        // 同心圆数量达到6个,删除最外层圆
        if (isStarting && startWidthList.size() == 6) {
            startWidthList.remove(0);
            alphaList.remove(0);
        }
        postDelayed(new Runnable() {
            @Override
            public void run() {
                // 刷新界面
                invalidate();
            }
        }, delay);
    }

    // 地震波开始/继续进行
    public void start() {
        isStarting = true;
    }

    // 地震波暂停
    public void stop() {
        isStarting = false;
    }

    public boolean isStarting() {
        return isStarting;
    }

    /**
     * 根据传入的数值决定刷新的频度,数值越大,刷新越快,效果越醒目
     * 
     * @param red
     */
    public void handleDelay(int red) {
        delay = 100 - red;
    }

}


以上代码中实现不同闪烁强度的部分是handleDelay(int red);【用于设置延时时长】和postDelayed(new Runnable());【用于异步请求,延时刷新界面】,值得注意的是,这里的数据量不大,处理逻辑也较简单,所以可以使用这种多线程异步消息通信机制。

再来设计实体类

StatePojo.java

[code]public class StatePojo {

    public static final String TAG = "StatePojo";

    public String area;
    public int red;// 这里我只设置了红色报警,以下其他属性可根据需求选择
    public int blue;
    public int yellow;

    public String getArea() {
        return area;
    }

    public StatePojo setArea(String area) {
        this.area = area;
        return this;
    }

    public int getRed() {
        return red;
    }

    public StatePojo setRed(int red) {
        this.red = red;
        return this;
    }

    public int getBlue() {
        return blue;
    }

    public StatePojo setBlue(int blue) {
        this.blue = blue;
        return this;
    }

    public int getYellow() {
        return yellow;
    }

    public StatePojo setYellow(int yellow) {
        this.yellow = yellow;
        return this;
    }
}


数据实体类实现后,设计Adapter类,里面用到了static class ViewHolder{}视图优化技术,如下:

StateAdapter .java

[code]package com.test.app.adapter;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import com.example.alarmtest.R;
import com.test.app.entity.StatePojo;
import com.test.widget.MyAlarmView;

/**
 * @author daij
 * @version 1.0
 * 
 *          状态的adapter
 */
public class StateAdapter extends BaseAdapter {
    Context context;
    private List<StatePojo> messages = null;
    private int resourceId;

    public StateAdapter(Context con) {
        this.context = con;
    }

    public StateAdapter(Context con, int gridviewItem,
            ArrayList<StatePojo> messages) {
        this.context = con;
        resourceId = gridviewItem;
        this.messages = messages;
    }

    @Override
    public int getCount() {
        // return messages.size();
        return 8;
    }

    @Override
    public StatePojo getItem(int arg0) {
        return messages.get(arg0);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View rowView = convertView;
        ViewHolder viewHolder;
        final StatePojo state = getItem(position);

        if (rowView == null) {
            LayoutInflater vi = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            rowView = vi.inflate(resourceId, parent, false);
            viewHolder = new ViewHolder();

            // 配置ViewHolder
            viewHolder.tvArea = (TextView) rowView.findViewById(R.id.tv_area);
            viewHolder.smwWave = (MyAlarmView) rowView
                    .findViewById(R.id.swvWave);
            viewHolder.tvRedNum = (TextView) rowView
                    .findViewById(R.id.tv_red_state);
            // viewHolder.tvYellowNum = (TextView) rowView
            // .findViewById(R.id.tv_yellow_state);
            // viewHolder.tvBlueNum = (TextView) rowView
            // .findViewById(R.id.tv_blue_state);

            rowView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) rowView.getTag();
        }

        viewHolder.tvArea.setText(state.area);
        viewHolder.smwWave.handleDelay(state.red);
        viewHolder.smwWave.start();
        viewHolder.tvRedNum.setText(String.valueOf(state.red));

        viewHolder.tvRedNum.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View arg0) {
                // TODO 处理点击事件
                // context.startActivity(new Intent(context,
                // MalfunctionList.class));
            }
        });
//       viewHolder.tvYellowNum.setText(String.valueOf(state.yellow));
//       viewHolder.tvBlueNum.setText(String.valueOf(state.blue));

        return rowView;
    }

    static class ViewHolder {
        // 获取所有item组件
        TextView tvArea;// 地区
        MyAlarmView smwWave;// 水波
        TextView tvRedNum;// 红色
//       TextView tvYellowNum;// ***
//       TextView tvBlueNum;// 绿色
    }
}


最后,实现主Activity,模拟数据,添加适配:

MainActivity.java

[code]package com.test.app;

import java.util.ArrayList;

import android.app.Activity;
import android.os.Bundle;
import android.widget.GridView;

import com.example.alarmtest.R;
import com.test.app.adapter.StateAdapter;
import com.test.app.entity.StatePojo;

/**
 * @author daij 设备监测
 */
public class MainActivity extends Activity {
    private ArrayList<StatePojo> messages = new ArrayList<StatePojo>();
    private StateAdapter stateAdapter;
    private GridView gvStates;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_monitror);

        setViews();
    }

    private void setViews() {
        gvStates = (GridView) findViewById(R.id.gv_monitor);

        messages.add(new StatePojo().setArea("地区A").setRed(89).setYellow(45)
                .setBlue(1));
        messages.add(new StatePojo().setArea("地区B").setRed(56).setYellow(12)
                .setBlue(3));
        messages.add(new StatePojo().setArea("地区C").setRed(32).setYellow(98)
                .setBlue(4));
        messages.add(new StatePojo().setArea("地区D").setRed(121).setYellow(11)
                .setBlue(5));
        messages.add(new StatePojo().setArea("地区E").setRed(12).setYellow(23)
                .setBlue(9));
        messages.add(new StatePojo().setArea("地区F").setRed(0).setYellow(12)
                .setBlue(7));
        messages.add(new StatePojo().setArea("地区G").setRed(45).setYellow(25)
                .setBlue(8));
        messages.add(new StatePojo().setArea("地区H").setRed(65).setYellow(8)
                .setBlue(0));

        // 设置的适配器
        stateAdapter = new StateAdapter(this, R.layout.gridview_item, messages);
        gvStates.setAdapter(stateAdapter);
    }
}


再附上布局文件:

activity_monitror.xml

[code]<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/monitor_bg"
    tools:context=".Monitor" >

    <GridView
        android:id="@+id/gv_monitor"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:columnWidth="90dp"
        android:gravity="center"
        android:horizontalSpacing="8dp"
        android:numColumns="2"
        android:stretchMode="columnWidth"
        android:verticalSpacing="8dp" >
    </GridView>

</RelativeLayout>


gridview_item.xml

[code]<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/gridview_item_bg"
    android:gravity="center"
    android:orientation="vertical"
    android:padding="5dp" >

    <TextView
        android:id="@+id/tv_area"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:padding="10dp"
        android:textColor="@color/gridview_item_text_color"
        android:textSize="25sp" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="0.5dp"
        android:layout_gravity="bottom"
        android:background="@color/white" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal" >

        <FrameLayout
            android:id="@+id/state"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="horizontal" >

            <com.test.widget.MyAlarmView
                android:id="@+id/swvWave"
                android:layout_width="80dp"
                android:layout_height="80dp"
                android:gravity="center" />

            <TextView
                android:id="@+id/tv_red_state"
                android:layout_width="45dp"
                android:layout_height="45dp"
                android:layout_gravity="center"
                android:background="@drawable/state_item_red"
                android:gravity="center"
                android:padding="2dp"
                android:textColor="@color/white"
                android:textSize="20sp" />
        </FrameLayout>
        <!-- 取消下面和Adapter中的注释即可显示红黄绿对比效果 -->
        <!--
        <TextView
            android:id="@+id/tv_yellow_state"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_margin="5dp"
            android:background="@drawable/state_item_yellow"
            android:gravity="center"
            android:padding="4dp"
            android:textColor="@color/white"
            android:textSize="16sp" />

        <TextView
            android:id="@+id/tv_blue_state"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:background="@drawable/state_item_blue"
            android:gravity="center"
            android:padding="4dp"
            android:textColor="@color/white"
            android:textSize="16sp" />
        -->
    </LinearLayout>

</LinearLayout>


为了实现较好看的样式,自定义TextView背景边框:

state_item_red.xml

[code]<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval"
    android:useLevel="false" >

    <solid android:color="@color/red_state" />
    <!-- state_item_blue.xml和state_item_yellow.xml中只需将这里对应分别改为@color/blue_state和@color/yellow_state即可 -->

    <padding
        android:bottom="1dp"
        android:left="2dp"
        android:right="2dp"
        android:top="1dp" />

    <solid android:color="@color/red_state" />
    <!-- state_item_blue.xml和state_item_yellow.xml中只需将这里对应分别改为@color/blue_state和@color/yellow_state即可 -->

    <stroke
        android:width="1dp"
        android:color="@android:color/white" />

    <size
        android:height="15dp"
        android:width="15dp" />

</shape>


最后附上资源文件:

colors.xml

[code]<?xml version="1.0" encoding="utf-8"?>
<resources>

    <color name="gridview_item_bg">#E4E7E7</color>
    <!-- 状态表格item的背景 -->
    <color name="gridview_item_text_color">#5F8FA3</color>
    <!-- 状态表格item的文字颜色 -->
    <color name="white">#FFFFFFFF</color>
    <color name="red_state">#F23829</color>
    <!-- 红色状态 -->
    <color name="yellow_state">#F2D883</color>
    <!-- ***状态 -->
    <color name="blue_state">#5D9A25</color>
    <!-- 绿色状态 -->
    <color name="monitor_bg">#D6DEE1</color>
    <!-- 设备监测页背景 -->

</resources>


至此,所有代码构建完成,附上源码。

http://download.csdn.net/detail/daijin888888/8771873

请尊重原创,转载请附上原文地址,谢谢!

原文地址:/article/2372933.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: