• [Android]从Helloworld开始,继续前进


    从Helloworld开始,继续前进

     

     [第二届 Google 暑期大学生博客分享大赛 - 2011 Android 成长篇]

     

      配置好了开发环境,写出了第一个Helloworld程序,很高兴。但是高兴之余又发现对于接下来的学习有点不知所措。书上介绍了很多控件怎么使用,Layout怎么使用,看了一会就觉得好烦啊。

      我觉得学习在一个平台开发程序,还是应该先自己摸索着写一点东西出来,有了一定的兴趣和成就感后,继续学习深入的开发,效果可能会更好。

      写一个小程序先。

      通过Intent实现Activity间的切换:

      第一个Activity   第二个Activity 

      通过Button和返回键,在两个Activity之前切换,这样一个程序应该很好写,网上和书上都有教程。注意点就是要新建一个布局文件,并且要把新的Activity在清单文件中注册一下。

      

      试着把这样一个简单的程序改成一个小游戏。

     

      Intent的另外一个功能,就是在两个Activity之前传递数据。这个功能非常有用,假设第一个Activity是刚进入游戏时的界面,有开始游戏、选择难度、游戏帮助、退出游戏等选项,第二个Activity则是真正的游戏界面,那么当从第一个Activity进入到第二个Activity时,肯定是要传递一些数据的,比方说难度、玩家昵称。现在把这样一个传输的功能简单实现一下。

      1.把第一个Activity的UI改成这样,即添加一个EditText控件,用ADT编辑布局文件即可。

      

      2.修改代码,第一个Activity:

    public class MoveActivity extends Activity {
    private Button jump;
    private EditText et;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    jump
    =(Button)findViewById(R.id.jump);//得到控件对象的引用
    et=(EditText)findViewById(R.id.nickname);
    jump.setOnClickListener(
    new OnClickListener() {
    @Override
    public void onClick(View v) {
    // TODO Auto-generated method stub
    Intent i=new Intent();
    i.setClass(MoveActivity.
    this, Game.class);//设置Intent
    String nickName=et.getText().toString();//得到EditText中的内容
    i.putExtra("NickName", nickName);//加入附加信息 nickname
    i.putExtra("Grade", 10);//Grade
    startActivity(i);//启动第二个Activity
    }
    });
    }
    }

      记得import进相应的包,Ctrl+Shift+O即可

      3.在第二个Activity中再加入两个TextView,然后修改代码:

    public class Game extends Activity {
    private TextView tv1,tv2,tv3;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setContentView(R.layout.game);
    tv1
    =(TextView)findViewById(R.id.tv1);//得到控件对象的引用
    tv2=(TextView)findViewById(R.id.tv2);//id已修改
    tv3=(TextView)findViewById(R.id.tv3);
    //得到Intent对象
    Intent i=getIntent();
    //从Intent对象中得到附加信息并在TextView中显示出来
    String nickName=i.getStringExtra("NickName");
    int iGrade=i.getIntExtra("Grade", 0);//默认是0
    tv2.setText(nickName);//设置TextView
    tv3.setText(""+iGrade);
    }
    }

      同样注意import。

      运行看结果后就可以看到数据传输是成功的。

      4.在第二个Activity中添加16个Button,4x4。因为xml里面默认布局是vertical的LinearLayout,所以只要先在UI中加一个LinearLayout(Horizontal),然后再加四个Button,如此重复四次即可。

      

      如果现在我说这已经是一个游戏了,你肯定不信。

      还记得小时候玩过的那种移拼图的玩具吗?

      

      应该有想法了吧。

      5.修改第二个Activity中的代码,让它变成一个Android上的移拼图小游戏。其实这已经和Android无关了,看的是Java和算法的基础。文章最后给出代码。

         

         

      说到写游戏,我想到的是游戏中的主循环。于是我试着在Android中模拟了一下,发现了一个问题。

      原先的想法是:在一个TextView中显示一个数字,然后在Activity中启动一个线程,该线程每隔一定的时间让TextView中显示的数字加1。

      看上去这十分简单,但是写了之后我才发现,单纯的这样做是不可行的,因为一个线程不能更改非该线程创建的控件的内容。网上看到的解决办法是使用Handler。具体请见这里。非常感谢原文作者的分享。

      使用这个方法,我让第二个Activity中的tv3里面的内容每隔一定时间加1。

      最终效果图:

        

      

      这离一个正式的游戏当然还距离很远,但是,如果看过这篇文章后,一些原本不善于思考的人能变得善于思考,例如,你会不会开始思考Menu和返回键在这个程序中的作用,会不会思考NumberAdder线程到底应该在OnCreate、OnStart、OnRestart等的哪个生命周期函数中被创建,会不会试着加一个Service进去,会不会试着让Button间的间距减小然后把数字替换成图片,会不会增加代码以判断游戏是否结束,等等,只要能够增加一点想法,那看过这篇文章就算值得了吧。

       

      不足之处,请不吝赐教,谢谢!

      

      最后是第二个Activity的代码,供参考,项目源代码下载

    package Yuleo.Android;

    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.util.Log;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.TextView;

    public class Game extends Activity {
    private TextView tv1,tv2,tv3;//三个TextView的引用
    private Button[][] allButtons;//所有Button对象的引用的二维数组
    private int[][] allValues;//Button对象对应的数值,另外一种办法是用Button的继承类

    //Handler
    static final int UPDATE_TV2=1;//消息的定义
    Handler h=new Handler()
    {
    @Override
    public void handleMessage(Message msg) {
    // TODO Auto-generated method stub
    super.handleMessage(msg);
    switch(msg.what)
    {
    case UPDATE_TV2://处理tv3中数字的增加
    {
    String sNum
    =(String) tv3.getText();//得到String并转为int
    Integer i=new Integer(sNum);
    int iNum=i.intValue();
    iNum
    ++;
    tv3.setText(
    ""+iNum);//更新
    break;
    }
    }
    }

    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setContentView(R.layout.game);
    tv1
    =(TextView)findViewById(R.id.tv1);//得到控件对象的引用
    tv2=(TextView)findViewById(R.id.tv2);//id已修改
    tv3=(TextView)findViewById(R.id.tv3);
    Intent i
    =getIntent();
    String nickName
    =i.getStringExtra("NickName");
    int iGrade=i.getIntExtra("Grade", 0);//默认是0
    tv2.setText(nickName);//设置TextView
    tv3.setText(""+iGrade);

    allButtons
    =new Button[5][5];//Button控件
    allButtons[1][1]=(Button)findViewById(R.id.button11);
    allButtons[
    1][2]=(Button)findViewById(R.id.button12);
    allButtons[
    1][3]=(Button)findViewById(R.id.button13);
    allButtons[
    1][4]=(Button)findViewById(R.id.button14);
    allButtons[
    2][1]=(Button)findViewById(R.id.button21);
    allButtons[
    2][2]=(Button)findViewById(R.id.button22);
    allButtons[
    2][3]=(Button)findViewById(R.id.button23);
    allButtons[
    2][4]=(Button)findViewById(R.id.button24);
    allButtons[
    3][1]=(Button)findViewById(R.id.button31);
    allButtons[
    3][2]=(Button)findViewById(R.id.button32);
    allButtons[
    3][3]=(Button)findViewById(R.id.button33);
    allButtons[
    3][4]=(Button)findViewById(R.id.button34);
    allButtons[
    4][1]=(Button)findViewById(R.id.button41);
    allButtons[
    4][2]=(Button)findViewById(R.id.button42);
    allButtons[
    4][3]=(Button)findViewById(R.id.button43);
    allButtons[
    4][4]=(Button)findViewById(R.id.button44);
    //这个真没办法偷懒


    allValues
    =new int[5][5];//数组对象

    for(int r=1;r<=4;r++)//row column
    {
    for(int c=1;c<=4;c++)
    {
    allValues[r][c]
    =(r-1)*4+c;
    if(allValues[r][c]<10)
    {
    allButtons[r][c].setText(
    " "+allValues[r][c]+" ");
    //加空格固定Button的宽度,也可以通过布局文件来固定
    }
    else
    {
    allButtons[r][c].setText(
    " "+allValues[r][c]+" ");
    }
    }
    }

    //修改右下角那个Button
    allValues[4][4]=111;
    allButtons[
    4][4].setText(" ");

    //设置监听器
    for(int r=1;r<=4;r++)
    {
    for(int c=1;c<=4;c++)
    {
    GameListener gl
    =new GameListener(r,c);
    allButtons[r][c].setOnClickListener(gl);

    }
    }
    }


    //Button监听器类,内部类可以方便地访问外部类中的成员变量
    class GameListener implements OnClickListener
    {
    private int iRow,iColumn;
    GameListener(
    int r, int c)
    {
    iRow
    =r;
    iColumn
    =c;
    }
    @Override
    public void onClick(View v) {
    // TODO Auto-generated method stub

    if(iRow>1)//上面有按钮的话
    {
    if(allValues[iRow-1][iColumn]==111)//如果上面那个按钮为空
    {
    //交换数据
    int iTemp=allValues[iRow][iColumn];
    allValues[iRow][iColumn]
    =111;
    allValues[iRow
    -1][iColumn]=iTemp;

    //交换显示的内容
    String sTemp=(String) (allButtons[iRow][iColumn]).getText();
    allButtons[iRow][iColumn].setText(allButtons[iRow
    -1][iColumn].getText());
    allButtons[iRow
    -1][iColumn].setText(sTemp);
    return ;
    }
    }

    if(iRow<4)//下面有按钮的话
    {
    if(allValues[iRow+1][iColumn]==111)
    {
    int iTemp=allValues[iRow][iColumn];
    allValues[iRow][iColumn]
    =111;
    allValues[iRow
    +1][iColumn]=iTemp;

    String sTemp
    =(String) (allButtons[iRow][iColumn]).getText();
    allButtons[iRow][iColumn].setText(allButtons[iRow
    +1][iColumn].getText());
    allButtons[iRow
    +1][iColumn].setText(sTemp);
    return ;
    }
    }

    if(iColumn>1)//左边有按钮的话
    {
    if(allValues[iRow][iColumn-1]==111)
    {
    int iTemp=allValues[iRow][iColumn];
    allValues[iRow][iColumn]
    =111;
    allValues[iRow][iColumn
    -1]=iTemp;

    String sTemp
    =(String) (allButtons[iRow][iColumn]).getText();
    allButtons[iRow][iColumn].setText(allButtons[iRow][iColumn
    -1].getText());
    allButtons[iRow][iColumn
    -1].setText(sTemp);
    return ;
    }
    }

    if(iColumn<4)//右边有按钮的话
    {
    if(allValues[iRow][iColumn+1]==111)
    {
    int iTemp=allValues[iRow][iColumn];
    allValues[iRow][iColumn]
    =111;
    allValues[iRow][iColumn
    +1]=iTemp;

    String sTemp
    =(String) (allButtons[iRow][iColumn]).getText();
    allButtons[iRow][iColumn].setText(allButtons[iRow][iColumn
    +1].getText());
    allButtons[iRow][iColumn
    +1].setText(sTemp);
    return ;
    }
    }
    }
    }

    //线程类,用于让tv3中的数字增加
    class NumberAdder implements Runnable
    {
    @Override
    public void run() {
    // TODO Auto-generated method stub
    for(int j=1;j<20;j++)
    {
    try
    {
    Thread.sleep(
    1000);
    Message msg
    = new Message();
    msg.what
    = UPDATE_TV2;//给Handler发消息,让Handler去处理
    h.sendMessage(msg);
    }
    catch (Exception e)
    {

    }
    }
    }
    }

    @Override
    protected void onStart() {
    // TODO Auto-generated method stub
    super.onStart();
    //建立线程
    NumberAdder na=new NumberAdder();
    new Thread(na).start();
    }
    }


      

      

  • 相关阅读:
    k8s使用
    7月3日课堂笔记
    7月6日课堂笔记
    画倒三角形
    6月29日课堂笔记
    understand试用笔记一阅读VS2010项目
    Spring Boot 入门(九)使用RabbitMQ
    Spring Boot 入门(十一)使用Schedule
    Spring Boot 入门(十三)使用Elasticsearch
    学习MySQL
  • 原文地址:https://www.cnblogs.com/yubin/p/HelloworldGo.html
Copyright © 2020-2023  润新知