一个简易的APP


记录了第一个简易app开发中遇到的知识点,以及一些自己对代码的理解

APP 预览

首先这一次我们要做一个类似于问卷的app:

字符串资源 strings.xml

每个项目都包含一个名为strings.xml的默认字符串文件。
在项目的app/res/values目录下,strings.xml文件用户统一保存整个项目的字符串资源,然后方便我们查阅管理。

引用字符串资源

strings.xml

<resources>
 <string name="app_name">GeoQuiz</string>
 <string name="true_button">TRUE</string>
</resources

在具体的布局界面中引用字符串资源

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android">
<Button
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="@string/true_button" />
</LinearLayout>

这里这个布局中具体定义的Button这个组件通过android:text="@string/true_button"就成功的调用了strings.xml文件中的TRUE,拿到了TRUE这个值。

设置事件监听器

添加组件成员变量

import android.widget.Button;
private Button mTrueButton;

引用组件

mTrueButton = (Button) findViewById(R.id.true_button);

这里先使用按钮的资源ID获取生成的对象,然后再进行Button类型的转换:(Button) findViewById(R.id.true_button)

设置监听器

监听器通俗的来说就是用户单击这个按钮出发的响应事件,需要实现View.OnClickListener接口
先实现一个空的监听器事件:

mTrueButton = (Button) findViewById(R.id.true_button);
 mTrueButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    //空的事件 这里暂时没有任何事件
    }
 });

传入setOnClickListener(OnClickListener)方法的参数是一个监听器。该参数是
一个实现了OnClickListener接口的对象。

创建提示消息

弹出我们称为toast的提示消息。Android的toast
是用来通知用户的简短弹出消息,用户无需输入或进行任何操作。

strings.xml文件完善

<string name="correct_toast">Correct!</string>
<string name="incorrect_toast">Incorrect!</string>

调用成makeText 创建提示消息

这里面弹出的toast消息其实也就是完善了上面的按钮监听事件

mTrueButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    Toast.makeText(QuizActivity.this,R.string.correct_toast,Toast.LENGTH_SHORT).show();
    }
});

这里的话,当用户点击这个mTrueButton按钮就会触发.makeText(QuizActivity.this,R.string.correct_toast,Toast.LENGTH_SHORT).show()这里就会调用correct_toast弹出strings.xml里面对应的Correct!消息。

创建新的问题类

到这里我们的APP只能进行单一的问题测试,当有很多个问题的时候,按照原来的方法去写就会很麻烦,效率也不高。所以这里我们创建一个Quesion.java类来单独的进行问题的整理。
Question.java

public class Question {
    private int mTextResId;
    private boolean mAnswerTrue;
    public Question(int textResId, boolean answerTrue) {
        mTextResId = textResId;
        mAnswerTrue = answerTrue;
    }
}

成员变量mTextResId的作用是:int类型显示问题的内容
成员变量mAnswerTrue的作用是:boolean类型的,用来判断问题的对错

int 类型的疑问

到这里小伙伴肯定有疑问了:成员变量mTextResIdint类型的,但是却用来显示问题的内容,说到内容这里我们第一时间肯定是想到了String类型.
哈哈,我也有这个疑问,还好书的作者这里给了一个很详细的解释:

变量mTextResId用来保存地理知识
问题字符串的资源ID。资源ID总是int类型,所以这里设置它为int而不是String类型

生成获取方法与设置方法

public int getTextResId() {
    return mTextResId;
}
public void setTextResId(int textResId) {
    mTextResId = textResId;
}
public boolean isAnswerTrue() {
    return mAnswerTrue;
}
public void setAnswerTrue(boolean answerTrue) {
    mAnswerTrue = answerTrue;
}

新增按钮以及文本视图调整

activity_quiz.xml

<TextView
 android:id="@+id/question_text_view"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:padding="24dp"
 />
 <Button
 android:id="@+id/next_button"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="@string/next_button" />

strings.xml

<string name="next_button">NEXT</string>

这里删除了TextViewandroid:text属性定义。取消了硬编码地理知识问题。
TextView新增android:id属性。TextView组件需要资源ID
新增了Button按钮对应了strings.xml文件里面的NEXT的值。

完善 strings.xml 问题字符串

<string name="question_xss">DOM XSS属于反射型XSS</string>
<string name="question_sql">XSS 注入不属于HTTP头注入</string>  

增加问题对象数组

QuizActivity.java

public class QuizActivity extends AppCompatActivity {
    private Button mTrueButton;
    private Button mFalseButton;
    private Button mNextButton;
    private TextView mQuestionTextView;
private Question[] mQuestionBank = new Question[] {
    new Question(R.string.question_xss, true),
    new Question(R.string.question_sql, false),
 };
 private int mCurrentIndex = 0;

通过多次调用Question类的构造方法,创建了Question对象数组

TextView 显示问题内容

    mQuestionTextView = (TextView) findViewById(R.id.question_text_view);
    int question = mQuestionBank[mCurrentIndex].getTextResId();
    mQuestionTextView.setText(question);
 }

这里首先去R.id.question_text_view找到text_view的值,然后转换为TextView类型,用int类型的question去拿到当前问题数组中的值,然后用setText(question)拿到textview的值,赋值给mQuestionTextView

为 next 按钮设置监听事件

mNextButton = (Button) findViewById(R.id.next_button);
mNextButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    mCurrentIndex = (mCurrentIndex + 1) % mQuestionBank.length;
    int question = mQuestionBank[mCurrentIndex].getTextResId();
    mQuestionTextView.setText(question);
    }
});

这里的主要的事件类型是mCurrentIndex = (mCurrentIndex + 1) % mQuestionBank.length; 这样的话就拿到了核心代码就是mCurrentIndex + 1,这里实现了问题数组往下一个切换。

封装 updateQuestion() 封公共代码

为什么要封装代码,因为我们一开始定义mQuestionTextView的时候就使用了如下的代码:

mQuestionTextView = (TextView) findViewById(R.id.question_text_view);
int question = mQuestionBank[mCurrentIndex].getTextResId();
mQuestionTextView.setText(question);

当我们 为 next 按钮触发监听事件的时候也写到了如下的代码:

public void onClick(View v) {
    mCurrentIndex = (mCurrentIndex + 1) % mQuestionBank.length;
    int question = mQuestionBank[mCurrentIndex].getTextResId();
    mQuestionTextView.setText(question);
 }

这里就出现了重复的去写一段代码了,这显然不是一个合格的程序员所做的事情,所以这里得想办法把这块重复代码进行封装一下:
定义一个updateQuestion()方法:

private void updateQuestion() {
    int question = mQuestionBank[mCurrentIndex].getTextResId();
    mQuestionTextView.setText(question);
 }

然后可以直接使用updateQuestion();来简化上面的操作。

对答案进行判断

增加方法checkAnswer(boolean),用于判断答案的正确与否:

private void updateQuestion() {
    int question = mQuestionBank[mCurrentIndex].getTextResId();
    mQuestionTextView.setText(question);
}

private void checkAnswer(boolean userPressedTrue) {
    boolean answerIsTrue = mQuestionBank[mCurrentIndex].isAnswerTrue();
    int messageResId = 0;
    if (userPressedTrue == answerIsTrue) {
        messageResId = R.string.correct_toast;
    } else {
        messageResId = R.string.incorrect_toast;
    }
    Toast.makeText(this, messageResId, Toast.LENGTH_SHORT).show();
 }

进行答案正确的基本的逻辑判断,当答案正确的时候,直接使用toast来弹出R.string.correct_toast的值;答案错误的时候,使用toast来弹出R.string.incorrect_toas的值。

为按钮设置 cheakAnswer 事件

mTrueButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    checkAnswer(true);
}
mFalseButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    checkAnswer(false);
}

第2章挑战练习

为 TextView 添加监听器

NEXT按钮不错,但如果用户单击应用的TextView文字区域(地理知识问题),也可以跳转
到下一道题,用户体验应该会更好。你来试一试。
这里面思路就是为mQuestionTextView对象也设置一个监听事件,然后功能上的代码和next按钮几乎是一样的。

 mQuestionTextView.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                mCurrentIndex = (mCurrentIndex + 1) % mQuestionBank.length;
                mIsCheater = false;
                updateQuestion();
            }
        });

添加后退按钮

为GeoQuiz应用新增后退按钮,用户单击时,可以显示上一道测试题目。
这里首先布局文件xml文件添加个 与 next按钮一样的 Button组件即可,这里不再叙述,下面写出 关键功能是 java代码,其实关键点就在于mCurrentIndex = (mCurrentIndex - 1) % mQuestionBank.length;

 mPrevButton = (Button) findViewById(R.id.prev_button);
        mPrevButton.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                mCurrentIndex = (mCurrentIndex - 1) % mQuestionBank.length;
                updateQuestion();
            }
        });

为按钮添加图标

<Button
 android:id="@+id/next_button"
 android:drawableRight="@drawable/arrow_right"
 android:drawablePadding="4dp"
 />

这里drawableRight就是将 图标添加到 按钮的 左边部分,反之要添加到 右面部分 只需要 改为:drawableLeft,这样图标就添加到左边了。


文章作者: 国光
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 国光 !
 上一篇
用户密码重置找回10种常见姿势 用户密码重置找回10种常见姿势
本篇文章是参考大神carry_your讲师(360补天排名第一)的任意用户密码重置的10种常见姿势总结的笔记。原视频地址:https://www.ichunqiu.com/course/59045 介绍本次课程主要针对挖掘逻辑漏洞中的
2017-10-26
下一篇 
Android 开发初体验 Android 开发初体验
解释了一些anroid开发中的一些基本的术语 算是一篇扫盲文章吧 Android Studio 的优势 界面美观 速度优于Eclipse 提示补全更加人性化 整合了Gradle构建工具 支持Google Cloud Platform 强大
2017-09-14
  目录