ImageView dans LinearLayout dans Scrollview avec CardStackView et Picasso L'image ne s'affiche pas
Je développe une application Android.
J'utilise "com.yuyakaido.android:card-stack-view:2.3.4" pour la bibliothèque de piles de cartes.
ImageView est dans LinearLayout dans ScrollView dans CardView.
Ce que je veux faire, c'est adapter l'image à la taille de la carte selon l'image ci-dessous lorsque la carte est chargée au début.
Et si vous faites défiler vers le bas, il affichera des textes selon l'image ci-dessous
J'utilise Picasso pour adapter l'image à ImageView mais l'image ne s'affiche pas.
C'est le fragment qui a le CardStackView
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_card_stack, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initCardStackView()
}
private fun initCardStackView() {
manager = CardStackLayoutManager(context)
manager.setCanScrollVertical(false)
manager.setSwipeableMethod(SwipeableMethod.Manual)
adapter = CardStackAdapter(context, createDummyProfiles())
cardStackView.layoutManager = manager
cardStackView.adapter = adapter
cardStackView.itemAnimator = DefaultItemAnimator()
}
Ceci est la mise en page Fragment
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.yuyakaido.android.cardstackview.CardStackView
android:id="@+id/cardStackView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="80dp"
android:clipToPadding="false"/>
</LinearLayout>
Ceci est le CardStackAdapter, ici je recadre et ajuste l'image à ImageView avec Piccaso
class CardStackAdapter(private var context: Context?, private var movies: MutableList<Movies>) :
RecyclerView.Adapter<CardStackAdapter.ViewHolder>() {
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(parent.context)
return ViewHolder(inflater.inflate(R.layout.card_view, parent, false))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
Picasso.get().load(R.drawable.person3).fit().centerCrop().into(holder.itemView.imageView)
}
override fun getItemCount(): Int {
return movies.size
}
fun setItems(items: MutableList<Profile>) {
this.movies = items
}
}
C'est le card_view qui est la mise en page pour viewHolder de CardStackAdapter
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/cardView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"
android:foreground="?attr/selectableItemBackground"
app:cardBackgroundColor="@android:color/white"
app:cardCornerRadius="18dp"
app:cardPreventCornerOverlap="false"
app:cardUseCompatPadding="true">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/lipsum"/>
</LinearLayout>
</ScrollView>
</androidx.cardview.widget.CardView>
Lorsque je lance l'application, j'obtiens la carte sans l'image mais uniquement des textes comme sur l'image ci-dessous
Comment puis-je afficher l'image au format de la carte lorsque la carte est chargée?
------------------------- METTRE À JOUR ------------------------ ----
** REMARQUE: l'image sera récupérée à partir du serveur non dessinable localement. Je viens d'utiliser les images dans un dessin local à des fins de test.
Je ne sais pas pourquoi l'image ne s'affiche pas. Mais si je règle la hauteur et la largeur de layoutParams de imageView selon le code ci-dessous, l'image apparaît.
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.itemView.imageView.layoutParams.height = 1918
holder.itemView.imageView.layoutParams.width = 970
Picasso.get().load(R.drawable.person3).fit().centerCrop().into(holder.itemView.imageView)
}
Donc, maintenant, la question est de savoir si je peux définir la hauteur et la largeur de ImageView égales à la hauteur et à la largeur de ScrollView( imageViewle parent du parent du parent) ou CardView( imageViewle parent du parent du parent) PAS LinearLayout (parent) car la hauteur de LinearLayout doit être "wrap_content".
------------------------- METTRE À JOUR ------------------------ ----
Il semble que votre solution soit basée sur la hauteur et la largeur de l'image, mais je dois adapter l'image dans CardView ou ScrollView
voici mon code onBindViewHolder. Je viens de supprimer Picasso.
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.itemView.imageView.setImageResource(R.drawable.person2)
}
Voici ma disposition CardView
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/cardView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"
android:foreground="?attr/selectableItemBackground"
app:cardCornerRadius="18dp"
app:cardPreventCornerOverlap="false"
app:cardUseCompatPadding="true">
<androidx.core.widget.NestedScrollView
android:fillViewport="true"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/imageView"
android:src="@drawable/person2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="centerCrop"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/lipsum"/>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.cardview.widget.CardView>
C'est ce que j'ai sur mon AVD. L'image ne remplit pas le bas de CardView car elle est mise à l'échelle en fonction de sa hauteur et de sa largeur?
Réponses
Ce que je comprends de votre question mise à jour, vous devez remplir la ImageViewhauteur CardViewmaximale et le textViewsera visible après le défilement. Cela semble difficile à ScrollViewutiliser car nous devons d'une manière ou d'une autre définir la hauteur de manière dynamique match_parentne fonctionnera pas ScrollView.
J'ai fait une solution ci-dessous pour voir si cet entraînement pour vous. Créez une vue d'image personnalisée et utilisez-la à l'intérieur CardView.
class FillImageView : AppCompatImageView {
constructor(context: Context?) : super(context!!) {}
constructor(context: Context?, attrs: AttributeSet?) : super(context!!, attrs) {}
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context!!, attrs, defStyleAttr) {}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
val parentWidth = MeasureSpec.getSize(widthMeasureSpec)
setMeasuredDimension(parentWidth, (parent.parent as View).measuredHeight)
}
}
Et ajoutez ce qui NestedScrolllViewsuit à l'intérieur de CardView
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:fillViewport="true"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<com.ace.myapplication.FillImageView
android:layout_width="match_parent"
android:src="@drawable/hello"
android:adjustViewBounds="true"
android:layout_height="match_parent"
android:scaleType="centerCrop"/>
<TextView
android:layout_width="match_parent"
android:textSize="23sp"
android:padding="10dp"
android:layout_height="wrap_content"/>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
PS - Cela pourrait être une solution moche avec le réglage de la hauteur avec, (parent.parent as View).measuredHeightmais c'est tout ce que je peux faire pour le moment. J'adore voir une solution élégante pour cela. Je ne l'ai pas testé avec CardStackView.
Mettre à jour Maintenant, RecyclerViewle problème est l'élément dessiné après la définition de l'adaptateur et nous devons écouter le layoutManagerrappel de l'élément dessiné depuis. Une façon d'aborder ce problème sans le compliquer Réglez la cadStackViewhauteur de l'imageView. Voir le code ci-dessous en ajoutant uniquement le code essentiel.
class CardStackAdapter(val stackViewHeight:Int, private var movies: MutableList<Moview>) :
RecyclerView.Adapter<CardStackAdapter.ViewHolder>() {
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val imageView:ImageView = itemView.findViewById(R.id.imageView)
init {
imageView.layoutParams.height= stackViewHeight
}
}
}
Maintenant dans ton fragment
cardStackView.post {
initCardStackView()
}
Et modifiez la création du dapter à l'intérieur initCardStackViewcomme suit. De plus, vous n'avez pas besoin de transmettre le contexte à l'adaptateur, chaque vue est associée à un contexte. N'utilisez pas non plus FillImageViewdans ce cas une utilisation normale ImageViewdans une mise en page XML.
// Since you are using android:padding it will be same for all sides
val cardHeight=cardStackView.height- (2*cardStackView.paddingTop)
val adapter = CardStackAdapter(cardHeight, createDummyProfiles())
Pourquoi utilisez-vous Picasso pour charger un dessin local? Vous pouvez simplement appliquer votre dessin source à ImageView.
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:scaleType="fitCenter"
android:src="@drawable/person3"
android:layout_height="wrap_content" />
En plus de cela, je vous conseille fortement d'utiliser à la NestedScrollViewplace de ScrollViewpuis, s'il vous plaît, définissez fillViewPort(l'attribut ScrollView) sur true pour étendre sa hauteur égale à la hauteur de l'enfant
Mettre à jour:
Si vous souhaitez vraiment utiliser Picasso pour charger une URL externe, veuillez effectuer la configuration suivante:
Picasso
.get()
.load([url_you_want_to_load])
.placeholder([placeholder_you_want_to_pre_load])
.into(imageView)
puis, configurez votre ImageView pour l'ajuster au centre et préserver son rapport hauteur / largeur:
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="centerCrop" />