Android学习笔记之资源目录

Hello各位小伙伴,第二期来了

这一期记录了Android设备和工程下的资源目录相关知识

资源

设备存储系统

Android采用VFS虚拟文件系统

 

/data/data是内部存储

/storage/emulated/0是内置SD卡,但是实际上这个链接通过软链接+挂载,有了好多个"快捷方式",你在很多地方都可以查看到

访问不同目录的方法

​​​​​​​Environment.isExternalStorageRemovable()//判断是内置SD卡还是外置SD卡

Context类中有一些在内部存储的沙盒目录中操作的方法

//获取/data/data/<包名>/files
getFilesDir();
//读取files文件夹下的某文件
openFileInput("files文件夹下的某文件");
//写入files文件夹下的某文件,不存在则新建,(private是若存在则覆盖,append是若存在则追加)
openFileOutput("想放在files文件夹下的文件",MODE_PRIVATE);
//获取/data/data/<包名>/子目录
getDir("子目录",MODE_PRIVATE);
//获取文件列表
fileList();
//获取/data/data/<包名>/cache
getCacheDir();

还有一些访问SD卡中本APP沙盒目录的方法

//获取/Android/data/<包名>/cache
getExternalCacheDir();
//获取/Android/data/<包名>/files/alarms
getExternalFilesDir(Environment.DIRECTORY_ALARMS);

Android 10 应用无法访问SD卡的非沙盒目录部分,需要在Manifest的application中添加"使用已过时的外部存储"

android:requestLegacyExternalStorage="true"

Android 11 已经完全无法使用上述方法,应用只能读写内存和SD卡中的沙盒目录

像素

1080*2208分辨率代表手机屏幕横向1080个像素块,纵向2208个像素块

我的手机拍照成片像素会被算法压缩到1200W(3000*4000)

所以此时手机屏幕显示图片就出现像素块不够用的情况

有两种可能的方式:

方式效果
1:1显示1个照片像素块对应1个屏幕像素块,那么屏幕上只能显示照片的不到1/4
智能压缩照片的多个像素块取均值合成为1个像素块,显示在屏幕上(抗锯齿)

所以Bitmap要进行手动压缩,不手动压缩的话,照片像素块数很可能远多于ImageView区域像素块数,导致Bitmap体积过大;

手动压缩可以使每个像素块物尽其用

数字单位

单位
px像素
in英寸
pt磅;1pt=1/72英寸
dp抽象单位;在分辨率160的设备上,1dp=1px
分辨率以1英寸为对角线长度的方块里面,能容纳多少个像素块

Assets

  • 无法自动响应配置限定的资源,在打包后不会以二进制的形式存在

  • 只能通过AssetManager获取

  • 在R.java里没有对应ID

//context对象的getAssets()方法可以获取AssetManager
AssetManager mAssets = getAssets();
//获得所有在assets/my_folder文件夹下的文件列表
String[] names = mAssets.list("my_folder");
//打开asset文件
InputStream in = mAssets.open("my_folder/filename");
//取得AssetsFileDescriptor
AssetsFileDescriptor afd = mAssets.openFD("my_folder/filename");
//取得FileDescriptor
FileDescriptor fd = afd.getFileDescriptor();

配置限定符

不同限定文件夹如果冲突,按照优先级表

屏幕分辨率

ldpi:提供给低分辨率设备的资源(120dpi以下)

mdpi:提供给中等分辨率设备的资源(120dpi~160dpi)

hdpi:提供给高分辨率设备的资源(160dpi~240dpi)

xhdpi:提供给超高分辨率设备的资源(240dpi~320dpi)

xxhdpi:提供给超超高分辨率设备的资源(320dpi~480dpi)

xxxhdpi:提供给超超超高分辨率设备的资源(480dpi~)

屏幕大小

small

normal

large

xlarge

layout-w600dp:提供给当前宽度超过600dp设备的资源

layout-sw600dp:提供给最小宽度超过600dp设备的资源

屏幕方向

layout-land:横屏

layout-port:默认竖屏

语言

zh:中文

en:英文

例子:程序会根据当前设备的屏幕大小,自动选择采用单页还是双页布局

新建layout-large文件夹,放入双页布局的xml文件

在原layout文件夹,放入单页布局的xml文件

如果不使用默认的限定符,也可以自定义最小宽度限定符

把layout-large文件夹重命名为layout-sw600dp文件夹,就意味着屏幕宽度超过600dp时,自动采用双页布局

更多查阅应用资源概览  |  Android 开发者  |  Android Developers

引用res资源的语法

在代码中通过R.string.string_name可以获得该字符串的引用

在XML中通过@string/string_name可以获得该字符串的引用

string可以替换为drawable,mipmap,layout...

在XML中通过@+id/id_name可以定义id

res中是没有id的,所以在其他XML中定义

raw

  • 该文件夹没有目录结构,不可创建子文件夹

  • 原封不动的存储到设备上,不会转换为二进制

strings.xml

%1$s是占位符

<string name="format">这是第%1$s个字符串</string>

使用时

getString(R.string.format,"1")

refs.xml

给单双页布局指定同一个别名,使用时用别名,系统会自动选择合适的

新建res/values/refs.xml

<!--从此之后activity_list是activity_xxx的别名-->
<item name="activity_list" type="layout">@layout/activity_xxx</item>

themes.xml

外部通过?attr/属性名获得<item name="属性名">xxx</item>指向的值

Menu

res中新建menu文件夹

menu文件夹中新建Menu resource file

<menu xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
    
<group android:checkableBehavior="single"><!--单选选项组-->
    <item
            android:id="@+id/add_item"
            android:title="添加"  <!--长按图标会显示-->
            android:icon="xxx"
            app:showAsAction="always" /><!--永远把这个选项以ImageButton的形式放在栏里,尽量使用ifRoom-->
    <item
            android:id="@+id/remove_item"
            android:title="删除"
            android:icon="xxx"
            app:showAsAction="ifRoom" /><!--如果有空间,就把这个选项以ImageButton的形式放在栏里-->
</group>
</menu>

回到Activity中重写onCreateOptionsMenu()方法,快捷键ctrl+o

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    super.getMenuInflater().inflate(R.menu.main, menu);//inflate膨胀
    return true;
}

现在有了菜单,需要给菜单里的每一个选项定义响应事件

继续重写onOptionsItemSelected()方法

@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
    switch (item.getItemId()){
        case R.id.add_item:
            Toast.makeText(this,"你点击了添加按钮~", Toast.LENGTH_SHORT).show();
            break;
        case R.id.remove_item:
            Toast.makeText(this,"你点击了删除按钮~",Toast.LENGTH_SHORT).show();
            invalidateOptionsMenu();//需要再次执行onCreateOptionsMenu时使用
            break;
    }
    return true;
}

注意:如果在Fragment中加载菜单,重写的方法是

@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
    super.onCreateOptionsMenu(menu, inflater);
    inflater.inflate(R.menu.xxx, menu);
}

并且需要在onCreate内加

setHasOptionsMenu(true);

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值