您的位置:首页 > 移动开发 > Android开发

android SwipeRefreshLayout使用遇到问题分(一)--布局

2016-05-27 19:11 555 查看
1) SwipeRefreshLayout布局中添多个控件时只能显示一个:

问题代码:

<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.zyhust.swiperefreshlayouttest.MainActivity">

<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Hello World!" />
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="This is two" />
</android.support.v4.widget.SwipeRefreshLayout>
这里我以为将两个TextView会显示出来结果只将HelloWorld这个组件显示出来了

原因:

这里主要的原因是SwipeRefreshLayout生成机制引起的。查看SwipeRefreshLayout的onLayout和onMeasure两个布局相关的函数很容易就发现出现这个问题的原因。

onMeasure函数:

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(mCircleWidth, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(mCircleHeight, MeasureSpec.EXACTLY));
if (!mUsingCustomStart && !mOriginalOffsetCalculated) {
mOriginalOffsetCalculated = true;
mCurrentTargetOffsetTop = mOriginalOffsetTop = -mCircleView.getMeasuredHeight();
}
mCircleViewIndex = -1;
// Get the index of the circleview.
for (int index = 0; index < getChildCount(); index++) {
if (getChildAt(index) == mCircleView) {
mCircleViewIndex = index;
break;
}
}
}


onLayout函数:

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);
}


由上面可以看出SwipeRefreshLayout布局中的测量和布局只对mTarget和mCircleView进行操作。mCircleView容易理解就是刷新是显示的ProgressBar了。那么主要就是mTarget了。mTarget的获取是通过ensureTarget得到的,通过查看这个函数可以明白mTarget是什么:

ensureTarget函数:

private void ensureTarget() {
// Don't bother getting the parent height if the parent hasn't been laid
// out yet.
if (mTarget == null) {
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
if (!child.equals(mCircleView)) {
mTarget = child;
break;
}
}
}
}


通过这个函数可以知道mTarget就是在SwipeRefreshLayout中不为mCircleView的第一个视图控件,这也就解释了为啥只有HelloWorld这个TextView显示出来了的原因了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: