本文介绍了Android开发中的四个核心功能实现:

1. Timer定时器使用:包括创建实例、任务调度(即时/循环执行)及通过Handler实现UI线程更新;

2. 容器布局控制:展示RelativeLayout与LinearLayout的嵌套使用,以及通过代码动态调整子容器位置;

3. 动画效果实现:涵盖平移动画(XML)、渐变动画(代码创建)和帧动画三种实现方式;

4. 音频播放功能:从资源准备到触摸事件绑定,并强调资源释放的重要性。全文提供了可直接使用的代码示例,适合快速实现基础功能。

一、Timer 定时器使用指南

(一)基本特性与创建

  • 核心规则:Timer 作为全局变量时,支持取消操作,但取消后无法重新复用,需重新创建实例。
  • 创建方式

java

运行

Timer timer = new Timer(); // 初始化定时器实例

(二)时间调度方法

Timer 提供灵活的任务调度方式,通过 schedule 方法实现不同需求:

  1. 即时执行(无延迟):任务创建后立即启动,仅执行一次

java

运行

TimerTask timerTask = new TimerTask() {
    @Override
    public void run() {
        // 任务执行逻辑
    }
};
timer.schedule(timerTask, 0); // 第二个参数为延迟时间(毫秒),0 表示无延迟
  1. 循环执行(固定间隔):延迟指定时间后,按固定周期重复执行

java

运行

// 延迟 0 毫秒启动,之后每 1000 毫秒(1 秒)执行一次
timer.schedule(timerTask, 0, 1000); 
// 注:原文档中第三个参数为 0 会导致循环逻辑异常,此处优化为合理间隔值

(三)UI 界面更新处理

由于 TimerTask 的 run 方法运行在子线程,直接操作 UI 会抛出异常,需通过 Handler 实现线程通信:

java

运行

// 1. 创建 Handler 实例(主线程中初始化)
Handler handler = new Handler(Looper.getMainLooper()) {
    @Override
    public void handleMessage(@NonNull Message msg) {
        super.handleMessage(msg);
        // 根据消息标识处理 UI 更新
        switch (msg.what) {
            case 3:
                // UI 操作逻辑(如控件状态修改、数据刷新)
                break;
            // 可扩展更多消息类型
        }
    }
};

// 2. TimerTask 中发送消息
TimerTask timerTask = new TimerTask() {
    @Override
    public void run() {
        Message message = new Message();
        message.what = 3; // 消息标识,与 Handler 中对应
        handler.sendMessage(message); // 发送消息到主线程
    }
};

// 3. 启动定时器
timer.schedule(timerTask, 0, 1000);

二、父子容器布局与位置控制

(一)XML 布局基础

以 RelativeLayout 作为父容器,LinearLayout 作为子容器为例,布局文件示例:

xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".Inits1Activity">

    <!-- 子容器 LinearLayout -->
    <LinearLayout
        android:id="@+id/s1_pl"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:orientation="vertical">
        <!-- 子容器内部控件 -->
    </LinearLayout>

</RelativeLayout>

(二)代码中控制子容器位置

通过 LayoutParams 动态设置子容器的边距,实现位置调整:

java

运行

public class Inits1Activity extends AppCompatActivity {
    private LinearLayout pL; // 子容器实例
    private RelativeLayout.LayoutParams params; // 父容器对应的布局参数

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.inits1);

        // 1. 绑定子容器
        pL = findViewById(R.id.s1_pl);

        // 2. 初始化布局参数(RelativeLayout 父容器专用)
        params = new RelativeLayout.LayoutParams(
            RelativeLayout.LayoutParams.WRAP_CONTENT,
            RelativeLayout.LayoutParams.WRAP_CONTENT
        );

        // 3. 设置边距(左、上、右、下,单位:像素)
        int marginLeft = 20;
        int marginTop = 400;
        params.setMargins(marginLeft, marginTop, 0, 0);

        // 4. 应用布局参数(主线程中直接操作)
        pL.setLayoutParams(params);
    }
}

(三)屏幕尺寸获取

如需根据屏幕尺寸动态调整布局,可通过 WindowManager 获取屏幕宽高:

java

运行

// 获取屏幕尺寸
WindowManager windowManager = getWindowManager();
Display display = windowManager.getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
display.getMetrics(metrics);

int screenWidth = metrics.widthPixels; // 屏幕宽度(像素)
int screenHeight = metrics.heightPixels; // 屏幕高度(像素)

三、动画效果实现

(一)平移动画(XML 定义)

res/anim 目录下创建动画文件 t_a.xml(没有则新建)

xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="100" <!-- 动画持续时间(毫秒) -->
    android:fillAfter="true" <!-- 动画结束后保持最终状态 -->
    android:repeatMode="restart"> <!-- 重复模式:重新开始 -->

    <!-- 平移动画:从(0,0)移动到(10,0) -->
    <translate
        android:fromXDelta="0.0" <!-- 起始X坐标 -->
        android:fromYDelta="0.0" <!-- 起始Y坐标 -->
        android:toXDelta="10"    <!-- 结束X坐标 -->
        android:toYDelta="0.0" /> <!-- 结束Y坐标 -->

</set>

(二)渐变动画(Java 动态创建)

通过 AlphaAnimation 实现控件渐变显示效果:

java

运行

private AlphaAnimation alphaAnimation;

/**
 * 为控件设置渐变动画(从透明到不透明)
 * @param view 目标控件(支持 LinearLayout、TextView 等任意 View 子类)
 */
private void setAlphaAnimation(View view) {
    // 渐变范围:0.0f(完全透明)→ 1.0f(完全不透明)
    alphaAnimation = new AlphaAnimation(0.0f, 1.0f);
    alphaAnimation.setDuration(500); // 动画持续500毫秒
    view.startAnimation(alphaAnimation); // 启动动画
}

// 调用示例
LinearLayout layout = findViewById(R.id.s1_pl);
setAlphaAnimation(layout);

(三)帧动画(背景动画)

  1. 步骤 1:准备帧资源:将动画帧图片放入 drawable 目录(如 ic_walk01.png、ic_walk02.png 等)
  2. 步骤 2:创建帧动画 XML:在 drawable 目录下创建 people_walking_soldiers.xml

xml

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false"> <!-- false:循环播放,true:仅播放一次 -->

    <!-- 帧序列:每个 item 为一帧,duration 为该帧显示时间 -->
    <item android:drawable="@drawable/ic_walk01" android:duration="100" />
    <item android:drawable="@drawable/ic_walk02" android:duration="100" />
    <item android:drawable="@drawable/ic_walk03" android:duration="100" />
    <!-- 可添加更多帧 -->

</animation-list>
  1. 步骤 3:布局中引用与代码控制

xml

<!-- XML 布局中设置背景动画 -->
<ImageView
    android:id="@+id/s1_people"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/people_walking_soldiers"
    android:visibility="visible" />

java

运行

// Java 代码控制动画启停
ImageView peopleImg = findViewById(R.id.s1_people);
AnimationDrawable walkAnimation = (AnimationDrawable) peopleImg.getBackground();

walkAnimation.start(); // 启动动画
// walkAnimation.stop(); // 停止动画

四、音频播放功能

(一)资源准备

res 目录下创建 raw 文件夹,放入音频文件(如 button_1.mp3、button_2.mp3)

(二)触摸事件绑定音频

通过 OnTouchListener 实现触摸(按下 / 抬起)时播放不同音频:

java

运行

public class MainActivity extends AppCompatActivity {
    private MediaPlayer mediaPlayer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button startBtn = findViewById(R.id.start_btn);
        // 绑定触摸事件
        startBtn.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                mediaPlayer = new MediaPlayer();
                mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); // 设置音频流类型

                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        // 按下时播放音频1
                        mediaPlayer = MediaPlayer.create(MainActivity.this, R.raw.button_1);
                        mediaPlayer.start();
                        break;
                    case MotionEvent.ACTION_UP:
                        // 抬起时播放音频2
                        mediaPlayer = MediaPlayer.create(MainActivity.this, R.raw.button_2);
                        mediaPlayer.start();
                        break;
                }
                return false; // 不拦截点击事件,保证 onClick 正常触发
            }
        });
    }

    // 生命周期管理:释放音频资源
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mediaPlayer != null) {
            mediaPlayer.release();
            mediaPlayer = null;
        }
    }
}

五、点击与触摸事件处理

(一)事件绑定方式

同时绑定 OnClickListener(点击事件)和 OnTouchListener(触摸事件):

java

运行

public class MainActivity extends AppCompatActivity {
    private Button startBtn, endBtn, ptBtn;
    private ButtonListener buttonListener;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 初始化控件
        startBtn = findViewById(R.id.start_btn);
        endBtn = findViewById(R.id.main_exit);
        ptBtn = findViewById(R.id.pt_btn);

        // 创建事件监听器实例
        buttonListener = new ButtonListener();

        // 绑定事件
        startBtn.setOnClickListener(buttonListener);
        startBtn.setOnTouchListener(buttonListener);
        endBtn.setOnClickListener(buttonListener);
        endBtn.setOnTouchListener(buttonListener);
        ptBtn.setOnClickListener(buttonListener);
        ptBtn.setOnTouchListener(buttonListener);
    }

    // 事件监听器实现类
    class ButtonListener implements View.OnClickListener, View.OnTouchListener {
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.main_exit:
                    // 退出应用
                    System.exit(0);
                    break;
                case R.id.pt_btn:
                    // 控件显示/隐藏切换
                    ptBtn.setVisibility(View.GONE);
                    findViewById(R.id.ptv).setVisibility(View.VISIBLE);
                    // 为控件设置动画(需实现 settvAnimation 方法)
                    settvAnimation(findViewById(R.id.ptv));
                    break;
                case R.id.start_btn:
                    // 页面跳转
                    Intent intent = new Intent(MainActivity.this, MainActivity2.class);
                    startActivity(intent);
                    // 释放音频资源
                    if (mediaPlayer != null) {
                        mediaPlayer.release();
                        mediaPlayer = null;
                    }
                    break;
            }
        }

        // 触摸事件处理(同音频播放逻辑,此处省略重复代码)
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            // 音频播放逻辑参考第四章第二节
            return false;
        }
    }

    // 自定义控件动画方法
    private void settvAnimation(View view) {
        // 可复用渐变、平移等动画逻辑
    }
}

(二)关键注意事项

  1. OnTouchListener 的 onTouch 方法返回 false 时,不会拦截点击事件,OnClickListener 可正常触发;返回 true 则拦截点击事件。
  2. 音频资源需在页面销毁时释放,避免内存泄漏。
  3. 事件处理中涉及 UI 操作时,需确保在主线程执行。
Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐