IOS Android Harmonyos next Pure code layout vs. pure (cross platform)
The comparison of the pure code layout of iOS, Android, and HarmonyOS 5/Next.
Preface
Hello everyone, Today I would like to share with you the comparison of the pure code layout of iOS, Android, and HarmonyOS Next. Because many students have a common problem is to rely too much on third-party frameworks, the basic skills are very poor, and even lazy, and they basically don't want to move when they encounter complex layouts.
iOS code implementation
cpp
代码解读
复制代码
// // 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
Renderings
Android code implementation
ini
代码解读
复制代码
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 端
scss
代码解读
复制代码
/** * 自定义中间弹窗 */ //线条样式 @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}) } }
Renderings
contrast
We compare the complexity of coding and the difficulty of reading, and our HarmonyOSnext is more simplified and easy to use, and at this time, someone jumped out and said that we have a swift ui in iOS, and that can also do declarative UI, yes, but in the beginning, there was only object-c, so any platform and language needs to be constantly developed to get to where we are today, and the same is true for Android, which uses kotlin with jetpack compose can also implement a similar declarative UI, but at the beginning, there was only a Java pure code layout or java+xml layout, which is why HarmonyOSnext has a late-mover advantage over the native Android and native ios, making up for the shortcomings of its predecessors and giving full play to its own advantages.
Comparison of design concepts
iOS
The pure code layout of ios has CGRectMake to set the x-y coordinates and width and height for us, the upper left corner of the screen is the origin, the horizontal is the right axis, and the vertical downward is the y-axis. It was the design which was relatively OK in that era.
Android
Android's pure code layout does not have the method of setting coordinates like ios, mainly through viewgroup to nest and wrap our view or other viewgroups, and finally add to our layout by calling addview, the code is relatively cumbersome and not easy to read. It's a copy of the XML layout. This is still a relatively high requirement for the programmer itself.
HarmonyOSNext
The pure code of HarmonyOSNext is innate, and the official designation is to use ArkUI to write layouts with the previewer, and the effect of WYSIWYG can be achieved, and the code reading is relatively clear and straightforward. Just like building blocks, we load child components through parent layouts such as linear and relative layouts, and it's easy to achieve the UI we want.
Final Summary:
Whether it's Android ios or other students who have turned over to learn HarmonyOSNext development, I very much recommend learning the basic skills, don't have xml similar to Android xml similar to xib in ios There is no similar front-end of various frameworks I don't want to learn, it's not necessary at all, the official components are already relatively rich, and the third-party library is also constantly improving, I wish every student can learn well and find a good job, and I hope that the domestic system is getting better and better. That's all for today's article, if you think the article is not bad, you can give me a one-click triple. If you are interested, follow my B station tutorial to learn more about the knowledge of Hongmeng development, you can pay attention to the nut pie public account. Thank you
Course address
Project Description:
1 Learn common layout components
2 Network request tool class encapsulation
3 Arkui Lifecycle Initiation Process
4 Encapsulation of the log tool class
5 Encapsulation of custom combination components
6 Use of Route Navigation Jumps
7 Caching of local data and the encapsulation of caching tools
8 Implementation of the Welcome Page
9 Login Cases and Automatic Login Effect Implementation
10 Request Network Data Paging Pull-Up Load Implementation of pull-down refresh
11 list data lazy loading implementation
12 Use of the WebView Component
If you use more easy-to-use HarmonyOS NEXT third-party libraries
作者:坚果派_xq9527
链接:https://juejin.cn/post/7463871170015559695
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Original date: 2025-01-26