Android 自定义控件---SpreadView
2015-09-14 17:00
489 查看
1、效果图:主要模仿Fuubo的欢迎界面,一个三层扩散的水波纹.
2、实现思路:
1、在布局主要用帧布局,让三个水波纹的View重叠
2、设置三个水波纹的View扩散的延迟时间
3、可设置三个水波纹的View的坐标,
可设置是否开始(因为我们有时要Activity中先设置好波纹的坐标,不能让波纹先出现),
可设置是否为第一次(第一次要进行初始化主要为了设置延迟,不然每次都会有延迟,不同延迟时间的SpreadView相差的时间越来越多)。
3、实现:
根据思路所以接下来要做的一个自定义VIEW就是去绘制一个可扩散的,可设置扩散延迟的实心圆。
1、 先设置自定义View属性(attr文件中):<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="SpreadView"> <attr name="xDown" format="integer" /> <attr name="yDown" format="integer" /> <attr name="start" format="boolean" /> <attr name="delay" format="integer" /> <attr name="first" format="boolean" /> </declare-styleable> </resources>
2、 然后新建一个继承View的SpreadView类:
public class SpreadView extends View { //建立一个波纹的集合 private List<Wave> waveList; //波纹的x,y坐标 private int x = 0 ; private int y = 0 ; //波纹是否在运行,是否为第一次 private boolean start ,first ; //波纹开始的延迟时间 private int delay ; public void setStart(boolean start) { this.start = start; } public void setFirst(boolean first) { this.first = first; } public void setX(int x) { this.x = x; } public void setY(int y) { this.y = y; } public void setDelay(int delay) { this.delay = delay; } //波纹设置的最大透明度 private static final int MAX_ALPHA = 255; public SpreadView(Context context, AttributeSet attrs) { super(context, attrs); //获取属性信息和设置默认值 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SpreadView); x = a.getInt(R.styleable.SpreadView_xDown,0); y = a.getInt(R.styleable.SpreadView_yDown,0); start = a.getBoolean(R.styleable.SpreadView_start,false); delay = a.getInt(R.styleable.SpreadView_delay,0); first = a.getBoolean(R.styleable.SpreadView_first,true); //波纹集合的实例化 waveList = Collections.synchronizedList(new ArrayList<Wave>()); //记得回收属性容器 a.recycle(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onDraw(Canvas canvas) { if(waveList.size()==0&&(!first)) //波纹集合大小为0时,初始化 init(); //非第一次初始化 else if(waveList.size()==0&&first) initFirst(); //第一次初始化 //绘制圆 Wave wave = waveList.get(0); if(wave!=null) canvas.drawCircle(wave.xDown, wave.yDown, wave.radius, wave.paint);//用波纹的属性 } private void initFirst() { if(this.start) { //如果属性值设为开始 Wave wave = new Wave(); wave.radius = 0; wave.alpha = MAX_ALPHA; wave.xDown = x; wave.yDown = y; wave.paint = initPaint(wave.alpha); waveList.add(wave); first = false; //设置第一次为false mHandler.sendEmptyMessageDelayed(0, delay);//带延迟异步任务 } } //更新画笔 private Paint initPaint(int alpha) { Paint paint = new Paint(); paint.setAntiAlias(true); paint.setAlpha(alpha); paint.setColor(Color.WHITE); return paint; } public final Handler.Callback mHandlerCallback = new Handler.Callback(){ @Override public boolean handleMessage(Message msg) { switch (msg.what){ case 0: refreshState(); invalidate(); if (waveList != null &&waveList.size()>0) { mHandler.sendEmptyMessage(0); //不带延迟的异步 } return true; default: return false; } } }; private Handler mHandler = new Handler(mHandlerCallback); private void refreshState() { Wave w = waveList.get(0); if (w == null) { this.postInvalidate(); //如果没有波纹就重新绘制,重新运行onDraw()初始化 } else { //波纹每次增加的半径大小,可自己修改,记得要转换为px。 //(这里0.6单位为dp可以大概指出最大半径),如果不转换,那波纹的最大半径因手机的分辨率不同而不同 w.radius += dip2px(getContext(),0.6f); //波纹每次减小的透明度 w.alpha -= 1; //更新波纹的透明度 w.paint.setAlpha(w.alpha); //当透明度小于0时,清理波纹列表,重新绘制初始化 if (w.alpha < 0) { waveList.clear(); this.postInvalidate(); } } } public void init() { if(this.start) { Wave wave = new Wave(); wave.radius = 0; wave.alpha = MAX_ALPHA; wave.xDown = x; wave.yDown = y; wave.paint = initPaint(wave.alpha); waveList.add(wave); mHandler.sendEmptyMessageDelayed(0, 1000); } } private class Wave { float radius; Paint paint; int xDown; int yDown; int alpha; } public static int dip2px(Context context, float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } }3、 先设置xml布局:
注意每个SpreadView的延迟时间和ImageView的属性
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/main" > <com.scb.administrator.a.SpreadView android:id="@+id/sv" app:xDown="0" app:yDown="0" app:start="false" app:first="true" app:delay="0" android:layout_width="match_parent" android:layout_height="match_parent" /> <com.scb.administrator.a.SpreadView android:id="@+id/sv1" app:xDown="0" app:yDown="0" app:start="false" app:first="true" app:delay="1900" android:layout_width="match_parent" android:layout_height="match_parent" /> <com.scb.administrator.a.SpreadView android:id="@+id/sv2" app:xDown="0" app:yDown="0" app:first="true" app:start="false" app:delay="3800" android:layout_width="match_parent" android:layout_height="match_parent" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="#00000000" android:id="@+id/re_create2" > <TextView android:gravity="center" android:textSize="19sp" android:layout_margin="80dp" android:textStyle="italic" android:textColor="@color/white" android:text="H\nU\nS\nT\nO\nO" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ImageView android:id="@+id/go" android:background="#00000000" android:src="@drawable/fap_login" android:layout_margin="40dp" android:scaleType="centerCrop" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_width="54dp" android:layout_height="54dp" /> </RelativeLayout> </FrameLayout>
4、接下来我们就要根据上面的布局在Activity手动计算波纹位置了:我们要把波纹的中心设在图片的中心(可看开始的效果图)
public class SplashActivity extends Activity { private SpreadView sv,sv1,sv2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.splash_main); sv = (SpreadView) findViewById(R.id.sv); sv1 = (SpreadView) findViewById(R.id.sv1); sv2 = (SpreadView) findViewById(R.id.sv2); int statusBarHeight = getStatusHeight(SplashActivity.this); float scale = getResources().getDisplayMetrics().density; DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); //为什么是67*scale+0.5f?因为从布局文件的ImageView上 //上面的式子是一个dp转px的式子,dp为67:ImageView的margin为40+ImageView的半个宽/高 int screenWidth= (int) (metrics.widthPixels-(67 * scale + 0.5f)); //屏幕宽度 //屏幕高度还要减去状态栏的高度,如果你用的全屏,则不需要了。 int screenHeight= (int) (metrics.heightPixels-statusBarHeight-(67 * scale + 0.5f)); //屏幕高度 ImageView iv = (ImageView) findViewById(R.id.go); sv.setX(screenWidth); sv.setY(screenHeight); sv1.setX(screenWidth); sv1.setY(screenHeight); sv2.setX(screenWidth); sv2.setY(screenHeight); iv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //TODO } }); } private int getStatusHeight(Activity activity) { int statusHeight = 0; Rect localRect = new Rect(); activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(localRect); statusHeight = localRect.top; if (0 == statusHeight){ Class<?> localClass; try { localClass = Class.forName("com.android.internal.R$dimen"); Object localObject = localClass.newInstance(); int i5 = Integer.parseInt(localClass.getField("status_bar_height").get(localObject).toString()); statusHeight = activity.getResources().getDimensionPixelSize(i5); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (NumberFormatException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } } return statusHeight; } @Override protected void onResume() { //根据Activity的生命周期来设置 sv1.setStart(false); sv.setStart(false); sv2.setStart(false); sv1.setStart(true); sv.setStart(true); sv2.setStart(true); sv1.setFirst(true); sv.setFirst(true); sv2.setFirst(true); super.onResume(); } @Override protected void onPause() { super.onPause(); } }
转载请注明出处:/article/10840499.html
相关文章推荐
- Android系统版本与API Level对照表
- Android Studio二--基本设置与运行
- Android Canvas绘图详解(图文)
- Android自定义圆形进度条
- Android Sqlite 导入外部数据库
- Android中的自定义圆形头像
- Android绘图深度解析
- Android(java)学习笔记247:ContentProvider使用之利用ContentProvider备份和还原手机短信(掌握)
- ADB+adbWireless 抛开USB调试,接入无线调试
- Error:Execution failed for task ':sample:dexDebug'. > com.android.ide.common.process.ProcessExceptio
- 如何一步步实现在Android平台下运用OpenGl
- Android SQLite使用
- Android Makefile 文件讲解
- Android自定义View原理详解02
- android 自定义View原理详解01
- Android OpenGL 学习笔记
- Android系统自带样式(android:theme)详解 (
- android_handler简单使用,测试
- 兔子--Android Studio中的项目怎么依赖library
- Android安卓开发中图片缩放讲解