<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Android實(shí)現(xiàn)類似黑客帝國字母雨效果

          共 11821字,需瀏覽 24分鐘

           ·

          2021-07-12 14:53

          效果圖:



          一、實(shí)現(xiàn)原理


          在實(shí)現(xiàn)過程中,主要考慮整個(gè)界面由若干個(gè)字母組成的子母線條組成,這樣的話把固定數(shù)量的字母封裝成一個(gè)字母線條,而每個(gè)字母又封裝成一個(gè)對(duì)象,這樣的話,就形成了如下組成效果:

          字母對(duì)象--》字母線條對(duì)象--》界面效果


          每個(gè)字母都應(yīng)該知道自己的位置坐標(biāo),自己上面的字母、以及自己的透明度:

          class HackCode{         Point p = new Point();//每一個(gè)字母的坐標(biāo)         int alpha = 255;//透明度值  默認(rèn)255         String code = "A";//字母的值    }


          而每個(gè)子母線條對(duì)象都有自己這條線條的初始底部起點(diǎn),內(nèi)部的多個(gè)字母都是根據(jù)線條的初始底部起點(diǎn)依次排列,包含多個(gè)字母對(duì)象集合,以及這條線條的唯一標(biāo)示:

          class HackLine{    public int NUM = 0;//用于記錄這列的標(biāo)示    private Point p = new Point();//線的初始位置    List<HackCode> hcs = new ArrayList<HackView.HackCode>();//黑客字母的一條線    }


          在初始化的時(shí)候創(chuàng)建所有子母線條對(duì)象以及字母對(duì)象存入集合中:

              @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
          mWidth = getMeasuredWidth();//獲取控件寬高 mHeight = getMeasuredHeight(); mHackLines.clear();//清空集合 initPlayData();//初始化播放數(shù)據(jù) }
          /** * 初始化播放數(shù)據(jù) */ public void initPlayData(){ initHackLine(mWidth/9, mHeight/12); initHackLine(mWidth/9, mHeight/7); HackLine hl; for (int i = 3; i < 9; i++) { hl= new HackLine(); hl.p.x = mWidth/9*(i+1); hl.p.y = mHeight/7*(9-i); for (int j = 0; j < 7; j++) { HackCode hc = new HackCode(); hc.alpha -= 30*j; hc.code = CODES[new Random().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方法中繪制:

          @Overrideprotected void onDraw(Canvas canvas) {    for (int i = 0; i < mHackLines.size(); i++) {        drawText(i, canvas);    }    mHandler.sendEmptyMessageDelayed(WHAT, 100);//用于開啟循環(huán)  線條滾動(dòng)    }
          public void drawText(int nindex,Canvas canvas){ HackLine hackLine = mHackLines.get(nindex); for (int i = 0; i < hackLine.hcs.size(); i++) { HackCode hackCode = hackLine.hcs.get(i); mPaint.setAlpha(hackCode.alpha); canvas.drawText(hackCode.code, hackCode.p.x, hackCode.p.y, mPaint); } }


          接下來要滾動(dòng)顯示由Handler發(fā)送一個(gè)延時(shí)100毫秒的消息開始:

          class WeakHandler extends Handler{        WeakReference<Activity> mActivity;         public WeakHandler(Activity activity){            mActivity = new WeakReference<Activity>(activity);        }        @Override        public void handleMessage(Message msg) {            if(mActivity.get() != null){                switch (msg.what) {                case WHAT:                    nextPlay(dip2px(getContext(), 20));                    for (int i = 0; i < mHackLines.size(); i++) {                        if(mHackLines.get(i).p.y >= mHeight/2*3){                            addHackLine(mHackLines.get(i));                        }                    }                    invalidate();                    break;                }            }        }    }


          讓整個(gè)線條往下走其實(shí)也就只用將線條的底部初始值Y坐標(biāo)不斷增加,內(nèi)部字母隨之更新位置就可以了:

          /**     *  下一幀播放     * @param Nnum 每次下移多遠(yuǎn) 距離     */    public void nextPlay(int Nnum){        for (int i = 0; i < mHackLines.size(); i++) {            List<HackCode> hcs = mHackLines.get(i).hcs;            hcs.clear();            mHackLines.get(i).p.y+=Nnum;            for (int j = 0; j < 7; j++) {                HackCode hc = new HackCode();                hc.alpha -= 30*j;                hc.code = CODES[new Random().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);            }        }    }


          之后我們要考慮在合適的時(shí)間移除掉不需要的字母線條并增加新的子母線條,這里我是判斷如果線條底部超過屏幕高度的一半時(shí)就移除當(dāng)前線條并根據(jù)唯一標(biāo)示添加新的線條:

              /**     * 刪除一列  同時(shí)添加初始化一列     * @param hackLine      */    public void addHackLine(HackLine hackLine){            if(hackLine == null){                return;            }            int num = hackLine.NUM;            mHackLines.remove(hackLine);//如果存在  刪除   重新添加
          HackLine hl; hl= new HackLine(); hl.p.x = mWidth/9*(num-1); hl.p.y = mHeight/12*(7-(num-1)); for (int j = 0; j < 7; j++) { HackCode hc = new HackCode(); hc.alpha -= 30*j; hc.code = CODES[new Random().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); }


          最后,在控件移除屏幕的時(shí)候終止消息循環(huán),運(yùn)行時(shí)記得將根布局設(shè)置背景為黑色:

              @Override    protected void onDetachedFromWindow() {        super.onDetachedFromWindow();        mHandler.removeCallbacksAndMessages(null);//停止刷新    }


          OKOK,字母雨已經(jīng)出來啦~~ 思路清晰之后還是很簡單的哦~


          二、實(shí)現(xiàn)代碼


          整個(gè)代碼也不算很長,就直接貼上了:

          /** * 字母雨 */public class HackView extends View {    /** 文字的畫筆 */    private Paint mPaint;    /** 控件的寬 */    private int mWidth;    /** 控件的高 */    private int mHeight;    /** 所有字母 */    private static final String[] 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"    };        private static final int WHAT = 1;    /** 所有的HackLine組合 */    private List<HackLine> mHackLines = new ArrayList<HackView.HackLine>();        private WeakHandler mHandler;        public HackView(Context context) {        this(context,null);    }    public HackView(Context context, AttributeSet attrs) {        this(context, attrs,0);    }    public HackView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init();        mHandler = new WeakHandler((Activity) context);    }        class WeakHandler extends Handler{        WeakReference<Activity> mActivity;         public WeakHandler(Activity activity){            mActivity = new WeakReference<Activity>(activity);        }        @Override        public void handleMessage(Message msg) {            if(mActivity.get() != null){                switch (msg.what) {                case WHAT:                    nextPlay(dip2px(getContext(), 20));                    for (int i = 0; i < mHackLines.size(); i++) {                        if(mHackLines.get(i).p.y >= mHeight/2*3){                            addHackLine(mHackLines.get(i));                        }                    }                    invalidate();                    break;                }            }        }    }    private void init() {        mPaint = new Paint(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    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);                mWidth = getMeasuredWidth();//獲取控件寬高        mHeight = getMeasuredHeight();        mHackLines.clear();//清空集合        initPlayData();    }    /**     *  下一幀播放     * @param Nnum 每次下移多遠(yuǎn) 距離     */    public void nextPlay(int Nnum){        for (int i = 0; i < mHackLines.size(); i++) {            List<HackCode> hcs = mHackLines.get(i).hcs;            hcs.clear();            mHackLines.get(i).p.y+=Nnum;            for (int j = 0; j < 7; j++) {                HackCode hc = new HackCode();                hc.alpha -= 30*j;                hc.code = CODES[new Random().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);            }        }    }    /**     * 刪除一列  同時(shí)添加初始化一列     * @param hackLine      */    public void addHackLine(HackLine hackLine){            if(hackLine == null){                return;            }            int num = hackLine.NUM;            mHackLines.remove(hackLine);//如果存在  刪除   重新添加                        HackLine hl;            hl= new HackLine();            hl.p.x = mWidth/9*(num-1);            hl.p.y = mHeight/12*(7-(num-1));            for (int j = 0; j < 7; j++) {                HackCode hc = new HackCode();                hc.alpha -= 30*j;                hc.code = CODES[new Random().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);    }    /**     * 初始化每一行數(shù)據(jù)     * @param x     * @param y     */    public void initHackLine(int x,int y){        HackLine hl;        for (int i = 0; i < 9; i++) {            hl= new HackLine();            hl.p.x = x*i;            hl.p.y = y*(7-i);            for (int j = 0; j < 7; j++) {                HackCode hc = new HackCode();                hc.alpha -= 30*j;                hc.code = CODES[new Random().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();        }    }    /**     * 初始化播放數(shù)據(jù)     */    public void initPlayData(){        initHackLine(mWidth/9, mHeight/12);        initHackLine(mWidth/9, mHeight/7);        HackLine hl;        for (int i = 3; i < 9; i++) {            hl= new HackLine();            hl.p.x = mWidth/9*(i+1);            hl.p.y = mHeight/7*(9-i);            for (int j = 0; j < 7; j++) {                HackCode hc = new HackCode();                hc.alpha -= 30*j;                hc.code = CODES[new Random().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    protected void onDraw(Canvas canvas) {        for (int i = 0; i < mHackLines.size(); i++) {            drawText(i, canvas);        }        mHandler.sendEmptyMessageDelayed(WHAT, 100);    }        public void drawText(int nindex,Canvas canvas){        HackLine hackLine = mHackLines.get(nindex);        for (int i = 0; i < hackLine.hcs.size(); i++) {            HackCode hackCode = hackLine.hcs.get(i);            mPaint.setAlpha(hackCode.alpha);            canvas.drawText(hackCode.code, hackCode.p.x, hackCode.p.y, mPaint);        }    }    /**     *  每條線  包含多個(gè)字母     **/    class HackLine{        public int NUM = 0;//用于記錄這列的標(biāo)示        private Point p = new Point();//線的初始位置        List<HackCode> hcs = new ArrayList<HackView.HackCode>();//黑客字母的一條線    }    /**     * 每個(gè)字母     */    class HackCode{         Point p = new Point();//每一個(gè)字母的坐標(biāo)         int alpha = 255;//透明度值  默認(rèn)255         String code = "A";//字母的值    }    @Override    protected void onDetachedFromWindow() {        super.onDetachedFromWindow();        mHandler.removeCallbacksAndMessages(null);//停止刷新    }     /**      * 根據(jù)手機(jī)的分辨率從 dip 的單位 轉(zhuǎn)成為 px(像素)      */      public static int dip2px(Context context, float dpValue) {          final float scale = context.getResources().getDisplayMetrics().density;          return (int) (dpValue * scale + 0.5f);      }  }


          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="#000"    tools:context=".MainActivity" >
          <com.zk.hack.HackView android:layout_width="match_parent"        android:layout_height="match_parent"/>
          </RelativeLayout>


          到這里就結(jié)束啦。點(diǎn)擊這里留言交流哦

          瀏覽 172
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  逼视频在线观看 | 国产乱码一区二区三区的区别 | 亚洲综合免费观看高清完整版在线观 | av电影在线一区 AV日韩中文字幕 AV天堂成人电影 AV天堂电影在线 AV天堂中文字幕 AV天堂资源网站 a在线免费视频了 | 黄色小电影免费在线观看网站 |