首页 > 其他分享 >Android开发笔记[14]-简单侧边栏

Android开发笔记[14]-简单侧边栏

时间:2024-03-18 15:14:03浏览次数:35  
标签:end 14 val 侧边 intent import Android 抽屉 android

摘要

使用最简单方式实现抽屉侧边栏,点击按钮打开抽屉侧边栏.

关键信息

  • Android Studio:Iguana | 2023.2.1
  • Gradle:distributionUrl=https://services.gradle.org/distributions/gradle-8.4-bin.zip
  • jvmTarget = '1.8'
  • minSdk 24
  • targetSdk 34
  • compileSdk 34
  • 开发语言:Kotlin,Java
  • ndkVersion = '21.1.6352462'
  • kotlin版本:1.9.20
  • kotlinCompilerExtensionVersion '1.5.4'
  • com.android.library:8.3

原理简介

抽屉式侧边栏

[https://pixso.cn/designskills/cechoutisheji/]
[https://juejin.cn/post/7109057588460797988]
[https://developer.android.google.cn/jetpack/androidx/releases/drawerlayout?hl=zh-cn]
[https://developer.android.google.cn/guide/navigation/integrations/ui?hl=zh-cn]
侧抽屉究竟有多强?合理设计让用户不迷路
当屏幕尺寸有限,产品功能越来越多时,侧抽屉可以 “收纳”功能,减少用户认知负担,使界面更加清爽好用.
移动用户在使用应用程序时需要随时知道去“哪里”,以及如何到“那里”。为了使UI导航既可发现又可用,UI设计师好的选择是侧抽屉。侧边抽屉减少了 UI 混乱并优先考虑重要的导航目的地。侧抽屉的设计非常简单,适合大多数移动应用程序布局。
侧边抽屉,也称为滑动菜单、导航抽屉或左侧导航,包含网站或移动应用程序的主要导航目的地。通常隐藏在视图之外,侧抽屉从屏幕的左边缘滑入。它可以用鼠标或手指滑动,也可以用汉堡图标打开或关闭。链接按优先级顺序显示为一个在另一个之下的多个行项目。
类型:

  • 永久侧抽屉
    始终可见并固定在屏幕的左边缘。此侧抽屉推荐用于桌面设计。
  • 持久侧边抽屉
    默认折叠,用户可以打开或关闭。它与屏幕内容的其余部分位于相同的表面高度。打开时,它会强制其他内容适应大小。建议将此侧抽屉用于任何大于移动设备的 UI 设计,例如台式机、平板电脑和横向模式。
  • 迷你变体侧抽屉
    类似于持久侧抽屉,该抽屉在其“静止位置”隐藏在视线之外。但是,与强制其他元素调整的持久侧抽屉不同,迷你变体抽屉根据 UI 的内容扩展宽度。对于需要快速选择访问的应用程序,建议使用此侧抽屉。
  • 临时侧边抽屉
    最常用于移动应用程序设计,临时侧边抽屉切换打开或关闭,并在所有其他内容之上打开。侧边抽屉导航从左侧滑出,占据整个屏幕高度,遵循普通列表的布局规则。手机端的侧边抽屉距离屏幕右侧56dp。

如果移动应用程序具有深度导航结构,则用户将需要一种在导航目的地之间移动的方法,从而不会被视觉混乱或复杂的导航路径分心。
侧抽屉将所有导航项分组在一个根视图下。通过整合项目,而不是将它们分散在 UI 中,提高可见性。还可以减少用户的认知负担,因为他们只需要关注单个UI组件。
此外,由于没有后退按钮,完成任务所需的用户操作数量保持在最低限度。作为一般经验法则,如果应用几乎没有导航选项,则应该避免使用侧边抽屉。默认情况下使用折叠视图,侧边抽屉降低了导航的可发现性。
事实上,侧边抽屉式导航可能会花费一半的用户参与度。所以请注意,如果没有可用性,简洁的设计就毫无意义。当导航选项较少时,最好设计一个导航栏或使用选项卡式导航。

添加侧边栏最简单方式:

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <!--主页面布局-->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center">

        <Button
            android:id="@+id/btn_open"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="打开滑动菜单"
            android:textColor="#000"
            android:textSize="18sp" />
    </LinearLayout>

    <!--滑动菜单布局-->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="@color/colorAccent"
        android:gravity="center">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="滑动菜单"
            android:textColor="#000"
            android:textSize="18sp" />
    </LinearLayout>

</androidx.drawerlayout.widget.DrawerLayout>

侧边栏的关键是android:layout_gravity="start",start设置了从左侧划出,end可设置从右侧划出.

Android导航图

[https://juejin.cn/post/7241184271318515773]
[https://developer.android.google.cn/guide/navigation?hl=zh-cn]
Navigation 作为 Android Jetpack 组件库中的一员,是一个通用的页面导航框架。为单 Activity 架构而生的端内路由导航,用来管理 Fragment 的切换,并且可以通过可视化的方式,看见 App 的交互流程。

导航图原理

实现

核心代码

注意:侧边栏布局在xml中需要放置在主页布局下方,否则可以显示无法交互.
activity_main.xml

<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main_drawerlayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:openDrawer="start"
    tools:context="cn.qsbye.grape_yolov5_detect_android.MainActivity" >

    <!-- start 主界面 -->
    <LinearLayout
        android:id="@+id/activity_main"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:paddingRight="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_vertical_margin"
        android:orientation="vertical">

        <!-- start 顶部标题栏 -->
        <com.google.android.material.card.MaterialCardView
            android:layout_width="380dp"
            android:layout_height="wrap_content"
            app:cardCornerRadius="8dp"
            app:cardElevation="4dp"
            app:strokeWidth="0dp"
            android:layout_gravity="center"
            app:cardBackgroundColor="@color/macaron_lavender_maple">
            <androidx.appcompat.widget.ActionMenuView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                >

                <Button
                    android:id="@+id/title_drawer_btn"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:backgroundTint="@color/macaron_lavender_maple"
                    android:text="爱(AI)数葡萄"
                    android:textColor="@color/white" />

            </androidx.appcompat.widget.ActionMenuView>
        </com.google.android.material.card.MaterialCardView>
        <!-- end 顶部标题栏 -->

        <ImageView
            android:id="@+id/background_image"
            android:layout_width="wrap_content"
            android:layout_height="450dp"
            android:layout_marginTop="@dimen/activity_horizontal_margin"
            android:src="@drawable/grape_bg"/>

        <!-- start 智慧视觉按钮 -->
        <Button
            android:id="@+id/smart_vision_btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingLeft="@dimen/activity_vertical_margin"
            android:paddingRight="@dimen/activity_vertical_margin"
            android:text="智慧视觉" />
        <!-- end 智慧视觉按钮 -->

        <!-- start 图片识别选择按钮 -->
        <Button
            android:id="@+id/photo_detect_btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingLeft="@dimen/activity_vertical_margin"
            android:paddingRight="@dimen/activity_vertical_margin"
            android:text="图片识别" />
        <!-- end 图片识别选择按钮 -->

        <!-- start 幸运按钮 -->
        <Button
            android:id="@+id/lucky_btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingLeft="@dimen/activity_vertical_margin"
            android:paddingRight="@dimen/activity_vertical_margin"
            android:text="幸运按钮" />
        <!-- end 幸运按钮 -->

    </LinearLayout>
    <!-- end 主界面 -->

    <!-- start 抽屉导航(必须放在主界面以下,否则无法交互) -->

    <!-- start 侧边栏按钮容器 -->
    <LinearLayout
        android:layout_width="200dp"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:layout_gravity="start"
        android:background="@color/white"
        android:paddingBottom="0dp">

        <!-- start 选择图片按钮 -->
        <Button
            android:id="@+id/select_from_album_btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="选择相册图片" />
        <!-- end 选择图片按钮 -->

        <!-- start 拍照按钮 -->
        <Button
            android:id="@+id/camera_btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="拍照" />
        <!-- end 拍照按钮 -->

        <!-- start 跳转关于页按钮 -->
        <Button
            android:id="@+id/about_activity_btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="关于" />
        <!-- end 跳转关于页按钮 -->

        <!-- start 跳转设置页按钮 -->
        <Button
            android:id="@+id/settings_activity_btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="设置" />
        <!-- end 跳转设置页按钮 -->

        <!-- start 跳转任意门按钮 -->
        <Button
            android:id="@+id/pattern_lock_activity_btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="任意门" />
        <!-- end 跳转任意门按钮 -->

    </LinearLayout>
    <!-- end 侧边栏按钮容器 -->

    <!-- end 抽屉导航 -->

</androidx.drawerlayout.widget.DrawerLayout>

MainActivity.kt

package cn.qsbye.grape_yolov5_detect_android

import android.content.Context
import android.content.Intent
import android.content.res.AssetManager
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Bundle
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.Button
import android.widget.LinearLayout
import android.widget.ProgressBar
import android.widget.Toast
import androidx.activity.result.ActivityResult
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.FileProvider
import androidx.core.view.GravityCompat
import androidx.drawerlayout.widget.DrawerLayout
import androidx.lifecycle.lifecycleScope
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp
import cn.qsbye.grape_yolov5_detect_android.databinding.ActivityMainBinding
import com.hjq.permissions.OnPermissionCallback
import com.hjq.permissions.Permission
import com.hjq.permissions.XXPermissions
import com.mikepenz.materialdrawer.model.DividerDrawerItem
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem
import com.mikepenz.materialdrawer.model.SecondaryDrawerItem
import com.mikepenz.materialdrawer.model.interfaces.nameRes
import com.mikepenz.materialdrawer.model.interfaces.withName
import com.mx.imgpicker.MXImagePicker
import com.mx.imgpicker.app.MXImgShowActivity
import com.mx.imgpicker.builder.MXCaptureBuilder
import com.mx.imgpicker.builder.MXPickerBuilder
import com.mx.imgpicker.models.MXPickerType
import github.leavesczy.matisse.*
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import kotlin.random.Random

class MainActivity : AppCompatActivity() {

    private lateinit var appBarConfiguration: AppBarConfiguration
    private lateinit var binding: ActivityMainBinding
    private lateinit var imagePickerLauncher: ActivityResultLauncher<Intent>

    /* start 图片选择器相关 */
    private val takePictureLauncher =
        registerForActivityResult(MatisseCaptureContract()) { result: MediaResource? ->
            if (result != null) {
                val uri = result.uri
                val path = result.path
                val name = result.name
                val mimeType = result.mimeType

                // 启动ResultActivity
                val imageUri = uri
                val intent = Intent(this@MainActivity, ResultActivity::class.java)
                intent.putExtra("original_grape_bitmap_uri", imageUri)
                startActivity(intent)
            }
    }

    val mediaPickerLauncher =
        registerForActivityResult(MatisseContract()) { result: List<MediaResource>? ->
            if (!result.isNullOrEmpty()) {
                val mediaResource = result[0]
                val uri = mediaResource.uri
                val path = mediaResource.path
                val name = mediaResource.name
                val mimeType = mediaResource.mimeType

                // 启动ResultActivity
                val imageUri = uri
                val intent = Intent(this@MainActivity, ResultActivity::class.java)
                intent.putExtra("original_grape_bitmap_uri", imageUri)
                startActivity(intent)
            }
        }

    val matisse = Matisse(
        maxSelectable = 1,
        mediaFilter = DefaultMediaFilter(supportedMimeTypes = MimeType.ofImage(hasGif = false)),
        imageEngine = GlideImageEngine(),
        singleMediaType = true,
        captureStrategy = null
    )
    /* end 图片选择器相关 */

    // toast函数
    fun Context.toast(message: CharSequence) =
        Toast.makeText(this, message, Toast.LENGTH_SHORT).show();

    companion object {
        @JvmStatic
        external fun initAssetManager(assetManager: AssetManager)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 预加载图片可以提前搜索本机图片/视频资源,减少首次进入选择页面时空白时间
        MXImagePicker.init(application)
        lifecycleScope.launch{ MXImagePicker.preScan(this@MainActivity) }

        // 注册ActivityResultLauncher处理图片选择成功事件
        val imagePickerLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult ->
            if (result.resultCode == RESULT_OK) {
                // 处理图片选择结果
                val data = result.data
                val imageUri = data?.data
                if (imageUri != null) {
                    Log.e("图片", "图片选择成功")

                    // 将图片传递到 ResultActivity
                    // this.startResultActivityWithSelectedImage(imageUri)
                }else{
                    Log.e("图片", "图片选择失败!")

                    // 测试显示图片
                    MXImgShowActivity.open(
                        this, arrayListOf(
                            "https://gitee.com/zhangmengxiong/MXImagePicker/raw/master/imgs/screenshot3.png",
                        ), "图片详情"
                    )

                }
            }
        }

        // 初始化assets文件夹实例
        val assetManager: AssetManager = assets
        initAssetManager(assetManager)

        /* start 监听幸运按钮 */
        val luckyButton = findViewById<Button>(R.id.lucky_btn)
        luckyButton.setOnClickListener {
            val s_grape_file_str = String.format("grape_img/G%04d.jpg", Random.nextInt(1, 10))

            try {
                // 从assets目录中读取位图数据
                val inputStream = assets.open(s_grape_file_str)
                val bitmap = BitmapFactory.decodeStream(inputStream)

                Log.e("检测", "当前识别的图片为:$s_grape_file_str")

                // 将位图保存到应用的缓存目录中
                val file = File(cacheDir, "grape_image.jpg")
                val outputStream = FileOutputStream(file)
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
                outputStream.flush()
                outputStream.close()

                // 创建一个 Intent 对象,指定当前活动(this)和目标活动(ResultActivity::class.java)
                val intent = Intent(this@MainActivity, ResultActivity::class.java)

                // 将位图的 URI 作为附加参数传递给 ResultActivity
                val imageUri = FileProvider.getUriForFile(this, "cn.qsbye.grape_yolov5_detect_android.fileprovider", file)
                intent.putExtra("original_grape_bitmap_uri", imageUri)

                // 启动 ResultActivity
                startActivity(intent)

                // 不会执行:在解析位图完成后发送广播通知 ResultActivity
                val broadcastIntent = Intent("cn.qsbye.grape_yolov5_detect_android.DETECTION_COMPLETE")
                sendBroadcast(broadcastIntent)
            } catch (e: IOException) {
                e.printStackTrace()
            }

        } // end setOnClickListener

        /* end 监听幸运按钮 */

        /* start 监听拍照按钮 */
        val cameraButton = findViewById<Button>(R.id.camera_btn)
        cameraButton.setOnClickListener {
            /* start 检查相机权限 */
            XXPermissions.with(this)
            // 申请单个权限
            .permission(Permission.CAMERA)
                .request(object : OnPermissionCallback {

                    override fun onGranted(permissions: MutableList<String>, allGranted: Boolean) {
                        if (!allGranted) {
                            // toast("相机权限正常")
                            return
                        }
                        toast("获取相机权限成功")
                    }

                    override fun onDenied(permissions: MutableList<String>, doNotAskAgain: Boolean) {
                        if (doNotAskAgain) {
                            toast("被永久拒绝授权,请手动授予相机权限")
                            // 如果是被永久拒绝就跳转到应用权限系统设置页面
                            XXPermissions.startPermissionActivity(this@MainActivity, permissions)
                        } else {
                            toast("获取相机权限失败")
                        }
                    }
                })
            /* end 检查相机权限 */

            // 使用Matisse库
            runOnUiThread{
                takePictureLauncher.launch(MatisseCapture(captureStrategy = MediaStoreCaptureStrategy()))
            }

        } // end setOnClickListener
        /* end 监听拍照按钮 */

        /* start 监听相册按钮 */
        val selectFromAlbumButton = findViewById<Button>(R.id.select_from_album_btn)
        selectFromAlbumButton.setOnClickListener{

            /* start 检查相册(存储)权限 */
            XXPermissions.with(this)
                // 申请多个权限
                .permission(Permission.CAMERA)
                .permission(Permission.READ_MEDIA_IMAGES)
                .permission(Permission.READ_MEDIA_VIDEO)
                .permission(Permission.READ_MEDIA_VISUAL_USER_SELECTED)
                .request(object : OnPermissionCallback {
                    override fun onGranted(permissions: MutableList<String>, allGranted: Boolean) {
                        if (!allGranted) {
                            toast("有权限没有获取成功")
                            return
                        }
                        toast("获取所需权限成功")
                    }

                    override fun onDenied(permissions: MutableList<String>, doNotAskAgain: Boolean) {
                        if (doNotAskAgain) {
                            toast("被永久拒绝授权,请手动授予相机、相册权限")
                            // 如果是被永久拒绝就跳转到应用权限系统设置页面
                            XXPermissions.startPermissionActivity(this@MainActivity, permissions)
                        } else {
                            toast("获取相机、相册权限失败")
                        }
                    }
            })
            /* end 检查相册(存储)权限 */

            Log.e("图片", "进入图片选择器!")

            // 使用Matisse库
           mediaPickerLauncher.launch(matisse)

        }// end setOnClickListener

        /* end 监听相册按钮 */

        /* start 监听抽屉栏开启按钮 */
        val drawerSlider = findViewById<DrawerLayout>(R.id.activity_main_drawerlayout)
        // 找到按钮并设置点击监听器
        val titleDrawerBtn: Button = findViewById(R.id.title_drawer_btn)
        titleDrawerBtn.setOnClickListener {
            //打开滑动菜单,左侧出现
            drawerSlider.openDrawer(GravityCompat.START)
        }
        /* end 监听抽屉栏开启按钮 */

        /* start 监听关于页按钮 */
        val aboutActivityBtn: Button = findViewById(R.id.about_activity_btn)
        aboutActivityBtn.setOnClickListener {
            // 跳转关于页
            val intent = Intent(this, AboutActivity::class.java)
            startActivity(intent)
            // finish()
        }
        /* end 监听关于页按钮 */

        /* start 监听设置页按钮 */
        val settingsActivityBtn: Button = findViewById(R.id.settings_activity_btn)
        settingsActivityBtn.setOnClickListener {
            // 跳转设置页
            val intent = Intent(this, SettingsActivity::class.java)
            startActivity(intent)
            // finish()
        }
        /* end 监听设置页按钮 */

        /* start 监听任意门按钮 */
        val patternLockActivityBtn: Button = findViewById(R.id.pattern_lock_activity_btn)
        patternLockActivityBtn.setOnClickListener {
            // 跳转任意门页
            val intent = Intent(this, PatternLockActivity::class.java)
            startActivity(intent)
            // finish()
        }
        /* end 监听任意门按钮 */

        /* start 监听智慧视觉按钮 */
        val smartVisionActivityBtn: Button = findViewById(R.id.smart_vision_btn)
        smartVisionActivityBtn.setOnClickListener {
            // pass
        }
        /* end 监听智慧视觉按钮 */

        /* start 监听图片识别按钮 */
        val photoDetectBtn: Button = findViewById(R.id.photo_detect_btn)
        photoDetectBtn.setOnClickListener {
            // pass
        }
        /* end 监听图片识别按钮 */

    } // end onCreate

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        // Inflate the menu; this adds items to the action bar if it is present.
        menuInflater.inflate(R.menu.menu_main, menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        return when (item.itemId) {
            R.id.action_settings -> true
            else -> super.onOptionsItemSelected(item)
        }
    }

    override fun onSupportNavigateUp(): Boolean {
        val navController = findNavController(R.id.nav_host_fragment_content_main)
        return navController.navigateUp(appBarConfiguration)
                || super.onSupportNavigateUp()
    }

    // 用选择的图片启动ResultActivity
    private fun startResultActivityWithSelectedImage(imageUri: Uri) {
        val intent = Intent(this, ResultActivity::class.java)
        intent.putExtra("original_grape_bitmap_uri", imageUri)
        startActivity(intent)
    }

}

效果

开启抽屉侧边栏并跳转页面

标签:end,14,val,侧边,intent,import,Android,抽屉,android
From: https://www.cnblogs.com/qsbye/p/18080432

相关文章

  • Honeywell 8LS14C
    传感器是一种可感知物理量或物体特征并将其转化为可用于测量、监测、控制等目的的信号的设备。传感器通过感知外部环境的物理量或物体特征,将其转换为电信号或其他形式的信号输出,以便进行相关的测量、控制和判断。常见的传感器包括温度传感器、压力传感器、光敏传感器、声音......
  • androidui开发框架,,三级缓存框架问题你都了解了吗
    面经分享第一部分是我前端面试的经验总结,第二部分是我认为比较有思考空间的题目经验总结一份漂亮的简历,需要包括以下部分(排版由上而下)个人亮点(专精领域,个人博客,开源项目)教育经历(毕业院校,在校经历、荣誉)工作经历(实习)项目经历专业技能扎实的前端基础,比如你知道<......
  • 2024Android研发必问高级面试题,,谈谈Android-Binder机制及AIDL使用
    中高级Android需要的知识技能技能:1.了解android的签名机制(实现原理,具体操作等等),打包机制(多渠道打包,打包流程等等)2.了解apk安装文件压缩(压缩图片,代码压缩,.so文件压缩等等)3.事件分发,View绘制流程,webview相关知识点(与Native的交互,性能优化等)4.熟悉数据库的使用(基本API,第三......
  • [Java、Android面试]_08_强软弱虚四种引用及应用场景
    本人今年参加了很多面试,也有幸拿到了一些大厂的offer,整理了众多面试资料,后续还会分享众多面试资料。整理成了面试系列,由于时间有限,每天整理一点,后续会陆续分享出来,感兴趣的朋友可关注+收藏文章目录1.强引用(默认的引用形式)2.软引用3.弱引用4.虚引用引用在java中......
  • android ipc
    AndroidIPC(Inter-ProcessCommunication,进程间通信)是指在Android系统中,不同应用程序或同一个应用程序的不同进程之间进行数据交换和通信的机制。Android提供了多种IPC的方式,包括:Intent:用于在不同组件之间传递数据,适用于同一应用程序内的不同组件之间通信。Binder:Andr......
  • QT5.14.2 探秘Qt信号槽奥秘--让对象间通信如虎添翼
    一、前言在当今这个万物互联的时代,对象间通信无疑是编程领域中最为基础也最为重要的问题。作为知名的跨平台开发框架,Qt自然也需要解决这一问题。于是,Qt巧妙地提出了信号与槽(Signals&Slots)这一机制,以观察者模式的思路让对象间通信变得行云流水。那么,Qt信号与槽的本质......
  • Android第一行代码——快速入门 Kotlin 编程(2.5 面向对象编程)
    目录2.5    面向对象编程2.5.1    类与对象2.5.2    继承与构造函数2.5.3    接口2.5.4    数据类与单列类2.5    面向对象编程        和很多现代高级语言一样,Kotlin也是面向对象的,因此理解什么是面向对......
  • androidstudio Unable to delete directory E:/xxxxx
    一、概述在使用AndroidStudio运行项目的时候,有时候会出现UnabletodeletedirectoryE:/xxxxx会提示某一个文件无法删除,导致clean和重新运行都会失败。二、解决办法导致这个问题的原因是可能有两个虚拟机同时使用了该文件。第一种情况:1.打开了......
  • vue3+ts+vant写移动端项目部Android机页面打开空白
    前言部分安卓机因为内置webview较老,所以无法识别最新的es6的语法,页面打开空白。解决方式,vite项目就使用@vitejs/plugin-legacy,其他项目可以选择使用@babel/core@babel/cli@babel/preset-env这里主要提vite项目,因为babel项目的相关博客较多,就不再复述。 vite.config......
  • Android开发笔记[13]-图案密码
    摘要输入图案密码123跳转到关于页面.关键信息AndroidStudio:Iguana|2023.2.1Gradle:distributionUrl=https://services.gradle.org/distributions/gradle-8.4-bin.zipjvmTarget='1.8'minSdk21targetSdk34compileSdk34开发语言:Kotlin,JavandkVersion='21.1.6......