我穿越回2013年,拿到一台旧电脑,只为给Android2.3设备写一个时钟程序

昨天收拾屋子,翻出一台 lenovo A360e ,其搭载联了发科单核芯片(MT6567)的3G智能(Android 2.3.6)手机,上市于2012年,于2017年停产。其屏幕尺寸为3.5英寸,分辨率是480x320像素。具备重力感应、光线感应和距离传感器。

然而,现在是2024年。几乎没有什么应用可以在Android2.3上面跑了。

所以,打开 AndroidStudio,新建一个项目。

完犊子了,最低只支持Android5.0!

好吧,我立刻坐进时光机,穿越到2013年,拿到当年我的一台旧电脑。上面有Android2.2的开发环境。

新建一个 Android 2.2 的项目。

接下来就是 xml 布局。对于习惯 jetpack components的人来讲,xml布局简直就是一坨屎。但是没办法,为了能在 Android 2.3 上面跑,只好硬着头搞了。

首先画一个简单的布局图:

看起来有点复杂,其实一点也不简单。

但是,可以先做上下结构:

xml 复制代码
<FrameLayout 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:background="#000"
    tools:context="org.deviceartist.clock.FullscreenActivity" >
    <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >
     </LinearLayout>
</FrameLayout>

然后在下面的结构中,再分出一个左右结构:

xml 复制代码
<FrameLayout 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:background="#000"
    tools:context="org.deviceartist.clock.FullscreenActivity" >
    <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center_horizontal" >
            </LinearLayout>
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="250sp"
                android:gravity="center_vertical" >
            </LinearLayout>
     </LinearLayout>
</FrameLayout>

然后按照布局图写 xml 的 layout 文件:

xml 复制代码
<FrameLayout 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:background="#000"
    tools:context="org.deviceartist.clock.FullscreenActivity" >
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center_horizontal" >

                <TextView
                    android:id="@+id/tab1"
                    android:layout_width="50sp"
                    android:layout_height="30sp"
                    android:layout_weight="1"
                    android:gravity="left"
                    android:padding="0dp"
                    android:text="STAT"
                    android:textColor="@color/green"
                    android:textSize="22sp" />
                
                <TextView
                    android:id="@+id/tab2"
                    android:layout_width="50sp"
                    android:layout_height="30sp"
                    android:layout_weight="1"
                    android:gravity="center"
                    android:padding="0dp"
                    android:text="INV"
                    android:textColor="@color/green"
                    android:textSize="22sp" />
                
                <TextView
                    android:id="@+id/tab3"
                    android:layout_width="50sp"
                    android:layout_height="30sp"
                    android:layout_weight="2"
                    android:gravity="center"
                    android:padding="0dp"
                    android:text="DATA"
                    android:textColor="@color/green"
                    android:textSize="22sp" />
                
                <TextView
                    android:id="@+id/tab4"
                    android:layout_width="50sp"
                    android:layout_height="30sp"
                    android:layout_weight="1"
                    android:gravity="center"
                    android:padding="0dp"
                    android:text="MAP"
                    android:textColor="@color/green"
                    android:textSize="22sp" />
                
                <TextView
                    android:id="@+id/tab5"
                    android:layout_width="50sp"
                    android:layout_height="30sp"
                    android:layout_weight="1"
                    android:gravity="right"
                    android:padding="0dp"
                    android:text="TERMUX"
                    android:textColor="@color/green"
                    android:textSize="22sp" />

            </LinearLayout>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="250sp"
                android:gravity="center_vertical" >

                <TextView
                    android:id="@+id/textViewTime"
                    android:layout_width="210sp"
                    android:layout_height="200sp"
                    android:textSize="100sp" />
                <TextView
                    android:id="@+id/textViewTimeS"
                    android:gravity="center"
                    android:layout_width="50sp"
                    android:layout_height="150sp"
                    android:textSize="20sp" />

                <org.deviceartist.clock.MyCanvas
                    android:id="@+id/myCanvas"
                    android:layout_width="200sp"
                    android:layout_height="200sp" />
            </LinearLayout>
        </LinearLayout>
</FrameLayout>

相应的 java 代码

java 复制代码
package org.deviceartist.clock;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Timer;
import org.deviceartist.clock.util.SystemUiHider;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.graphics.Typeface;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;

public class FullscreenActivity extends Activity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		if (Build.VERSION.SDK_INT < 16) {
                getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
	    }
		setContentView(R.layout.activity_fullscreen);		
		Typeface typeface = Typeface.createFromAsset(this.getAssets(), "fonts/font.ttf");
		
		final TextView textViewTime = (TextView) findViewById(R.id.textViewTime);
		final TextView textViewTimeS = (TextView) findViewById(R.id.textViewTimeS);
		final MyCanvas c = (MyCanvas) findViewById(R.id.myCanvas);
		textViewTime.setTextColor(0xff5CB31D);
		textViewTime.setTypeface(typeface);
		textViewTimeS.setTextColor(0xff5CB31D);
		textViewTimeS.setTypeface(typeface);
		final Handler handler = new Handler();
		Runnable runnable = new Runnable(){
			@Override
			public void run() {
				String currentTime = new SimpleDateFormat("HH\nmm",Locale.getDefault()).format(new Date());
				textViewTime.setText(currentTime);
				String currentTimeS = new SimpleDateFormat("ss",Locale.getDefault()).format(new Date());
				textViewTimeS.setText(currentTimeS);
				handler.postDelayed(this, 1000);
			}	
		};
		handler.postDelayed(runnable, 0);
		final Handler handler2 = new Handler();
		Runnable runnable2 = new Runnable(){
			@Override
			public void run() {
				c.next();
				handler.postDelayed(this, 100);
			}
		};
		handler2.postDelayed(runnable2, 100);
	}
}

知识点:

1、定时器

java 复制代码
final Handler handler = new Handler();
    Runnable runnable = new Runnable(){
    @Override
    public void run() {
        //todo
    }
};		
handler.postDelayed(runnable, 0);

2、Canvas画布就是自定义的View类

关键代码:

java 复制代码
package org.deviceartist.clock;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.View;

public class MyCanvas extends View {
	
	private Paint paint;
	Canvas canvas;

	public MyCanvas(Context context) {
		super(context);
		init();
	}

	public MyCanvas(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	public MyCanvas(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		init();
	}

	private void init() {
		paint = new Paint();
		paint.setColor(0xff5CB31D);
		paint.setStyle(Paint.Style.FILL);
	}

	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
	}
}

全部代码:

java 复制代码
package org.deviceartist.clock;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.View;

public class MyCanvas extends View {

	private int index = 0;
	ArrayList<Bitmap> bitmaps = new ArrayList<>();

	Bitmap voltage;
	Bitmap nuclear;
	Bitmap shield;
	Bitmap aim;
	Bitmap gun;
	Bitmap helmet;
	
	private Paint paint;
	Canvas canvas;

	public MyCanvas(Context context) {
		super(context);
		init();
		// TODO Auto-generated constructor stub
	}

	public MyCanvas(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	public MyCanvas(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		init();
	}

	private void init() {
		 
		
		voltage = BitmapFactory.decodeResource(getResources(),
				R.drawable.voltage);
		nuclear = BitmapFactory.decodeResource(getResources(),
				R.drawable.nuclear);
		shield  = BitmapFactory.decodeResource(getResources(),
				R.drawable.shield);
		aim  = BitmapFactory.decodeResource(getResources(),
				R.drawable.aim);
		gun  = BitmapFactory.decodeResource(getResources(),
				R.drawable.gun);
		helmet  = BitmapFactory.decodeResource(getResources(),
				R.drawable.helmet);
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy1));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy2));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy3));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy4));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy5));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy6));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy7));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy8));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy9));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy10));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy11));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy12));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy13));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy14));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy15));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy16));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy17));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy18));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy19));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy10));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy11));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy12));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy13));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy14));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy15));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy16));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy17));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy18));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy19));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy20));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy21));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy22));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy23));
		bitmaps.add(BitmapFactory.decodeResource(getResources(),
				R.drawable.boy24));

		paint = new Paint();
		paint.setColor(0xff5CB31D); // 设置圆形的颜色
		paint.setStyle(Paint.Style.FILL); // 设置填充样式
	}

	void next() {
		index += 1;
		index += 1;
		if (index == 24) {
			index = 0;
		}
		invalidate();
	}

	protected void onDraw(Canvas canvas) {
		this.canvas = canvas;
		
		super.onDraw(canvas);
		
		Bitmap bitmap =  bitmaps.get(index);
		int w = bitmap.getWidth();
		int h = bitmap.getHeight();
		
		// 获取View的中心点坐标
		int x = getWidth() / 2 - w/2;
		int y = getHeight() / 2 - h/2;
		
		canvas.drawBitmap(bitmap, x, y, paint);
		
		
		canvas.drawLine(10, 20, 55, 20, paint);
		canvas.drawLine(55, 20, 90, 70, paint);
		canvas.drawBitmap(shield, 10, 30, paint);
		
		
		canvas.drawLine(50, getHeight()/2, 100, getHeight()/2, paint);
		canvas.drawText("98%", 50, getHeight()/2-10, paint);
		canvas.drawBitmap(voltage, 10, getHeight()/2-30, paint);
		
		
		canvas.drawLine(10, getHeight()-30, 90, getHeight()-30, paint);
		canvas.drawLine(90, getHeight()-30, 100, getHeight()-80, paint);
		canvas.drawBitmap(gun, 10, getHeight()-90, paint);
		
		canvas.drawLine(getWidth()-30, 20, getWidth(), 20, paint);
		canvas.drawLine(getWidth()-30, 20, getWidth()-90, 70, paint);
		canvas.drawBitmap(aim, getWidth()-40, 30, paint);		
		
		
		canvas.drawLine(getWidth()-110, getHeight()/2, getWidth()-50, getHeight()/2, paint);
		canvas.drawText("9.9", getWidth()-80, getHeight()/2-10, paint);
		canvas.drawBitmap(nuclear, getWidth()-50, getHeight()/2-30, paint);
		
		canvas.drawLine(getWidth()-100, getHeight()-80, getWidth()-70, getHeight()-30, paint);
		canvas.drawLine(getWidth()-70, getHeight()-30, getWidth(), getHeight()-30, paint);
		canvas.drawBitmap(helmet, getWidth()-70, getHeight()-90, paint);

	}
}

最终效果

源码地址: git.sr.ht/~devicearti...

相关推荐
wclass-zhengge13 分钟前
SpringBoot篇(运维实用篇 - 临时属性)
运维·spring boot·后端
2401_8576009515 分钟前
商场应急管理:SpringBoot技术解决方案
java·spring boot·后端
半夏之沫38 分钟前
✨最新金九银十✨大厂后端面经✨
java·后端·面试
小宇1 小时前
The valid characters are defined in RFC 7230 and RFC 3986
java·开发语言·后端·tomcat
景天科技苑2 小时前
【Golang】Go语言中如何进行包管理
开发语言·后端·golang·go mod·go语言包管理·go包管理·go sum
秦朝胖子得加钱2 小时前
Flask
后端·python·flask
uzong2 小时前
JDK高性能套路: 自旋(for(;;)) + CAS
java·后端
程序员yt3 小时前
2025秋招八股文--服务器篇
linux·运维·服务器·c++·后端·面试
不会写代码的903 小时前
基于Java和Spring Boot的微服务架构设计--订单服务
后端