Android——布局

上一篇简单说明了Android架构。

现在开始Android开发:Android应用界面元素有Activity、Fragment、Dialog等,这些元素都有各自对应的xml文件,即布局文件。界面显示元素的排布方式由布局文件决定,那么Android应用开发首先需要从布局开始,当然首先你得会Android开发语言:Java或Kotlin,推荐用Kotlin。

一、布局方式

布局方式布局用法
ConstraintLayout约束布局
LinearLayout线性布局
RelativeLayout相对布局
FrameLayout帧布局

目前推荐的是约束布局ConstraintLayout,可以说是它是其余几个的集合体也不为过,所以就不写其他布局的属性,其实也不多,可以参照ConstraintLayout的属性。

约束布局跟相对布局的相似点就是需要有参照物,关于ConstraintLayout是有单独的库的,那么它的属性用法就相当于自定义属性,需要添加xmlns:app="http://schemas.android.com/apk/res-auto":

属性名简介
layout_constraintTop_toTopOf视图与参照物顶部对齐,值id
layout_constraintBottom_toBottomOf视图与参照物底部对齐,值id
layout_constraintStart_toStartOf视图与参照物左边对齐,值id
layout_constraintEnd_toEndOf视图与参照物右边对齐,值id
layout_constraintTop_toBottomOf视图顶部与参照物底部对齐,值id
layout_constraintBottom_toTopOf视图底部与参照物顶部对齐,值id
layout_constraintStart_toEndOf视图左边与参照物右边对齐,值id
layout_constraintEnd_toStartOf视图右边与参照物左边对齐,值id
layout_constraintCircle视图在参照物圆形定位上,值id
layout_constraintCircleAngle视图在参照物圆形定位某角度上,值0-359
layout_constraintCircleRadius视图在参照物圆形定位某半径上,值xxpx/dp
layout_constraintHorizontal_bias水平偏移,需要确定左右对齐,值0~1
layout_constraintVertical_bias垂直偏移,需要确定上下对齐,值0~1
layout_constrainedHeight强制约束高度,值true/false
layout_constrainedWidth强制约束宽度,值true/false
layout_constraintWidth_percent水平占比,前置条件:width=0dp
layout_constraintHeight_percent垂直占比,前置条件:height=0dp
layout_constraintDimensionRatio宽高比约束,如宽高比2:1
layout_constraintHorizontal_chainStyle水平链式关联,链式视图需要跟其中之一对齐,可设置weight
layout_constraintVertical_chainStyle垂直链式关联,链式视图需要跟其中之一对齐,可设置weight
layout_constraintHorizontal_weight水平占比权重,前置:width=0dp
layout_constraintVertical_weight垂直占比权重,前置:height=0dp
layout_goneMarginTop当参考视图为gone时生效,等同于marginTop,其余类似

二、Activity、Dialog

每一个界面都对应有布局文件,没有布局文件的界面就是一个空白界面,并没有意义。

将布局文件加载到界面调用setContentView,Fragment也对应着自己的布局文件,但Fragment的定义是Activity的碎片,意思是fragment是加载到Activity的layout中的,加载的方式是LayoutInflater.inflate()。

三、SwipeRefreshLayout


1、用法
```
<android.support.v4.widget.SwipeRefreshLayout
    android:id="@+id/refreshClient"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@+id/spinner1">
    <!-- 这里是一个子view,仅能有一个子view,一般为AbsListView -->
</android.support.v4.widget.SwipeRefreshLayout>

让Activity继承SwipeRefreshLayout.OnRefreshListener
然后refreshLayout.setOnRefreshListener(this);
即可监听刷新动作,只要在onRefresh()里执行刷新代码即可
```
博主在使用时发现SwipeRefreshLayout会占满剩余屏幕,且它的子view也是一样,可以看SwipeRefreshLayout源码的onMeasure和onLayout方法。如果想要使它的子view是适应内容高度的话,博主测试了下,跟ScrollView的做法是一样的,但是这样子的话AbsListView就不能滑动了,从而知道SwipeRefreshLayout跟ScrollView还是不同的,之后就试了下在AbsListView外面套一层ScrollView,这时候就能让AbsListView自适应内容高度且能上下滑动了。

```
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (mTarget == null) {
            ensureTarget();
        }
        if (mTarget == null) {
            return;
        }
        mTarget.measure(MeasureSpec.makeMeasureSpec(
                getMeasuredWidth() - getPaddingLeft() - getPaddingRight(),
                MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(
                getMeasuredHeight() - getPaddingTop() - getPaddingBottom(), MeasureSpec.EXACTLY));
        mCircleView.measure(MeasureSpec.makeMeasureSpec(mCircleDiameter, MeasureSpec.EXACTLY),
                MeasureSpec.makeMeasureSpec(mCircleDiameter, MeasureSpec.EXACTLY));
        mCircleViewIndex = -1;
        // Get the index of the circleview.
        for (int index = 0; index < getChildCount(); index++) {
            if (getChildAt(index) == mCircleView) {
                mCircleViewIndex = index;
                break;
            }
        }
    }
    其中mCircleView就是那个刷新时出现的转圈圈的ImageView,而mTarget就是我们在布局文件里定义的SwipeRefreshLayout子View。可以看到mTarget和SwipeRefreshLayout的宽高是一致的,当然啦,不包括SwipeRefreshLayout的padding。
```

```
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        final int width = getMeasuredWidth();
        final int height = getMeasuredHeight();
        if (getChildCount() == 0) {
            return;
        }
        if (mTarget == null) {
            ensureTarget();
        }
        if (mTarget == null) {
            return;
        }
        final View child = mTarget;
        final int childLeft = getPaddingLeft();
        final int childTop = getPaddingTop();
        final int childWidth = width - getPaddingLeft() - getPaddingRight();
        final int childHeight = height - getPaddingTop() - getPaddingBottom();
        child.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
        int circleWidth = mCircleView.getMeasuredWidth();
        int circleHeight = mCircleView.getMeasuredHeight();
        mCircleView.layout((width / 2 - circleWidth / 2), mCurrentTargetOffsetTop,
                (width / 2 + circleWidth / 2), mCurrentTargetOffsetTop + circleHeight);
    }
    一开始博主有试过在这里让mTarget自适应内容高度,也成功了,结果就是不能滑动,跟上面的一个方法效果一样,所以最后只能选择再套一层ScrollView了。
```
这里只是android本身自带的刷新控件的使用,网上很多人把这个layout修改成下拉刷新,上拉加载的控件了,博主还没看过源码,水平较低,暂不知怎么实现。如果要实现,怎么的也要将SwipeRefreshLayout负责出来修改,同时也要把MaterialProgressDrawable和CircleImageView复制出来。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值