J'ai un ImageView
qui affiche un png qui a un rapport hauteur / largeur plus grand que celui de l'appareil (verticalement, ce qui signifie qu'il est plus long). Je veux l'afficher tout en conservant le rapport hauteur / largeur, en faisant correspondre la largeur du parent et en épinglant la vue d'image en haut de l'écran.
Le problème que j'ai avec l'utilisation CENTER_CROP
comme type d'échelle est qu'il va (compréhensible) centrer l'image mise à l'échelle au lieu d'aligner le bord supérieur sur le bord supérieur de la vue de l'image.
Le problème avec FIT_START
est que l'image s'adaptera à la hauteur de l'écran et ne remplira pas la largeur.
J'ai résolu ce problème en utilisant un ImageView personnalisé onDraw(Canvas)
et en le remplaçant et en le gérant manuellement à l'aide du canevas; le problème avec cette approche est que 1) je crains qu'il n'y ait une solution plus simple, 2) j'obtiens une exception VM mem lors de l'appel super(AttributeSet)
du constructeur en essayant de définir une img src de 330kb lorsque le tas a 3 mb libres (avec une taille de tas de 6 Mo) et je ne peux pas comprendre pourquoi.
Toutes les idées / suggestions / solutions sont les bienvenues :)
Merci
ps je pensais qu'une solution pourrait être d'utiliser un type d'échelle matricielle et de le faire moi-même, mais cela semble être le même ou plus de travail que ma solution actuelle!
Réponses:
Ok, j'ai une solution de travail. L'invite de Darko m'a fait revoir la classe ImageView (merci) et j'ai appliqué la transformation à l'aide d'une matrice (comme je le soupçonnais à l'origine, mais je n'ai pas réussi à ma première tentative!). Dans ma classe imageView personnalisée, j'appelle
setScaleType(ScaleType.MATRIX)
aprèssuper()
dans le constructeur et j'ai la méthode suivante.J'ai placé int dans la
setFrame()
méthode comme dans ImageView, l'appel àconfigureBounds()
est dans cette méthode, qui est l'endroit où se déroule toute la mise à l'échelle et la matrice, cela me semble donc logique (disons si vous n'êtes pas d'accord)Vous trouverez ci-dessous la méthode super.setFrame () d'AOSP
Trouvez la classe complète src ici
la source
voici mon code pour le centrer en bas. Btw. dans Dori's Code, il y a un petit bogue: puisque le
super.frame()
est appelé à la toute fin, lagetWidth()
méthode peut renvoyer une valeur incorrecte. Si vous voulez le centrer en haut, supprimez simplement la ligne postTranslate et vous avez terminé. La bonne chose est qu'avec ce code, vous pouvez le déplacer où vous le souhaitez. (droite, centre => pas de problème;)la source
(r-l)
place?if((frameWidth > originalImageWidth) || (frameHeight > originalImageHeight))
devrait sûrement être inversée? En d'autres termes, ne devriez-vous pas tester si l'image est plus grande que le cadre? Je suggère de le remplacer parif((originalImageWidth > frameWidth ) || (originalImageHeight > frameHeight ))
((View) getParent()).getWidth()
depuis leImageView
hasMATCH_PARENT
Vous n'avez pas besoin d'écrire une vue d'image personnalisée pour obtenir la
TOP_CROP
fonctionnalité. Vous avez juste besoin de modifier lematrix
duImageView
.Définissez le
scaleType
surmatrix
pourImageView
:Définissez une matrice personnalisée pour
ImageView
:Cela vous donnera la
TOP_CROP
fonctionnalité.la source
scaleType
encenterCrop
sinon je verrai un espace vide sur les bords.Cet exemple fonctionne avec des images chargées après la création de l'objet + une certaine optimisation. J'ai ajouté quelques commentaires dans le code qui expliquent ce qui se passe.
N'oubliez pas d'appeler:
ou
Source Java:
la source
Basé sur Dori, j'utilise une solution qui redimensionne l'image en fonction de la largeur ou de la hauteur de l'image pour toujours remplir le conteneur environnant. Cela permet de mettre à l'échelle une image pour remplir tout l'espace disponible en utilisant le point supérieur gauche de l'image plutôt que le centre comme origine (CENTER_CROP):
J'espère que cela aide - fonctionne comme un régal dans mon projet.
la source
Aucune de ces solutions n'a fonctionné pour moi, car je voulais une classe qui supporte un recadrage arbitraire dans la direction horizontale ou verticale, et je voulais qu'elle me permette de modifier le recadrage de manière dynamique. J'avais également besoin de la compatibilité Picasso , et Picasso définit paresseusement les dessinables d'image.
Mon implémentation est adaptée directement depuis ImageView.java dans l'AOSP. Pour l'utiliser, déclarez comme ceci en XML:
Depuis la source, si vous souhaitez avoir un top crop, appelez:
Si vous souhaitez avoir une récolte inférieure, appelez:
Si vous souhaitez avoir un recadrage 1/3 de la descente, appelez:
De plus, si vous choisissez d'utiliser une autre méthode de recadrage, comme fit_center, vous pouvez le faire et aucune de cette logique personnalisée ne sera déclenchée. (D'autres implémentations vous permettent UNIQUEMENT d'utiliser leurs méthodes de recadrage).
Enfin, j'ai ajouté une méthode, redraw (), donc si vous choisissez de changer votre méthode de recadrage / scaleType dynamiquement dans le code, vous pouvez forcer la vue à se redessiner. Par exemple:
Pour revenir à votre recadrage personnalisé en haut au centre du tiers, appelez:
Voici la classe:
la source
Peut-être aller dans le code source de la vue image sur Android et voir comment il dessine le recadrage central etc. et peut-être copier une partie de ce code dans vos méthodes. Je ne sais pas vraiment pour une meilleure solution que de faire cela. J'ai de l'expérience en redimensionnant et en recadrant manuellement le bitmap (recherche de transformations bitmap), ce qui réduit sa taille réelle, mais cela crée toujours un peu de surcharge dans le processus.
la source
}
la source
onLayout
me sauve beaucoup! Merci! J'ai rencontré un problème où il calcule la matrice mais n'affiche pas l'image immédiatement et l'ajoutonLayout
du code résout mon problème.Si vous utilisez Fresco (SimpleDraweeView), vous pouvez facilement le faire avec:
Celui-ci serait pour une récolte supérieure.
Plus d'informations sur le lien de référence
la source
Il y a 2 problèmes avec les solutions ici:
Cette petite modification résout le problème (placez le code dans onDraw et vérifiez les facteurs d'échelle de largeur et de hauteur):
la source
Solution la plus simple: découper l'image
la source