IOS Android Harmonyos next 纯代码布局对比纯手撸
前言导读
各位同学大家好,今天也是给大家分享下iOS Android Harmonyos next 纯代码布局的对比, 因为很多的同学有个通病就是太过依赖第三方框架基本功很差 甚至说是懒,遇到复杂的布局基本就不想动,今天也是用原始ios 原生Android 的纯代码布局 来对比我们的Harmonyos next 给我们开发者到底提供了哪些便利,和好用的点,那么不废话我们正式开始。
iOS 端 代码实现
//
// LoginView.m
// 016登录界面
//
// Created by xuqing on 2022/5/5.
//
#import "LoginView.h"
#import "WHToast.h"
#import "AFNetworking.h"
#import "TextUtils.h"
#import "ToastUtils.h"
#import "RegisterView.h"
@implementation LoginView
@synthesize usernameLabel=_usernameLabel;
@synthesize pswLabel=_passwordLabel;
@synthesize userTextfield=_userTextfield;
@synthesize pswfield=_passwordfield;
@synthesize loginBtn=_loginBtn;
@synthesize registerBtn=_registerBtn;
@synthesize blackBgV=_blackBgV;
@synthesize alertV=_alertV;
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
[self setUpSubView];
}
return self;
}
- (void)setUpSubView
{
self.frame = [UIScreen mainScreen].bounds;
// 初始化遮罩视图
self.blackBgV = [[UIView alloc]initWithFrame:self.bounds];
self.blackBgV.backgroundColor = [UIColor grayColor];
self.blackBgV.alpha = 0;
[self addSubview:self.blackBgV];
// 初始化actionSheetView
self.alertV = [[UIView alloc] initWithFrame:CGRectMake(30,self.bounds.size.height/2-120, self.bounds.size.width-60, 240)];
self.alertV.backgroundColor = [UIColor whiteColor];
self.alertV.layer.cornerRadius = 5;
self.alertV.layer.masksToBounds = YES;
self.alertV.alpha = 0;
[self addSubview:self.alertV];
_usernameLabel =[[UILabel alloc]init];
_usernameLabel.frame=CGRectMake(60, 50, 60, 40);
_usernameLabel.text=@"账号:";
_usernameLabel.textColor=[UIColor blueColor];
[self.alertV addSubview:_usernameLabel];
_userTextfield =[[UITextField alloc] init];
_userTextfield.frame=CGRectMake(100, 50,180, 40);
_userTextfield.font= [UIFont systemFontOfSize:15];
// 设置字体颜色
_userTextfield.textColor=[UIColor blackColor];
//设置边框的风格
// UITextBorderStyleBezel bezel线框
// UITextBorderStyleRoundedRect 圆角风格
// UITextBorderStyleLine 线框风格
// UITextBorderStyleNone 无边框风格
_userTextfield.borderStyle= UITextBorderStyleRoundedRect;
//设置虚拟键盘风格
//UIKeyboardTypeDefault 默认风格
//UIKeyboardTypeNumberPad 纯数字风格
//UIKeyboardTypeNamePhonePad 字母和数字组合风格
_userTextfield.keyboardType=UIKeyboardTypeNamePhonePad;
_userTextfield.placeholder=@"请输入用户名...";
//是否作为密码输入
//YES 做为处理 圆点加密
//NO: 正常显示输入的文字
_userTextfield.secureTextEntry= NO;
[self.alertV addSubview: _userTextfield];
_passwordLabel =[[UILabel alloc]init];
_passwordLabel.frame=CGRectMake(60, 100, 60, 40);
_passwordLabel.text=@"密码:";
_passwordLabel.textColor=[UIColor blueColor];
[self.alertV addSubview:_passwordLabel];
_passwordfield =[[UITextField alloc] init];
_passwordfield.frame=CGRectMake(100, 100,180, 40);
_passwordfield.font= [UIFont systemFontOfSize:15];
// 设置字体颜色
_passwordfield.textColor=[UIColor blackColor];
//设置边框的风格
// UITextBorderStyleBezel bezel线框
// UITextBorderStyleRoundedRect 圆角风格
// UITextBorderStyleLine 线框风格
// UITextBorderStyleNone 无边框风格
_passwordfield.borderStyle= UITextBorderStyleRoundedRect;
//设置虚拟键盘风格
//UIKeyboardTypeDefault 默认风格
//UIKeyboardTypeNumberPad 纯数字风格
//UIKeyboardTypeNamePhonePad 字母和数字组合风格
_passwordfield.keyboardType=UIKeyboardTypeNamePhonePad;
_passwordfield.placeholder=@"请输入密码...";
//是否作为密码输入
//YES 做为处理 圆点加密
//NO: 正常显示输入的文字
_passwordfield.secureTextEntry= YES;
[self.alertV addSubview: _passwordfield];
_loginBtn=[UIButton buttonWithType: UIButtonTypeRoundedRect];
_loginBtn.frame=CGRectMake(80, 160, 80, 40);
[_loginBtn setTitle:@"登录" forState:UIControlStateNormal];
[_loginBtn addTarget:self action:@selector(login) forControlEvents:UIControlEventTouchUpInside];
_loginBtn.backgroundColor=[UIColor blueColor];
[_loginBtn setTitleColor: [UIColor whiteColor ] forState:UIControlStateNormal] ;
//设置按钮颜色
[_loginBtn setTitleColor: [UIColor grayColor] forState:UIControlStateHighlighted] ;
[self.alertV addSubview:_loginBtn];
_registerBtn=[UIButton buttonWithType:UIButtonTypeRoundedRect];
_registerBtn.frame=CGRectMake(180, 160, 80, 40);
[_registerBtn setTitle:@"注册" forState:UIControlStateNormal];
[_registerBtn addTarget:self action:@selector(registerMethod) forControlEvents:UIControlEventTouchUpInside];
_registerBtn.backgroundColor=[UIColor blueColor];
[_registerBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[self.alertV addSubview:_registerBtn];
}
-(void)registerMethod{
[self hidden];
RegisterView * registerview=[[RegisterView alloc]init];
registerview.registerBlock=_logBlock;
[registerview show];
}
-(void)login{
NSString * _strTextName=_userTextfield.text;
NSString * _strTextPsw=_passwordfield.text;
if(![TextUtils isBlankString:_strTextName]
&&![TextUtils isBlankString:_strTextPsw]){
NSLog(@"登录成功");
NSLog(@"%@ %@",_strTextName,_strTextPsw);
NSString * registerString=@"http://175.178.200.180:8090/boss/user/validlogin?";
NSString * str1=@"username=";
NSString * str2=@"password=";
NSMutableString *geturl = [NSMutableString string];
[geturl appendString:registerString];
[geturl appendString:str1];
[geturl appendString:_strTextName];
[geturl appendString:@"&"];
[geturl appendString:str2];
[geturl appendString:_strTextPsw];
NSLog(@" geturl --- > %@",geturl);
[[AFHTTPSessionManager manager]GET:geturl parameters:nil headers:nil progress:^(NSProgress * _Nonnull downloadProgress) {
NSLog(@"");
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"");
NSLog(@"请求成功---%@",responseObject);
NSLog(@"请求 msg ---%@",[responseObject objectForKey:(@"msg")]);
NSString * msg=[responseObject objectForKey:(@"msg")];
NSInteger code = [[responseObject objectForKey:(@"code")] integerValue];
if(code==200){
if (self.logBlock) {
//缓存token
NSString * token=[responseObject objectForKey:(@"token")];
NSUserDefaults * ud =[NSUserDefaults standardUserDefaults];
[ud setObject:token forKey:@"token"];
self.logBlock(YES, responseObject);
[self hidden];
}
}else{
[ToastUtils showInfo:msg];
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"");
}];
}else {
[ToastUtils showInfo:@"账号或者密码不能为空" ];
}
}
- (void)show {
[self setUpSubView];
[[UIApplication sharedApplication].keyWindow addSubview:self];
self.hidden = NO;
[UIView animateWithDuration:0.3 animations:^{
self.alertV.alpha = 1;
self.blackBgV.alpha = 0.5;
} completion:^(BOOL finished) {
}];
}
- (void)hidden {
__block typeof(self) weakSelf = self;
[UIView animateWithDuration:0.3 animations:^{
self.alertV.alpha = 0;
self.blackBgV.alpha = 0;
} completion:^(BOOL finished) {
weakSelf.hidden = YES;
[weakSelf removeFromSuperview];
}];
}
#pragma mark -- 遮罩视图点击
- (void)tapClick:(UIGestureRecognizer *)tap {
NSLog(@"遮罩视图点击");
}
@end
效果图
Android端 代码实现
package com.example.myapplication;
import android.app.Dialog;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.text.InputType;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.appcompat.widget.AppCompatCheckBox;
/**
*
*创建人:xuqing
*创建时间:2025年1月26日15:18:50
* 类说明:登录弹出
*
*/
public class LoginDialog extends Dialog {
protected final static int MATCH_PARENT = LinearLayout.LayoutParams.MATCH_PARENT;
protected final static int WRAP_CONTENT = LinearLayout.LayoutParams.WRAP_CONTENT;
protected final int _10dp = DisplayUtils.dip2Px(getContext(), 10);
protected final int _5dp = DisplayUtils.dip2Px(getContext(), 5);
protected final int _32dp = DisplayUtils.dip2Px(getContext(), 32);
protected final int _20dp = DisplayUtils.dip2Px(getContext(), 20);
public static final String C_COMFIRM = "#FF26ADF0";
public static final String C_COMFIRM_P = "#DD26ADF0";
public static final String C_CANCEL = "#FFCCCCCC";
public static final String C_CANCEL_P = "#DDCCCCCC";
private Context mContext;
protected LinearLayout mParentView;
protected LinearLayout mContentView;
private EditText editAccount;
private EditText editPwd;
protected LinearLayout editAccountiLlView;
protected LinearLayout editPwdLlView;
protected LinearLayout buttomLlView;
private TextView accountText;
private TextView editPwdText;
private RelativeLayout editAccountRl;
private RelativeLayout editPwdRl;
public LoginDialog(Context context) {
super(context);
this.mContext = context;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setBackgroundDrawableResource(android.R.color.transparent);
getWindow().requestFeature(Window.FEATURE_NO_TITLE);
mParentView = new LinearLayout(getContext());
mParentView.setOrientation(LinearLayout.VERTICAL);
mParentView.setPadding(0, 0, _5dp, _5dp);
mParentView.setBackground(DrawableUtils.createShape(0,
0, 0, "#ffffff", "#ffffff"));//#ffffff
mContentView=new LinearLayout(getContext());
mContentView.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams mContentViewlayoutparams=new LinearLayout.LayoutParams(
DisplayUtils.dip2Px(getContext(), 255), DisplayUtils.dip2Px(getContext(), 255));
mContentView.setLayoutParams(mContentViewlayoutparams);
mContentView.setGravity(Gravity.CENTER);
// 账号输入框
editAccount = addNOBgEditText();
//suakuds_pinputaccount_str
editAccount.setHint("请输入账号");
//editAccount.setText("huangyueze");
RelativeLayout.LayoutParams editAccountlayoutParams = new RelativeLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT);
editAccountlayoutParams.setMargins(dip2px(0),0,dip2px(30),0);
editAccount.setLayoutParams(editAccountlayoutParams);
accountText =addTextView();
LinearLayout.LayoutParams layoutParams = new
LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
accountText.setLayoutParams(layoutParams);
accountText.setText("账号:");
layoutParams.setMargins(dip2px(20),0,0,0);
editAccountRl=new RelativeLayout(getContext());
RelativeLayout.LayoutParams editAccountRllayoutParams =
new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.MATCH_PARENT);
editAccountRl.setBackground(DrawableUtils.createShape(1, 10,
-1, "#000000", "#ffffff"));
editAccountRl.setLayoutParams(editAccountRllayoutParams);
editAccountRllayoutParams.setMargins(dip2px(10),0,0,0);
editAccountRl.addView(editAccount,editAccountlayoutParams);
//账号线性布局
editAccountiLlView=new LinearLayout(getContext());
LinearLayout.LayoutParams editAccountiLlViewlayoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
dip2px(40));
editAccountiLlView.setLayoutParams(editAccountiLlViewlayoutParams);
editAccountiLlView.setOrientation(LinearLayout.HORIZONTAL);
editAccountiLlView.setGravity(Gravity.CENTER);
editAccountiLlView.setPadding(0, 0, _5dp, _5dp);
editAccountiLlView.addView(accountText,layoutParams);
editAccountiLlView.addView(editAccountRl,editAccountRllayoutParams);
mContentView.addView(editAccountiLlView, editAccountiLlViewlayoutParams);
// 密码输入框
editPwd = addNOBgEditText();
LinearLayout.LayoutParams editPwdlayoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT);
editPwd.setLayoutParams(editPwdlayoutParams);
editPwdlayoutParams.setMargins(dip2px(0),0,dip2px(30),0);
editPwd.setGravity(Gravity.CENTER_VERTICAL);
editPwd.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
//suakuds_pinputpwd_str
editPwd.setHint("请输入密码");
editPwdText = addTextView();
LinearLayout.LayoutParams editPwdImagelayoutParams = new
LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);;
editPwdText.setLayoutParams(editPwdImagelayoutParams);
editPwdText.setText("密码:");
editPwdImagelayoutParams.setMargins(dip2px(20),0,0,0);
//账号线性布局
editPwdLlView=new LinearLayout(getContext());
editPwdRl=new RelativeLayout(getContext());
LinearLayout.LayoutParams editPwdRllayoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT);
editPwdRl.setBackground(DrawableUtils.createShape(1,
10, -1, "#000000", "#ffffff"));
editPwdRl.setLayoutParams(editPwdRllayoutParams);
editPwdRllayoutParams.setMargins(dip2px(10),0,0,0);
editPwdRl.addView(editPwd,editPwdlayoutParams);
LinearLayout.LayoutParams editPwdLlViewlayoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
dip2px(40));
editPwdLlView.setLayoutParams(editPwdLlViewlayoutParams);
editPwdLlView.setOrientation(LinearLayout.HORIZONTAL);
editPwdLlView.setGravity(Gravity.CENTER);
editPwdLlView.setPadding(0, 0, _5dp, _5dp);
editPwdLlView.addView(editPwdText,editPwdImagelayoutParams);
editPwdLlView.addView(editPwdRl,editPwdRllayoutParams);
mContentView.addView(editPwdLlView, editPwdLlViewlayoutParams);
LinearLayout btnLayout = new LinearLayout(getContext());
btnLayout.setOrientation(LinearLayout.HORIZONTAL);
btnLayout.setGravity(Gravity.CENTER);
LinearLayout.LayoutParams btnLayoutlayoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
dip2px(32));
btnLayoutlayoutParams.setMargins(dip2px(40),dip2px(20),dip2px(20),0);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(0, _32dp);
lp.weight = 1;
lp.setMargins(_5dp, _5dp, _5dp, _5dp);
Button registerBtn = addCancelBtn("注册");
btnLayout.addView(registerBtn, lp);
//添加登陆
lp = new LinearLayout.LayoutParams(0, _32dp);
lp.weight = 1;
//suakuds_login
Button loginBtn = addConfirmBtn("登录");
btnLayout.addView(loginBtn, lp);
mContentView.addView(btnLayout,btnLayoutlayoutParams);
mParentView.addView(mContentView,mContentViewlayoutparams);
setContentView(mParentView, new LinearLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
}
@Override
public void show() {
super.show();
DisplayMetrics dmDisplayMetrics = new DisplayMetrics(); //为获取屏幕宽、高
getWindow().getWindowManager().getDefaultDisplay().getMetrics(dmDisplayMetrics);
android.view.WindowManager.LayoutParams p = this.getWindow().getAttributes(); //获取对话框当前的参数值
p.gravity = Gravity.CENTER;
this.getWindow().setLayout(DisplayUtils.dip2Px(getContext(), 300), DisplayUtils.dip2Px(getContext(), 250));
}
public int dip2px(float dpValue) {
final float scale = getContext().getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
protected TextView addTextView() {
TextView tv = new TextView(getContext());
tv.setTextColor(0xff222222);
tv.setTextSize(12);
tv.setGravity(Gravity.CENTER_VERTICAL);
return tv;
}
protected EditText addNOBgEditText() {
EditText et = new EditText(getContext());
et.setSingleLine();
et.setMinHeight(_32dp);
et.setGravity(Gravity.CENTER_VERTICAL);
et.setPadding(dp(5), 5, dp(2), 0);
et.setTextSize(dp(5));
et.setTextColor(Color.BLACK);
et.setInputType(InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
et.setBackground(null);
return et;
}
protected int dp(int _dp) {
return DisplayUtils.dip2Px(getContext(), _dp);
}
//添加取消按钮
protected Button addCancelBtn(String text) {
Button cancelBtn = new Button(getContext());
//cancelBtn.setTextSize(10);
cancelBtn.setTextColor(Color.WHITE);
cancelBtn.setAllCaps(false);
cancelBtn.setBackground(DrawableUtils.createStateDrawable(_5dp, C_COMFIRM, C_COMFIRM_P));
cancelBtn.setText(text);
cancelBtn.setPadding(_5dp, _5dp, _5dp, _5dp);
return cancelBtn;
}
protected Button addConfirmBtn(String text) {
Button confirmBtn = new Button(getContext());
confirmBtn.setTextColor(Color.WHITE);
confirmBtn.setAllCaps(false);
confirmBtn.setBackground(DrawableUtils.createStateDrawable(_5dp, C_COMFIRM, C_COMFIRM_P));
confirmBtn.setText(text);
confirmBtn.setPadding(_5dp, _5dp, _5dp, _5dp);
return confirmBtn;
}
}
HarmonyOSNext 端
/**
* 自定义中间弹窗
*/
//线条样式
@Extend(Line) function lineStyle(){
.width('100%')
.height(1)
.backgroundColor($r('app.color.line_color'))
}
//黑色字体样式
@Extend(Text) function blackTextStyle(){
.fontColor($r('app.color.black_text_color'))
.fontSize(18)
.fontWeight(FontWeight.Medium)
}
@Extend(TextInput) function inputStyle(){
.placeholderColor($r('app.color.placeholder_color'))
.height(45)
.fontSize(18)
.backgroundColor($r('app.color.background'))
.width('100%')
.padding({left:0})
.margin({top:12})
}
export class LoginCenterPopup extends BaseCenterPopup<CenterBean> {
private data = new CenterBean()
constructor() {
super(wrapBuilder(customPopupBuilder))
this.setParams(this.data)
this.data.dismiss = () => {
this.dismiss()
}
}
}
@Builder
function customPopupBuilder(data: CenterBean) {
Column() {
Row(){
Text('账号').blackTextStyle()
TextInput({placeholder:'请输入账号'})
.width('100%')
.height(35)
.type(InputType.Normal)
.margin(5)
.onChange((value:string)=>{
DataStoreController.getInstance().setUsername(value);
}).margin({left:20})
.onSecurityStateChange(((isShowPassword: boolean) => {
// 更新密码显示状态
console.info('isShowPassword', isShowPassword)
})).backgroundColor("#00000000")
.layoutWeight(1)
.borderRadius(8)
}.justifyContent(FlexAlign.SpaceBetween)
.width('100%')
.margin({top:8})
Line().lineStyle().margin({left:80,right:10})
Row(){
Text('密码').blackTextStyle()
TextInput({placeholder:'请输入密码'})
.width('100%')
.height(35)
.type(InputType.Normal)
.margin(5)
.onChange((value:string)=>{
DataStoreController.getInstance().setpasswroid(value);
}).margin({left:20})
.onSecurityStateChange(((isShowPassword: boolean) => {
// 更新密码显示状态
console.info('isShowPassword', isShowPassword)
})).backgroundColor("#00000000")
.layoutWeight(1)
.borderRadius(8)
}.justifyContent(FlexAlign.SpaceBetween)
.width('100%')
.margin({top:8})
Line().lineStyle().margin({left:80,right:10})
//Line().lineStyle().margin({left:80,right:10})
Row({space:10}){
Button('登录',{type:ButtonType.Capsule})
.width('90%')
.height(40)
.fontSize(16)
.fontWeight(FontWeight.Medium)
.backgroundColor($r('app.color.login_button_color'))
.margin({top:47,bottom:12})
.onClick(()=>{
}).layoutWeight(1)
Button('注册',{type:ButtonType.Capsule})
.width('90%')
.height(40)
.fontSize(16)
.fontWeight(FontWeight.Medium)
.backgroundColor($r('app.color.login_button_color'))
.margin({top:47,bottom:12})
.onClick(()=>{
}).layoutWeight(1)
}.justifyContent(FlexAlign.SpaceBetween)
.width('100%')
.margin({top:8})
}
}
效果图
对比
我们对比代码编码复杂程度和阅读难度 都是我们的 HarmonyOSnext 更加简化容易上手,这时候有人跳出来说我们iOS里面还有swift ui 那个也可以做到声明式UI 是没错 但是最开始的时候就只有object-c 所以任何平台和语言都是需要不断的发展才有今天的局面, Android 也是如此 Android里面使用kotlin 配合jetpack compose 也是可以实现类似的声明式UI 但是最开始也只有Java纯代码布局或者java+xml布局,正是因为如此HarmonyOSnext 对比原生Android 原生ios都有后发优势 ,弥补掉前人的不足 发挥自己的优势。
设计理念对比
-
iOS
ios的纯代码布局里面有CGRectMake 方式给我们设置x y 坐标和宽高 屏幕的左上角是原点 横向是往右是x轴 纵向往下是y轴 这个设计就比较清晰通过坐标和宽高限制控件的位置和大小。是在那个时代比较ok的一种设计。
-
Android
Android的纯代码布局就没有ios这种设置坐标的方法了 主要还是通过viewgroup 来嵌套包裹我们的view或者其他的viewgroup 最后通过调用addview 添加到我们的布局中 代码是相对繁琐和不容易阅读的。简直就是xml布局翻版。这个还是对程序员本身的要求比较高。
-
HarmonyOSNext
HarmonyOSNext 的纯代码是天生的在next上面 官方指定就是使用ArkUI 来编写布局配合预览器也可以达到所见即所得的效果,代码阅读方面也比较清晰明了。就像搭积木一样我们通过线性布局和相对布局等父布局来装载子组件,很容易就实现我们想要的UI效果。
最后总结:
无论是Android ios 还是其他端转过来的同学学习 HarmonyOSNext 开发的,我都非常建议学好基本功,不要没有类似Android里面xml 类似ios里面的xib 没有类似前端的各种框架就 不想学习,完全没有必要,官方提供的组件已经比较丰富了,而且三方库也在不断的完善,祝愿每位同学都能学好找到好工作,也希望国产系统越来越好。今天的文章讲到这里, 如果觉得文章还不错可以给我一个一键三连。 有兴趣的 关注我B站教程 了解更多鸿蒙开发的知识 可以关注坚果派公众号 。 谢谢
- 0回答
- 3粉丝
- 0关注
- 带你玩转ArkUI-X 调用原生 iOS 端代码通信
- 真正的纯血鸿蒙开发者是怎样开发应用的?纯血鸿蒙到底”纯“在哪里?
- OpenHarmony5.0应用开发 (三、应用程序包结构理解及Ability的跳转,与Android的对比)
- (六)HarmonyOS Design 与其他设计系统的对比
- 42.HarmonyOS NEXT Layout布局组件系统详解(九):嵌套布局实现
- Java Android 开发利器 JSON to JavaBean 工具来了
- (二十)ArkTS 与低代码 / 无代码开发
- 小白必看 HarmonyOS Next HMRouter 轻松上手秘籍
- 【芙莉莲教你写代码】元服务 DevEco Studio 第二章 页面与布局
- 【芙莉莲教你写代码】元服务 DevEco Studio 第三章 布局基础
- OpenHarmony:Android XML 到OpenHarmony ArkUI一键转化
- 第十五课:HarmonyOS Next开发规范与代码风格全解析
- 手把手教你用 Ark-TS UI 做一个会 “动” 的计数器:从代码到原理全解析
- 【HarmonyOS NEXT】 ArkUI常用布局及组件库介绍
- 第一课:HarmonyOS Next布局开发指南