本文主要讲述了利用android自定义控件实现瀑布流与水波纹效果
首先为实现效果,应了解touch事件在android中的传递机制
在执行touch事件时
首先执行dispatchTouchEvent方法,执行事件分发。
再执行onInterceptTouchEvent方法,判断是否中断事件,返回true时中断,执行自己的onTouchEvnet方法.
最后执行onTouchEvent方法,处理事件
瀑布流实现
首先定义三个listView竖起排列,并且配置适配器
public class MainActivity extends Activity {private ListView lv1;private ListView lv2;private ListView lv3;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);lv1 = (ListView) findViewById(R.id.lv1);lv2 = (ListView) findViewById(R.id.lv2);lv3 = (ListView) findViewById(R.id.lv3);try {lv1.setAdapter(new MyAdapter1());lv2.setAdapter(new MyAdapter1());lv3.setAdapter(new MyAdapter1());} catch (Exception e) {e.printStackTrace();}}private int ids[] = new int[] { R.drawable.default1, R.drawable.girl1,R.drawable.girl2, R.drawable.girl3 };class MyAdapter1 extends BaseAdapter {@Overridepublic int getCount() {return 3000;}@Overridepublic Object getItem(int position) {return position;}@Overridepublic long getItemId(int position) {return 0;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ImageView iv = (ImageView) View.inflate(getApplicationContext(),R.layout.lv_item, null);int resId = (int) (Math.random() * 4);iv.setImageResource(ids[resId]);return iv;}}
}
布局文件的配置
<com.example.pinterestlistview.MyLinearLayout 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:id="@+id/mll"tools:context=".MainActivity" ><ListViewandroid:id="@+id/lv2"android:scrollbars="none"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1" /><ListViewandroid:id="@+id/lv1"android:scrollbars="none"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1" /><ListViewandroid:id="@+id/lv3"android:scrollbars="none"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1" /></com.example.pinterestlistview.MyLinearLayout>
自定义类截取事件分发
public class MyLinearLayout extends LinearLayout {public MyLinearLayout(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {return true;}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {return super.dispatchTouchEvent(ev);}@Overridepublic boolean onTouchEvent(MotionEvent event) {int width=getWidth()/getChildCount();int height = getHeight();int count=getChildCount();float eventX = event.getX();if (eventX<width){ // 滑动左边的 listViewevent.setLocation(width/2, event.getY());getChildAt(0).dispatchTouchEvent(event);return true;} else if (eventX > width && eventX < 2 * width) { //滑动中间的 listView float eventY = event.getY();if (eventY < height / 2) {event.setLocation(width / 2, event.getY());for (int i = 0; i < count; i++) {View child = getChildAt(i);try {child.dispatchTouchEvent(event);} catch (Exception e) {e.printStackTrace();}}return true;} else if (eventY > height / 2) {event.setLocation(width / 2, event.getY());try {getChildAt(1).dispatchTouchEvent(event);} catch (Exception e) {e.printStackTrace();}return true;}}else if (eventX>2*width){event.setLocation(width/2, event.getY());getChildAt(2).dispatchTouchEvent(event);return true;}return true;}}
完成,运行效果如下
水波纹效果实现
要实现水波纹效果,只需用一个自定义控件填充整个Activity即可
<com.zj.wave.MyWaveandroid:layout_width="fill_parent"android:layout_height="fill_parent"/>
自定义控件实现
/*** 水波纹效果* @author leo**/
public class MyRingWave extends View{/*** 二个相临波浪中心点的最小距离*/private static final int DIS_SOLP = 13;protected boolean isRunning = false;private ArrayList<Wave> wList;public MyRingWave(Context context, AttributeSet attrs) {super(context, attrs);wList = new ArrayList<MyRingWave.Wave>();}private Handler handler = new Handler(){public void handleMessage(android.os.Message msg) {//刷新数据flushData();//刷新页面invalidate();//循环动画if (isRunning) {handler.sendEmptyMessageDelayed(0, 50);}};};@Overrideprotected void onDraw(Canvas canvas) {for (int i = 0; i < wList.size(); i++) {Wave wave = wList.get(i);canvas.drawCircle(wave.cx, wave.cy, wave.r, wave.p);}}@Overridepublic boolean onTouchEvent(MotionEvent event) {super.onTouchEvent(event);switch (event.getAction()) {case MotionEvent.ACTION_DOWN:case MotionEvent.ACTION_MOVE:int x = (int) event.getX();int y = (int) event.getY();addPoint(x,y);break;default:break;}return true; }/*** 添加新的波浪中心点* @param x* @param y*/private void addPoint(int x, int y) {if(wList.size() == 0){addPoint2List(x,y);/** 第一次启动动画*/isRunning = true;handler.sendEmptyMessage(0);}else{Wave w = wList.get(wList.size()-1);if(Math.abs(w.cx - x)>DIS_SOLP || Math.abs(w.cy-y)>DIS_SOLP){addPoint2List(x,y);}};}/*** 添加新的波浪* @param x* @param y*/private void addPoint2List(int x, int y) {Wave w = new Wave();w.cx = x;w.cy=y;Paint pa=new Paint();pa.setColor(colors[(int)(Math.random()*4)]);pa.setAntiAlias(true);pa.setStyle(Style.STROKE);w.p = pa;wList.add(w);}private int [] colors = new int[]{Color.BLUE,Color.RED,Color.YELLOW,Color.GREEN};/*** 刷新数据*/private void flushData() {for (int i = 0; i < wList.size(); i++) {Wave w = wList.get(i);//如果透明度为 0 从集合中删除int alpha = w.p.getAlpha();if(alpha == 0){wList.remove(i); //删除i 以后,i的值应该再减1 否则会漏掉一个对象,不过,在此处影响不大,效果上看不出来。continue;}alpha-=5;if(alpha<5){alpha =0;}//降低透明度w.p.setAlpha(alpha);//扩大半径w.r = w.r+3;//设置半径厚度w.p.setStrokeWidth(w.r/3);}/** 如果集合被清空,就停止刷新动画*/if(wList.size() == 0){isRunning = false;}}/*** 定义一个波浪* @author leo*/private class Wave {//圆心int cx;int cy;//画笔Paint p;//半径int r;}
}