【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex

简介: 【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex

【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex

章节内容【08】

【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-卓伊凡换人优雅草Alex

开发背景

由于卓伊凡工作实在太多,工作繁忙且卓伊凡每天晚上还要直播,因此本项目已前端部分转交优雅草Alex继续并且更新-为了保证每日更新

优雅草Alex 【高级全栈开发工程师-任职世界500强企业-月薪30k+】接下来就看这位大佬的表演吧

经典案例-在优雅草手撸加速器-win-mac-安卓+苹果 4端【仅用了一个月时间】

上篇我们做了自定义组件,本文继续完善注册相关页面并且实现跳转

闲话不多,开源仓库地址,可以观摩已经写好的代码:

https://gitee.com/youyacao/ff-flutter

demo下载

https://www.youyacao.cn/freefirend

更新代码文件和日志文件-gitee可见

·更新了getx路由
·增加了屏幕适配
·基础导航栏开发处理
·重建了Android
·布局规划了包含注册,直播,其他等页面框架
·整体处理

remote: Enumerating objects: 98, done.
remote: Counting objects: 100% (94/94), done.
remote: Compressing objects: 100% (50/50), done.
remote: Total 62 (delta 19), reused 13 (delta 0), pack-reused 0
Unpacking objects: 100% (62/62), 18.63 KiB | 141.00 KiB/s, done.
From https://gitee.com/youyacao/ff-flutter
   2d36d20..71239bb  master     -> origin/master
Updating 2d36d20..71239bb
Fast-forward
 .cursorrules                                       | 130 +++++++++++
 .fvmrc                                             |   3 +
 .gitignore                                         |   3 +
 .metadata                                          |  30 +--
 .vscode/launch.json                                |   6 +-
 .vscode/settings.json                              |   3 +
 android/.gitignore                                 |   2 +-
 android/app/build.gradle                           |  53 +++--
 android/app/src/main/AndroidManifest.xml           |   5 +-
 .../{freefirend => ff_flutter}/MainActivity.kt     |   2 +-
 .../app/src/main/res/mipmap-hdpi/ic_launcher.png   | Bin 1508805 -> 544 bytes
 .../app/src/main/res/mipmap-mdpi/ic_launcher.png   | Bin 1508805 -> 442 bytes
 .../app/src/main/res/mipmap-xhdpi/ic_launcher.png  | Bin 1508805 -> 721 bytes
 .../app/src/main/res/mipmap-xxhdpi/ic_launcher.png | Bin 1508805 -> 1031 bytes
 .../src/main/res/mipmap-xxxhdpi/ic_launcher.png    | Bin 1508805 -> 1443 bytes
 android/build.gradle                               |   4 +-
 android/gradle.properties                          |   2 +-
 android/gradle/wrapper/gradle-wrapper.properties   |   2 +-
 android/settings.gradle                            |   9 +-
 lib/controllers/index_controller.dart              |   5 +
 lib/controllers/register_controller.dart           |  14 ++
 lib/controllers/sms_login_controller.dart          |   5 +
 lib/main.dart                                      |  34 +--
 lib/routes/app_pages.dart                          |  38 +++
 lib/routes/app_routes.dart                         |   5 +
 lib/screens/account_screen.dart                    |  16 ++
 lib/screens/home_screen.dart                       | 254 ++++++++++++++++++++
 lib/screens/index.dart                             | 259 ++++++++-------------
 lib/screens/message_screen.dart                    |  16 ++
 lib/screens/register.dart                          | 109 +++++----
 lib/screens/short_video_screen.dart                |  16 ++
 linux/main.cc                                      |   6 +
 linux/my_application.cc                            | 124 ++++++++++
 linux/my_application.h                             |  18 ++
 pubspec.lock                                       |  66 ++++--
 pubspec.yaml                                       |   2 +
 test/widget_test.dart                              |  30 +++
 37 files changed, 972 insertions(+), 299 deletions(-)
 create mode 100644 .cursorrules
 create mode 100644 .fvmrc
 create mode 100644 .vscode/settings.json
 rename android/app/src/main/kotlin/com/example/{freefirend => ff_flutter}/MainActivity.kt (74%)
 create mode 100644 lib/controllers/index_controller.dart
 create mode 100644 lib/controllers/register_controller.dart
 create mode 100644 lib/controllers/sms_login_controller.dart
 create mode 100644 lib/routes/app_pages.dart
 create mode 100644 lib/routes/app_routes.dart
 create mode 100644 lib/screens/account_screen.dart
 create mode 100644 lib/screens/home_screen.dart
 create mode 100644 lib/screens/message_screen.dart
 create mode 100644 lib/screens/short_video_screen.dart
 create mode 100644 linux/main.cc
 create mode 100644 linux/my_application.cc
 create mode 100644 linux/my_application.h
 create mode 100644 test/widget_test.dart

实战开始

先打包个,flutter build apk 运行, 报错

先运行下看看

可以成功运行,那么已经可以确定肯定是gradle 打包问题了,解决打包问题前我们已经看看更新的内容吧,

import 'package:flutter/material.dart';
import 'package:logging/logging.dart';
import 'package:get/get.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:ff_flutter/routes/app_pages.dart';
import 'package:ff_flutter/routes/app_routes.dart';
void main() {
  // 初始化日志记录器
  Logger.root.level = Level.ALL;
  Logger.root.onRecord.listen((record) {
    debugPrint('${record.level.name}: ${record.time}: ${record.message}');
  });
  runApp(const MainApp());
}
class MainApp extends StatelessWidget {
  const MainApp({super.key});
  @override
  Widget build(BuildContext context) {
    return ScreenUtilInit(
        designSize: const Size(750, 1624), // 设置设计稿尺寸
        minTextAdapt: true,
        splitScreenMode: true,
        builder: (context, child) {
          return GetMaterialApp(
            debugShowCheckedModeBanner: false,
            title: 'freefirend',
            theme: ThemeData(
              primarySwatch: Colors.blue,
            ),
            initialRoute: AppRoutes.INDEX,
            getPages: AppPages.pages,
          );
        });
  }
}

从入口文件看到 更新了 路由app_routes.dart,更新了要么框架 app_pages.dart

页面框架代码:

import 'package:get/get.dart';
import 'package:ff_flutter/screens/index.dart';
import 'package:ff_flutter/screens/register.dart';
import 'package:ff_flutter/screens/smslogin.dart' as sms;
import 'package:ff_flutter/screens/home_screen.dart';
import 'package:ff_flutter/screens/short_video_screen.dart';
import 'package:ff_flutter/screens/message_screen.dart';
import 'package:ff_flutter/screens/account_screen.dart';
import 'package:ff_flutter/routes/app_routes.dart';
import 'package:ff_flutter/controllers/index_controller.dart';
import 'package:ff_flutter/controllers/register_controller.dart';
import 'package:ff_flutter/controllers/sms_login_controller.dart';
class AppPages {
  static final pages = [
    GetPage(
      name: AppRoutes.INDEX,
      page: () => IndexScreen(),
      binding: BindingsBuilder(() {
        Get.lazyPut(() => IndexController());
      }),
    ),
    GetPage(
      name: AppRoutes.REGISTER,
      page: () => const RegisterScreen(),
      binding: BindingsBuilder(() {
        Get.lazyPut(() => RegisterController());
      }),
    ),
    GetPage(
      name: AppRoutes.SMS_LOGIN,
      page: () => const sms.SmsLoginScreen(),
      binding: BindingsBuilder(() {
        Get.lazyPut(() => SmsLoginController());
      }),
    ),
  ];
}

路由文件代码,

abstract class AppRoutes {
  static const INDEX = '/';
  static const REGISTER = '/register';
  static const SMS_LOGIN = '/sms-login';
}

创建了 control 文件,里面对页面进行了方法的文件创建和默认的内容,诸如注册的调用

import 'package:get/get.dart';
class RegisterController extends GetxController {
  final RxBool agreedToTerms = false.obs;
  final RxString selectedCountryCode = '+1'.obs;
  void updateAgreedToTerms(bool value) {
    agreedToTerms.value = value;
  }
  void updateSelectedCountryCode(String value) {
    selectedCountryCode.value = value;
  }
}

这段代码定义了一个名为 RegisterController 的类,继承自 GetxController。它包含两个可观察变量:agreedToTerms 表示用户是否同意条款,默认为 falseselectedCountryCode 表示选择的国家代码,默认为 +1。还提供了两个方法用于更新这些变量的值。

控制流图

mermaid

flowchart TD A[初始化 RegisterController] --> B{更新 agreedToTerms} B -->|调用 updateAgreedToTerms| C[设置 agreedToTerms 值] A --> D{更新 selectedCountryCode} D -->|调用 updateSelectedCountryCode| E[设置 selectedCountryCode 值]

整体主要是对框架进行了适配,此刻我发现同事把我打包图标默认的默认被换了,因此我建立APP打包的图标自定义

找到原图标,下载并保存

修改pubspec.yaml, 加入自定义图标代码

flutter_launcher_icons:
  image_path: "assets/icon/logo.png"  # 指定用于生成图标的源图像路径
  android: true  # 表示要为 Android 平台生成图标
  ios: true      # 表示要为 iOS 平台生成图标
  remove_alpha_ios: true  # 移除 iOS 图标中的透明通道

在资源目录加入assets\icons中logo.png文件

再来看看index.dart中对导航栏的书写,

import 'package:flutter/material.dart';
import 'package:ff_flutter/screens/register.dart'; // 导入 register.dart 文件
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:ff_flutter/routes/app_routes.dart';
import 'package:ff_flutter/screens/home_screen.dart';
import 'package:ff_flutter/screens/short_video_screen.dart';
import 'package:ff_flutter/screens/message_screen.dart';
import 'package:ff_flutter/screens/account_screen.dart';
class IndexScreen extends StatefulWidget {
  // 改为 StatefulWidget
  @override
  State<IndexScreen> createState() => _IndexScreenState();
}
class _IndexScreenState extends State<IndexScreen> {
  int _selectedIndex = 0;
  final List<Widget> _pages = [
    HomeScreen(),
    ShortVideoScreen(),
    MessageScreen(),
    AccountScreen(),
  ];
  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: const Color(0xFF1E1E1E),
      body: IndexedStack(
        index: _selectedIndex,
        children: _pages,
      ),
      bottomNavigationBar: Container(
        height: 168.h,
        decoration: const BoxDecoration(
          color: Color(0xFF1E1E1E),
        ),
        child: Theme(
          data: ThemeData(
            splashColor: Colors.transparent,
            highlightColor: Colors.transparent,
          ),
          child: BottomNavigationBar(
            items: const <BottomNavigationBarItem>[
              BottomNavigationBarItem(
                icon: Icon(Icons.home),
                label: 'Home',
                activeIcon: Icon(Icons.home, color: Color(0xFFE7568C)),
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.play_circle_outline),
                label: 'Short Video',
                activeIcon:
                    Icon(Icons.play_circle_outline, color: Color(0xFFE7568C)),
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.notifications_none),
                label: 'Message',
                activeIcon:
                    Icon(Icons.notifications_none, color: Color(0xFFE7568C)),
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.person_outline),
                label: 'Account',
                activeIcon:
                    Icon(Icons.person_outline, color: Color(0xFFE7568C)),
              ),
            ],
            currentIndex: _selectedIndex,
            selectedItemColor: const Color(0xFFE7568C),
            unselectedItemColor: Colors.grey,
            backgroundColor: const Color(0xFF1E1E1E),
            type: BottomNavigationBarType.fixed,
            selectedFontSize: 24.sp,
            unselectedFontSize: 24.sp,
            iconSize: 48.sp,
            elevation: 0,
            onTap: _onItemTapped,
          ),
        ),
      ),
    );
  }
}
class DownloadButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ElevatedButton.icon(
      onPressed: () {
        // 处理下载逻辑
      },
      icon: const Icon(
        Icons.system_update_alt,
        size: 30,
        color: Color(0xfff1f1f1), // 设置图标颜色为 0xfff1f1f1
      ),
      label: const Text(
        "Download",
        style: TextStyle(
          color: Color(0xfff1f1f1),
          fontSize: 26,
          fontFamily: "PingFang SC",
          fontWeight: FontWeight.w800,
        ),
      ),
      style: ElevatedButton.styleFrom(
        backgroundColor:
            const Color(0xffe7568c), // 使用 backgroundColor 替代 primary
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(27.r),
        ),
        padding: EdgeInsets.symmetric(horizontal: 17.w, vertical: 9.h),
        minimumSize: Size(195.w, 54.h),
      ),
    );
  }
}
class CustomIconButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 54.w,
      height: 54.h,
      child: Stack(
        children: [
          Container(
            width: 54.w,
            height: 54.h,
            decoration: const BoxDecoration(
              shape: BoxShape.circle,
              color: Color(0xff151313),
            ),
          ),
          Positioned.fill(
            child: Align(
              alignment: Alignment.center,
              child: const Icon(
                Icons.notifications,
                size: 36,
                color: Color(0xfff1f1f1), // 设置图标颜色为 0xfff1f1f1
              ),
            ),
          ),
        ],
      ),
    );
  }
}
class MoreButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisSize: MainAxisSize.min,
      mainAxisAlignment: MainAxisAlignment.start,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        const Text(
          "more",
          style: TextStyle(
            color: Color(0xff929292),
            fontSize: 26,
          ),
        ),
        SizedBox(width: 10.w),
        Transform.rotate(
          angle: 3.14,
          child: Container(
            width: 26.w,
            height: 26.h,
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(8.r),
            ),
            child: const Icon(
              Icons.arrow_back, // 替换为合适的图标
              size: 26,
              color: Color(0xfff1f1f1), // 设置图标颜色为 0xfff1f1f1
            ),
          ),
        ),
      ],
    );
  }
}

结束,最后我们再来看看打包问题,解决之前的报错 只需要对Gradle处理,以下是常用处理方式,gradlew clean解决了我们的问题

java.net.SocketException: Unexpected end of file from server 错误通常发生在 Gradle 尝试从服务器下载依赖项时遇到连接问题。以下是一些可能的解决方案:

  • 检查网络连接
  • 确保你的网络连接稳定。
  • 如果使用代理,请确保代理配置正确。
  • 清理 Gradle 缓存
  • 进入项目根目录,运行命令 gradlew clean 清理构建缓存。
  • 删除 .gradle 文件夹(位于用户主目录下)以清除全局 Gradle 缓存。
  • 更新 Gradle 和插件
  • 检查并更新项目的 Gradle 版本和 Android 插件版本到最新稳定版。
  • 修改 build.gradle 文件中的 distributionUrl 到最新的 Gradle 版本。
  • 检查依赖项
  • 确认 pubspec.yaml 中的所有依赖项都能正常访问。
  • 使用 flutter pub get 命令来获取 Dart/Flutter 依赖项。
  • 尝试离线模式(如果网络不稳定):
  • gradle.properties 文件中添加 org.gradle.offline=true 来启用 Gradle 离线模式。
  • 防火墙或杀毒软件干扰
  • 暂时禁用防火墙或杀毒软件,测试是否是它们阻止了 Gradle 的网络请求。
  • 重试构建
  • 有时候简单的重试可以解决问题,因为可能是临时的网络波动导致的。

但是又遇到了新的问题,

问题出在 Gradle 版本与 Java 版本不兼容。具体来说,Gradle 不支持当前使用的 Java 版本(Java 11 或更高版本)。以下是解决此问题的步骤

  1. 检查当前 Java 和 Gradle 版本
  • 运行 flutter doctor --verbose 检查当前使用的 Java 和 Gradle 版本。
  1. 更新 Gradle 版本
  • 打开项目中的 android/gradle/wrapper/gradle-wrapper.properties 文件。
  • 修改 distributionUrl 以使用一个与当前 Java 版本兼容的 Gradle 版本。例如:

properties

distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip

  1. 更新 Android Studio 的 JDK
  • 如果你使用的是 Android Studio,确保它使用的是与 Gradle 兼容的 JDK 版本。可以在 Android Studio 的设置中更改 JDK 版本:
  • 打开 File -> Project Structure -> SDK Location
  • 更改 JDK location 到一个兼容的 JDK 版本。
  1. 清理和重建项目
  • 清理 Gradle 缓存:

bash

cd android ./gradlew clean

  • 重新构建项目:

bash

flutter clean flutter pub get flutter build apk --release

最后我们成功解决问题,已经提交打包,发现,还是不兼容,这时候怎么办,我们需要用到 FVM (Flutter Version Manager)

由于错误发生在 flutter_tools 中,你还需要确保 Flutter 工具本身使用的 Gradle 版本是最新的。你可以通过以下步骤来更新 Flutter 工具的 Gradle 版本:

  1. 打开 Flutter SDK 目录下的 packages/flutter_tools/gradle/gradle-wrapper.properties 文件。
  2. 修改 distributionUrl 为最新的 Gradle 版本,例如:

properties

distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip

使用 FVM (Flutter Version Manager)

如果你使用多个 Flutter 版本,建议使用 FVM 来管理不同项目的 Flutter 版本,确保每个项目使用兼容的 Flutter 和 Gradle 版本。

通过以上步骤,你应该能够解决 Gradle 版本与 Java 版本不兼容的问题,并成功构建你的 Flutter 项目。如果问题仍然存在,请提供更多的日志输出(如 --stacktrace --info),以便进一步诊断。

使用 FVM(Flutter Version Manager)可以帮助你管理不同项目的 Flutter 版本,确保每个项目使用兼容的 Flutter 和 Gradle 版本。以下是详细的步骤来安装和配置 FVM:

安装 FVM

  1. 安装 FVM: 你可以通过以下命令全局安装 FVM:

bash

dart pub global activate fvm

  1. 将 FVM 添加到 PATH: 确保 FVM 的二进制文件路径已添加到你的系统 PATH 中。通常路径为 ~/.pub-cache/bin。你可以通过以下命令将其添加到当前终端会话中:

bash

export PATH="$PATH":"$HOME/.pub-cache/bin"

如果你想永久添加,请将上述命令添加到你的 shell 配置文件中(例如 .bashrc.zshrc .bash_profile)。

使用 FVM 初始化项目

  1. 初始化 FVM: 在你的项目根目录下运行以下命令以初始化 FVM:

bash

fvm install

  1. 选择 Flutter 版本: FVM 会自动从 fvm.yaml 文件中读取指定的 Flutter 版本。如果没有该文件,FVM 会提示你选择一个版本并创建 fvm.yaml 文件。你也可以手动编辑 fvm.yaml 文件来指定版本:

yaml

flutter_sdk: version: "3.7.12" # 替换为你需要的版本号

  1. 使用指定的 Flutter 版本: 运行以下命令以使用 FVM 管理的 Flutter 版本:

bash

fvm flutter --version

更新项目中的依赖项

  1. 获取 Dart/Flutter 依赖项: 使用 FVM 管理的 Flutter 版本来获取依赖项:

bash

fvm flutter pub get

  1. 清理和重建项目: 清理 Gradle 缓存并重新构建项目:

bash

cd android ../.fvm/flutter_sdk/bin/flutter clean ../.fvm/flutter_sdk/bin/flutter pub get ../.fvm/flutter_sdk/bin/flutter build apk --release

更新 Gradle 和 Java 版本

  1. 更新 Gradle 版本: 打开项目中的 android/gradle/wrapper/gradle-wrapper.properties 文件,修改 distributionUrl 以使用一个与当前 Java 版本兼容的 Gradle 版本。例如:

properties

distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip

  1. 更新 Android Studio 的 JDK: 如果你使用的是 Android Studio,确保它使用的是与 Gradle 兼容的 JDK 版本。可以在 Android Studio 的设置中更改 JDK 版本:
  • 打开 File -> Project Structure -> SDK Location
  • 更改 JDK location 到一个兼容的 JDK 版本。

检查环境变量配置

确保你的环境变量配置正确,特别是 JAVA_HOME PATH 变量,指向正确的 JDK 和 Gradle 安装路径。

示例流程

假设你已经安装了 FVM 并将其添加到 PATH 中,以下是完整的示例流程:

  1. 初始化 FVM 并选择 Flutter 版本:

bash

cd g:\clone\ff-flutter fvm install

  1. 使用 FVM 管理的 Flutter 版本检查当前版本:

bash

fvm flutter --version

  1. 获取 Dart/Flutter 依赖项:

bash

fvm flutter pub get

  1. 清理和重建项目:

bash

cd android ../.fvm/flutter_sdk/bin/flutter clean ../.fvm/flutter_sdk/bin/flutter pub get ../.fvm/flutter_sdk/bin/flutter build apk --release

目录
打赏
0
20
20
0
200
分享
相关文章
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
98 72
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
171 90
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
54 4
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
Android软件版本更新
 转的:适合新手学习,但在实际项目中不可这么做。 以下是我转的内容: =================================================================== androiddownloaddialogfilestringbuffer 各种平台软件更新做法差不多,大体做法如下: 1.服务器存放一个最新版本的xml文件,或者存在数据库,各种做法都可以。
1032 0
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
50 8
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
105 12
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
escrcpy:【技术党必看】Android开发,Escrcpy 让你无线投屏新体验!图形界面掌控 Android,30-120fps 超流畅!🔥
escrcpy 是一款基于 Scrcpy 的开源项目,使用 Electron 构建,提供图形化界面来显示和控制 Android 设备。它支持 USB 和 Wi-Fi 连接,帧率可达 30-120fps,延迟低至 35-70ms,启动迅速且画质清晰。escrcpy 拥有丰富的功能,包括自动化任务、多设备管理、反向网络共享、批量操作等,无需注册账号或广告干扰。适用于游戏直播、办公协作和教育演示等多种场景,是一款轻量级、高性能的 Android 控制工具。
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
43 1
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
探索安卓开发中的自定义视图:打造个性化用户界面
在安卓应用开发的广阔天地中,自定义视图是一块神奇的画布,让开发者能够突破标准控件的限制,绘制出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战技巧,逐步揭示如何在安卓平台上创建和运用自定义视图来提升用户体验。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开新的视野,让你的应用在众多同质化产品中脱颖而出。
84 19
探索安卓开发:打造你的首个天气应用
在这篇技术指南中,我们将一起潜入安卓开发的海洋,学习如何从零开始构建一个简单的天气应用。通过这个实践项目,你将掌握安卓开发的核心概念、界面设计、网络编程以及数据解析等技能。无论你是初学者还是有一定基础的开发者,这篇文章都将为你提供一个清晰的路线图和实用的代码示例,帮助你在安卓开发的道路上迈出坚实的一步。让我们一起开始这段旅程,打造属于你自己的第一个安卓应用吧!
107 14

热门文章

最新文章

推荐镜像

更多