【Android、IOS、Flutter、鸿蒙、ReactNative 】自定义View
Android Java 自定义View
步骤
创建一个新的Java类,继承自
View
、ViewGroup
或其他任何一个视图类。如果需要,重写构造函数以支持不同的初始化方式。
重写
onMeasure
方法以提供正确的测量逻辑。重写
onDraw
方法以实现绘制逻辑。根据需要重写其他方法,如
onSizeChanged
、onTouchEvent
等。
自定义 View
public class CustomView extends View {
private Paint paint;
public CustomView(Context context) {
super(context);
init();
}
public CustomView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
paint = new Paint();
paint.setColor(Color.BLUE);
paint.setStyle(Paint.Style.FILL);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int defaultSize = 200;
setMeasuredDimension(
getDefaultSize(defaultSize, widthMeasureSpec),
getDefaultSize(defaultSize, heightMeasureSpec)
);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 绘制一个简单的蓝色圆形
canvas.drawCircle(getWidth() / 2, getHeight() / 2, 100, paint);
}
}
<com.example.yourapplication.CustomView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
Android Java 自定义View
步骤
创建一个新的Kotlin类,继承自
View
或其子类(如TextView
,LinearLayout
等)。重写构造函数,至少提供一个能够接受
Context
和AttributeSet
的构造函数。如果需要,重写其他构造函数。
重写
onMeasure
方法以提供正确的测量逻辑。重写
onDraw
方法以提供绘制逻辑。根据需要重写其他方法,如
onSizeChanged
,onTouchEvent
等。
自定义View
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.util.AttributeSet
import android.view.View
class CustomView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
private val paint = Paint().apply {
color = Color.RED
strokeWidth = 5f
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
// 设置默认的大小
val defaultSize = 200
setMeasuredDimension(
resolveSize(defaultSize, widthMeasureSpec),
resolveSize(defaultSize, heightMeasureSpec)
)
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
// 绘制一个简单的矩形
canvas.drawRect(0f, 0f, width.toFloat(), height.toFloat(), paint)
}
}
ios Object-c 自定义 View
在Objective-C中创建自定义视图通常涉及到继承自
UIView
类并实现自定义的初始化方法、绘图方法和其他需要的方法。以下是一个简单的自定义视图的例子:
自定义View
// MyCustomView.h
#import <UIKit/UIKit.h>
@interface MyCustomView : UIView
@end
// MyCustomView.m
#import "MyCustomView.h"
@implementation MyCustomView
// 初始化方法,可以自定义或使用默认的初始化方法
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// 自定义初始化代码
}
return self;
}
// 当视图需要重绘时调用
- (void)drawRect:(CGRect)rect {
// 获取图形上下文
CGContextRef context = UIGraphicsGetCurrentContext();
// 在这里绘制图形或图像
// 例如,绘制一个简单的红色矩形
CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
CGContextFillRect(context, rect);
}
@end
// 在你的视图控制器中
#import "MyCustomView.h"
// ...
MyCustomView *customView = [[MyCustomView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
[self.view addSubview:customView];
IOS Swift 自定义 View
在Swift中创建自定义视图通常涉及到定义一个继承自
UIView
的新类,并且通常需要重写init(frame:)
和layoutSubviews()
方法。以下是一个简单的自定义视图的例子:
import UIKit
class CustomView: UIView {
// 自定义视图的初始化
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
// 使用Storyboard或者XIB时需要的初始化方法
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupView()
}
// 视图布局发生变化时调用
override func layoutSubviews() {
super.layoutSubviews()
// 在这里可以根据视图的新布局进行调整
}
// 设置视图的共有属性
private func setupView() {
backgroundColor = .blue // 设置背景颜色为蓝色
// 其他自定义设置...
}
// 可以添加更多自定义的方法和属性
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let customView = CustomView()
customView.frame = CGRect(x: 50, y: 100, width: 200, height: 200)
view.addSubview(customView)
}
}
HarmonyOS Next 自定义View
@Component 表示这是一个自定义组件
@Entry 表示该自定义组件为入口组件
@State 表示组件中的状态变量,状态变量变化会触发UI刷新
UI部分 :以声明式的方式来描述UI的结构
@Component
export struct HelloPage {
@State message: string = 'Hello World'
build() {
Row() {
Column() {
Text(this.message)
.fontSize(40)
.fontWeight(FontWeight.Bold)
.onClick(() => {
this.message = "Hello Harmonyos"
})
}
.width('100%')
}
.height('100%')
}
}
React Native 自定义组件
描述
定义组件结构: 使用 JSX 定义组件的 UI 结构。
定义组件样式: 使用 StyleSheet 或内联样式定义组件的样式。
处理组件逻辑: 使用 React Hooks(如 useState, useEffect)管理组件状态和副作用。
定义组件接口: 通过 props 传递数据和事件处理器,实现组件的可配置性。
自定义组件
// components/MyButton.js
import React from 'react';
import { TouchableOpacity, Text, StyleSheet } from 'react-native';
const MyButton = ({ title, onPress, style, textStyle }) => {
return (
<TouchableOpacity style={[styles.button, style]} onPress={onPress}>
<Text style={[styles.text, textStyle]}>{title}</Text>
</TouchableOpacity>
);
};
const styles = StyleSheet.create({
button: {
backgroundColor: '#007bff',
padding: 10,
borderRadius: 5,
alignItems: 'center',
},
text: {
color: '#fff',
fontSize: 16,
},
});
export default MyButton;
// screens/HomeScreen.js
import React from 'react';
import { View, StyleSheet } from 'react-native';
import MyButton from '../components/MyButton';
const HomeScreen = () => {
const handlePress = () => {
alert('Button Pressed!');
};
return (
<View style={styles.container}>
<MyButton title="Press Me" onPress={handlePress} />
<MyButton title="Custom Style" onPress={handlePress} style={{ backgroundColor: '#28a745' }} textStyle={{ fontSize: 18 }} />
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: 20,
},
});
export default HomeScreen;
Flutter 自定义Widget
描述
创建一个新的Dart文件。
导入必要的Flutter库。
定义一个继承自
StatelessWidget
或StatefulWidget
的类。重写
build
方法以返回一个Widget。
自定义Widget
import 'package:flutter/material.dart';
class CustomButton extends StatelessWidget {
final String label;
final VoidCallback onPressed;
const CustomButton({Key? key, required this.label, required this.onPressed}) : super(key: key);
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: onPressed,
child: Text(label),
);
}
}
CustomButton
是一个继承自StatelessWidget
的自定义Widget,它接受两个参数:label
和onPressed
。build
方法返回一个ElevatedButton
,它是Flutter提供的一个按钮Widget,并使用构造函数中传入的参数。
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: CustomButton(
label: 'Click Me',
onPressed: () {
// Handle button press
},
),
),
),
);
}
}