android 界面设计基本知识Ⅱ
上一章讲述了Android界面设计时,一些基本控件的使用,本章主要讲述自定义控件,Fragment和Headler线程机制。
1.自定义控件
(1)基本知识
dp、sp和dx
px:像素点
dp:与像素密度密切相关
sp:相当于dp,修饰文字专用
dip:相当于dp
用法:
文字尺寸一律用sp
非文字尺寸一律用dp
偶尔需要用px 例如:在屏幕上画细的分割线 1px
当一个控件不在右侧预览视图里面显示的时候是因为控件没有明确的位置,需要设置一个位置之后才能正常显示
构造器初始化 :
- onMesure() 定大小
- onLayout() 定位置
- onDraw() 绘制
- invalidate() 刷新
自定义控件的三种主要创建形式:
- 继承已有的控件来实现自定义控件,如 Button、 CheckedTextView;
- 通过继承一个布局文件实现自定义控件,如RelativeLayout;
- 通过继承view类来实现自定义控件。
(2)提取布局属性 theme & style
- Theme是针对窗体级别的,改变窗体样式;Style 是针对窗体元素级别的,改变指定控件或者Layout的样式;
- 抽象view的共同属性;
- 可继承
对于定制一个自定义控件,可通过如下步骤:
(1)基本属性定义在一个配置文件中attrs.xml :
<?xml version="1.0" encoding="utf-8"?>
<resources>
//类
<declare-styleable name="ViewTest">
//每一个attr都是一个属性,每个属性都有一个format
<attr name="backgroundColor" format="color"/>
<attr name="textColor" format="color"/>
<attr name="textSize" format="dimension"/>
</declare-styleable>
</
resources>
(2)定义一个控件View类:

1 package com.example.chenjinhua.redcircle;
2
3 import android.content.Context;
4 import android.graphics.Canvas;
5 import android.graphics.Color;
6 import android.graphics.Paint;
7 import android.graphics.Rect;
8 import android.util.AttributeSet;
9 import android.view.View;
10
11 public class DrawRedCircleView extends View implements View.OnClickListener{
12 private Paint mPaint;
13 private Rect mRect;
14 private int mNumber = 20;
15
16 public DrawRedCircleView(Context context) {
17 this(context, null);
18 }
19
20 public DrawRedCircleView(Context context, AttributeSet attrs) {
21 this(context, attrs, 0);
22 }
23
24 public DrawRedCircleView(Context context, AttributeSet attrs, int defStyleAttr) {
25 super(context, attrs, defStyleAttr);
26 init();
27 }
28
29 private void init() {
30 mPaint = new Paint();
31 mRect = new Rect();
32 }
33
34 @Override
35 protected void onDraw(Canvas canvas) {
36 super.onDraw(canvas);
37 mPaint.setColor(Color.RED);
38 canvas.drawCircle(getWidth() / 2, getWidth() / 2, getWidth() / 2, mPaint);
39
40 mPaint.setColor(Color.WHITE);
41 mPaint.setTextSize(100);
42 String textNumber = String.valueOf(mNumber);
43 mPaint.getTextBounds(textNumber,0,textNumber.length(),mRect);
44 int textWidth = mRect.width();
45 int textHight = mRect.height();
46 canvas.drawText(textNumber,getWidth()/2 - textWidth/2,getWidth()/2 + textHight/2,mPaint);
47
48 View view = findViewById(R.id.redCircle_view);
49 view.setOnClickListener(this);
50
51 }
52
53 @Override
54 public void onClick(View view) {
55 if ( mNumber > 0 ){
56 mNumber --;
57 }else{
58 mNumber = 20;
59 }
60 invalidate();
61 }
62 }
(3)视图页面引用:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
//添加自定义命名空间
xmlns:jinhua="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--引用自定义的控件-->
<com.example.chenjinhua.thirdweek.ViewTest
android:layout_width="300dp"
android:layout_height="300dp"
jinhua:backgroundColor="@color/colorAccent"
jinhua:textSize="18dp"/> <!--attrs文件中定义的属性-->
</LinearLayout>
(4)Activity类中定义和使用
<!--attrs文件中定义的属性-->
2.Fragment
(1)什么是Fragment
Fragment是activity界面中的一部分,多个Fragment组合到一个activity中。多个activity中可重用一个Fragment。
Fragment相当于模块化一个activity具有自己的生命周期,接收自己的事件,在activity运行时被添加或删除。
(2)为什么要使用Fragment
支持更动态更灵活的界面设计,在平板上的应用(左边列表,右边新闻)Activity的layout分成Fragment。
(3)Fragmet应用
getSupportFragmentManager().beginTransaction().
setCustomAnimations(R.anim.slide_in_from_right, R.anim.slide_out_to_left).
replace(R.id.fl_content, new ReadCardFragment(), "latest").
commit();
//setCustomAnimations:指定Fragment切换的动画效果
3.Headler多线程与异步
(1)Handler用来做什么?
- 定时执行Message和MessageQueue;
- 在不同线程中执行Runnable。
(2)Handler怎么使用?
- obtainMessage() //取得消息
- sendMessage() //发送消息
- handlerMessage() //处理消息
(3)Handler基本使用方法:
Handler myHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case TestHandler.GUIUPDATEIDENTIFIER:
myBounceView.invalidate();
break;
}
super.handleMessage(msg);
}
};
class myThread implements Runnable {
public void run() {
while (!Thread.currentThread().isInterrupted()) {
Message message = new Message();
message.what = TestHandler.GUIUPDATEIDENTIFIER;
TestHandler.this.myHandler.sendMessage(message);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
在android中提供了一种异步回调机制Handler,使用它,我们可以在完成一个很长时间的任务后做出相应的通知。
在主线程中,使用handler很简单,new一个Handler对象实现其handleMessage方法,在handleMessage中提供收到消息后相应的处理方法即可。
使用myThreadHandler.sendEmptyMessage(0);发送一个message对象,那么Handler是如何接收该message对象并处理的呢?如下数据结构图:
从这个图中我们很清楚可以看到调用sendEmptyMessage后,会把 Message对象放入一个MessageQueue队列,该队列属于某个Looper对象,每个Looper对象通过 ThreadLocal.set(new Looper())跟一个Thread绑定了,Looper对象所属的线程在Looper.Loop方法中循环执行从MessageQueue队列读取 Message对象,并把Message对象交由Handler处理,调用Handler的dispatchMessage方法。
喜欢请赞赏一下啦^_^
微信赞赏
支付宝赞赏
作者:@wuya11
本文为作者原创,转载请注明出处:https://www.cnblogs.com/wlandwl/p/android_2.html
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
限于本人有限的知识水平,文中可能存在误解或错误(轻喷~),欢迎指出。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?