Android开发(14)-- 多线程中实现利用自定义控件绘制小球并完成小球自动下落的功能

1、布局界面

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:paddingBottom="@dimen/activity_vertical_margin"
  6. android:paddingLeft="@dimen/activity_horizontal_margin"
  7. android:paddingRight="@dimen/activity_horizontal_margin"
  8. android:paddingTop="@dimen/activity_vertical_margin"
  9. tools:context=".GameActivity" >
  10. <www.csdn.net.tetris.view.GameView
  11. android:id="@+id/gameview"
  12. android:layout_width="wrap_content"
  13. android:layout_height="wrap_content"/>
  14. <Button
  15. android:id="@+id/btn_left"
  16. android:layout_width="wrap_content"
  17. android:layout_height="wrap_content"
  18. android:layout_alignLeft="@+id/gameview"
  19. android:layout_alignParentBottom="true"
  20. android:text="@string/btn_text" />
  21. <Button
  22. android:id="@+id/btn_right"
  23. android:layout_width="wrap_content"
  24. android:layout_height="wrap_content"
  25. android:layout_alignBottom="@+id/gameview"
  26. android:layout_centerHorizontal="true"
  27. android:layout_alignParentBottom="true"
  28. android:text="@string/btn_right" />
  29. </RelativeLayout>
<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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".GameActivity" >


    <www.csdn.net.tetris.view.GameView 
        android:id="@+id/gameview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <Button
        android:id="@+id/btn_left"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/gameview"
        android:layout_alignParentBottom="true"
        android:text="@string/btn_text" />

    <Button
        android:id="@+id/btn_right"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/gameview"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true"
        android:text="@string/btn_right" />

    

</RelativeLayout>


2、封装的一个绘制的图的类

  1. package www.csdn.net.tetris.domain;
  2. import www.csdn.net.tetris.view.GameView;
  3. public class Block {
  4. private int x=20,y=20;
  5. public GameView gameView;
  6. public Block(GameView gameView){
  7. this.gameView=gameView;
  8. }
  9. //向左移动
  10. public void moveLeft(){
  11. x-=10;
  12. gameView.invalidate();
  13. }
  14. //向右移动
  15. public void moveRight(){
  16. x+=10;
  17. gameView.invalidate();
  18. }
  19. //下落方法
  20. public void downLoad(){
  21. y+=10;
  22. gameView.invalidate();//重新绘制
  23. }
  24. public int getX() {
  25. return x;
  26. }
  27. public void setX(int x) {
  28. this.x = x;
  29. }
  30. public int getY() {
  31. return y;
  32. }
  33. public void setY(int y) {
  34. this.y = y;
  35. }
  36. }
package www.csdn.net.tetris.domain;

import www.csdn.net.tetris.view.GameView;

public class Block {

	private int x=20,y=20;
	
	
	public GameView gameView;
	public Block(GameView gameView){
		this.gameView=gameView;
	}
	
	

	//向左移动
	public void moveLeft(){
		x-=10;
		gameView.invalidate();
	}
	
	//向右移动
	public void moveRight(){
		x+=10;
		gameView.invalidate();
	}
	
	//下落方法
		public void downLoad(){
			y+=10;
			gameView.invalidate();//重新绘制
		}
	
	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}
	
	
}


3、创建一个画布和线程的操作

  1. package www.csdn.net.tetris.view;
  2. import android.content.Context;
  3. import android.graphics.Canvas;
  4. import android.graphics.Paint;
  5. import android.os.Handler;
  6. import android.os.Message;
  7. import android.util.AttributeSet;
  8. import android.view.View;
  9. import www.csdn.net.tetris.domain.Block;
  10. public class GameView extends View {
  11. public static Block block;
  12. public Handler handler;
  13. //定义方向
  14. public static int dir=-1;
  15. //上下左右
  16. public static final int DIRUP=1;
  17. public static final int DIRDOWN=2;
  18. public static final int DIRLEFT=3;
  19. public static final int DIRRIGHT=4;
  20. public GameView(Context context,AttributeSet attrs) {
  21. super(context);
  22. //创建俄罗斯方块对象
  23. this.block=new Block(this);
  24. handler=new Handler(){
  25. public void handleMessage(Message msg) {
  26. super.handleMessage(msg);
  27. switch (msg.what) {
  28. case DIRLEFT:
  29. GameView.block.moveLeft();
  30. break;
  31. case DIRRIGHT:
  32. GameView.block.moveRight();
  33. break;
  34. default:
  35. GameView.block.downLoad();
  36. break;
  37. }
  38. }
  39. };
  40. //创建线程
  41. new Thread (new Runnable(){
  42. @Override
  43. public void run() {
  44. while(true){
  45. try{
  46. System.out.println("子线程名称:::"+Thread.currentThread().getName());
  47. //block.downLoad();
  48. Thread.sleep(1000);
  49. handler.sendEmptyMessage(dir);
  50. }catch(Exception e){
  51. e.printStackTrace();
  52. }
  53. }
  54. }
  55. }).start();
  56. }
  57. @Override
  58. protected void onDraw(Canvas canvas) {
  59. super.onDraw(canvas);
  60. //设置了画布的颜色
  61. canvas.drawARGB(255, 0, 0, 255);
  62. //设置一个画笔
  63. Paint paint=new Paint();
  64. paint.setARGB(255, 255, 0, 0);
  65. canvas.drawCircle(block.getX(), block.getY(), 10, paint);
  66. }
  67. }
package www.csdn.net.tetris.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.View;
import www.csdn.net.tetris.domain.Block;

public class GameView extends View {

	public static Block block;
	
	public Handler handler;
	//定义方向
	public static  int dir=-1;
	//上下左右
	public static final int DIRUP=1;
	public static final int DIRDOWN=2;
	public static final int DIRLEFT=3;
	public static final int DIRRIGHT=4;
	
	public GameView(Context context,AttributeSet attrs) {
		super(context);
		//创建俄罗斯方块对象
		this.block=new Block(this);
		
		
		handler=new Handler(){
			public void handleMessage(Message msg) {
				super.handleMessage(msg);
				switch (msg.what) {
				case DIRLEFT:
					GameView.block.moveLeft();
					break;
				case DIRRIGHT:
					GameView.block.moveRight();
					break;
				
					
				default:
					GameView.block.downLoad();
					break;
				}

			}
		};
		
		
		
		
		//创建线程
		new Thread (new Runnable(){

			@Override
			public void run() {
				while(true){
					try{
						System.out.println("子线程名称:::"+Thread.currentThread().getName());
						//block.downLoad();
						Thread.sleep(1000);
						handler.sendEmptyMessage(dir);
					}catch(Exception e){
						e.printStackTrace();
					}
				}
				
			}
			
		}).start();
	}

	@Override
	protected void onDraw(Canvas canvas) {
		
		super.onDraw(canvas);
		//设置了画布的颜色
		canvas.drawARGB(255, 0, 0, 255);
		//设置一个画笔
		Paint paint=new Paint();
		paint.setARGB(255, 255, 0, 0);
		canvas.drawCircle(block.getX(), block.getY(), 10, paint);
	}
	
}


4、在MainActivity中的操作

  1. package com.example.tetris;
  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. import android.os.Handler;
  5. import android.os.Message;
  6. import android.view.Menu;
  7. import android.view.View;
  8. import android.widget.Button;
  9. import android.widget.Toast;
  10. import www.csdn.net.tetris.domain.Block;
  11. import www.csdn.net.tetris.view.GameView;
  12. public class GameActivity extends Activity {
  13. //声明按钮控件
  14. public Button btn_start;
  15. public Button btn_right;
  16. public Button btn_left;
  17. @Override
  18. protected void onCreate(Bundle savedInstanceState) {
  19. super.onCreate(savedInstanceState);
  20. setContentView(R.layout.activity_game);
  21. //获取按钮控件
  22. btn_start=(Button) findViewById(R.id.btn_start);
  23. btn_start.setOnClickListener(new MyOnClickListener());
  24. System.out.println("主线程:::"+Thread.currentThread().getName());
  25. }
  26. @Override
  27. public boolean onCreateOptionsMenu(Menu menu) {
  28. // Inflate the menu; this adds items to the action bar if it is present.
  29. getMenuInflater().inflate(R.menu.main, menu);
  30. return true;
  31. }
  32. class MyOnClickListener implements View.OnClickListener{
  33. @Override
  34. public void onClick(View v) {
  35. int id=v.getId();
  36. switch (id) {
  37. case R.id.btn_start:
  38. //GameView gameView=new GameView(GameActivity.this,null);
  39. GameActivity.this.setContentView(R.layout.activity_layout);
  40. //获取控件
  41. btn_right=(Button) findViewById(R.id.btn_right);
  42. btn_left=(Button) findViewById(R.id.btn_left);
  43. btn_left.setOnClickListener(new MyOnClickListener());
  44. btn_right.setOnClickListener(new MyOnClickListener());
  45. break;
  46. case R.id.btn_left:
  47. Toast.makeText(GameActivity.this, "向左移动", Toast.LENGTH_LONG).show();
  48. GameView.block.moveLeft();
  49. //GameView.dir=GameView.DIRLEFT;
  50. break;
  51. case R.id.btn_right:
  52. Toast.makeText(GameActivity.this, "向右移动", Toast.LENGTH_LONG).show();
  53. GameView.block.moveRight();
  54. //GameView.dir=GameView.DIRRIGHT;
  55. break;
  56. default:
  57. break;
  58. }
  59. }
  60. }
  61. }
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,下面是详细的代码实现。 首先,在主线程定义一个 Handler 对象,并覆写其 handleMessage() 方法: ``` private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_CHANGE_COLOR: int color = msg.arg1; mRootView.setBackgroundColor(color); break; default: break; } } }; ``` 上述代码,MSG_CHANGE_COLOR 是自定义的消息类型,用于指示要改变背景颜色。handleMessage() 方法根据消息类型执行相应的操作,这里只有一种类型,即改变背景颜色。其 msg.arg1 是消息携带的参数,即要改变的颜色值。 接下来,我们在子线程发送消息,以触发主线程的 handleMessage() 方法。这里我们使用 Message.obtain() 方法获取一个 Message 对象,并设置其 what 和 arg1 属性: ``` private void changeColor(final int color) { new Thread(new Runnable() { @Override public void run() { Message msg = Message.obtain(); msg.what = MSG_CHANGE_COLOR; msg.arg1 = color; mHandler.sendMessage(msg); } }).start(); } ``` 上述代码,changeColor() 方法是在子线程执行的,它接收一个颜色值作为参数,然后创建一个新的线程,并在其获取一个 Message 对象并设置其属性,最后使用 mHandler.sendMessage() 方法将消息发送到主线程。 最后,我们在 Activity 的 onCreate() 方法调用 changeColor() 方法,即可实现自动化变化界面背景颜色的功能: ``` @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); changeColor(Color.RED); changeColor(Color.GREEN); changeColor(Color.BLUE); } ``` 上述代码,我们先设置了布局文件,然后依次调用 changeColor() 方法修改背景颜色为红、绿、蓝三种颜色。由于 changeColor() 方法是在子线程执行的,因此它们不会阻塞主线程,而是通过消息传递机制与主线程通信,完成自动化变化界面背景颜色的功能

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值