Repetir até encaixar
Recentemente me deparei com uma situação onde o layout proposto era uma imagem que se repetia por várias vezes em uma linha horizontal
Comecei a pensar em como fazer essa tela, o meu primeiro teste foi usando o atributo android:tileMode=”repeat” dentro de um drawable bitmap, o resultado final não me agradou, mas senti que eu estava chegado lá e com pouco código!
Perceba que o último triângulo ficou cortado no final, isso acontece pois o tileMode não da "resize" do elemento que será repetido.
Bom, acabei tendo que pensar um pouco mais, dai fiz umas continhas e cheguei em algumas premissas.
- Os triângulos devem ser repetidos até preencher o layout pai (no caso esse retângulo vermelho), vamos assumir parentLayoutWidth.
- A imagem do triângulo tem um comprimento X, esse X depende do tamanho da imagem que for repetida, vamos assumir triangleWidth.
- Logo eu tenho que saber quantos triangleWidth cabem dentro de parentLayoutWidth.
Seguindo essas premissas cheguei no seguinte código:
int parentLayoutWidth, triangleWidth;
parentLayoutWidth = linearLayout.getWidth();
triangleWidth = imageView.getWidth();
int qtdTriangle = (int) Math.round((double) parentLayoutWidth / (double) triangleWidth);int newTriangleWidth = parentLayoutWidth / qtdTriangle;
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(newTriangleWidth, imageView.getHeight());
int trianglesSumWidth = newTriangleWidth * qtdTriangle;
int diff = parentLayoutWidth - trianglesSumWidth;
Temos então 6 variáveis
- parentLayoutWidth: Comprimento do layout pai.
- triangleWidth: Comprimento do triângulo.
- qtdTriangle: Aqui já sabemos quantos triângulos vão caber.
- newTriangleWidth: Este será o novo comprimento do triângulo, calculado pela divisão do parentLayoutWidth / qtdTriangle.
- trianglesSumWidth: Soma do comprimento total com todos os triângulos.
- diff: Como utilizamos valores inteiros arredondados, vai acabar dando uma diferença entre o valor de trianglesSumWidth e parentLayoutWidth, essa diferença eu guardo para aplicar entre os triângulos repetidos. Aqui é onde fica o pulo do gato do "resize".
Explicada a teoria, vamos a prática ver o que resulta toda essa parada:
Teremos então 18 triângulos completos, porém o diff deu 16 pixels, e agora?
Esse diff é o que causa o corte no final da repetição, sabendo disso eu vou pegar esse diff e distribuir entre os triângulos, como vai ser coisa de apenas 1 pixel a mais no comprimento do triângulo, o resultado final nem parece que existe essa diferença entre eles.
Por fim temos que fazer um loop que vai adicionar em tempo de execução esses triângulos, chegando aqui fica fácil:
for (int i = 0; i < qtdTriangle; i++) {
ImageView ivTriangle = new ImageView(getApplicationContext());
ivTriangle.setImageResource(R.drawable.triangle_1);
ivTriangle.setLayoutParams(layoutParams);
int plusPixel = diff > 0 ? 1 : 0;
LinearLayout.LayoutParams triangleLayoutParams = new LinearLayout.LayoutParams(newTriangleWidth + plusPixel, imageView.getHeight());
ivTriangle.setScaleType(ImageView.ScaleType.FIT_XY);
ivTriangle.setColorFilter(plusPixel == 1 ? Color.GREEN : Color.WHITE);
ivTriangle.setLayoutParams(triangleLayoutParams);
linearLayout.addView(ivTriangle);
diff--;
}
Repare que no laço da quantidade de triângulos eu vou decrementando o valor de diff, dai quando chegar a zero nenhum pixel será somado no comprimento do triângulo respectivo.
Beleza, e como ficou esse POC? Veja só.
- O triângulo solitário no topo eu uso ele como "view de referência", pois quando ele inflar no layout já terei todas as medidas deste ImageView para a densidade do dispositivo.
- A segunda linha horizontal com os triângulos brancos é o resultado usando tileMode="repeat"
- Por último e não menos importante, a terceira linha já é usando o código de repetição de views maroto. Os triângulos verdes são os que tiveram 1 pixel adicionado em seu comprimento, já os brancos continuam como vieram ao mundo.
Bacana? O final dessa novela toda ficou um layout muito, muito parecido como que me foi proposto, coloquei até uma sombrinha com gradient para ficar mais legal ainda.