1.界面布局
2.动画
3.View焦点及事件响应机制
4.尺寸单位了解
5.资源分享
1.界面布局
线性布局 : 用来控制其子View以水平或垂直方式展开显示
重要属性:
orientation(方向)
layout_weight(权重)
特点:
使用方向属性可以方便处理上下/左右结果的UI;使用权重可以ui均匀显示,同时在不同分辨率有较好适配能力
相对布局:用来控制其子View以相对定位的方式进行布局显示
相关属性多:
兄弟视图之间: 同方向对齐, 反方向对齐
与父视图之间: 同方向对齐, 居中
特点:
可以处理较为复杂的界面显示,并且更具有扁平化优点,减少界面渲染
兄弟视图
同方向对齐
android:layout_alignEnd (alignRight)
android:layout_alignStart(alignLeft)
android:layout_alignTop
android:layout_alignBottom
反方向对齐
android:layout_toEndOf(toRightOf)
android:layout_toStartOf(toLeftOf)
android:layout_below
android:layout_above
相对父视图
与父视图同方向对齐
android:layout_alignParentTop
android:layout_alignParentBottom
android:layout_alignParentStart(alignParentLeft)
android:layout_alignParentEnd(alignParentRight)
相对父视图居中属性
android:layout_centerInParent
android:layout_centerHorizontal
android:layout_centerVertical
帧布局:默认以屏幕左上角作为坐标,按定义的先后顺序依次逐屏显示 ,后面出现的会覆盖前面的画面
属性:
android:layout_gravity:通过子View通过该属性来指定的位置
特点:
界面层叠覆盖,但不能较好定位控件的位置,目前一般在fragment切换使用
模糊的属性:
android:padding 与 android:layout_margin
android:padding 内边距属性,表示里面的内容相对本身的距离
android:layout_margin 外边距属性,表示当前View相对父控件的距离
android:background 与 android:src
对于ImageView:
android:background 设置的是背景图片
android:src 设置的是前景图片
android:visibility=“invisible” 与 android:visibility= “gone”
visible : 标识可见
invisible: 标识不可见, 但占屏幕空间
gone : 标识不可见, 不占屏幕空间
android:layout_gravity 与 android:gravity
android:layout_gravity :控件本身相对于父视图的位置
android:grivity:控件中的内容的基本位置
注意:宽高不能为“wrap_content”
layout_alignRight 与 layout_alignEnd
即:在不同的区域(如阿拉伯),文本呈现的方向不一定是从左->右,将会导致布局出现问题。建议使用 layout_alignEnd
解决地域问题:
android:supportsRtl = “false” //默认值是true
声明你的application是否愿意支持从右到左(RTL就是right-to-left 的缩写)的布局
listView
ListView是一种用来显示多个可滑动项(Item)列表ViewGroup
需要使用Adapter将集合数据和每一个Item所对应的布局动态适配到ListView中显示
显示列表: listView.setAdapter(adapter)
更新列表: adapter.notifyDataSetChanged()
Adapter
1.ArrayAdapter: 显示最简单的列表(文本)
集合数据为List或String[]
2.SimpleAdapter: 显示复杂的列表
集合数据必须是List<Map<String,Object>>
3.BaseAdapter: 显示复杂的列表
集合数据可以是任意类型的集合List
4.SimpleCursorAdapter: 显示复杂的列表
集合数据是数据库查询结果集
通用的Adapter:CommonAdapter.java
RecyclerView
目前盒子项目,使用会出现较多问题,比如焦点,滚动导致错乱;在手机上,建议使用,缓存性能更好
2.动画
动画主要分为3类:
Drawable Animation
图片动画,也是逐帧动画,是通过一个接一个的加载Drawable资源来创建动画,按顺序的播放,像一个胶卷。对于视图动画,他只是单独的图片内容在变换,而不是整个视图。很显然,如果图片过多多大就会导致OOM异常。
项目中,几乎不用,如果需要用该种动画,可以使用 .gif 代替
View Animation
视图动画,通多对整个视图不断做图像的变换(平移、缩放、旋转、透明度)产生的动画效果,是一种渐进式动画,实现动画的对象只能是view。
Property Animation
属性动画,在Android 3.0的(API级别11)引入的,该属性动画系统可以制作动画的任何对象的属性。
View Animation 介绍
支持4种动画效果,分别是:
- 透明度动画(AlphaAnimation)
- 缩放动画(ScaleAnimation)
- 平移动画(TranslateAnimation)
- 旋转动画(RotateAnimation)
在xml中,属性值:
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@[package:]anim/interpolator_resource"
android:shareInterpolator=["true" | "false"] >
<alpha
android:fromAlpha="float"
android:toAlpha="float" />
<scale
android:fromXScale="float"
android:toXScale="float"
android:fromYScale="float"
android:toYScale="float"
android:pivotX="float"
android:pivotY="float" />
<translate
android:fromXDelta="float"
android:toXDelta="float"
android:fromYDelta="float"
android:toYDelta="float" />
<rotate
android:fromDegrees="float"
android:toDegrees="float"
android:pivotX="float"
android:pivotY="float" />
<set>
...
</set>
</set>
以上属性,几乎见名知意,需要注意pivotX的理解。
如何使用
1.在xml文件,通过标签(如)实现动画
2.在代码中,通过AnimationUtils加载xml中的动画 animation
3.开始动画 startAnimation(animation)
shine -> ChannelListFragment
Animation animation = AnimationUtils.loadAnimation(getContext(), R.anim.find_layout_in);
mAZbg.startAnimation(animation);
Activity切换:
Scrawl > MainAcitity -> SettingActivity (视频all)
startActivity(new Intent(this, MainActivity.class));
overridePendingTransition(R.anim.left_in, R.anim.right_out);
finish();
注意:需要先执行startActivity()方法
Fragment切换
Fragment是在api11才引入,如果导入的Fragment的是v4包,那么只能支持ViewAnimation,如果是android.app下的,那么也支持Property Animation。
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction .setCustomAnimations(R.animator.cube_left_in, R.animator.cube_right_out); //使用属性动画
transaction.hide(mFrontFragment).add(R.id.fragment_layout, nextFragment, fragmentTag);
transaction.commit();
ViewGroup的使用,如:ListView
1.在xml文件,创建动画
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="500"
android:fromXDelta="-100%p"
android:toXDelta="0" />
</set>
2.在xml文件中,使用 标签,指定动画效果
<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:delay="0.2"
android:animationOrder="normal"
android:animation="@anim/left_in">
</layoutAnimation>
3.使用该动画:
a.在xml中使用:
<ListView
android:id="@+id/listView_setting_title"
android:layout_width="378dp"
android:paddingTop="89.2dp"
android:layout_height="match_parent"
android:divider="@color/transparent"
android:dividerHeight="4dp"
android:layoutAnimation="@anim/menu_setting_title_list"
android:listSelector="@color/transparent">
</ListView>
b.在代码中使用:
//获取Animation对象
Animation animation = AnimationUtils.loadAnimation(this, R.anim.menu_installation_list);
//得到LayoutAnimationController对象
LayoutAnimationController controller = new LayoutAnimationController(animation);
//设置动画播放顺序
controller.setOrder(LayoutAnimationController.ORDER_NORMAL);
//设置延迟时间
controller.setDelay(0.2f);
//listView设置LayoutAnimation,实现动画
mMenuTitlesList.setLayoutAnimation(controller);
Dialog使用
(视屏dialog)
1.创建xml文件, 设置动画
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="true"
android:interpolator="@android:anim/decelerate_interpolator">
<translate
android:fromXDelta="-100%p"
android:toXDelta="0"
android:fromYDelta="0"
android:toYDelta="0"
android:duration="600"/>
<scale android:fromXScale="0"
android:fromYScale="0"
android:toXScale="1"
android:toYScale="1"
android:duration="600"
android:pivotX="50%"
android:pivotY="50%"/>
</set>
在styles.xml ,添加样式属性
<style name="AnimationsratateInOut">
<item name="android:windowEnterAnimation">@anim/rotate_tran_in_animation</item>
<item name="android:windowExitAnimation">@anim/rotate_tran_out_animation</item>
</style>
3.在代码中设置动画
getWindow().setWindowAnimations(R.style.AnimationsratateInOut);
注:官方:不建议使用dialog实现弹框,使用FragmentDialog,有生命周期。
属性动画
Animator的子类:
ValueAnimator
主要提供了属性动画的时间引擎,并且以动画的方式计算各种属性值。
ObjectAnimator
它是ValueAnimator的直接子类,允许指定目标对象和相关属性值执行动画。设置目标的属性值有一定的限制,目标对象需要拥有特定的方法属性。(必须有setter方法,getter根据参数而定)
AnimatorSet
用于组合多个动画,类似视图动画的AnimationSet
ObjectAnimator的使用
ofFloat(Object target, String propertyName, int… values)
参数:target:目标对象 ; propertyName 属性名 ; values 属性范围值,可变参数
ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(view, "rotationY", 0, 360);
ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(view, "scaleX", 0, 1f);
ObjectAnimator objectAnimator3 = ObjectAnimator.ofFloat(view, "scaleY", 0, 1f);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(1000);
animatorSet.playTogether(objectAnimator1, objectAnimator2, objectAnimator3);
animatorSet.start();
(视频All)
常用的propertyName的值:
translationX和translationY:控制View由它的布局容器设置其左侧和顶部坐标的增量。
rotation,rotationX和rotationY:控制View在容器2D(旋转rotation绕枢轴点属性)和3D旋转,可以支持3D效果。
scaleX和scaleY:这些属性控制围绕其轴心点视图的2D缩放。
alpha:代表在查看Alpha透明度。此值是1(不透明)通过默认,以0表示全透明度的值(不可见)
除了以上常用的,还可以是:
textColors,textSize ,backgroundColor...
属性动画的监听:
objectAnimator.addListener(new AnimatorListenerAdapter() {
//可以自行覆盖未实现方法
});
onAnimationStart() - 动画启动时调用。
onAnimationEnd() - 当动画结束时调用。
onAnimationRepeat() - 当动画重演调用。
onAnimationCancel() -当动画被取消调用。取消的动画还呼吁onAnimationEnd(),不管他们是如何结束。
属性还可以在xml定义(可自行了解)。但是,一般属性动画,设置比较简单,代码简洁,所以平时用的时候,还是在代码中直接设置比较多。
插值器 和 估值器
插值器:决定值的变化速率;
估值器:决定返回值的具体变化;
插值器:
animator.setInterpolator(new LinearInterpolator());
参考:
https://blog.csdn.net/pzm1993/article/details/77926373
ViewAnimation 与 Property Animation的区别
ViewAnimation
对象只能是View,且只能实现平面动画;
只修改View的绘制位置,而不是实际View的本身;
PropertyAnimation
没有以上缺点,并且ViewAnimation的动画效果,多能实现;
可以对任何对象(视图和非视图)的任何属性进行动画处理,并且对象本身实际上进行了修改;
总结:属性动画系统在执行动画的过程中也更为强大,在大部分场合完全可以替换ViewAnimation。但ViewAnimation并非一无是处,比如ListView动画,activity切换等需要用。
3.焦点和事件处理
在xml处理焦点问题:
android:focusable:设置一个控件能否获得焦点
android:nextFocusDown:定义下一个获得焦点的控件当按下键时
android:nextFocusUp:定义下一个获得焦点的控件当按上键时
android:nextFocusLeft:定义下一个获得焦点的控件当按左键时
android:nextFocusRight:定义下一个获得焦点的控件当按右键时
在代码上处理焦点问题:
hasFocus() 自身或者其子类是否有焦点
isFocused() 自身是否有焦点
这2个区别主要在ViewGroup上,前者只要自己或者子视图是焦点视图都返回true,而后者是一定要自己是焦点视图
requestFocus() 请求获取焦点
setFocusable() 设置是否可以获取焦点
clearFocus() 清除焦点
setOnFocusChangeListener() 焦点变化监听
项目的例子:
1.view
PopupTimer.java
2.ViewGroup
listView 获取焦点的问题
Shine -> InstallationActivity (视频 listview_foucs)
case Constants.KEY_UP:
if (mCurIndex == 0)
{
mListContent.setSelection(mAdapter.getCount() - 1);
mAdapter.notifyDataSetChanged();
return true;
}
else
{
return mListContent.onKeyDown(keyCode, event);
}
case Constants.KEY_DOWN:
if (mCurIndex == mAdapter.getCount() - 1)
{
mListContent.setSelection(0);
mAdapter.notifyDataSetChanged();
return true;
}
else
{
return mListContent.onKeyDown(keyCode, event);
}
gridView 获取焦点
Shine -> SettingsActivity (视频 gridView_foucs)
case Constants.KEY_LEFT:
if (mSelection == 0)
{
mSelection = ITEM_MAX_SIZE - 1;
}
else
{
mSelection--;
}
mView.setSelection(mSelection);
return true;
case Constants.KEY_RIGHT:
if (mSelection == ITEM_MAX_SIZE - 1)
{
mSelection = 0;
}
else
{
mSelection++;
}
mView.setSelection(mSelection);
return true;
1.一些顽固的焦点问题
界面比较复杂时,如Listview + Xxx
解决方案:略!
事件处理
触摸响应流程:
Cancel事件:比如在点击录音时,系统弹出系统权限
更详细的响应可以使用 GestureDetector
事件分发流程:
/**
* 当前视图是ViewGroup
*/
public boolean dispatchTouchEvent(MotionEvent ev) {
boolean consume = false;
if(onInterceptTouchEvent()) {
consume = onTouchEvent()
}else {
child.dispatchTouchEvent();
}
return consume;
}
dispatchTouchEvent方法用于事件的分发。返回true表示不继续分发,事件直接被消费。
onInterceptTouchEvent 代表事件拦截,如果返回false,说明不拦截,向下传递;如果返回true,代表拦截,不分发;
在 Activity 和 View 中是没有onInterceptTouchEvent()方法
onTouchEvent 用于事件的处理,返回true表示消费处理当前事件;
实践demo:
触摸事件与点击事件
顺序是这样的: dispatchTouchEvent - onInterceptTouchEvent - onTouch(监听) - onTouchEvent - onClick(监听)
按键响应流程
down–>down–>down–>…->up
关于按键流程,可以自行测试
事件小结:
1.目前开发中,事件存在冲突时,需要考虑,其他很少处理分发过程,只要处理touch事件响应;
2.一般在子view的onTouchEvent()处理,并且直接消费(即返回 true)
3.目前代码中,在Activity中处理按键多是使用dispatchKeyEvent()方法处理,可以第一时间处理与分发;
尺寸
尺寸: 屏幕对角线的长度,单位为英寸(2.54cm)
分辨率: 屏幕能显示的像素的数量, 一般用在长方向数量*宽方向数量来表达
像素密度: pixels per inch,也称PPi,即每英寸屏幕能显示的像素数,像素密度越大,显示画面细节就越丰富。
密度: Density, 以160ppi为基准, 即像素密度为160时Density为1
px: pixels(像素) 1px长度就对应屏幕一个像素点的大小
dp/dip: device-independent pixels(设备无关像素)
sp:scaled pixels(可缩放像素)与dp类似
注意: Android在运行时会自动将dp/dip/sp为单位的尺寸转换为像素单位的值
dp与px的比较?
以px为单位的长度, 在不同分辨率手机上会变化
以dp为单位则不会变化
dp与sp的比较?
当用户在系统中设置文本的大小:
如果字体大小使用sp为单位, 设置有效果
如果字体大小使用dp为单位, 设置没有效果
在布局文件视图的宽高尽量用match_parent/wrap_content
如果必须指定特定值, 使用dp为单位
文本大小使用sp做单位
hdpi 72* 72
xhdpi 96* 96
xxhdpi 144* 144
1.分辨率越大,像素密度越大
2.在越大分辨率(高密度)的手机,要想显示的图片区域一致,那么就需要越大像素的图片
3.在自定义View时,避免出现单独的数字,需要进行尺寸转换;
domai -> DensityUtil.java
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*/
public static int dip2px(Context context,float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* 根据手机的分辨率从 px(像素) 的单位 转成为 dp
*/
public static int px2dip(Context context,float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
资源分享
谷歌:
谷歌中文地址:https://developer.android.google.cn/
谷歌官方demoAPI:路径:…\sdk\samples\android-19\legacy\ApiDemos
(android基础、android studio使用、Material Design、Kotlin)
视频资源:
尚硅谷视频教学:http://www.atguigu.com/
(android基础、框架学习、项目实践)
书籍:
《疯狂android讲义》
《Android开发艺术探索》
博客资源:
胡凯:http://hukai.me/android-training-course-in-chinese/index.html
郭霖: https://blog.csdn.net/guolin_blog?viewmode=contents
鸿洋:https://blog.csdn.net/lmj623565791?viewmode=contents
任玉刚:https://blog.csdn.net/singwhatiwanna?viewmode=contents
扔物线:https://juejin.im/user/552f20a7e4b060d72a89d87f/posts
公众号:
郭霖:guolin_blog
鸿洋:hongyangAndroid
github
学习他人的代码,取精华
第三方开源库
自己学习的代码仓库