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

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: