提交 a7be0d70 编写于 作者: T Takeshi Hagikura 提交者: Takeshi Hagikura

Improvement in the demo app and several fixes. (#171)

- Preserve the flex items state across a configuration change in the demo app
- Throw an Exception when order or alignContent which aren't supported by
  FlexboxLayoutManager are changed (setXXXX is invoked)
- Clear the existing flex lines and views if an incompatible, in which prior views
  states or flex lines states can't be shared, attribute change happens
  (e.g. flex direction is changd from row to column)
上级 d5123a30
......@@ -137,6 +137,10 @@ public class FlexItemEditFragment extends DialogFragment {
orderEdit.addTextChangedListener(
new FlexEditTextWatcher(orderTextInput, new IntegerInputValidator(),
R.string.must_be_integer));
if (mFlexItem instanceof FlexboxLayoutManager.LayoutParams) {
// Order is not enabled in FlexboxLayoutManager
orderEdit.setEnabled(false);
}
final TextInputLayout flexGrowInput = (TextInputLayout) view
.findViewById(R.id.input_layout_flex_grow);
......
......@@ -27,6 +27,7 @@ import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.Toast;
/**
* Helper class that has the common logic for initializing the Fragment for the play ground demo
......@@ -72,6 +73,7 @@ class FragmentHelper {
private SharedPreferences mSharedPreferences;
FragmentHelper(MainActivity mainActivity, FlexContainer flexContainer) {
mActivity = mainActivity;
mFlexContainer = flexContainer;
......@@ -124,9 +126,12 @@ class FragmentHelper {
flexItem.setHeight(Util.dpToPixel(mActivity,
readPreferenceAsInteger(mActivity.getString(R.string.new_height_key),
DEFAULT_HEIGHT)));
flexItem.setOrder(
readPreferenceAsInteger(mActivity.getString(R.string.new_flex_item_order_key),
"1"));
// Order is not supported in the FlexboxLayoutManager
if (!(flexItem instanceof FlexboxLayoutManager.LayoutParams)) {
flexItem.setOrder(
readPreferenceAsInteger(mActivity.getString(R.string.new_flex_item_order_key),
"1"));
}
flexItem.setFlexGrow(
readPreferenceAsFloat(mActivity.getString(R.string.new_flex_grow_key), "0.0"));
flexItem.setFlexShrink(
......@@ -228,7 +233,15 @@ class FragmentHelper {
} else if (selected.equals(WRAP_REVERSE)) {
flexWrap = FlexWrap.WRAP_REVERSE;
}
mFlexContainer.setFlexWrap(flexWrap);
if (mFlexContainer instanceof FlexboxLayoutManager &&
flexWrap == FlexWrap.WRAP_REVERSE) {
Toast.makeText(mActivity,
R.string.wrap_reverse_not_supported,
Toast.LENGTH_SHORT).show();
} else {
mFlexContainer.setFlexWrap(flexWrap);
}
}
@Override
......@@ -370,7 +383,13 @@ class FragmentHelper {
} else if (selected.equals(STRETCH)) {
alignContent = AlignContent.STRETCH;
}
mFlexContainer.setAlignContent(alignContent);
if (mFlexContainer instanceof FlexboxLayoutManager) {
Toast.makeText(mActivity, R.string.align_content_not_supported,
Toast.LENGTH_SHORT).show();
} else {
mFlexContainer.setAlignContent(alignContent);
}
}
@Override
......
......@@ -59,24 +59,21 @@ public class MainActivity extends AppCompatActivity
RadioGroup radioGroup = (RadioGroup) navigationView.getHeaderView(0)
.findViewById(R.id.radiogroup_container_implementation);
final FragmentManager fragmentManager = getSupportFragmentManager();
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup radioGroup, int checkedId) {
if (checkedId == R.id.radiobutton_viewgroup) {
replaceToFlexboxLayoutFragment(fragmentManager);
} else {
RecyclerViewFragment fragment = (RecyclerViewFragment)
fragmentManager.findFragmentByTag(RECYCLERVIEW_FRAGMENT);
if (fragment == null) {
fragment = RecyclerViewFragment.newInstance();
}
fragmentManager.beginTransaction()
.replace(R.id.container, fragment, RECYCLERVIEW_FRAGMENT).commit();
replaceToRecyclerViewFragment(fragmentManager);
}
}
});
replaceToFlexboxLayoutFragment(fragmentManager);
if (savedInstanceState == null) {
replaceToFlexboxLayoutFragment(fragmentManager);
}
}
private void replaceToFlexboxLayoutFragment(FragmentManager fragmentManager) {
......@@ -89,6 +86,16 @@ public class MainActivity extends AppCompatActivity
.replace(R.id.container, fragment, FLEXBOXLAYOUT_FRAGMENT).commit();
}
private void replaceToRecyclerViewFragment(FragmentManager fragmentManager) {
RecyclerViewFragment fragment = (RecyclerViewFragment)
fragmentManager.findFragmentByTag(RECYCLERVIEW_FRAGMENT);
if (fragment == null) {
fragment = RecyclerViewFragment.newInstance();
}
fragmentManager.beginTransaction()
.replace(R.id.container, fragment, RECYCLERVIEW_FRAGMENT).commit();
}
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
return false;
......
......@@ -28,16 +28,22 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
/**
* Fragment that contains the {@link RecyclerView} and the {@link FlexboxLayoutManager} as its
* LayoutManager for the flexbox playground.
*/
public class RecyclerViewFragment extends Fragment {
private static final String FLEX_ITEMS_KEY = "flex_items";
public static RecyclerViewFragment newInstance() {
return new RecyclerViewFragment();
}
private FlexItemAdapter mAdapter;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
......@@ -54,8 +60,19 @@ public class RecyclerViewFragment extends Fragment {
final FlexboxLayoutManager flexboxLayoutManager = new FlexboxLayoutManager();
final MainActivity activity = (MainActivity) getActivity();
recyclerView.setLayoutManager(flexboxLayoutManager);
final FlexItemAdapter adapter = new FlexItemAdapter(activity, flexboxLayoutManager);
recyclerView.setAdapter(adapter);
if (mAdapter == null) {
mAdapter = new FlexItemAdapter(activity, flexboxLayoutManager);
}
recyclerView.setAdapter(mAdapter);
if (savedInstanceState != null) {
ArrayList<FlexboxLayoutManager.LayoutParams> layoutParams = savedInstanceState
.getParcelableArrayList(FLEX_ITEMS_KEY);
assert layoutParams != null;
for (int i = 0; i < layoutParams.size(); i++) {
mAdapter.addItem(layoutParams.get(i));
}
mAdapter.notifyDataSetChanged();
}
final FragmentHelper fragmentHelper = new FragmentHelper(activity, flexboxLayoutManager);
fragmentHelper.initializeViews();
......@@ -69,8 +86,8 @@ public class RecyclerViewFragment extends Fragment {
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
fragmentHelper.setFlexItemAttributes(lp);
adapter.addItem(lp);
adapter.notifyDataSetChanged();
mAdapter.addItem(lp);
mAdapter.notifyDataSetChanged();
}
});
}
......@@ -80,15 +97,21 @@ public class RecyclerViewFragment extends Fragment {
removeFab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (adapter.getItemCount() == 0) {
if (mAdapter.getItemCount() == 0) {
return;
}
adapter.removeItem(adapter.getItemCount() - 1);
mAdapter.removeItem(mAdapter.getItemCount() - 1);
// TODO: Specify index?
adapter.notifyDataSetChanged();
mAdapter.notifyDataSetChanged();
}
});
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelableArrayList(FLEX_ITEMS_KEY, new ArrayList<>(mAdapter.getItems()));
}
}
......@@ -28,6 +28,7 @@ import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
......@@ -39,7 +40,7 @@ public class FlexItemAdapter extends RecyclerView.Adapter<FlexItemViewHolder> {
private FlexboxLayoutManager mLayoutManager;
private List<RecyclerView.LayoutParams> mLayoutParams;
private List<FlexboxLayoutManager.LayoutParams> mLayoutParams;
public FlexItemAdapter(AppCompatActivity activity, FlexboxLayoutManager layoutManager) {
mActivity = activity;
......@@ -62,7 +63,7 @@ public class FlexItemAdapter extends RecyclerView.Adapter<FlexItemViewHolder> {
holder.bindTo(mLayoutParams.get(position));
}
public void addItem(RecyclerView.LayoutParams lp) {
public void addItem(FlexboxLayoutManager.LayoutParams lp) {
mLayoutParams.add(lp);
}
......@@ -73,6 +74,10 @@ public class FlexItemAdapter extends RecyclerView.Adapter<FlexItemViewHolder> {
mLayoutParams.remove(position);
}
public List<FlexboxLayoutManager.LayoutParams> getItems() {
return Collections.unmodifiableList(mLayoutParams);
}
@Override
public int getItemCount() {
return mLayoutParams.size();
......
......@@ -131,4 +131,6 @@ limitations under the License.
<string name="viewgroup">ViewGroup</string>
<string name="recyclerview">RecyclerView</string>
<string name="underlying_implementation">Underlying implementation</string>
<string name="align_content_not_supported">Setting the alignContent in FlexboxLayoutManager is not supported. Ignoring.</string>
<string name="wrap_reverse_not_supported">wrap_reverse is not supporeted in the FlexboxLayoutManager.</string>
</resources>
......@@ -16,7 +16,6 @@
package com.google.android.flexbox.test;
import com.google.android.flexbox.AlignContent;
import com.google.android.flexbox.AlignItems;
import com.google.android.flexbox.AlignSelf;
import com.google.android.flexbox.FlexDirection;
......@@ -79,7 +78,7 @@ public class FlexboxLayoutManagerTest {
assertThat(layoutManager, is(instanceOf(FlexboxLayoutManager.class)));
FlexboxLayoutManager flexboxLayoutManager = (FlexboxLayoutManager) layoutManager;
assertThat(flexboxLayoutManager.getFlexDirection(), is(FlexDirection.ROW_REVERSE));
assertThat(flexboxLayoutManager.getFlexWrap(), is(FlexWrap.WRAP_REVERSE));
assertThat(flexboxLayoutManager.getFlexWrap(), is(FlexWrap.WRAP));
}
@Test
......@@ -98,18 +97,16 @@ public class FlexboxLayoutManagerTest {
assertThat(layoutManager, is(instanceOf(FlexboxLayoutManager.class)));
FlexboxLayoutManager flexboxLayoutManager = (FlexboxLayoutManager) layoutManager;
assertThat(flexboxLayoutManager.getFlexDirection(), is(FlexDirection.ROW_REVERSE));
assertThat(flexboxLayoutManager.getFlexWrap(), is(FlexWrap.WRAP_REVERSE));
assertThat(flexboxLayoutManager.getFlexWrap(), is(FlexWrap.WRAP));
flexboxLayoutManager.setFlexDirection(FlexDirection.COLUMN);
flexboxLayoutManager.setFlexWrap(FlexWrap.NOWRAP);
flexboxLayoutManager.setJustifyContent(JustifyContent.CENTER);
flexboxLayoutManager.setAlignItems(AlignItems.FLEX_END);
flexboxLayoutManager.setAlignContent(AlignContent.SPACE_BETWEEN);
assertThat(flexboxLayoutManager.getFlexDirection(), is(FlexDirection.COLUMN));
assertThat(flexboxLayoutManager.getFlexWrap(), is(FlexWrap.NOWRAP));
assertThat(flexboxLayoutManager.getJustifyContent(), is(JustifyContent.CENTER));
assertThat(flexboxLayoutManager.getAlignItems(), is(AlignItems.FLEX_END));
assertThat(flexboxLayoutManager.getAlignContent(), is(AlignContent.SPACE_BETWEEN));
}
@Test
......
......@@ -701,6 +701,9 @@ class FlexboxHelper {
*/
void determineMainSize(int widthMeasureSpec, int heightMeasureSpec, int fromIndex) {
ensureChildrenFrozen(mFlexContainer.getFlexItemCount());
if (fromIndex >= mFlexContainer.getFlexItemCount()) {
return;
}
int mainSize;
int paddingAlongMainAxis;
int flexDirection = mFlexContainer.getFlexDirection();
......@@ -1304,6 +1307,9 @@ class FlexboxHelper {
* @see FlexboxLayout.LayoutParams#mAlignSelf
*/
void stretchViews(int fromIndex) {
if (fromIndex >= mFlexContainer.getFlexItemCount()) {
return;
}
int flexDirection = mFlexContainer.getFlexDirection();
if (mFlexContainer.getAlignItems() == AlignItems.STRETCH) {
int viewIndex = fromIndex;
......
......@@ -79,14 +79,6 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements
*/
private int mAlignItems;
/**
* The current value of the {@link AlignContent}, the default value is
* {@link AlignContent#STRETCH}.
*
* @see {@link FlexContainer#getAlignContent()}
*/
private int mAlignContent;
/**
* True if the layout direction is right to left, false otherwise.
*/
......@@ -173,10 +165,6 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements
* {@link FlexDirection}, i.e. if reverseLayout is {@code true}, {@link FlexDirection#ROW} is
* changed to {@link FlexDirection#ROW_REVERSE}. Similarly {@link FlexDirection#COLUMN} is
* changed to {@link FlexDirection#COLUMN_REVERSE}.
*
* {@code android.support.v7.recyclerview:stackFromEnd} maps to the {@link FlexWrap},
* if stackFromEnd is set to {@code true} -> {@link FlexWrap#WRAP_REVERSE} otherwise ->
* {@link FlexWrap#WRAP}.
*/
public FlexboxLayoutManager(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
......@@ -197,11 +185,8 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements
}
break;
}
if (properties.stackFromEnd) {
setFlexWrap(FlexWrap.WRAP_REVERSE);
} else {
setFlexWrap(FlexWrap.WRAP);
}
setFlexWrap(FlexWrap.WRAP);
setAutoMeasureEnabled(true);
}
......@@ -215,9 +200,12 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements
@Override
public void setFlexDirection(@FlexDirection int flexDirection) {
if (mFlexDirection != flexDirection) {
if (isMainAxisDirectionChanging(flexDirection)) {
removeAllViews();
clearFlexLines();
}
mFlexDirection = flexDirection;
mOrientationHelper = null;
clearFlexLines();
requestLayout();
}
}
......@@ -230,10 +218,17 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements
@Override
public void setFlexWrap(@FlexWrap int flexWrap) {
if (flexWrap == FlexWrap.WRAP_REVERSE) {
throw new UnsupportedOperationException("wrap_reverse is not supported in "
+ "FlexboxLayoutManager");
}
if (mFlexWrap != flexWrap) {
if (mFlexWrap == FlexWrap.NOWRAP || flexWrap == FlexWrap.NOWRAP) {
removeAllViews();
clearFlexLines();
}
mFlexWrap = flexWrap;
mOrientationHelper = null;
clearFlexLines();
requestLayout();
}
}
......@@ -261,8 +256,11 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements
@Override
public void setAlignItems(@AlignItems int alignItems) {
if (mAlignItems != alignItems) {
if (mAlignItems == AlignItems.STRETCH || alignItems == AlignItems.STRETCH) {
removeAllViews();
clearFlexLines();
}
mAlignItems = alignItems;
clearFlexLines();
requestLayout();
}
}
......@@ -270,16 +268,14 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements
@AlignContent
@Override
public int getAlignContent() {
return mAlignContent;
return AlignContent.STRETCH;
}
@Override
public void setAlignContent(@AlignContent int alignContent) {
if (mAlignContent != alignContent) {
mAlignContent = alignContent;
clearFlexLines();
requestLayout();
}
throw new UnsupportedOperationException("Setting the alignContent in the "
+ "FlexboxLayoutManager is not supported. Use FlexboxLayout "
+ "if you need to reorder using the attribute.");
}
@Override
......@@ -1042,6 +1038,20 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements
return mFlexDirection == FlexDirection.ROW || mFlexDirection == FlexDirection.ROW_REVERSE;
}
private boolean isMainAxisDirectionVertical() {
return mFlexDirection == FlexDirection.COLUMN
|| mFlexDirection == FlexDirection.COLUMN_REVERSE;
}
private boolean isMainAxisDirectionChanging(@FlexDirection int newDirection) {
boolean mainAxisHorizontal = isMainAxisDirectionHorizontal();
boolean mainAxisVertical = isMainAxisDirectionVertical();
return (mainAxisHorizontal && newDirection == FlexDirection.COLUMN ||
mainAxisHorizontal && newDirection == FlexDirection.COLUMN_REVERSE) ||
(mainAxisVertical && newDirection == FlexDirection.ROW ||
mainAxisVertical && newDirection == FlexDirection.ROW_REVERSE);
}
private void updateLayoutStateToFillEnd(AnchorInfo anchorInfo) {
mLayoutState.mAvailable = mOrientationHelper.getEndAfterPadding() - anchorInfo.mCoordinate;
mLayoutState.mPosition = anchorInfo.mPosition;
......@@ -1179,9 +1189,12 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements
// Loop through the views in the same line of the last visible view because the
// next view should be placed to the end of the flex line to which the last visible view
// belongs
for (int i = getChildCount() - 2, to = getChildCount() - lastVisibleLine.mItemCount;
for (int i = getChildCount() - 2, to = getChildCount() - lastVisibleLine.mItemCount - 1;
i > to; i--) {
View viewInSameLine = getChildAt(i);
if (viewInSameLine == null || viewInSameLine.getVisibility() == View.GONE) {
continue;
}
if (mIsRtl && mainAxisHorizontal) {
// The end edge of the view is left, should be the minimum left edge
// where the next view should be placed
......@@ -1225,6 +1238,9 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements
widthMeasureSpec, heightMeasureSpec, needsToFill,
mLayoutState.mPosition, mFlexLines);
}
mFlexboxHelper.determineMainSize(widthMeasureSpec, heightMeasureSpec,
mLayoutState.mPosition);
mFlexboxHelper.stretchViews(mLayoutState.mPosition);
}
}
} else {
......@@ -1531,8 +1547,8 @@ public class FlexboxLayoutManager extends RecyclerView.LayoutManager implements
@Override
public void setOrder(int order) {
Log.w(TAG, "Setting the order in the "
+ "FlexboxLayoutManager is not supported(ignored). Use FlexboxLayout "
throw new UnsupportedOperationException("Setting the order in the "
+ "FlexboxLayoutManager is not supported. Use FlexboxLayout "
+ "if you need to reorder using the attribute.");
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册