字母雨的实现.docx
- 文档编号:9746927
- 上传时间:2023-02-06
- 格式:DOCX
- 页数:15
- 大小:45.43KB
字母雨的实现.docx
《字母雨的实现.docx》由会员分享,可在线阅读,更多相关《字母雨的实现.docx(15页珍藏版)》请在冰豆网上搜索。
字母雨的实现
字母雨的实现
一、实现原理
在实现过程中,主要考虑整个界面由若干个字母组成的子母线条组成,这样的话把固定数量的字母封装成一个字母线条,而每个字母又封装成一个对象,这样的话,就形成了如下组成效果:
字母对象--》字母线条对象--》界面效果
每个字母都应该知道自己的位置坐标,自己上面的字母、以及自己的透明度:
classHackCode{
Pointp=newPoint();//每一个字母的坐标
intalpha=255;//透明度值默认255
Stringcode="A";//字母的值
}
而每个子母线条对象都有自己这条线条的初始底部起点,内部的多个字母都是根据线条的初始底部起点依次排列,包含多个字母对象集合,以及这条线条的唯一标示:
classHackLine{
publicintNUM=0;//用于记录这列的标示
privatePointp=newPoint();//线的初始位置
List
}
在初始化的时候创建所有子母线条对象以及字母对象存入集合中:
@Override
protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){
super.onMeasure(widthMeasureSpec,heightMeasureSpec);
mWidth=getMeasuredWidth();//获取控件宽高
mHeight=getMeasuredHeight();
mHackLines.clear();//清空集合
initPlayData();//初始化播放数据
}
/**
*初始化播放数据
*/
publicvoidinitPlayData(){
initHackLine(mWidth/9,mHeight/12);
initHackLine(mWidth/9,mHeight/7);
HackLinehl;
for(inti=3;i<9;i++){
hl=newHackLine();
hl.p.x=mWidth/9*(i+1);
hl.p.y=mHeight/7*(9-i);
for(intj=0;j<7;j++){
HackCodehc=newHackCode();
hc.alpha-=30*j;
hc.code=CODES[newRandom().nextInt(CODES.length)];
hc.p.x=hl.p.x;
hc.p.y=hl.p.y-dip2px(getContext(),25)*j;
hl.hcs.add(hc);
}
mHackLines.add(hl);
hl.NUM=mHackLines.size();
}
}
然后在onDraw方法中绘制:
@Override
protectedvoidonDraw(Canvascanvas){
for(inti=0;i drawText(i,canvas); } mHandler.sendEmptyMessageDelayed(WHAT,100);//用于开启循环线条滚动 } publicvoiddrawText(intnindex,Canvascanvas){ HackLinehackLine=mHackLines.get(nindex); for(inti=0;i HackCodehackCode=hackLine.hcs.get(i); mPaint.setAlpha(hackCode.alpha); canvas.drawText(hackCode.code,hackCode.p.x,hackCode.p.y,mPaint); } } 接下来要滚动显示由Handler发送一个延时100毫秒的消息开始: classWeakHandlerextendsHandler{ WeakReference publicWeakHandler(Activityactivity){ mActivity=newWeakReference } @Override publicvoidhandleMessage(Messagemsg){ if(mActivity.get()! =null){ switch(msg.what){ caseWHAT: nextPlay(dip2px(getContext(),20)); for(inti=0;i if(mHackLines.get(i).p.y>=mHeight/2*3){ addHackLine(mHackLines.get(i)); } } invalidate(); break; } } } } 让整个线条往下走其实也就只用将线条的底部初始值Y坐标不断增加,内部字母随之更新位置就可以了: /** *下一帧播放 *@paramNnum每次下移多远距离 */ publicvoidnextPlay(intNnum){ for(inti=0;i List hcs.clear(); mHackLines.get(i).p.y+=Nnum; for(intj=0;j<7;j++){ HackCodehc=newHackCode(); hc.alpha-=30*j; hc.code=CODES[newRandom().nextInt(CODES.length)]; hc.p.x=mHackLines.get(i).p.x; hc.p.y=mHackLines.get(i).p.y-dip2px(getContext(),25)*j; hcs.add(hc); } } } 之后我们要考虑在合适的时间移除掉不需要的字母线条并增加新的子母线条,这里我是判断如果线条底部超过屏幕高度的一半时就移除当前线条并根据唯一标示添加新的线条: /** *删除一列同时添加初始化一列 *@paramhackLine */ publicvoidaddHackLine(HackLinehackLine){ if(hackLine==null){ return; } intnum=hackLine.NUM; mHackLines.remove(hackLine);//如果存在删除重新添加 HackLinehl; hl=newHackLine(); hl.p.x=mWidth/9*(num-1); hl.p.y=mHeight/12*(7-(num-1)); for(intj=0;j<7;j++){ HackCodehc=newHackCode(); hc.alpha-=30*j; hc.code=CODES[newRandom().nextInt(CODES.length)]; hc.p.x=hl.p.x; hc.p.y=hl.p.y-dip2px(getContext(),25)*j; hl.hcs.add(hc); } hl.NUM=num; mHackLines.add(hl); } 最后,在控件移除屏幕的时候终止消息循环,运行时记得将根布局设置背景为黑色: @Override protectedvoidonDetachedFromWindow(){ super.onDetachedFromWindow(); mHandler.removeCallbacksAndMessages(null);//停止刷新 } OKOK,字母雨已经出来啦~~思路清晰之后还是很简单的哦~ 二、实现代码 整个代码也不算很长,就直接贴上了: /** *字母雨 *@authorzhang * */ publicclassHackViewextendsView{ /**文字的画笔*/ privatePaintmPaint; /**控件的宽*/ privateintmWidth; /**控件的高*/ privateintmHeight; /**所有字母*/ privatestaticfinalString[]CODES={ "A","B","C","D","E","F","G","H","I","J","K", "L","M","N","O","P","Q","R","S","T","U","V", "W","K","Y","Z" }; privatestaticfinalintWHAT=1; /**所有的HackLine组合*/ privateList privateWeakHandlermHandler; publicHackView(Contextcontext){ this(context,null); } publicHackView(Contextcontext,AttributeSetattrs){ this(context,attrs,0); } publicHackView(Contextcontext,AttributeSetattrs,intdefStyleAttr){ super(context,attrs,defStyleAttr); t(); mHandler=newWeakHandler((Activity)context); } classWeakHandlerextendsHandler{ WeakReference publicWeakHandler(Activityactivity){ mActivity=newWeakReference } @Override publicvoidhandleMessage(Messagemsg){ if(mActivity.get()! =null){ switch(msg.what){ caseWHAT: nextPlay(dip2px(getContext(),20)); for(inti=0;i if(mHackLines.get(i).p.y>=mHeight/2*3){ addHackLine(mHackLines.get(i)); } } invalidate(); break; } } } } privatevoidinit(){ mPaint=newPaint(Paint.ANTI_ALIAS_FLAG); mPaint.setColor(Color.WHITE); mPaint.setTextSize(dip2px(getContext(),20)); mPaint.setStrokeCap(Cap.ROUND); mPaint.setStrokeWidth(dip2px(getContext(),5)); setLayerType(View.LAYER_TYPE_SOFTWARE,null); } @Override protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){ super.onMeasure(widthMeasureSpec,heightMeasureSpec); mWidth=getMeasuredWidth();//获取控件宽高 mHeight=getMeasuredHeight(); mHackLines.clear();//清空集合 initPlayData(); } /** *下一帧播放 *@paramNnum每次下移多远距离 */ publicvoidnextPlay(intNnum){ for(inti=0;i List hcs.clear(); mHackLines.get(i).p.y+=Nnum; for(intj=0;j<7;j++){ HackCodehc=newHackCode(); hc.alpha-=30*j; hc.code=CODES[newRandom().nextInt(CODES.length)]; hc.p.x=mHackLines.get(i).p.x; hc.p.y=mHackLines.get(i).p.y-dip2px(getContext(),25)*j; hcs.add(hc); } } } /** *删除一列同时添加初始化一列 *@paramhackLine */ publicvoidaddHackLine(HackLinehackLine){ if(hackLine==null){ return; } intnum=hackLine.NUM; mHackLines.remove(hackLine);//如果存在删除重新添加 HackLinehl; hl=newHackLine(); hl.p.x=mWidth/9*(num-1); hl.p.y=mHeight/12*(7-(num-1)); for(intj=0;j<7;j++){ HackCodehc=newHackCode(); hc.alpha-=30*j; hc.code=CODES[newRandom().nextInt(CODES.length)]; hc.p.x=hl.p.x; hc.p.y=hl.p.y-dip2px(getContext(),25)*j; hl.hcs.add(hc); } hl.NUM=num; mHackLines.add(hl); } /** *初始化每一行数据 *@paramx *@paramy */ publicvoidinitHackLine(intx,inty){ HackLinehl; for(inti=0;i<9;i++){ hl=newHackLine(); hl.p.x=x*i; hl.p.y=y*(7-i); for(intj=0;j<7;j++){ HackCodehc=newHackCode(); hc.alpha-=30*j; hc.code=CODES[newRandom().nextInt(CODES.length)]; hc.p.x=hl.p.x; hc.p.y=hl.p.y-dip2px(getContext(),25)*j; hl.hcs.add(hc); } mHackLines.add(hl); hl.NUM=mHackLines.size(); } } /** *初始化播放数据 */ publicvoidinitPlayData(){ initHackLine(mWidth/9,mHeight/12); initHackLine(mWidth/9,mHeight/7); HackLinehl; for(inti=3;i<9;i++){ hl=newHackLine(); hl.p.x=mWidth/9*(i+1); hl.p.y=mHeight/7*(9-i); for(intj=0;j<7;j++){ HackCodehc=newHackCode(); hc.alpha-=30*j; hc.code=CODES[newRandom().nextInt(CODES.length)]; hc.p.x=hl.p.x; hc.p.y=hl.p.y-dip2px(getContext(),25)*j; hl.hcs.add(hc); } mHackLines.add(hl); hl.NUM=mHackLines.size(); } } @Override protectedvoidonDraw(Canvascanvas){ for(inti=0;i drawText(i,canvas); } mHandler.sendEmptyMessageDelayed(WHAT,100); } publicvoiddrawText(intnindex,Canvascanvas){ HackLinehackLine=mHackLines.get(nindex); for(inti=0;i HackCodehackCode=hackLine.hcs.get(i); mPaint.setAlpha(hackCode.alpha); canvas.drawText(hackCode.code,hackCode.p.x,hackCode.p.y,mPaint); } } /** *每条线包含多个字母 **/ classHackLine{ publicintNUM=0;//用于记录这列的标示 privatePointp=wPoint();//线的初始位置 List } /** *每个字母 */ classHackCode{ Pointp=newPoint();//每一个字母的坐标 intalpha=255;//透明度值默认255 Stringcode="A";//字母的值 } @Override protectedvoidonDetachedFromWindow(){ super.onDetachedFromWindow(); mHandler.removeCallbacksAndMessages(null);//停止刷新 } /** *根据手机的分辨率从dip的单位转成为px(像素) */ publicstaticintdip2px(Contextcontext,floatdpValue){ finalfloatscale=context.getResources().getDisplayMetrics().density; return(int)(dpValue*scale+0.5f); } } xml: android=" xmlns: tools=" android: layout_width="match_parent" android: layout_height="match_parent" android: background="#000" tools: context=".MainActivity"> android: layout_width="match_parent" android: layout_height="match_parent" />
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 字母 实现