Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
门心叼龙
flexbox-layout
提交
163d5714
F
flexbox-layout
项目概览
门心叼龙
/
flexbox-layout
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
F
flexbox-layout
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
163d5714
编写于
5月 31, 2016
作者:
T
Takeshi Hagikura
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #51 from google/evant-pull34-min
Implement the attributes for minWidth and minHeight
上级
f76af916
196afa85
变更
13
隐藏空白更改
内联
并排
Showing
13 changed file
with
519 addition
and
50 deletion
+519
-50
app/src/main/java/com/google/android/apps/flexbox/FlexItem.java
...c/main/java/com/google/android/apps/flexbox/FlexItem.java
+14
-0
app/src/main/java/com/google/android/apps/flexbox/FlexItemEditFragment.java
...com/google/android/apps/flexbox/FlexItemEditFragment.java
+26
-1
app/src/main/java/com/google/android/apps/flexbox/validators/DimensionInputValidator.java
...roid/apps/flexbox/validators/DimensionInputValidator.java
+1
-1
app/src/main/java/com/google/android/apps/flexbox/validators/FixedDimensionInputValidator.java
...apps/flexbox/validators/FixedDimensionInputValidator.java
+30
-0
app/src/main/res/layout/fragment_flex_item_edit.xml
app/src/main/res/layout/fragment_flex_item_edit.xml
+30
-0
app/src/main/res/values/strings.xml
app/src/main/res/values/strings.xml
+3
-0
flexbox/src/androidTest/java/com/google/android/flexbox/test/FlexboxAndroidTest.java
...a/com/google/android/flexbox/test/FlexboxAndroidTest.java
+143
-1
flexbox/src/androidTest/res/layout/activity_minheight_lower_bound_test.xml
...idTest/res/layout/activity_minheight_lower_bound_test.xml
+48
-0
flexbox/src/androidTest/res/layout/activity_minheight_test.xml
...ox/src/androidTest/res/layout/activity_minheight_test.xml
+36
-0
flexbox/src/androidTest/res/layout/activity_minwidth_lower_bound_test.xml
...oidTest/res/layout/activity_minwidth_lower_bound_test.xml
+47
-0
flexbox/src/androidTest/res/layout/activity_minwidth_test.xml
...box/src/androidTest/res/layout/activity_minwidth_test.xml
+35
-0
flexbox/src/main/java/com/google/android/flexbox/FlexboxLayout.java
...c/main/java/com/google/android/flexbox/FlexboxLayout.java
+103
-47
flexbox/src/main/res/values/attrs.xml
flexbox/src/main/res/values/attrs.xml
+3
-0
未找到文件。
app/src/main/java/com/google/android/apps/flexbox/FlexItem.java
浏览文件 @
163d5714
...
...
@@ -64,6 +64,12 @@ public class FlexItem implements Parcelable {
public
float
flexBasisPercent
;
/** Minimum with in DP */
public
int
minWidth
;
/** Minimum height in DP */
public
int
minHeight
;
public
FlexItem
()
{
}
...
...
@@ -90,6 +96,8 @@ public class FlexItem implements Parcelable {
dest
.
writeFloat
(
this
.
flexShrink
);
dest
.
writeInt
(
this
.
alignSelf
);
dest
.
writeFloat
(
this
.
flexBasisPercent
);
dest
.
writeInt
(
this
.
minWidth
);
dest
.
writeInt
(
this
.
minHeight
);
}
protected
FlexItem
(
Parcel
in
)
{
...
...
@@ -109,6 +117,8 @@ public class FlexItem implements Parcelable {
this
.
flexShrink
=
in
.
readFloat
();
this
.
alignSelf
=
in
.
readInt
();
this
.
flexBasisPercent
=
in
.
readFloat
();
this
.
minWidth
=
in
.
readInt
();
this
.
minHeight
=
in
.
readInt
();
}
public
FlexboxLayout
.
LayoutParams
toLayoutParams
(
Context
context
)
{
...
...
@@ -124,6 +134,8 @@ public class FlexItem implements Parcelable {
MarginLayoutParamsCompat
.
setMarginStart
(
lp
,
startMargin
);
MarginLayoutParamsCompat
.
setMarginEnd
(
lp
,
endMargin
);
lp
.
bottomMargin
=
bottomMargin
;
lp
.
minWidth
=
Util
.
dpToPixel
(
context
,
minWidth
);
lp
.
minHeight
=
Util
.
dpToPixel
(
context
,
minHeight
);
return
lp
;
}
...
...
@@ -146,6 +158,8 @@ public class FlexItem implements Parcelable {
flexItem
.
paddingStart
=
ViewCompat
.
getPaddingStart
(
view
);
flexItem
.
paddingEnd
=
ViewCompat
.
getPaddingEnd
(
view
);
flexItem
.
paddingBottom
=
view
.
getPaddingBottom
();
flexItem
.
minWidth
=
Util
.
pixelToDp
(
view
.
getContext
(),
lp
.
minWidth
);
flexItem
.
minHeight
=
Util
.
pixelToDp
(
view
.
getContext
(),
lp
.
minHeight
);
return
flexItem
;
}
...
...
app/src/main/java/com/google/android/apps/flexbox/FlexItemEditFragment.java
浏览文件 @
163d5714
...
...
@@ -16,6 +16,7 @@
package
com.google.android.apps.flexbox
;
import
com.google.android.apps.flexbox.validators.FixedDimensionInputValidator
;
import
com.google.android.apps.flexbox.validators.FlexBasisPercentInputValidator
;
import
com.google.android.apps.flexbox.validators.InputValidator
;
import
com.google.android.apps.flexbox.validators.IntegerInputValidator
;
...
...
@@ -156,6 +157,23 @@ public class FlexItemEditFragment extends DialogFragment {
new
FlexEditTextWatcher
(
heightInput
,
new
DimensionInputValidator
(),
R
.
string
.
must_be_minus_one_or_minus_two_or_non_negative_integer
));
final
TextInputLayout
minWidthInput
=
(
TextInputLayout
)
view
.
findViewById
(
R
.
id
.
input_layout_min_width
);
EditText
minWidthEdit
=
(
EditText
)
view
.
findViewById
(
R
.
id
.
edit_text_min_width
);
minWidthEdit
.
setText
(
String
.
valueOf
(
mFlexItem
.
minWidth
));
minWidthEdit
.
addTextChangedListener
(
new
FlexEditTextWatcher
(
minWidthInput
,
new
FixedDimensionInputValidator
(),
R
.
string
.
must_be_non_negative_integer
));
final
TextInputLayout
minHeightInput
=
(
TextInputLayout
)
view
.
findViewById
(
R
.
id
.
input_layout_min_height
);
EditText
minHeightEdit
=
(
EditText
)
view
.
findViewById
(
R
.
id
.
edit_text_min_height
);
minHeightEdit
.
setText
(
String
.
valueOf
(
mFlexItem
.
minHeight
));
minHeightEdit
.
addTextChangedListener
(
new
FlexEditTextWatcher
(
minHeightInput
,
new
FixedDimensionInputValidator
(),
R
.
string
.
must_be_non_negative_integer
));
Spinner
alignSelfSpinner
=
(
Spinner
)
view
.
findViewById
(
R
.
id
.
spinner_align_self
);
ArrayAdapter
<
CharSequence
>
arrayAdapter
=
ArrayAdapter
.
createFromResource
(
getActivity
(),
...
...
@@ -200,7 +218,8 @@ public class FlexItemEditFragment extends DialogFragment {
public
void
onClick
(
View
v
)
{
if
(
orderTextInput
.
isErrorEnabled
()
||
flexGrowInput
.
isErrorEnabled
()
||
flexBasisPercentInput
.
isErrorEnabled
()
||
widthInput
.
isErrorEnabled
()
||
heightInput
.
isErrorEnabled
())
{
heightInput
.
isErrorEnabled
()
||
minWidthInput
.
isErrorEnabled
()
||
minHeightInput
.
isErrorEnabled
())
{
Toast
.
makeText
(
getActivity
(),
R
.
string
.
invalid_values_exist
,
Toast
.
LENGTH_SHORT
)
.
show
();
return
;
...
...
@@ -305,6 +324,12 @@ public class FlexItemEditFragment extends DialogFragment {
=
FlexboxLayout
.
LayoutParams
.
FLEX_BASIS_PERCENT_DEFAULT
;
}
break
;
case
R
.
id
.
input_layout_min_width
:
mFlexItem
.
minWidth
=
intValue
;
break
;
case
R
.
id
.
input_layout_min_height
:
mFlexItem
.
minHeight
=
intValue
;
break
;
}
}
}
...
...
app/src/main/java/com/google/android/apps/flexbox/validators/DimensionInputValidator.java
浏览文件 @
163d5714
...
...
@@ -19,7 +19,7 @@ package com.google.android.apps.flexbox.validators;
import
android.text.TextUtils
;
/**
* Validator for dimension values.
* Validator for dimension values
including match_parent and wrap_content
.
*/
public
class
DimensionInputValidator
implements
InputValidator
{
...
...
app/src/main/java/com/google/android/apps/flexbox/validators/FixedDimensionInputValidator.java
0 → 100644
浏览文件 @
163d5714
/*
* Copyright 2016 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com.google.android.apps.flexbox.validators
;
import
android.text.TextUtils
;
/**
* Validator for dimension values.
*/
public
class
FixedDimensionInputValidator
implements
InputValidator
{
@Override
public
boolean
isValidInput
(
CharSequence
charSequence
)
{
return
!
TextUtils
.
isEmpty
(
charSequence
)
&&
TextUtils
.
isDigitsOnly
(
charSequence
);
}
}
app/src/main/res/layout/fragment_flex_item_edit.xml
浏览文件 @
163d5714
...
...
@@ -114,6 +114,36 @@ limitations under the License.
android:singleLine=
"true"
/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:id=
"@+id/input_layout_min_width"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
>
<EditText
android:id=
"@+id/edit_text_min_width"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:lines=
"1"
android:singleLine=
"true"
android:inputType=
"number"
android:hint=
"@string/hint_min_width"
/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:id=
"@+id/input_layout_min_height"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
>
<EditText
android:id=
"@+id/edit_text_min_height"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:lines=
"1"
android:singleLine=
"true"
android:inputType=
"number"
android:hint=
"@string/hint_min_height"
/>
</android.support.design.widget.TextInputLayout>
<LinearLayout
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
...
...
app/src/main/res/values/strings.xml
浏览文件 @
163d5714
...
...
@@ -100,8 +100,11 @@ limitations under the License.
<string
name=
"hint_align_self"
>
Align Self
</string>
<string
name=
"hint_width"
>
Width (-1: match_parent, -2: wrap_content)
</string>
<string
name=
"hint_height"
>
Height (-1: match_parent, -2: wrap_content)
</string>
<string
name=
"hint_min_width"
>
Min Width
</string>
<string
name=
"hint_min_height"
>
Min Height
</string>
<string
name=
"must_be_non_negative_float"
>
Must be a non-negative float value
</string>
<string
name=
"must_be_non_negative_integer"
>
Must be a non-negative integer value
</string>
<string
name=
"must_be_minus_one_or_minus_two_or_non_negative_integer"
>
Must be -1 or -2 or a non-negative integer value
</string>
<string
name=
"must_be_integer"
>
Must be an integer value
</string>
<string
name=
"must_be_minus_one_or_non_negative_integer"
>
Must be -1 or a non-negative integer value
</string>
...
...
flexbox/src/androidTest/java/com/google/android/flexbox/test/FlexboxAndroidTest.java
浏览文件 @
163d5714
...
...
@@ -19,12 +19,16 @@ package com.google.android.flexbox.test;
import
com.google.android.flexbox.FlexboxLayout
;
import
org.hamcrest.Description
;
import
org.hamcrest.TypeSafeMatcher
;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
android.content.Context
;
import
android.support.test.InstrumentationRegistry
;
import
android.support.test.espresso.ViewAssertion
;
import
android.support.test.espresso.assertion.ViewAssertions
;
import
android.support.test.filters.MediumTest
;
import
android.support.test.rule.ActivityTestRule
;
import
android.support.test.runner.AndroidJUnit4
;
...
...
@@ -43,6 +47,7 @@ import static android.support.test.espresso.assertion.PositionAssertions.isRight
import
static
android
.
support
.
test
.
espresso
.
assertion
.
PositionAssertions
.
isRightOf
;
import
static
android
.
support
.
test
.
espresso
.
assertion
.
PositionAssertions
.
isTopAlignedWith
;
import
static
android
.
support
.
test
.
espresso
.
matcher
.
ViewMatchers
.
withId
;
import
static
junit
.
framework
.
Assert
.
assertEquals
;
import
static
junit
.
framework
.
Assert
.
assertTrue
;
import
static
org
.
hamcrest
.
core
.
Is
.
is
;
import
static
org
.
hamcrest
.
core
.
IsNot
.
not
;
...
...
@@ -694,7 +699,8 @@ public class FlexboxAndroidTest {
// Both the parent FrameLayout and the FlexboxLayout have different padding values
// but the text3.getRight should be the padding value for the FlexboxLayout, not including
// the parent's padding value
assertThat
(
flexboxLayout
.
getWidth
()
-
text3
.
getRight
(),
is
(
flexboxLayout
.
getPaddingRight
()));
assertThat
(
flexboxLayout
.
getWidth
()
-
text3
.
getRight
(),
is
(
flexboxLayout
.
getPaddingRight
()));
assertThat
(
text3
.
getTop
(),
is
(
flexboxLayout
.
getPaddingTop
()));
}
...
...
@@ -2446,6 +2452,104 @@ public class FlexboxAndroidTest {
totalHeight
<=
flexboxLayout
.
getHeight
()
+
3
);
}
@Test
@FlakyTest
(
tolerance
=
TOLERANCE
)
public
void
testMinWidth_initial_width_less_than_minWidth
()
throws
Throwable
{
final
FlexboxTestActivity
activity
=
mActivityRule
.
getActivity
();
mActivityRule
.
runOnUiThread
(
new
Runnable
()
{
@Override
public
void
run
()
{
activity
.
setContentView
(
R
.
layout
.
activity_minwidth_test
);
}
});
// This test case verifies if the minWidth attribute works as a minimum constraint
// If the initial view width is less than the value of minWidth.
// The textView1's layout_width is set to wrap_content and its text is "1" apparently
// the initial measured width is less than the value of layout_minWidth (100dp)
FlexboxLayout
flexboxLayout
=
(
FlexboxLayout
)
activity
.
findViewById
(
R
.
id
.
flexbox_layout
);
TextView
textView1
=
(
TextView
)
activity
.
findViewById
(
R
.
id
.
text1
);
int
minWidth
=
((
FlexboxLayout
.
LayoutParams
)
textView1
.
getLayoutParams
()).
minWidth
;
onView
(
withId
(
R
.
id
.
text1
)).
check
(
hasWidth
(
minWidth
));
onView
(
withId
(
R
.
id
.
text2
)).
check
(
hasWidth
(
flexboxLayout
.
getWidth
()
-
minWidth
));
}
@Test
@FlakyTest
(
tolerance
=
TOLERANCE
)
public
void
testMinWidth_works_as_lower_bound_shrink_to
()
throws
Throwable
{
final
FlexboxTestActivity
activity
=
mActivityRule
.
getActivity
();
mActivityRule
.
runOnUiThread
(
new
Runnable
()
{
@Override
public
void
run
()
{
activity
.
setContentView
(
R
.
layout
.
activity_minwidth_lower_bound_test
);
}
});
// This test case verifies if the minWidth attribute works as a lower bound
// when the view would shrink less than the minWidth if the minWidth weren't set
FlexboxLayout
flexboxLayout
=
(
FlexboxLayout
)
activity
.
findViewById
(
R
.
id
.
flexbox_layout
);
TextView
textView1
=
(
TextView
)
activity
.
findViewById
(
R
.
id
.
text1
);
TextView
textView2
=
(
TextView
)
activity
.
findViewById
(
R
.
id
.
text2
);
TextView
textView3
=
(
TextView
)
activity
.
findViewById
(
R
.
id
.
text3
);
TextView
textView4
=
(
TextView
)
activity
.
findViewById
(
R
.
id
.
text4
);
int
minWidth
=
((
FlexboxLayout
.
LayoutParams
)
textView1
.
getLayoutParams
()).
minWidth
;
onView
(
withId
(
R
.
id
.
text1
)).
check
(
hasWidth
(
minWidth
));
assertEquals
(
flexboxLayout
.
getWidth
(),
textView1
.
getWidth
()
+
textView2
.
getWidth
()
+
textView3
.
getWidth
()
+
textView4
.
getWidth
());
}
@Test
@FlakyTest
(
tolerance
=
TOLERANCE
)
public
void
testMinHeight_initial_height_less_than_minHeight
()
throws
Throwable
{
final
FlexboxTestActivity
activity
=
mActivityRule
.
getActivity
();
mActivityRule
.
runOnUiThread
(
new
Runnable
()
{
@Override
public
void
run
()
{
activity
.
setContentView
(
R
.
layout
.
activity_minheight_test
);
}
});
// This test case verifies if the minHeight attribute works as a minimum constraint
// If the initial view height is less than the value of minHeight.
// The textView1's layout_height is set to wrap_content and its text is "1" apparently
// the initial measured height is less than the value of layout_minHeight (100dp)
FlexboxLayout
flexboxLayout
=
(
FlexboxLayout
)
activity
.
findViewById
(
R
.
id
.
flexbox_layout
);
TextView
textView1
=
(
TextView
)
activity
.
findViewById
(
R
.
id
.
text1
);
int
minHeight
=
((
FlexboxLayout
.
LayoutParams
)
textView1
.
getLayoutParams
()).
minHeight
;
onView
(
withId
(
R
.
id
.
text1
)).
check
(
hasHeight
(
minHeight
));
onView
(
withId
(
R
.
id
.
text2
)).
check
(
hasHeight
(
flexboxLayout
.
getHeight
()
-
minHeight
));
}
@Test
@FlakyTest
(
tolerance
=
TOLERANCE
)
public
void
testMinHeight_works_as_lower_bound_shrink_to
()
throws
Throwable
{
final
FlexboxTestActivity
activity
=
mActivityRule
.
getActivity
();
mActivityRule
.
runOnUiThread
(
new
Runnable
()
{
@Override
public
void
run
()
{
activity
.
setContentView
(
R
.
layout
.
activity_minheight_lower_bound_test
);
}
});
// This test case verifies if the minHeight attribute works as a lower bound
// when the view would shrink less than the minHeight if the minHeight weren't set
FlexboxLayout
flexboxLayout
=
(
FlexboxLayout
)
activity
.
findViewById
(
R
.
id
.
flexbox_layout
);
TextView
textView1
=
(
TextView
)
activity
.
findViewById
(
R
.
id
.
text1
);
TextView
textView2
=
(
TextView
)
activity
.
findViewById
(
R
.
id
.
text2
);
TextView
textView3
=
(
TextView
)
activity
.
findViewById
(
R
.
id
.
text3
);
TextView
textView4
=
(
TextView
)
activity
.
findViewById
(
R
.
id
.
text4
);
int
minHeight
=
((
FlexboxLayout
.
LayoutParams
)
textView1
.
getLayoutParams
()).
minHeight
;
onView
(
withId
(
R
.
id
.
text1
)).
check
(
hasHeight
(
minHeight
));
assertEquals
(
flexboxLayout
.
getHeight
(),
textView1
.
getHeight
()
+
textView2
.
getHeight
()
+
textView3
.
getHeight
()
+
textView4
.
getHeight
());
}
@Test
@FlakyTest
(
tolerance
=
TOLERANCE
)
public
void
testView_visibility_gone
()
throws
Throwable
{
...
...
@@ -2518,4 +2622,42 @@ public class FlexboxAndroidTest {
textView
.
setLayoutParams
(
lp
);
return
textView
;
}
private
ViewAssertion
hasWidth
(
final
int
width
)
{
return
ViewAssertions
.
matches
(
new
TypeSafeMatcher
<
View
>()
{
@Override
public
void
describeTo
(
Description
description
)
{
description
.
appendText
(
"expected width: "
+
width
);
}
@Override
protected
void
describeMismatchSafely
(
View
item
,
Description
mismatchDescription
)
{
mismatchDescription
.
appendText
(
"actual width: "
+
item
.
getWidth
());
}
@Override
protected
boolean
matchesSafely
(
View
item
)
{
return
item
.
getWidth
()
==
width
;
}
});
}
private
ViewAssertion
hasHeight
(
final
int
height
)
{
return
ViewAssertions
.
matches
(
new
TypeSafeMatcher
<
View
>()
{
@Override
public
void
describeTo
(
Description
description
)
{
description
.
appendText
(
"expected height: "
+
height
);
}
@Override
protected
void
describeMismatchSafely
(
View
item
,
Description
mismatchDescription
)
{
mismatchDescription
.
appendText
(
"actual height: "
+
item
.
getHeight
());
}
@Override
protected
boolean
matchesSafely
(
View
item
)
{
return
item
.
getHeight
()
==
height
;
}
});
}
}
flexbox/src/androidTest/res/layout/activity_minheight_lower_bound_test.xml
0 → 100644
浏览文件 @
163d5714
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2016 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<com.google.android.flexbox.FlexboxLayout
android:id=
"@+id/flexbox_layout"
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
android:layout_width=
"400dp"
android:layout_height=
"400dp"
app:flexDirection=
"column"
app:flexWrap=
"nowrap"
>
<TextView
android:id=
"@+id/text1"
android:layout_width=
"wrap_content"
android:layout_height=
"200dp"
android:text=
"1"
app:layout_minHeight=
"150dp"
/>
<TextView
android:id=
"@+id/text2"
android:layout_width=
"wrap_content"
android:layout_height=
"200dp"
android:text=
"2"
/>
<TextView
android:id=
"@+id/text3"
android:layout_width=
"wrap_content"
android:layout_height=
"200dp"
android:text=
"3"
/>
<TextView
android:id=
"@+id/text4"
android:layout_width=
"wrap_content"
android:layout_height=
"200dp"
android:text=
"4"
/>
</com.google.android.flexbox.FlexboxLayout>
\ No newline at end of file
flexbox/src/androidTest/res/layout/activity_minheight_test.xml
0 → 100644
浏览文件 @
163d5714
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2016 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<com.google.android.flexbox.FlexboxLayout
android:id=
"@+id/flexbox_layout"
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
android:layout_width=
"400dp"
android:layout_height=
"400dp"
app:flexDirection=
"column"
>
<TextView
android:id=
"@+id/text1"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:text=
"1"
app:layout_minHeight=
"100dp"
/>
<TextView
android:id=
"@+id/text2"
android:layout_width=
"wrap_content"
android:layout_height=
"0dp"
android:text=
"2"
app:layout_flexGrow=
"1"
/>
</com.google.android.flexbox.FlexboxLayout>
\ No newline at end of file
flexbox/src/androidTest/res/layout/activity_minwidth_lower_bound_test.xml
0 → 100644
浏览文件 @
163d5714
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2016 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<com.google.android.flexbox.FlexboxLayout
android:id=
"@+id/flexbox_layout"
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
android:layout_width=
"400dp"
android:layout_height=
"400dp"
app:flexWrap=
"nowrap"
>
<TextView
android:id=
"@+id/text1"
android:layout_width=
"200dp"
android:layout_height=
"wrap_content"
android:text=
"1"
app:layout_minWidth=
"150dp"
/>
<TextView
android:id=
"@+id/text2"
android:layout_width=
"200dp"
android:layout_height=
"wrap_content"
android:text=
"2"
/>
<TextView
android:id=
"@+id/text3"
android:layout_width=
"200dp"
android:layout_height=
"wrap_content"
android:text=
"3"
/>
<TextView
android:id=
"@+id/text4"
android:layout_width=
"200dp"
android:layout_height=
"wrap_content"
android:text=
"4"
/>
</com.google.android.flexbox.FlexboxLayout>
\ No newline at end of file
flexbox/src/androidTest/res/layout/activity_minwidth_test.xml
0 → 100644
浏览文件 @
163d5714
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2016 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<com.google.android.flexbox.FlexboxLayout
android:id=
"@+id/flexbox_layout"
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
android:layout_width=
"400dp"
android:layout_height=
"400dp"
>
<TextView
android:id=
"@+id/text1"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:text=
"1"
app:layout_minWidth=
"100dp"
/>
<TextView
android:id=
"@+id/text2"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:text=
"2"
app:layout_flexGrow=
"1"
/>
</com.google.android.flexbox.FlexboxLayout>
\ No newline at end of file
flexbox/src/main/java/com/google/android/flexbox/FlexboxLayout.java
浏览文件 @
163d5714
...
...
@@ -57,6 +57,8 @@ import java.util.List;
* <li>{@code layout_flexShrink}</li>
* <li>{@code layout_flexBasisPercent}</li>
* <li>{@code layout_alignSelf}</li>
* <li>{@code layout_minWidth}</li>
* <li>{@code layout_minHeight}</li>
* </ul>
*/
public
class
FlexboxLayout
extends
ViewGroup
{
...
...
@@ -219,6 +221,13 @@ public class FlexboxLayout extends ViewGroup {
private
List
<
FlexLine
>
mFlexLines
=
new
ArrayList
<>();
/**
* Holds the 'frozen' state of children during measure. If a view is frozen it will no longer
* expand or shrink regardless of flexGrow/flexShrink. Items are indexed by the child's
* reordered index.
*/
private
boolean
[]
mChildrenFrozen
;
public
FlexboxLayout
(
Context
context
)
{
this
(
context
,
null
);
}
...
...
@@ -247,6 +256,9 @@ public class FlexboxLayout extends ViewGroup {
if
(
isOrderChangedFromLastMeasurement
())
{
mReorderedIndices
=
createReorderedIndices
();
}
// TODO: Move the object allocation to other methods instead of onMeasure
mChildrenFrozen
=
new
boolean
[
getChildCount
()];
// TODO: Only calculate the children views which are affected from the last measure.
switch
(
mFlexDirection
)
{
...
...
@@ -459,6 +471,16 @@ public class FlexboxLayout extends ViewGroup {
getPaddingTop
()
+
getPaddingBottom
()
+
lp
.
topMargin
+
lp
.
bottomMargin
,
lp
.
height
);
child
.
measure
(
childWidthMeasureSpec
,
childHeightMeasureSpec
);
// Check the minimum constraint after the first measurement for the child
// To prevent the child's width becomes less than the value of minWidth
// E.g. When the child's layout_width is wrap_content the measured width may be
// less than the min width after the first measurement.
if
(
child
.
getMeasuredWidth
()
<
lp
.
minWidth
)
{
child
.
measure
(
MeasureSpec
.
makeMeasureSpec
(
lp
.
minWidth
,
MeasureSpec
.
EXACTLY
),
MeasureSpec
.
makeMeasureSpec
(
child
.
getMeasuredHeight
(),
MeasureSpec
.
EXACTLY
));
}
childState
=
ViewCompat
.
combineMeasuredStates
(
childState
,
ViewCompat
.
getMeasuredState
(
child
));
largestHeightInRow
=
Math
.
max
(
largestHeightInRow
,
...
...
@@ -602,6 +624,16 @@ public class FlexboxLayout extends ViewGroup {
getPaddingTop
()
+
getPaddingBottom
()
+
lp
.
topMargin
+
lp
.
bottomMargin
,
childHeight
);
child
.
measure
(
childWidthMeasureSpec
,
childHeightMeasureSpec
);
// Check the minimum constraint after the first measurement for the child
// To prevent the child's height becomes less than the value of minHeight
// E.g. When the child's layout_height is wrap_content the measured height may be
// less than the min height after the first measurement.
if
(
child
.
getMeasuredHeight
()
<
lp
.
minHeight
)
{
child
.
measure
(
MeasureSpec
.
makeMeasureSpec
(
child
.
getMeasuredWidth
(),
MeasureSpec
.
EXACTLY
),
MeasureSpec
.
makeMeasureSpec
(
lp
.
minHeight
,
MeasureSpec
.
EXACTLY
));
}
childState
=
ViewCompat
.
combineMeasuredStates
(
childState
,
ViewCompat
.
getMeasuredState
(
child
));
largestWidthInColumn
=
Math
.
max
(
largestWidthInColumn
,
...
...
@@ -817,59 +849,70 @@ public class FlexboxLayout extends ViewGroup {
LayoutParams
lp
=
(
LayoutParams
)
child
.
getLayoutParams
();
if
(
flexDirection
==
FLEX_DIRECTION_ROW
||
flexDirection
==
FLEX_DIRECTION_ROW_REVERSE
)
{
float
rawCalculatedWidth
=
child
.
getMeasuredWidth
()
-
unitShrink
*
lp
.
flexShrink
;
if
(
i
==
flexLine
.
itemCount
-
1
)
{
rawCalculatedWidth
+=
accumulatedRoundError
;
accumulatedRoundError
=
0
;
}
int
newWidth
=
Math
.
round
(
rawCalculatedWidth
);
if
(
newWidth
<
0
)
{
// This means the child doesn't have enough space to distribute the negative
// free space. To adjust the flex line length down to the maxMainSize, remaining
// negative free space needs to be re-distributed to other flex items
// (children views). In that case, invoke this method again with the same
// startIndex.
needsReshrink
=
true
;
newWidth
=
0
;
}
else
{
accumulatedRoundError
+=
(
rawCalculatedWidth
-
newWidth
);
if
(
accumulatedRoundError
>
1.0
)
{
newWidth
+=
1
;
accumulatedRoundError
-=
1
;
}
else
if
(
accumulatedRoundError
<
-
1.0
)
{
newWidth
-=
1
;
accumulatedRoundError
+=
1
;
// The direction of main axis is horizontal
if
(!
mChildrenFrozen
[
childIndex
])
{
float
rawCalculatedWidth
=
child
.
getMeasuredWidth
()
-
unitShrink
*
lp
.
flexShrink
;
if
(
i
==
flexLine
.
itemCount
-
1
)
{
rawCalculatedWidth
+=
accumulatedRoundError
;
accumulatedRoundError
=
0
;
}
int
newWidth
=
Math
.
round
(
rawCalculatedWidth
);
if
(
newWidth
<
lp
.
minWidth
)
{
// This means the child doesn't have enough space to distribute the negative
// free space. To adjust the flex line length down to the maxMainSize, remaining
// negative free space needs to be re-distributed to other flex items
// (children views). In that case, invoke this method again with the same
// startIndex.
needsReshrink
=
true
;
newWidth
=
lp
.
minWidth
;
mChildrenFrozen
[
childIndex
]
=
true
;
flexLine
.
totalFlexShrink
-=
lp
.
flexShrink
;
}
else
{
accumulatedRoundError
+=
(
rawCalculatedWidth
-
newWidth
);
if
(
accumulatedRoundError
>
1.0
)
{
newWidth
+=
1
;
accumulatedRoundError
-=
1
;
}
else
if
(
accumulatedRoundError
<
-
1.0
)
{
newWidth
-=
1
;
accumulatedRoundError
+=
1
;
}
}
child
.
measure
(
MeasureSpec
.
makeMeasureSpec
(
newWidth
,
MeasureSpec
.
EXACTLY
),
MeasureSpec
.
makeMeasureSpec
(
child
.
getMeasuredHeight
(),
MeasureSpec
.
EXACTLY
));
}
child
.
measure
(
MeasureSpec
.
makeMeasureSpec
(
newWidth
,
MeasureSpec
.
EXACTLY
),
MeasureSpec
.
makeMeasureSpec
(
child
.
getMeasuredHeight
(),
MeasureSpec
.
EXACTLY
));
flexLine
.
mainSize
+=
child
.
getMeasuredWidth
()
+
lp
.
leftMargin
+
lp
.
rightMargin
;
}
else
{
float
rawCalculatedHeight
=
child
.
getMeasuredHeight
()
-
unitShrink
*
lp
.
flexShrink
;
if
(
i
==
flexLine
.
itemCount
-
1
)
{
rawCalculatedHeight
+=
accumulatedRoundError
;
accumulatedRoundError
=
0
;
}
int
newHeight
=
Math
.
round
(
rawCalculatedHeight
);
if
(
newHeight
<
0
)
{
// Need to invoke this method again like the case flex direction is vertical
needsReshrink
=
true
;
newHeight
=
0
;
}
else
{
accumulatedRoundError
+=
(
rawCalculatedHeight
-
newHeight
);
if
(
accumulatedRoundError
>
1.0
)
{
newHeight
+=
1
;
accumulatedRoundError
-=
1
;
}
else
if
(
accumulatedRoundError
<
-
1.0
)
{
newHeight
-=
1
;
accumulatedRoundError
+=
1
;
// The direction of main axis is vertical
if
(!
mChildrenFrozen
[
childIndex
])
{
float
rawCalculatedHeight
=
child
.
getMeasuredHeight
()
-
unitShrink
*
lp
.
flexShrink
;
if
(
i
==
flexLine
.
itemCount
-
1
)
{
rawCalculatedHeight
+=
accumulatedRoundError
;
accumulatedRoundError
=
0
;
}
int
newHeight
=
Math
.
round
(
rawCalculatedHeight
);
if
(
newHeight
<
lp
.
minHeight
)
{
// Need to invoke this method again like the case flex direction is vertical
needsReshrink
=
true
;
newHeight
=
lp
.
minHeight
;
mChildrenFrozen
[
childIndex
]
=
true
;
flexLine
.
totalFlexShrink
-=
lp
.
flexShrink
;
}
else
{
accumulatedRoundError
+=
(
rawCalculatedHeight
-
newHeight
);
if
(
accumulatedRoundError
>
1.0
)
{
newHeight
+=
1
;
accumulatedRoundError
-=
1
;
}
else
if
(
accumulatedRoundError
<
-
1.0
)
{
newHeight
-=
1
;
accumulatedRoundError
+=
1
;
}
}
child
.
measure
(
MeasureSpec
.
makeMeasureSpec
(
child
.
getMeasuredWidth
(),
MeasureSpec
.
EXACTLY
),
MeasureSpec
.
makeMeasureSpec
(
newHeight
,
MeasureSpec
.
EXACTLY
));
}
child
.
measure
(
MeasureSpec
.
makeMeasureSpec
(
child
.
getMeasuredWidth
(),
MeasureSpec
.
EXACTLY
),
MeasureSpec
.
makeMeasureSpec
(
newHeight
,
MeasureSpec
.
EXACTLY
));
flexLine
.
mainSize
+=
child
.
getMeasuredHeight
()
+
lp
.
topMargin
+
lp
.
bottomMargin
;
}
childIndex
++;
...
...
@@ -1827,6 +1870,16 @@ public class FlexboxLayout extends ViewGroup {
*/
public
float
flexBasisPercent
=
FLEX_BASIS_PERCENT_DEFAULT
;
/**
* This attribute determines the minimum width the child can shrink to.
*/
public
int
minWidth
;
/**
* This attribute determines the minimum height the child can shrink to.
*/
public
int
minHeight
;
public
LayoutParams
(
Context
context
,
AttributeSet
attrs
)
{
super
(
context
,
attrs
);
...
...
@@ -1842,6 +1895,9 @@ public class FlexboxLayout extends ViewGroup {
flexBasisPercent
=
a
.
getFraction
(
R
.
styleable
.
FlexboxLayout_Layout_layout_flexBasisPercent
,
1
,
1
,
FLEX_BASIS_PERCENT_DEFAULT
);
minWidth
=
a
.
getDimensionPixelSize
(
R
.
styleable
.
FlexboxLayout_Layout_layout_minWidth
,
0
);
minHeight
=
a
.
getDimensionPixelSize
(
R
.
styleable
.
FlexboxLayout_Layout_layout_minHeight
,
0
);
a
.
recycle
();
}
...
...
flexbox/src/main/res/values/attrs.xml
浏览文件 @
163d5714
...
...
@@ -99,5 +99,8 @@ limitations under the License.
<enum
name=
"baseline"
value=
"3"
/>
<enum
name=
"stretch"
value=
"4"
/>
</attr>
<attr
name=
"layout_minWidth"
format=
"dimension"
/>
<attr
name=
"layout_minHeight"
format=
"dimension"
/>
</declare-styleable>
</resources>
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录