我穿越回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...

相关推荐
yuuki23323329 分钟前
【C语言】文件操作(附源码与图片)
c语言·后端
IT_陈寒32 分钟前
Python+AI实战:用LangChain构建智能问答系统的5个核心技巧
前端·人工智能·后端
无名之辈J1 小时前
系统崩溃(OOM)
后端
码农刚子1 小时前
ASP.NET Core Blazor简介和快速入门 二(组件基础)
javascript·后端
间彧1 小时前
Java ConcurrentHashMap如何合理指定初始容量
后端
catchadmin1 小时前
PHP8.5 的新 URI 扩展
开发语言·后端·php
少妇的美梦1 小时前
Maven Profile 教程
后端·maven
白衣鸽子1 小时前
RPO 与 RTO:分布式系统容灾的双子星
后端·架构
Jagger_2 小时前
SOLID原则与设计模式关系详解
后端
间彧2 小时前
Java: HashMap底层源码实现详解
后端