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

来源:互联网 发布:mac 大型网游 编辑:程序博客网 时间:2024/05/21 07:04

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

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

附上源码地址: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

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

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

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

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

<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

<?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

<?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

<?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

请尊重原创,转载请附上原文地址,谢谢!
原文地址:http://blog.csdn.net/daijin888888/article/details/46357515

1 0
原创粉丝点击