需求:
工作中有个项目需求:在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
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
GitHub(给个星杯~):
https://github.com/VingeDai/AlarmAnimationDemo
请尊重原创,转载请附上原文地址,谢谢!
原文地址:http://blog.csdn.net/daijin888888/article/details/46357515