Android-一个简单的手机屏保程序

本实例实现了一个手机屏保功能,控制和判断用户静止未触动手机键盘或者屏幕的时间及其事件,并且通过动态全屏幕渐入渐出的交换效果。我们以时间戳的方式,判断距离上一次单击键盘或者屏幕的时间,计算两个时间的差值。当超过了设置的时间后,会进入屏保程序。具体实现代码如下:
在activity_main.xml文件中:

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:scaleType="fitCenter"
            android:layout_gravity="center"
            android:id="@+id/imageview"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/textview"
            android:visibility="visible"
            android:text="就是显示文字"
            android:textColor="#66ff0000"/>

        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:hint="请输入内容"
            android:id="@+id/edittext"/>

接下来在MainActivity声明需要的变量

    private ImageView imageView;

    private TextView textView;

    //LayoutInflater对象,作为新建AlertDialog之用
    private LayoutInflater mInflater;

    //用mView来输入解锁的View 通过Menu选项identifier 用以表示具体的事件
    //输入解锁的View
    private View mView01;

    private EditText mEditText01,mEditText02;

    //Menu选项identifier 用以识别事件
    static final private int MENU_ABOUT = Menu.FIRST;
    static final private int MENU_EXIT = Menu.FIRST + 1;


    private Handler mHandle01 = new Handler();
    private Handler mHandle02 = new Handler();
    private Handler mHandle03 = new Handler();
    private Handler mHandle04 = new Handler();


    //分别定义控制user静止与否的Counter,控制FadeIn和FadeOut的Counter,控制循序替换背景图ID的Counter

    //控制User静止与否的Counter
    private int intCounter1,intCounter2;

    //控制FadeIn和FadeOut的Counter,
    private int intCounter3,intCounter4;

    //控制循序替换背景图ID的Counter
    private int intDrawable = 0;



    //设置timePeriod,设置当静止超过n秒将自动进入屏幕保护

    //上一次user有动作的Time Steamp
    private Date lastUpdateTime;

    //计算User共几秒没有动作
    private long timePeriod;

    //静止超过n秒将自动进入屏幕保护
    private float fHoldStillSecond = (float)5;

    private boolean bIfRunScreenSaver;

    private boolean bFadeFlagOut,bfadeFlagIn = false;

    private long intervarScreenSaver = 1000;

    private long intervarKeypadeSaver = 1000;

    private long intervarFade = 100;

    private int screenWidth,screenHeight;

    //设置每5秒置换图片 用Screen Saver保存需要用到的背景图
    //置换间隔
    private int intSecondToChange = 5;

    //设置Screen Saver用到的背景图
    private static int[] screenDrawable = new int[]{
            R.drawable.user,
            R.drawable.two,
            R.drawable.three,
            R.drawable.four
    };

设置在setContentView之前调用全屏幕显示,通过lastUpdateTime初始取得User触摸手机的时间,并用recorverOriginalLayout()来初始化Layou上的idget可见性

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //全屏幕显示
        requestWindowFeature(Window.FEATURE_NO_TITLE);

        getWindow().setFlags(
                WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN
        );

        setContentView(R.layout.activity_main);

        textView = (TextView) findViewById(R.id.textview);

        imageView = (ImageView) findViewById(R.id.imageview);

        mEditText01 = (EditText) findViewById(R.id.edittext);

        //初始失去的用户触摸手机的时间
        lastUpdateTime = new Date(System.currentTimeMillis());

        recorverOriginalLayout();
    }

设置menu群组ID 然后通过menu.add创建具有subMenu的Menu

       public boolean onCreateOptionsMenu(Menu menu){

           int idGroup1 = 0;
           int orderMenuItem1 = Menu.NONE;
           int orderMenuItem2 = Menu.NONE + 1;

           menu.add(idGroup1,MENU_ABOUT,orderMenuItem1,"呵呵");
           menu.add(idGroup1,MENU_EXIT,orderMenuItem2,"退出");
           menu.setGroupCheckable(idGroup1,true,true);

           return super.onCreateOptionsMenu(menu);
        }

根据用户选择的Menu选项显示对应的AlertDialog提示框

         @Override
        public boolean onOptionsItemSelected(MenuItem item) {

           switch (item.getItemId()){

               case MENU_ABOUT:

                   new AlertDialog.Builder(MainActivity.this).setTitle("嘎嘎嘎嘎").setIcon(R.drawable.user1).setMessage("message内容啊")
                           .setPositiveButton("好的", new DialogInterface.OnClickListener() {
                               @Override
                               public void onClick(DialogInterface dialogInterface, int i) {

                               }
                           }).show();
                   break;

               case MENU_EXIT:

                   finish();
                   break;

           }

           return super.onOptionsItemSelected(item);
       }

用mTasks监控User没有动作的运行线程,通过timePeroid计算User静止不动的时间间距, 如果静止不动 超过设置的时间5秒,则运行对应的线程

    private Runnable mTasks = new Runnable() {
        @Override
        public void run() {

            intCounter1 ++;

            // 计算用户静止不动作的时间间隔
            Date timeNew = new Date(System.currentTimeMillis());

            timePeriod = (long)timeNew.getTime() - (long)lastUpdateTime.getTime();

            float timePeriodSecond = ((float)timePeriod / 1000);

            //如果超过时间静止不动
            if (timePeriodSecond > fHoldStillSecond){

                //如果超过时间静止不动
                if (bIfRunScreenSaver == false){

                    //启动运行线程2
                    mHandle02.postDelayed(mTasks02,intervarScreenSaver);

                    if (intCounter1 % (intSecondToChange) == 0){

                        bFadeFlagOut = true;

                        mHandle03.postDelayed(mTasks03,intervarFade);

                    }else {

                        if (bFadeFlagOut == true){

                            bfadeFlagIn  = true;
                            mHandle04.postDelayed(mTasks04,intervarFade);
                        }else{

                            bfadeFlagIn  = false;
                            intCounter4 = 0;
                            mHandle04.removeCallbacks(mTasks04);
                        }

                        intCounter3 = 0;

                        bFadeFlagOut = false;

                    }

                    bIfRunScreenSaver = true;

                }else {

                    //screen save正在进行中
                    if (intCounter1 % (intSecondToChange) == 0){

                        bFadeFlagOut = true;

                        mHandle03.postDelayed(mTasks03,intervarFade);

                    }else {

                        if (bFadeFlagOut == true){

                            bfadeFlagIn = true;

                            mHandle04.postDelayed(mTasks04,intervarFade);

                        }else {

                            bfadeFlagIn = false;

                            intCounter4 = 0;

                            mHandle04.removeCallbacks(mTasks04);

                        }
                        intCounter3 = 0;

                        bFadeFlagOut = false;
                    }
                }
            }else {

                //当User没有动作的间距未超过时间
                bIfRunScreenSaver = false;

                //回复原来的Layout Visible
                recorverOriginalLayout();


            }

            //以Logcat监看User静止不动的时间间距
            Log.i("HIPPO","Counter1:"+Integer.toString(intCounter1)+"/"+Float.toString(timePeriodSecond));

            mHandle01.postDelayed(mTasks,intervarKeypadeSaver);

        }
    };

使用mTasks02设置每一秒运行一次屏保程序,隐藏原有的Layout上面的Widget, 并调用ScreenSaver()加载图片 即轮换显示预设的图片

    private Runnable mTasks02 = new Runnable() {
        @Override
        public void run() {
            if (bIfRunScreenSaver == true){

                intCounter2++;

                hideOriginallayout();

                showScreenSaver();

                mHandle02.postDelayed(mTasks02,intervarScreenSaver);

            }else {

                mHandle02.removeCallbacks(mTasks02);

            }
        }
    };

定义mTasks03 通过setAlpha设置ImageView的透明度渐暗下去

    private Runnable mTasks03 = new Runnable() {
        @Override
        public void run() {


            if (bIfRunScreenSaver == true && bFadeFlagOut == true ){

                intCounter3++;

                imageView.setAlpha(255-intCounter3*28);

                Log.i("HIPPO","Fade Out:"+Integer.toString(intCounter3));

                mHandle03.postDelayed(mTasks03,intervarFade);

            }else {

                mHandle03.removeCallbacks(mTasks03,intervarFade);

            }
        }
    };

定义mTasks04 通过setAlpha设置ImageView的透明度渐亮起来

    private Runnable mTasks04 = new Runnable() {
        @Override
        public void run() {

            if (bIfRunScreenSaver == true && bfadeFlagIn == true){

                intCounter4++;

                imageView.setAlpha(intCounter4 * 28);

                mHandle04.postDelayed(mTasks04,intervarFade);

                Log.i("HIPPO","Fade In:"+Integer.toString(intCounter4));
            }else {

                mHandle04.removeCallbacks(mTasks04,intervarFade);

            }
        }
    };

定义可视性隐藏与恢复方法

    //恢复原有的layout的可视性
    private void recorverOriginalLayout(){

        textView.setVisibility(View.VISIBLE);

        mEditText01.setVisibility(View.VISIBLE);

        imageView.setVisibility(View.GONE);

    }


    //隐藏原有的应用程序里的布局配置组合
    private void hideOriginallayout(){

        textView.setVisibility(View.INVISIBLE);

        mEditText01.setVisibility(View.INVISIBLE);

    }

屏保程序的开始

    private void showScreenSaver(){

        //保护屏幕之后要做的事情写在此
        if (intDrawable > 4){

            intDrawable = 0;

        }

        DisplayMetrics dm = new DisplayMetrics();

        getWindowManager().getDefaultDisplay().getMetrics(dm);

        screenWidth = dm.widthPixels;

        screenHeight = dm.heightPixels;

        Bitmap bmp = BitmapFactory.decodeResource(getResources(),screenDrawable[intDrawable]);

        //使用Matrix比例
        float scaleWidth = (float)screenWidth / bmp.getWidth();

        float scaleHeight = (float)screenHeight / bmp.getHeight();

        Matrix matrix = new Matrix();

        //使用Matrix。postScale设置维度Resize
        matrix.postScale(scaleWidth,scaleHeight);

        //Resize图文件至屏幕分辨率
        Bitmap resizeBitmap = Bitmap.createBitmap(
                bmp,0,0,bmp.getWidth(),bmp.getHeight(),matrix,true
        );


        //新建Drawable放大图文件至全屏幕
        BitmapDrawable myNewBitmapDrawable = new BitmapDrawable(resizeBitmap);

        imageView.setImageDrawable(myNewBitmapDrawable);

        //是Imageview可见
        imageView.setVisibility(View.VISIBLE);

        //每间隔设置描述切换图片Id,与下一次runable2才会生效
        if (intCounter2 % intSecondToChange == 0){

            intDrawable++;
        }
    }

定义方法onUserWakeUpEvent实现解锁和加密处理

    public void onUserWakeUpEvent(){

        if (bIfRunScreenSaver == true){


            try{

               mInflater = LayoutInflater.from(MainActivity.this);

                mView01 = mInflater.inflate(R.layout.layout,null);

                mEditText02 = (EditText)mView01.findViewById(R.id.edit_text01);


                new AlertDialog.Builder(this).setView(mView01)
                        .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {

                                if (mEditText01.getText().toString().equals(mEditText02.getText().toString())){

                                    //比较输入的密码与原Activity的设置是否相等
                                     resetScreenSaverListerner();
                                }
                            }
                        }).show();


            }catch (Exception e){

                e.printStackTrace();

            }

        }
    }

定义updateUserActionTime(),用于统计用户单击键盘或者屏幕的时间间隔,首先取得点击按钮事件时的系统时间TimeMillis,然后重新计算点击按键距离上一次静止的时间间隔。

    public void updateUserActionTime(){

        //获取点击按键事件的系统 time Millis
        Date timeNow = new Date(System.currentTimeMillis());

        //重新计算点击按键距离上一次静止的时间间隔
        timePeriod = (long)timeNow.getTime() - (long)lastUpdateTime.getTime();

        lastUpdateTime.setTime(timeNow.getTime());
    }

定义方法resetScreenSaverListerner()来重新设置屏幕

    public void resetScreenSaverListerner(){

        //删除现有的Runable
        mHandle01.removeCallbacks(mTasks);

        mHandle02.removeCallbacks(mTasks02);

        //取得点击按键时间时的系统时间
        Date timeNow = new Date(System.currentTimeMillis());

        //重新计算点击按键距离上一次静止时的时间间距
        timePeriod = (Long)timeNow.getTime() - (long)lastUpdateTime.getTime();

        lastUpdateTime.setTime(timeNow.getTime());

        //取消屏幕保护
        bIfRunScreenSaver = false;

        intCounter1 = 0;

        intCounter2 = 0;

        //回复原来的layout Visible
        recorverOriginalLayout();

        //重新postDelayed新的Runnable
        mHandle01.postDelayed(mTasks,intervarKeypadeSaver);

    }

定义onKeyDown(int keyCode, KeyEvent event)来监听用户的触摸单击事件

    public boolean onKeyDown(int keyCode, KeyEvent event){

        if (bIfRunScreenSaver == true && keyCode != 4){

            //当屏幕保护程序在运行中,触动解除屏幕保护程序
            onUserWakeUpEvent();

        }else {

            //更新User未触动手机的时间戳
            updateUserActionTime();

        }
        return super.onKeyDown(keyCode,event);
    }

其它

    @Override
    public boolean onTouchEvent(MotionEvent event) {


        if (bIfRunScreenSaver == true){

            onUserWakeUpEvent();

        }else {

            updateUserActionTime();
        }

        return super.onTouchEvent(event);
    }


    @Override
    protected void onResume() {

        mHandle01.postDelayed(mTasks,intervarKeypadeSaver);

        super.onResume();
    }

    @Override
    protected void onPause() {

        try{

            //删除运行中的线程
            mHandle01.removeCallbacks(mTasks);
            mHandle02.removeCallbacks(mTasks02);
            mHandle03.removeCallbacks(mTasks03);
            mHandle04.removeCallbacks(mTasks04);

        }catch (Exception e){

            e.printStackTrace();

        }

        super.onPause();
    }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容