Android界面编程

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
hdpi 72* 72

xhdpi
xhdpi 96* 96

xxhdpi
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

学习他人的代码,取精华

第三方开源库

自己学习的代码仓库

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值