昨天收拾屋子,翻出一台 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...