Eu tenho um ImageView
que está exibindo um png que tem uma proporção de aspecto maior do que a do dispositivo (verticalmente falando - o que significa que é mais longo). Desejo exibir isso mantendo a proporção da imagem, combinando a largura do pai e fixando a visualização da imagem no topo da tela.
O problema que tenho ao usar CENTER_CROP
como tipo de escala é que ele irá (compreensível) centralizar a imagem dimensionada em vez de alinhar a borda superior com a borda superior da visualização da imagem.
O problema FIT_START
é que a imagem se ajusta à altura da tela e não ocupa a largura.
Resolvi esse problema usando um ImageView personalizado e substituindo onDraw(Canvas)
e manipulando isso manualmente usando a tela; o problema com essa abordagem é que 1) Estou preocupado que possa haver uma solução mais simples, 2) Estou recebendo uma exceção VM mem ao chamarsuper(AttributeSet)
o construtor ao tentar definir um src img de 330kb quando o heap tem 3 MB livres (com um tamanho de heap de 6 MB) e não consigo descobrir o porquê.
Quaisquer ideias / sugestões / soluções são bem-vindas :)
obrigado
ps pensei que uma solução pode ser usar um tipo de escala de matriz e fazer eu mesmo, mas isso parece ser o mesmo ou mais trabalho do que minha solução atual!
Respostas:
Ok, eu tenho uma solução de trabalho. O prompt de Darko me fez olhar novamente para a classe ImageView (obrigado) e aplicar a transformação usando uma Matrix (como eu suspeitei originalmente, mas não tive sucesso na minha primeira tentativa!). Na minha classe imageView personalizada, chamo
setScaleType(ScaleType.MATRIX)
aftersuper()
no construtor e tenho o método a seguir.Eu coloquei int no
setFrame()
método como em ImageView a chamada paraconfigureBounds()
está dentro deste método, que é onde todas as coisas de dimensionamento e matriz acontecem, então me parece lógico (digamos, se você discordar)Abaixo está o método super.setFrame () do AOSP
Encontre a classe src completa aqui
fonte
aqui está meu código para centralizá-lo na parte inferior. Btw. no código de Dori há um pequeno bug: como o
super.frame()
é chamado no final, ogetWidth()
método pode retornar o valor errado. Se você quiser centralizá-lo no topo, simplesmente remova a linha postTranslate e pronto. O bom é que, com esse código, você pode movê-lo para onde quiser. (direita, centro => sem problemas;)fonte
(r-l)
?if((frameWidth > originalImageWidth) || (frameHeight > originalImageHeight))
deve ser invertida? Em outras palavras, você não deveria testar se a imagem é maior do que o quadro? Sugiro substituí-lo porif((originalImageWidth > frameWidth ) || (originalImageHeight > frameHeight ))
((View) getParent()).getWidth()
desde oImageView
hasMATCH_PARENT
Você não precisa escrever uma Visualização de imagem personalizada para obter a
TOP_CROP
funcionalidade. Você só precisa modificar omatrix
doImageView
.Defina
scaleType
comomatrix
paraImageView
:Defina uma matriz personalizada para
ImageView
:Isso lhe dará a
TOP_CROP
funcionalidade.fonte
scaleType
para,centerCrop
caso contrário, verei um espaço em branco nas bordas.Este exemplo trabalha com imagens que são carregadas após a criação do objeto + alguma otimização. Eu adicionei alguns comentários no código que explicam o que está acontecendo.
Lembre-se de ligar para:
ou
Fonte Java:
fonte
Com base em Dori, estou usando uma solução que dimensiona a imagem com base na largura ou altura da imagem para sempre preencher o contêiner circundante. Isso permite dimensionar uma imagem para preencher todo o espaço disponível usando o ponto superior esquerdo da imagem em vez do centro como origem (CENTER_CROP):
Espero que isso ajude - funciona como um mimo no meu projeto.
fonte
Nenhuma dessas soluções funcionou para mim, porque eu queria uma classe que suportasse um corte arbitrário na direção horizontal ou vertical e queria que me permitisse alterar o corte dinamicamente. Eu também precisava da compatibilidade do Picasso , e o Picasso define drawables de imagem preguiçosamente.
Minha implementação é adaptada diretamente de ImageView.java no AOSP. Para usá-lo, declare assim em XML:
Da fonte, se você deseja ter um corte superior, chame:
Se você deseja ter um corte inferior, chame:
Se você deseja ter um corte 1/3 do caminho para baixo, ligue:
Além disso, se você optar por usar outro método de corte, como fit_center, poderá fazê-lo e nenhuma lógica personalizada será acionada. (Outras implementações SÓ permitem que você use seus métodos de recorte).
Por último, adicionei um método, redraw (), portanto, se você decidir alterar seu método de corte / scaleType dinamicamente no código, poderá forçar o redesenho da visualização. Por exemplo:
Para voltar ao seu terceiro corte central superior personalizado, chame:
Aqui está a aula:
fonte
Talvez vá para o código-fonte para a visualização da imagem no Android e veja como ele desenha o corte central etc. e talvez copie parte desse código em seus métodos. Eu realmente não sei por uma solução melhor do que fazer isso. Tenho experiência em redimensionar e cortar manualmente o bitmap (pesquisa por transformações de bitmap), o que reduz seu tamanho real, mas ainda cria um pouco de sobrecarga no processo.
fonte
}
fonte
onLayout
me salva muito! Obrigado! Eu encontrei um problema onde ele calcula a matriz, mas não exibe a imagem imediatamente e adicionaronLayout
o código resolve meu problema.Se você estiver usando Fresco (SimpleDraweeView), você pode fazer isso facilmente com:
Este seria para uma safra superior.
Mais informações no link de referência
fonte
Existem 2 problemas com as soluções aqui:
Esta pequena modificação corrige o problema (coloque o código no onDraw e verifique os fatores de escala de largura e altura):
fonte
Solução mais simples: corte a imagem
fonte