Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Евгений Васильев @vasil.ev.genij #19

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public void setContentView(View view, ViewGroup.LayoutParams params) {

private void setupToolbar() {
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// setSupportActionBar(toolbar);
}

@Nullable
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package ru.yandex.yamblz.ui.views;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

import static android.view.View.MeasureSpec.EXACTLY;
import static android.view.View.MeasureSpec.UNSPECIFIED;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;

public class LightweightHorizontalLayout extends ViewGroup {
private static final String TAG = LightweightHorizontalLayout.class.getSimpleName();
private static final String ERROR_MSG = " supports at most one child with layout_width set to 'match_parent'!";

private static final int NONE = -1;

private int[] childrenWidth;
private int[] childrenHeight;
private int childMaxHeight;

public LightweightHorizontalLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}


@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Круто, что паддинги обработал, но код работает правильно, только если width wrap_content, с match_parent или фиксированной шириной растягивающаяся вью не отображается

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Прошу пояснить, что именно и в каких случая не работает; в демо-лейауте и, соответственно, на скринах выше есть вьюхи со всеми перечисленными значениями width, и всё ок.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Я имел ввиду LightweightHorizontalLayout, если у нее выставить match_parent или фиксированную ширину, то вьюха с match_parent не отображается

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Да, была логическая ошибка.
Пофиксил.

int widthMeasured = 0;
int specialChildIndex = NONE;
int limitlessSpec = MeasureSpec.makeMeasureSpec(0, UNSPECIFIED);

childrenWidth = new int[getChildCount()];
childrenHeight = new int[childrenWidth.length];

for (int i = 0; i < childrenWidth.length; i++) {
View child = getChildAt(i);

if (child.getVisibility() == GONE) continue;

child.measure(limitlessSpec, limitlessSpec);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

К слову, measureChild учитывает паддинги автоматически


childrenWidth[i] = computeChildSize(child, true);
if (childrenWidth[i] == MATCH_PARENT) {
if (specialChildIndex != NONE) throw new IllegalArgumentException(TAG + ERROR_MSG);
specialChildIndex = i;
} else {
widthMeasured += childrenWidth[i];
}

childrenHeight[i] = computeChildSize(child, false);
childMaxHeight = Math.max(childrenHeight[i], childMaxHeight);
}

int horizontalPadding = getPaddingLeft() + getPaddingRight();
int contentMaxWidth = MeasureSpec.getSize(widthMeasureSpec) - horizontalPadding;

widthMeasured = Math.min(widthMeasured, contentMaxWidth);

if (specialChildIndex != NONE) {
childrenWidth[specialChildIndex] = contentMaxWidth - widthMeasured;
widthMeasured = contentMaxWidth;
}

int verticalPadding = getPaddingTop() + getPaddingBottom();
int contentMaxHeight = MeasureSpec.getSize(heightMeasureSpec) - verticalPadding;

int heightMeasured;
if (MeasureSpec.getMode(heightMeasureSpec) == EXACTLY) {
heightMeasured = childMaxHeight = contentMaxHeight;
} else {
heightMeasured = Math.min(childMaxHeight, contentMaxHeight);
}

setMeasuredDimension(widthMeasured + horizontalPadding, heightMeasured + verticalPadding);
}


private int computeChildSize(View child, boolean isWidth) {
LayoutParams params = child.getLayoutParams();
int size = isWidth ? params.width : params.height;

switch (size) {
case MATCH_PARENT:
return MATCH_PARENT;

case WRAP_CONTENT:
return isWidth ? child.getMeasuredWidth() : child.getMeasuredHeight();

default:
return size;
}
}


@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int drawn = getPaddingLeft();
int topPadding = getPaddingTop();

for (int i = 0; i < this.getChildCount(); i++) {
int width = childrenWidth[i];

int height = childrenHeight[i];
if (height == MATCH_PARENT) {
height = childMaxHeight;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

а почему getMeasuredHeight не стал использовать?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

В onMeasure() я определяю размеры детей с помощью MeasureSpec.makeMeasureSpec(0, UNSPECIFIED). Это позволяет определить их "пожелания" и оставить право выбора за собой, сохраняя фактические значения в массивах для последующей отрисовки. При таком раскладе getMeasuredHeight() в onLayout() у всех детей будет возвращать значение равное высоте родительского лейаута. Чтобы этого избежать и использовать getMeasuredHeight(), на этапе measure следовало еще раз вызвать child.measure(wSpec, hSpec) с модом EXACTLY, но по заданию второго такого вызова быть не должно.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Мне кажется UNSPECIFIED использовать не совсем верно, так как нас то особо не интересуют пожелания потомков, у нас же есть ограничения, которые идут от родителя, UNSPECIFIED может быть только тогда, когда LightweightHorizontalLayout лежит в HorizontalScrollView, например.

}

getChildAt(i).layout(drawn, topPadding, drawn + width, height + topPadding);

drawn += width;
}
}
}
2 changes: 1 addition & 1 deletion app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
android:layout_height="match_parent"
android:orientation="vertical">

<include layout="@layout/toolbar" />
<!--<include layout="@layout/toolbar" />-->

<FrameLayout
android:id="@+id/main_frame_layout"
Expand Down
171 changes: 160 additions & 11 deletions app/src/main/res/layout/fragment_content.xml
Original file line number Diff line number Diff line change
@@ -1,14 +1,163 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<TextView
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/content"
android:textSize="42sp"
android:gravity="center"
/>
android:layout_height="0dp"
android:layout_weight="1"
android:background="#eee">

</FrameLayout>
<ru.yandex.yamblz.ui.views.LightweightHorizontalLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:background="#f97"
android:padding="10dp">

<View
android:layout_width="20dp"
android:layout_height="100dp"
android:background="#0f0"/>

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#f00"
android:padding="10dp"
android:text="@string/content"/>

<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ff0"
android:padding="10dp"
android:text="@string/app_name"
android:textSize="32sp"/>

</ru.yandex.yamblz.ui.views.LightweightHorizontalLayout>

</FrameLayout>

<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#19f">

<ru.yandex.yamblz.ui.views.LightweightHorizontalLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#d7f">

<TextView
android:layout_width="150dp"
android:layout_height="match_parent"
android:background="#f00"
android:padding="10dp"
android:text="@string/app_name"
android:textSize="32sp"/>

<TextView
android:layout_width="55dp"
android:layout_height="100dp"
android:background="#0f0"
android:paddingTop="10dp"
android:text="@string/content"
android:textSize="32sp"/>

<View
android:layout_width="55dp"
android:layout_height="100dp"
android:background="#f00"/>

</ru.yandex.yamblz.ui.views.LightweightHorizontalLayout>

</FrameLayout>

<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#eee">

<ru.yandex.yamblz.ui.views.LightweightHorizontalLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#fff">

<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ff0"
android:padding="10dp"
android:text="@string/content"
android:textSize="32sp"/>

<View
android:layout_width="20dp"
android:layout_height="100dp"
android:background="#0f0"/>

<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="#000"/>

<View
android:layout_width="20dp"
android:layout_height="100dp"
android:background="#0f0"/>

<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="#000"/>

<View
android:layout_width="20dp"
android:layout_height="100dp"
android:background="#0f0"/>

<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="#000"/>

<View
android:layout_width="20dp"
android:layout_height="100dp"
android:background="#0f0"/>

<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="#000"/>

<View
android:layout_width="20dp"
android:layout_height="100dp"
android:background="#0f0"/>

<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="#000"/>

<View
android:layout_width="20dp"
android:layout_height="100dp"
android:background="#0f0"/>

<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="#000"/>

</ru.yandex.yamblz.ui.views.LightweightHorizontalLayout>

</FrameLayout>

</LinearLayout>
2 changes: 1 addition & 1 deletion dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ ext.versions = [
compileSdk : 23,
buildTools : '23.0.3',

androidGradlePlugin : '2.2.0-alpha4',
androidGradlePlugin : '2.1.2',
aptGradlePlugin : '1.8',
retrolambdaGradlePlugin : '3.2.5',
lombokGradlePlugin : '0.2.3.a2',
Expand Down