1 /* 2 * Copyright (C) 2016 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 17 package com.android.internal.widget; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertTrue; 22 23 import android.content.Context; 24 import android.view.LayoutInflater; 25 import android.view.View.MeasureSpec; 26 27 import androidx.test.InstrumentationRegistry; 28 import androidx.test.filters.SmallTest; 29 30 import com.android.frameworks.coretests.R; 31 32 import org.junit.Before; 33 import org.junit.Test; 34 35 import java.lang.reflect.Field; 36 37 @SmallTest 38 public class MessagingLinearLayoutTest { 39 40 public static final int WIDTH_SPEC = MeasureSpec.makeMeasureSpec(500, MeasureSpec.EXACTLY); 41 public static final int HEIGHT_SPEC = MeasureSpec.makeMeasureSpec(400, MeasureSpec.AT_MOST); 42 private Context mContext; 43 private MessagingLinearLayout mView; 44 45 @Before setup()46 public void setup() { 47 mContext = InstrumentationRegistry.getTargetContext(); 48 // spacing: 5px 49 mView = (MessagingLinearLayout) LayoutInflater.from(mContext).inflate( 50 R.layout.messaging_linear_layout_test, null); 51 } 52 53 @Test testSingleChild()54 public void testSingleChild() { 55 FakeImageFloatingTextView child = fakeChild(3); 56 57 mView.addView(child); 58 59 mView.measure(WIDTH_SPEC, HEIGHT_SPEC); 60 mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight()); 61 62 assertFalse(child.isHidden()); 63 assertEquals(150, mView.getMeasuredHeight()); 64 } 65 66 @Test testLargeSmall()67 public void testLargeSmall() { 68 FakeImageFloatingTextView child1 = fakeChild(3); 69 FakeImageFloatingTextView child2 = fakeChild(1); 70 71 mView.addView(child1); 72 mView.addView(child2); 73 74 mView.measure(WIDTH_SPEC, HEIGHT_SPEC); 75 mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight()); 76 77 assertFalse("child1 should not be hidden", child1.isHidden()); 78 assertFalse("child2 should not be hidden", child2.isHidden()); 79 assertEquals(205, mView.getMeasuredHeight()); 80 } 81 82 @Test testSmallSmall()83 public void testSmallSmall() { 84 FakeImageFloatingTextView child1 = fakeChild(1); 85 FakeImageFloatingTextView child2 = fakeChild(1); 86 87 mView.addView(child1); 88 mView.addView(child2); 89 90 mView.measure(WIDTH_SPEC, HEIGHT_SPEC); 91 mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight()); 92 93 assertFalse("child1 should not be hidden", child1.isHidden()); 94 assertFalse("child2 should not be hidden", child2.isHidden()); 95 assertEquals(105, mView.getMeasuredHeight()); 96 } 97 98 @Test testLargeLarge()99 public void testLargeLarge() { 100 FakeImageFloatingTextView child1 = fakeChild(7); 101 FakeImageFloatingTextView child2 = fakeChild(7); 102 103 mView.addView(child1); 104 mView.addView(child2); 105 106 mView.measure(WIDTH_SPEC, HEIGHT_SPEC); 107 mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight()); 108 109 assertTrue("child1 should be hidden", child1.isHidden()); 110 assertFalse("child2 should not be hidden", child2.isHidden()); 111 assertEquals(350, mView.getMeasuredHeight()); 112 } 113 114 @Test testLargeSmall_largeWrapsWith3indentbutNotFullHeight_andHitsMax()115 public void testLargeSmall_largeWrapsWith3indentbutNotFullHeight_andHitsMax() { 116 FakeImageFloatingTextView child1 = fakeChild(7); 117 FakeImageFloatingTextView child2 = fakeChild(1); 118 119 mView.addView(child1); 120 mView.addView(child2); 121 122 mView.measure(WIDTH_SPEC, HEIGHT_SPEC); 123 mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight()); 124 125 assertFalse("child1 should not be hidden", child1.isHidden()); 126 assertFalse("child2 should not be hidden", child2.isHidden()); 127 assertEquals(355, mView.getMeasuredHeight());; 128 } 129 130 private class FakeImageFloatingTextView extends MessagingTextMessage { 131 132 public static final int LINE_HEIGHT = 50; 133 private final int mNumLines; 134 FakeImageFloatingTextView(Context context, int linesForIndent)135 public FakeImageFloatingTextView(Context context, 136 int linesForIndent) { 137 super(context, null, 0, 0); 138 mNumLines = linesForIndent; 139 } 140 141 @Override getLayoutHeight()142 public int getLayoutHeight() { 143 return Math.max(LINE_HEIGHT, getMeasuredHeight()); 144 } 145 146 @Override onMeasure(int widthMeasureSpec, int heightMeasureSpec)147 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 148 setMeasuredDimension( 149 getDefaultSize(500, widthMeasureSpec), 150 clampToMultiplesOfLineHeight(resolveSize(getDesiredHeight(), 151 heightMeasureSpec))); 152 } 153 getMeasuredType()154 public int getMeasuredType() { 155 boolean measuredTooSmall = getMeasuredHeight() 156 < getLayoutHeight() + getPaddingTop() + getPaddingBottom(); 157 if (measuredTooSmall) { 158 return MEASURED_TOO_SMALL; 159 } else { 160 if (getMeasuredHeight() == getDesiredHeight()) { 161 return MEASURED_NORMAL; 162 } else { 163 return MEASURED_SHORTENED; 164 } 165 } 166 } 167 168 private int clampToMultiplesOfLineHeight(int size) { 169 if (size <= LINE_HEIGHT) { 170 return size; 171 } 172 return (size / LINE_HEIGHT) * LINE_HEIGHT; 173 } 174 175 @Override 176 public int getLineCount() { 177 return mNumLines; 178 } 179 180 public int getDesiredHeight() { 181 return LINE_HEIGHT * getLineCount(); 182 } 183 184 @Override 185 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 186 // swallow 187 } 188 189 public boolean isHidden() { 190 MessagingLinearLayout.LayoutParams lp = 191 (MessagingLinearLayout.LayoutParams) getLayoutParams(); 192 try { 193 Field hide = MessagingLinearLayout.LayoutParams.class.getDeclaredField("hide"); 194 hide.setAccessible(true); 195 return hide.getBoolean(lp); 196 } catch (ReflectiveOperationException e) { 197 throw new RuntimeException(e); 198 } 199 } 200 } 201 202 private FakeImageFloatingTextView fakeChild(int numLines) { 203 return new FakeImageFloatingTextView(mContext, numLines); 204 } 205 } 206