一、Android中项目中各个文件夹的含义和用途详解
原文地址: http://www.cnblogs.com/shellway/p/4032464.html
1.src:存放所有的*.java源程序。
2.assets:可以存放项目一些较大的资源文件,例如:图片、音乐、字体等。
3.res:可以存放项目中所有的资源文件,例如:图片(.png、.jpg)、文本等。
4.res/drawable-hdpi:保存高分辨率图片资源,可以使用Resources.getDrawable(id)可以获得资源类型。
5.res/drawable-ldpi:保存低分辩率图片资源,可以使用Resources.getDrawable(id)可以获得资源类型。
6.res/drawable-mdpi:保存中等分辨率图片资源,可以使用Resources.getDrawable(id)可以获得资源类型。
7.res/layout:存放所有的布局文件,主要是用于排列不同的显示组件,在Android程序中要读取此配置。
8.res/values:存放一些资源文件的信息,用于读取文本资源,在本文件夹之中有一些约定的文件名称:
10.res/raw:自定义的一些原生文件所在目录,像音乐、视频等文件格式。存放直接**到设备中的任意文件。它们无需编译,添加到你的应用程序编译产生的压缩文件中。要使用这些资源,可以调用 Resources.openRawResource(),参数是资源的ID也可以用,即R.raw.somefilename, Resources.getRawResource()`方法可以获得这些资源。
11.res/xml:用户自定义的XML文件,所有的文件在程序运行时编译到应用程序之中,在程序运行时可以使用Resources.getXML()方法获取。
12.res/anim:用于定义动画对象。存放定义了补间动画(tweened animation)或逐帧动画(frameby frame animation)的XML文件。(该目录下也可以存放定义property animations的XML文件,但是最好还是分开存放)
13.res/animator:存放定义了propertyanimations(android 3.0新定义的动画框架)的XML文件
14.res/color/:存放定义了颜色状态列表资源(ColorState List Resource)的XML文件
15.res/drawable/:存放定义了图片状态列表资源(ColorState List Resource)的XML文件
16.res/menu/:存放定义了应用程序菜单资源的XML文件。正确创建文件的方法:new Folder,名字menu,new Other——Android——XML,选择menu类型,填写名称,确定即可。菜单资源文件必须放在res/menu目录中。菜单资源文件必须使用<menu>标签作为根节点。除了<menu>标签外,还有另外两个标签用于设置菜单项和分组,这两个标签是<item>和<group>。
注意:
对于res/color和res/drawable这两个文件中的内容在这作一下详解:
首先说一下color文件夹,在这个文件夹下放的是color_selector.xml等文件,主要是用于背景色的selector,比如TextView中的textColor属性,点击改变TextView中的字体颜色,在这个文件中的文件color_selector.xml中定义如下:
二、Android 多返回栈技术详解
用户通过系统返回按钮导航回去的一组页面,在开发中被称为返回栈(back stack)。多返回栈即一堆"返回栈",对多返回栈的支持是在 Navigation 2.4.0-alpha01和 Fragment 1.4.0-alpha01中开始的。本文将为您展开多返回栈的技术详解。
无论您在使用 Android全新的手势导航还是传统的导航栏,用户的"返回"操作是 Android用户体验中关键的一环,把握好返回功能的设计可以使应用更加贴近整个生态系统。
在最简单的应用场景中,系统返回按钮仅仅 finish您的 Activity。在过去您可能需要覆写 Activity的 onBackPressed()方法来自定义返回操作,而在 2021年您无需再这样操作。我们已经在 OnBackPressedDispatcher中提供了针对自定义返回导航的 API。实际上这与 FragmentManager和 NavController中已经添加的 API相同。
这意味着当您使用 Fragments或 Navigation时,它们会通过 OnBackPressedDispatcher来确保您调用了它们返回栈的 API,系统的返回按钮会将您推入返回栈的页面逐层返回。
多返回栈不会改变这个基本逻辑。系统的返回按钮仍然是一个单向指令——"返回"。这对多返回栈 API的实现机制有深远影响。
在 surface层级,对于多返回栈的支持貌似很直接,但其实需要额外解释一下"Fragment返回栈"到底是什么。FragmentManager的返回栈其实包含的不是 Fragment,而是由 Fragment事务组成的。更准确地说,是由那些调用了 addToBackStack(String name) API的事务组成的。
这就意味着当您调用 commit()提交了一个调用过 addToBackStack()方法的 Fragment事务时, FragmentManager会执行所有您在事务中所指定的操作(比如替换操作),从而将每个 Fragment转换为预期的状态。然后 FragmentManager会将该事务作为它返回栈的一部分。
当您调用 popBackStack()方法时(无论是直接调用,还是通过系统返回键以 FragmentManager内部机制调用),Fragment返回栈的最上层事务会从栈中弹出--比如新添加的 Fragment会被移除,隐藏的 Fragment会显示。这会使得 FragmentManager恢复到最初提交 Fragment事务之前的状态。
也就是说 popBackStack()变成了销毁操作:任何已添加的 Fragment在事务被弹出的时候都会丢失它的状态。换言之,您会失去视图的状态,任何所保存的实例状态(Saved Instance State),并且任何绑定到该 Fragment的 ViewModel实例都会被清除。这也是该 API和新的 saveBackStack()方法之间的主要区别。 saveBackStack()可以实现弹出事务所实现的返回效果,此外它还可以确保视图状态、已保存的实例状态,以及 ViewModel实例能够在销毁时被保存。这使得 restoreBackStack() API后续可以通过已保存的状态重建这些事务和它们的 Fragment,并且高效"重现"已保存的全部细节。太神奇了!
而实现这个目的必须要解决大量技术上的问题。
虽然 Fragment总是会保存 Fragment的视图状态,但是 Fragment的 onSaveInstanceState()方法只有在 Activity的 onSaveInstanceState()被调用时才会被调用。为了能够保证调用 saveBackStack()时 SavedInstanceState会被保存,我们还需要在 Fragment生命周期切换的正确时机注入对 onSaveInstanceState()的调用。我们不能调用得太早(您的 Fragment不应该在 STARTED状态下保存状态),也不能调用得太晚(您需要在 Fragment被销毁之前保存状态)。
这样的前提条件就开启了需要解决 FragmentManager转换到对应状态的问题,以此来保障有一个地方能够将 Fragment转换为所需状态,并且处理可重入行为和 Fragment内部的状态转换。
在 Fragment的重构工作进行了 6个月,进行了 35次修改时,发现 Postponed Fragment功能已经严重损坏,这一问题使得被推迟的事务处于一个中间状态——既没有被提交也并不是未被提交。之后的 65个修改和 5个月的时间里,我们几乎重写了 FragmentManager管理状态、延迟状态切换和动画的内部代码,具体请参见我们之前的文章《全新的 Fragment:使用新的状态管理器》。
随着技术问题的逐步解决,包括更加可靠和更易理解的 FragmentManager,我们新增加了两个 API: saveBackStack()和 restoreBackStack()。
如果您不使用这些新增 API,则一切照旧:单个 FragmentManager返回栈和之前的功能相同。现有的 addToBackStack()保持不变——您可以将 name赋值为 null或者任意 name。然而,当您使用多返回栈时, name的作用就非常重要了:在您调用 saveBackStack()和之后的 restoreBackStack()方法时,它将作为 Fragment事务的唯一的 key。
举个例子,会更容易理解。比如您已经添加了一个初始的 Fragment到 Activity,然后提交了两个事务,每个事务中包含一个单独的 replace操作:
也就是说我们的 FragmentManager会变成这样:
比如说我们希望将 profile页换出返回栈,然后切换到通知 Fragment。这就需要调用 saveBackStack()并且紧跟一个新的事务:
现在我们添加 ProfileFragment的事务和添加 EditProfileFragment的事务都保存在"profile"关键字下。这些 Fragment已经完全将状态保存,并且 FragmentManager会随同事务状态一起保持它们的状态。很重要的一点:这些 Fragment的实例并不在内存中或者在 FragmentManager中——存在的仅仅只有状态(以及任何以 ViewModel实例形式存在的非配置状态)。
替换回来非常简单:我们可以在"notifications"事务中同样调用 saveBackStack()操作,然后调用 restoreBackStack():
这两个堆栈项高效地交换了位置:
维持一个单独且活跃的返回栈并且将事务在其中交换,这保证了当返回按钮被点击时, FragmentManager和系统的其他部分可以保持一致的响应。实际上,整个逻辑并未改变,同之前一样,仍然弹出 Fragment返回栈的最后一个事务。
这些 API都特意按照最小化设计,尽管它们会产生潜在的影响。这使得开发者可以基于这些接口设计自己的结构,而无需通过任何非常规的方式保存 Fragment的视图状态、已保存的实例状态、非配置的状态。
当然了,如果您不希望在这些 API之上构建您的框架,那么可以使用我们所提供的框架进行开发。
Navigation Component最初是作为通用运行时组件进行开发的,其中不涉及 View、Fragment、Composable或者其他屏幕显示相关类型及您可能会在 Activity中实现的"目的地界面"。然而,NavHost接口的实现中需要考虑这些内容,通过它添加一个或者多个 Navigator实例时,这些实例确实清楚如何与特定类型的目的地进行交互。
这也就意味着与 Fragment的交互逻辑全部封装在了 navigation-fragment开发库和它其中的 FragmentNavigator与 DialogFragmentNavigator中。类似的,与 Composable的交互逻辑被封装在完全独立的 navigation-compose开发库和它的 ComposeNavigator中。这里的抽象设计意味着如果您希望仅仅通过 Composable构建您的应用,那么当您使用 Navigation Compose时无需任何涉及到 Fragment的依赖。
该级别的分离意味着 Navigation中有两个层次来实现多返回栈:
仍需特别注意那些尚未更新的 Navigator,它们无法支持保存自身状态。底层的 Navigator API已经整体重写来支持状态保存(您需要覆写新增的 navigate()和 popBackStack() API的重载方法,而不是覆写之前的版本),即使 Navigator并未更新, NavController仍会保存 NavBackStackEntry的状态(在 Jetpack世界中向后兼容是非常重要的)。
如果您仅仅在应用中使用 Navigation,那么 Navigator这个层面更多的是实现细节,而不是您需要直接与之交互的内容。可以这么说,我们已经完成了将 FragmentNavigator和 ComposeNavigator迁移到新的 Navigator API的工作,使其能够正确地保存和恢复它们的状态,在这个层面上您无需再做任何额外工作。
如果您正在使用 NavigationUI,它是用于连接您的 NavController到 Material视图组件的一系列专用助手,您会发现对于菜单项、 BottomNavigationView(现在叫 NavigationRailView)和 NavigationView,多返回栈是默认启用的。这就意味着结合 navigation-fragment和 navigation-ui使用就可以。
NavigationUI API是基于 Navigation的其他公共 API构建的,确保您可以准确地为自定义组件构建您自己的版本。保证您可以构建所需的自定义组件。启用保存和恢复返回栈的 API也不例外,在 Navigation XML中通过 NavOptions上的新 API,也就是 navOptions Kotlin DSL,以及 popBackStack()的重载方法可以帮助您指定 pop操作保存状态或者指定 navigate操作来恢复之前已保存的状态。
比如,在 Compose中,任何全局的导航模式(无论是底部导航栏、导航边栏、抽屉式导航栏或者任何您能想到的形式)都可以使用我们在与底部导航栏集成所介绍的相同的技术,并且结合 saveState和 restoreState属性一起调用 navigate():
对用户来说,最令人沮丧的事情之一便是丢失之前的状态。这也是为什么 Fragment用一整页来讲解保存与 Fragment相关的状态,而且也是我非常乐于更新每个层级来支持多返回栈的原因之一:
如果您希望了解更多使用该 API的示例,请参考 NavigationAdvancedSample(它是最新更新的,且不包含任何用于支持多返回栈的 NavigationExtensions代码)。
对于 Navigation Compose的示例,请参考 Tivi。
如果您遇到任何问题,请使用官方的问题追踪页面提交关于 Fragment或者 Navigation的 bug,我们会尽快处理。
三、【Android 动画】动画详解之补间动画(一)
之前很早就想写写Android的动画,最近刚好有时间,大概聊一聊安卓动画。
个人习惯将动画分为:补间动画(透明度、旋转、位移、缩放)、帧动画、和属性动画,这一篇,我们先说说补间动画。
补间动画这个词出于flash,在两个关键帧(可以理解成动画开始和结束)中间需要做“补间动画”,才能实现图画的运动;插入补间动画后两个关键帧之间的插补帧是由计算机自动运算而得到的。
实际上,Android的补间动画也是由我们指定动画开始、动画结束2个关键点,中间部分的动画由系统完成
在正式开始之前,我们先说下Android系统的坐标系,屏幕左上角为坐标原点,假如屏幕为1080*1980,那么左上角为(0,0),右上角为(1080,0),左下角为(0,1980),右下角为(1080,1980)
所有动画有以下公共属性,注释比较详细,这里就不在详述了
ScaleAnimation有3种构造方法
我们先看第一种,其起始比例为0,缩放比例为1.4,即放大到1.4倍
效果如下:
第二种,pivotx,pivotY分别代表起始位置的x、y方向的坐标,我们设置为(100,100)
效果如下:
第三种,pivotXType和pivotYType有2种模式,RELATIVE_TO_SELF(相对于自身)和RELATIVE_TO_PARENT(相对于父布局),如果设置这个,pivotx,pivotY的值就应该是0-1的浮点数,这里分别对应xml中的%(自身)和%p(父布局)
TranslateAnimation有2种构造方法,和ScaleAnimation类似
效果如下:
效果如下:
RELATIVE_TO_PARENT
效果如下:
RotateAnimation有3种构造方法
顺时针720度
效果如下:
逆时针720度
效果如下:
效果如下:
再来RELATIVE_TO_PARENT
效果如下:
这是什么鬼???怎么跑到屏幕外面去了?
原来设置为RELATIVE_TO_PARENT时,旋转中心x方向应该为该空间离左边的边距+父布局宽度/2,y方向同理,而此时,我们布局中红色的Textview为居中状态,所以旋转中心为屏幕右下角。让我们来看个例子
修改布局如下:
效果如下:
这时,我们看到旋转中心x方向为离左边100dp处
AlphaAnimation只有1种构造方法
其中fromAlpha为动画开始的透明度;toAlpha为动画结束的透明度
效果如下:
效果如下:
AnimationSet是一个动画的**,可以按照添加的顺序播放动画,让我们来看个例子,通过组合动画,实现旋转渐入动画
效果如下:
到这里,补间动画就介绍完了
参考资料:自定义控件三部曲之动画篇
好了,文章到这里就结束啦,如果本次分享的Android 动画详解和【Android 动画】动画详解之补间动画(一)问题对您有所帮助,还望关注下本站哦!