1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.support.v7.widget; 18 19import org.junit.After; 20import org.junit.Before; 21import org.junit.Test; 22import org.junit.runner.RunWith; 23import org.junit.runners.Parameterized; 24 25import android.support.test.InstrumentationRegistry; 26import android.test.suitebuilder.annotation.MediumTest; 27import android.view.View; 28 29import java.util.ArrayList; 30import java.util.List; 31 32import static android.support.v7.widget.LinearLayoutManager.HORIZONTAL; 33import static org.junit.Assert.*; 34 35@RunWith(Parameterized.class) 36public class LinearLayoutManagerPrepareForDropTest extends BaseLinearLayoutManagerTest { 37 38 final BaseLinearLayoutManagerTest.Config mConfig; 39 final SelectTargetChildren mSelectTargetChildren; 40 41 public LinearLayoutManagerPrepareForDropTest( 42 Config config, SelectTargetChildren selectTargetChildren) { 43 mConfig = config; 44 mSelectTargetChildren = selectTargetChildren; 45 } 46 47 @Parameterized.Parameters(name = "{0}_{1}") 48 public static Iterable<Object[]> params() { 49 SelectTargetChildren[] selectors 50 = new SelectTargetChildren[]{ 51 new SelectTargetChildren() { 52 @Override 53 public int[] selectTargetChildren(int childCount) { 54 return new int[]{1, 0}; 55 } 56 }, 57 new SelectTargetChildren() { 58 @Override 59 public int[] selectTargetChildren(int childCount) { 60 return new int[]{0, 1}; 61 } 62 }, 63 new SelectTargetChildren() { 64 @Override 65 public int[] selectTargetChildren(int childCount) { 66 return new int[]{childCount - 1, childCount - 2}; 67 } 68 }, 69 new SelectTargetChildren() { 70 @Override 71 public int[] selectTargetChildren(int childCount) { 72 return new int[]{childCount - 2, childCount - 1}; 73 } 74 }, 75 new SelectTargetChildren() { 76 @Override 77 public int[] selectTargetChildren(int childCount) { 78 return new int[]{childCount / 2, childCount / 2 + 1}; 79 } 80 }, 81 new SelectTargetChildren() { 82 @Override 83 public int[] selectTargetChildren(int childCount) { 84 return new int[]{childCount / 2 + 1, childCount / 2}; 85 } 86 } 87 }; 88 List<Object[]> variations = new ArrayList<>(); 89 for (SelectTargetChildren selector : selectors) { 90 for (BaseLinearLayoutManagerTest.Config config : createBaseVariations()) { 91 variations.add(new Object[]{config, selector}); 92 } 93 } 94 return variations; 95 } 96 97 @Test 98 @MediumTest 99 public void prepareForDropTest() 100 throws Throwable { 101 final Config config = (Config) mConfig.clone(); 102 config.mTestAdapter = new BaseRecyclerViewInstrumentationTest.TestAdapter(100) { 103 @Override 104 public void onBindViewHolder(BaseRecyclerViewInstrumentationTest.TestViewHolder holder, 105 int position) { 106 super.onBindViewHolder(holder, position); 107 if (config.mOrientation == HORIZONTAL) { 108 final int base = mLayoutManager.getWidth() / 5; 109 final int itemRand = holder.mBoundItem.mText.hashCode() % base; 110 holder.itemView.setMinimumWidth(base + itemRand); 111 } else { 112 final int base = mLayoutManager.getHeight() / 5; 113 final int itemRand = holder.mBoundItem.mText.hashCode() % base; 114 holder.itemView.setMinimumHeight(base + itemRand); 115 } 116 } 117 }; 118 setupByConfig(config, true); 119 mLayoutManager.expectLayouts(1); 120 scrollToPosition(mTestAdapter.getItemCount() / 2); 121 mLayoutManager.waitForLayout(1); 122 int[] positions = mSelectTargetChildren.selectTargetChildren(mRecyclerView.getChildCount()); 123 final View fromChild = mLayoutManager.getChildAt(positions[0]); 124 final int fromPos = mLayoutManager.getPosition(fromChild); 125 final View onChild = mLayoutManager.getChildAt(positions[1]); 126 final int toPos = mLayoutManager.getPosition(onChild); 127 final OrientationHelper helper = mLayoutManager.mOrientationHelper; 128 final int dragCoordinate; 129 final boolean towardsHead = toPos < fromPos; 130 final int referenceLine; 131 if (config.mReverseLayout == towardsHead) { 132 referenceLine = helper.getDecoratedEnd(onChild); 133 dragCoordinate = referenceLine + 3 - 134 helper.getDecoratedMeasurement(fromChild); 135 } else { 136 referenceLine = helper.getDecoratedStart(onChild); 137 dragCoordinate = referenceLine - 3; 138 } 139 mLayoutManager.expectLayouts(2); 140 141 final int x, y; 142 if (config.mOrientation == HORIZONTAL) { 143 x = dragCoordinate; 144 y = fromChild.getTop(); 145 } else { 146 y = dragCoordinate; 147 x = fromChild.getLeft(); 148 } 149 runTestOnUiThread(new Runnable() { 150 @Override 151 public void run() { 152 mTestAdapter.moveInUIThread(fromPos, toPos); 153 mTestAdapter.notifyItemMoved(fromPos, toPos); 154 mLayoutManager.prepareForDrop(fromChild, onChild, x, y); 155 } 156 }); 157 mLayoutManager.waitForLayout(2); 158 159 assertSame(fromChild, mRecyclerView.findViewHolderForAdapterPosition(toPos).itemView); 160 // make sure it has the position we wanted 161 if (config.mReverseLayout == towardsHead) { 162 assertEquals(referenceLine, helper.getDecoratedEnd(fromChild)); 163 } else { 164 assertEquals(referenceLine, helper.getDecoratedStart(fromChild)); 165 } 166 } 167 168 protected interface SelectTargetChildren { 169 170 int[] selectTargetChildren(int childCount); 171 } 172} 173