美文网首页
05 Anykey阶段性总结、bug汇总及解决

05 Anykey阶段性总结、bug汇总及解决

作者: 85b64b9f7de3 | 来源:发表于2017-12-04 12:19 被阅读15次

    首发于:http://blog.csdn.net/Likianta/article/details/78690286

    对前四章的学习进行一次回顾和总结,本章集中解决之前的代码中产生的各种bug,尝试翻新结构以及使用更好的开源插件。

    1. 先讲一下如何在真机上调试app

    这里以红米Note2手机(MIUI9 开发版)为例:

    1. 准备一条可以传输数据的数据线
    2. 手机在开发者选项中启用“USB调试”和“允许USB安装”
    3. 手机连接PC
    4. 在Android Studio中运行AVD,选择“Xiaomi Redmi Note 2”,app将会安装到手机中
    5. 在初次安装中需要自己在手机上点击接受。安装完成后的调试会自动启动app

    注意事项:

    1. 一定要选择可以传输数据的数据线
    2. 不同的手机开启开发者选项的方式不同,小米手机(MIUI9 开发版)的开启方式为连续点击MIUI版本号6次进入开发者模式
    3. 如果Android Studio在运行时提示“error:前言中不允许有内容”,则点击菜单栏 - Build - Rebuild Project即可解决

    参考:http://m.blog.csdn.net/wenxin2011/article/details/50845563


    2. 实机测试问题汇总

    2.1. 首次创建密码后无法进入主界面

    这是因为第一章中忘了在LoginActivity中写intent的跳转代码了。

    解决方法:在LoginActivity的“进入(loginOn)”按钮的监听事件中,创建密码成功则跳转至主界面

    修改代码如下:

    LoginActivity.java:

    public class LoginActivity extends AppCompatActivity {
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
    
            //触发点击事件,监听登录按钮
            loginOn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
    
                    if (saved_userPassword.equals("N/A")) {
                        //首次使用的业务逻辑
               
                        ...
    
                        Toast.makeText(LoginActivity.this, "创建成功", Toast.LENGTH_SHORT).show();
                        //跳转至主界面
                        Intent intent = new Intent(LoginActivity.this, MainActivity.class);
                        LoginActivity.this.startActivity(intent);
                        finish();
                    }
                }
            });
        }
    }
    
    

    2.2. 登录界面在输入错误时软键盘不能自动弹出

    1. 首先修改Enter键的监听,将返回值改为“true”。其他代码保持不变
    2. 然后在“进入”按钮的点击监听事件中,判断登录成功,则强制关闭软键盘。其他代码保持不变

    修改代码如下:

    LoginActivity.java:

    public class LoginActivity extends AppCompatActivity {
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
    
            //触发点击事件,监听登录按钮
            loginOn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
    
                    if (saved_userPassword.equals("N/A")) {
                        //首次使用的业务逻辑
                        ...
    
                    } else {
                        //判断输入的密码是否正确
                        if (passwordValue.equals(saved_userPassword)) {
    
                            //通过调用输入管理器来隐藏软键盘
                            InputMethodManager inputMethodManager = (InputMethodManager) etPassword.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
                            inputMethodManager.hideSoftInputFromWindow(etPassword.getWindowToken(), 0); //强制隐藏软键盘
    
                            ...
    
                        }
                        
                    }
                }
            });
            
            //另外再设置一个监听软键盘输入,当输入Enter的时候,也能触发上面的登录按钮
            etPassword.setOnKeyListener(new View.OnKeyListener() {
                @Override
                public boolean onKey(View view, int i, KeyEvent keyEvent) {
                    if (i == keyEvent.KEYCODE_ENTER) {
                        loginOn.callOnClick(); //callOnClick是performClick的简化版,适合简单触发点击监听事件
                        return true;
                    }
                    return false;
                }
            });
        }
    }
    
    

    参考:Android 手动显示和隐藏软键盘 - 一点点征服 - 博客园 https://www.cnblogs.com/ldq2016/p/6861128.html

    2.3. 密码错误时的提示语不醒目

    之前的效果是当密码多次输入错误时,欢迎语文字都不会变化,所以看起来不醒目;
    下图是更改后的样式——每次密码错误,提示语都会变成红色并且闪烁一下:

    image

    实现思路为:当输入错误时,设置文本颜色为亮红色,然后利用透明度动画AlphaAnimation来完成颜色的由亮到浅的变化(动画持续时间在300-800ms之间)。代码如下所示:

    LoginActivity.java:

    public class LoginActivity extends AppCompatActivity {
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
    
            //判断是否为首次使用
            changeLoginWelcome(saved_userPassword); //将原先的“LoginWelcome”更改为“changeLoginWelcome”,用于专门处理欢迎语的变化
    
            //触发点击事件,监听登录按钮
            loginOn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
    
                    if (saved_userPassword.equals("N/A")) {
                        //首次使用的业务逻辑
                        ...
                    } else {
                        //非首次登录时的常规业务
                        if (passwordValue.equals(saved_userPassword)) {
                            ...
                        } else {
                            //密码错误时的业务
                            changeLoginWelcome("WRONG_CODE"); //欢迎语的变化放在changeLoginWelcome中处理
    
                            etPassword.setText(""); //重置密码框为空
                            
                            //让输入框重新获取焦点
                            etPassword.setFocusable(true);
                            etPassword.setFocusableInTouchMode(true);
                            etPassword.requestFocus();
                            //通过调用输入管理器来自动弹出软键盘
                            InputMethodManager inputMethodManager = (InputMethodManager) etPassword.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
                            inputMethodManager.showSoftInput(etPassword, 0);
                        }
                    }
                }
            });
        }
    
    
        //判断是否为首次使用,不是的话什么都不做
        public void changeLoginWelcome(String userCode) {
            
            switch (userCode) {
                case "N/A":
                    //首次使用时是欢迎语
                    loginWelcome.setText("首次使用\n请创建你的主密码");
                    break;
                case "WRONG_CODE":
                    //密码输入错误时的欢迎语
                    loginWelcome.setText("密码错误\n请重新登录");//在“欢迎词”中显示出错提示
                    loginWelcome.setTextColor(0xFFF4297E);//显示为红色
                    final AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0.6f);//不透明度的参数取值是小数,范围在0-1之间,0表示完全透明,1表示完全显示
                    alphaAnimation.setDuration(500);
                    alphaAnimation.setFillAfter(true); //表示停留在最终状态上
                    loginWelcome.setAnimation(alphaAnimation);
                    alphaAnimation.startNow();
                    break;
            }
        }
    }
    
    

    2.4. 在登录界面按返回键无法退出

    解决方法:新增一个按键监听设置,当按返回键时,则finish掉当前Activity:

    LoginActivity.java:

    public class LoginActivity extends AppCompatActivity {
        
        @Override
        public void onCreate(Bundle savedInstanceState) {
            ...
        }
    
    
        //监听按下的按键,如果按下了返回键,则退出登录界面
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent keyEvent) {
            
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                LoginActivity.this.finish();
                return true;
            }
            
            return super.onKeyDown(keyCode, keyEvent);
        }
    }
    
    

    PS:为什么要使用finish(),而不使用onDestroy()或者System.exit(0)

    finish是把当前Activity关闭,而onDestroy会销毁当前Activity的实例,System.exit(0)则会将当前整个进程给终结掉。
    在实际使用中会发现,后两者在退出时屏幕会闪一下,而使用finish退出,退出动画更加自然一些。

    参考:安卓开发-Activity中finish() onDestroy() 和System.exit()的区别 - CSDN博客 http://blog.csdn.net/imzoer/article/details/9380807

    2.5. 一进入主界面软键盘就自动弹出

    这是因为MainActivity的子分页布局里面有EditText控件,这个EditText会率先获取焦点,导致软键盘检测并触发弹出。
    解决方法也很简单,在MainActivity中设置键盘默认不许自动弹出即可(只需新增一行代码):

    MainActivity.java:

    public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
    
            //开始绑定按钮
            ...
    
            //http://blog.csdn.net/Vivian8725118/article/details/23184501
            getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
    
        }
    }
    
    

    参考:Android避免进入页面EditText自动弹出软键盘 - CSDN博客 http://blog.csdn.net/Vivian8725118/article/details/23184501

    2.6. 主界面顶部标签文字下的指示器的位置有问题

    这是因为代码中用的是绝对位置,不是相对位置引起的。其实这个坑早就该填了,现在使用开源库CircleIndicator来重新实现指示器的功能。

    CircleIndicator的Github地址:GitHub - ongakuer/CircleIndicator: A lightweight viewpager indicator like in nexus 5 launcher https://github.com/ongakuer/CircleIndicator

    2.6.1. 首先添加库的依赖(app:build.gradle):

    dependencies {
        compile 'me.relex:circleindicator:1.2.2'
    }
    
    

    添加完后注意点击页面右上角的Sync Now

    Sync Now

    2.6.2. 修改activity_main.xml文件

    activity_main.xml中重新修改标题栏的两个文字属性(宽度改为0,weight改为1:1,margin各距100dp)。
    然后删除原indicator,新增一个CircleIndicator。

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.likianta.anykey.MainActivity">
        
        <!--LinearLayout代替原标题栏的位置-->
        <LinearLayout
            android:id="@+id/linearLayout"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="#ffffff">
            <!--?attr/actionBarSize表示匹配原actionBar高度-->
            
            <!--显示两个标题-->
            <TextView
                android:id="@+id/title_all"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_marginStart="100dp"
                android:layout_weight="1.0"
                android:gravity="center_vertical|end"
                android:padding="15dp"
                android:text="全部"
                android:textColor="@color/mycolorText1"
                android:textSize="20sp" />
            
            <TextView
                android:id="@+id/title_new"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_marginEnd="100dp"
                android:layout_weight="1.0"
                android:gravity="center_vertical|start"
                android:padding="15dp"
                android:text="新增"
                android:textColor="@color/mycolorText2"
                android:textSize="20sp" />
            <!--这里设置的两个文本的初始状态是文字1是深色,文字2是浅色。
            之后会在函数中实现点击变色的功能-->
        
        </LinearLayout>
        
        <!--制作线条,line1是标题栏下的阴影-->
        <TextView
            android:id="@+id/shadow_line1"
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:layout_alignBottom="@id/linearLayout"
            android:background="@color/mycolorLineShadow" />
        
        <!--制作主体部分viewpager-->
        <android.support.v4.view.ViewPager
            android:id="@+id/viewPager"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/shadow_line1">
        </android.support.v4.view.ViewPager>
        
        <!--指示器,紧贴着文字下方的一个小短线,用于指示当前页面编号-->
        <me.relex.circleindicator.CircleIndicator
            android:id="@+id/indicator"
            android:layout_width="match_parent"
            android:layout_height="5dp"
            android:layout_above="@id/viewPager"
            android:layout_marginBottom="1dp"
            app:ci_drawable="@drawable/shape_indicator"
            app:ci_margin="22dp"
            app:ci_width="25dp" />
    
    </RelativeLayout>
    

    在CircleIndicator中用到了app:ci_drawable="@drawable/shape_indicator",这个shape只是一个简单的黑色背景,代码如下(在drawable目录下新建shape_indicator.xml):

    <shape xmlns:android="http://schemas.android.com/apk/res/android">
        <solid android:color="@color/mycolorText1" />
        <corners android:radius="8dp" />
    </shape>
    

    实际效果图如下:

    image

    2.6.3. 在MainActivity中创建indicator并绑定

    MainActivity.java

    public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    
        private CircleIndicator indicator; //将原先的ImageView indicator改为CircleIndicator indicator滚动指示器
    
        /*这三行可以删掉了
        private int offset = 0; //滚动条初始偏移量
        private int currIndex = 0; //当前页编号
        private int bmpW; //滚动条宽度
        private int one; //一倍滚动量
        */
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            
            indicator = (CircleIndicator) findViewById(R.id.indicator);
    
            ...
    
            //初始化适配器数据
            PagerAdapter pagerAdapter = new PagerAdapter() {...};
    
            //绑定适配器
            viewPager.setAdapter(pagerAdapter);
            //装载indicator,只需短短一行代码就替代了之前的初始化、一倍位移量等各种操作
            indicator.setViewPager(viewPager);
    
            //设置viewPager的初始界面为第一个界面
            ...
        }
    
        //页面滚动监听器功能,实现标签页左右滑动切换效果
        public class MyOnPageChangeListener implements ViewPager.OnPageChangeListener {
            
            @Override
            public void onPageSelected(int index) {
                switch (index) {
                    case 0:
                        titleAll.setTextColor(0xff000000);//0x表示整型,ff表示透明度为0,最后的6位数字表示颜色,必须这样写,不能省略
                        titleNew.setTextColor(0xff8e8e8e);
                        break;
                    case 1:
                        titleNew.setTextColor(0xff000000);
                        titleAll.setTextColor(0xff8e8e8e);
                        break;
                }
            }
            
            @Override
            public void onPageScrolled(int arg0, float arg1, int arg2) {
            }
            
            @Override
            public void onPageScrollStateChanged(int arg0) {
            }
        }
    
        /*这里可以删除了
        public void InitScrollbar(int bmpW) {...}
        */
    
    }
    
    

    3. 布局地图

    该流程图用于梳理整体的布局逻辑以及命名规范:

    image

    相关参考

    1. Android 手动显示和隐藏软键盘 - 一点点征服 - 博客园 https://www.cnblogs.com/ldq2016/p/6861128.html
    2. http://m.blog.csdn.net/wenxin2011/article/details/50845563
    3. 安卓开发-Activity中finish() onDestroy() 和System.exit()的区别 - CSDN博客 http://blog.csdn.net/imzoer/article/details/9380807
    4. Android避免进入页面EditText自动弹出软键盘 - CSDN博客 http://blog.csdn.net/Vivian8725118/article/details/23184501
    5. 第三方框架ViewPagerIndicator引入到Android Studio的方法总结 - chironmy - 博客园 https://www.cnblogs.com/baipengzhan/p/6286619.html
    6. GitHub - ongakuer/CircleIndicator: A lightweight viewpager indicator like in nexus 5 launcher https://github.com/ongakuer/CircleIndicator
    7. android开发之GridLayout详解 - CSDN博客 http://blog.csdn.net/huangxiaominglipeng/article/details/17448045
    8. scrollview底部加入不滑动的button - CSDN博客 http://blog.csdn.net/lzq520210/article/details/49333321
    9. **【Android】EditText 遇到软键盘遮挡底部一点的问题 - CSDN博客 http://blog.csdn.net/xiaoguda1/article/details/52084248 **
    10. android selector 和 layer-list复合使用 - CSDN博客 http://blog.csdn.net/qq_20976303/article/details/51162649
    11. Android 显示和隐藏软键盘 - 简书 http://www.jianshu.com/p/dc9387417914

    日志

    2017年11月26日

    1. 【修改】解决登录界面密码输入错误键盘无法自动回弹的问题
    2. 【更新】登录界面的欢迎语的判断逻辑统一放在changeLoginWelcome()中
    3. 【更新】当登录密码输入错误时,欢迎语变为红色并闪烁一下(利用AlphaAnimation属性)

    2017年11月27日

    1. 【修改】解决登录界面按返回键无法退出的问题
    2. 【修改】解决一进入主界面键盘就自动弹出的问题
    3. 【更新】解决指示器位置不准确的问题,换用开源库CircleIndicator实现指示器功能
    4. 【修改】解决EditText的背景的下半边被软键盘遮挡的问题
    5. 【新增】制作布局地图,梳理逻辑

    2017年11月28日

    1. 【创建】Github Project

    相关文章

      网友评论

          本文标题:05 Anykey阶段性总结、bug汇总及解决

          本文链接:https://www.haomeiwen.com/subject/pjatixtx.html