Je souhaite créer une activité ou un fragment 'Détails de la photo' dans lequel j'affiche la photo au-dessus et au-dessous de celle-ci. Un visualiseur de pages affiche les commentaires et les préférences de la photo associée (2 onglets) . Afin de rendre l'écran 'Scrollable' afin que je puisse faire défiler les commentaires et les goûts vers le haut/bas et faire glisser gauche/droite, j'ai décidé d'utiliser un RecyclerView avec 2 lignes:
ROW 1: La photo (ImageView).
ROW 2: SlidingTabLayout + ViewPager + FragmentPagerAdapter.
Le code compiler et exécuter, affiche l'image et le slideTabLayout mais pas le ViewPager.
Donc, mes deux questions principales sont:
1-Quel est le problème avec ma mise en œuvre.
2-Existe-t-il une solution alternative ou meilleure pour ce que je veux réaliser?
Remarque: Je ne souhaite pas utiliser un listView avec en-tête. Je souhaite utiliser RecyclerView car il est plus facile d'ajouter des éléments en haut/en bas du réseau.
PhotoDetailsActivity.Java
public class MainActivity extends ActionBarActivity {
RecyclerView recyclerViewPhotoDetails;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.recyclerViewPhotoDetails = (RecyclerView) this.findViewById(R.id.recycler_view_photo_details);
this.recyclerViewPhotoDetails.setLayoutManager(new LinearLayoutManager(this));
this.recyclerViewPhotoDetails.setAdapter(new PhotoDetailsRecyclerAdapter(this.getSupportFragmentManager()));
}
}
PhotosDetailsRecyclerAdapter.Java
public class PhotoDetailsRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int ROW_IMAGE = 0;
private static final int ROW_LIKES_AND_COMMENTS = 1;
private static final int TOTAL_ROWS = 2;
private FragmentManager fragmentManager;
public PhotoDetailsRecyclerAdapter(FragmentManager fragmentManager) {
this.fragmentManager = fragmentManager;
}
@Override
public int getItemViewType(int position) {
if (position == 0) {
return ROW_IMAGE;
} else {
return ROW_LIKES_AND_COMMENTS;
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if(viewType == ROW_IMAGE) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_image, parent, false);
return new ImageViewHolder(view);
} else {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_comments_and_likes, parent, false);
return new CommentsAndLikesViewHolder(view);
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i) {
}
@Override
public int getItemCount() {
return TOTAL_ROWS;
}
public class ImageViewHolder extends RecyclerView.ViewHolder {
public ImageViewHolder(View itemView) {
super(itemView);
}
}
public class CommentsAndLikesViewHolder extends RecyclerView.ViewHolder {
private SlidingTabLayout slidingTabLayout;
private ViewPager viewPager;
public CommentsAndLikesViewHolder(View view) {
super(view);
slidingTabLayout = (SlidingTabLayout) view.findViewById(R.id.sliding_tab_layout_comments_and_likes);
viewPager = (ViewPager) view.findViewById(R.id.view_pager_comments_and_likes);
viewPager.setAdapter(new CommentsAndLikesPagerAdapter(fragmentManager));
slidingTabLayout.setDistributeEvenly(true);
slidingTabLayout.setViewPager(viewPager);
}
}
}
activity_main.xml
<Android.support.v7.widget.RecyclerView
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:id="@+id/recycler_view_photo_details"
Android:scrollbars="vertical"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
/>
layout_image.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:orientation="vertical"
>
<ImageView
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:adjustViewBounds="true"
Android:scaleType="centerCrop"
Android:src="@drawable/img"
/>
</FrameLayout>
layout_comments_and_likes.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:orientation="vertical"
>
<org.bitbucket.androidapp.SlidingTabLayout
Android:id="@+id/sliding_tab_layout_comments_and_likes"
Android:layout_width="match_parent"
Android:layout_height="48dp"
Android:background="@Android:color/darker_gray"
/>
<Android.support.v4.view.ViewPager
Android:id="@+id/view_pager_comments_and_likes"
Android:layout_height="match_parent"
Android:layout_width="match_parent"
Android:background="@Android:color/holo_blue_dark"
/>
</LinearLayout>
CommentairesAndLikesPagerAdapter.Java
public class CommentsAndLikesPagerAdapter extends FragmentPagerAdapter {
private static final int TOTAL_TABS = 2;
private String[] tabs = { "comments", "likes" };
public CommentsAndLikesPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
if(position == 0) {
return new CommentsFragment();
} else {
return new LikesFragment();
}
}
@Override
public CharSequence getPageTitle(int position) {
return tabs[position];
}
@Override
public int getCount() {
return TOTAL_TABS;
}
}
CommentairesFragment.Java
public class CommentsFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_comments, container, false);
RecyclerView recyclerViewComments = (RecyclerView) view.findViewById(R.id.recycler_view_comments);
recyclerViewComments.setLayoutManager(new LinearLayoutManager(this.getActivity()));
recyclerViewComments.setAdapter(new CommentsRecyclerAdapter());
return view;
}
}
fragment_comments.xml
<Android.support.v7.widget.RecyclerView
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:id="@+id/recycler_view_comments"
Android:scrollbars="vertical"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
/>
J'aimeFragment.Java
public class LikesFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_likes, container, false);
RecyclerView recyclerViewLikes = (RecyclerView) view.findViewById(R.id.recycler_view_likes);
recyclerViewLikes.setLayoutManager(new LinearLayoutManager(this.getActivity()));
recyclerViewLikes.setAdapter(new LikesRecyclerAdapter());
return view;
}
}
fragment_likes.xml
<Android.support.v7.widget.RecyclerView
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:id="@+id/recycler_view_likes"
Android:scrollbars="vertical"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
/>
layout_comment.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:orientation="vertical"
Android:layout_width="match_parent"
Android:layout_height="match_parent">
<TextView
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_centerInParent="true"
Android:text="Comment"
/>
</RelativeLayout>
layout_like.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:orientation="vertical"
Android:layout_width="match_parent"
Android:layout_height="match_parent">
<TextView
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_centerInParent="true"
Android:text="Like"
/>
</RelativeLayout>
J'ai rencontré ce problème et résolu ce problème en définissant l'ID de chaque ViewPager:) ViewPager n'autorise pas le partage de l'ID dans le même fragment, même s'il fait partie d'un contexte recyclerview.
pagerHolder.pager.setId(position);
Mettez à jour la hauteur de ViewPager, les éléments de recyclerView ont besoin d'une hauteur spécifique
<Android.support.v4.view.ViewPager
Android:id="@+id/view_pager"
Android:layout_height="300dp"
Android:layout_width="match_parent"
Android:background="@Android:color/holo_blue_dark" />
Vous pouvez regarder ce code et mettre à jour votre code. J'ai utilisé ce code mon projet et travaillé. Vous devez définir ViewPagerAdapter sur viewpager dans la méthode onBinViewHolder. Si cela ne fonctionne pas, je veux aider.
// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
initializeViews("Mustafa", holder, position);
}
private void initializeViews(final String object, final ViewHolder holder, int position) {
holder.textViewCount.setText("5");
holder.imageViewStar.setImageResource(R.drawable.info);
holder.imageViewFavorite.setImageResource(R.drawable.info);
ViewPagerBoundariesAdapter adapter = new ViewPagerBoundariesAdapter(activity, new ArrayList<ViewPagerItem>(), listener);
holder.viewPager.setAdapter(adapter);
holder.viewPager.setClipToPadding(false);
holder.viewPager.setPadding(40, 0, 40, 0);
}
/**
* Created by MustafaS on 10.3.2015.
*/
public class ViewPagerBoundariesAdapter extends PagerAdapter {
private ArrayList<ViewPagerItem> pagerItems;
private LayoutInflater inflater;
private Context context;
private ViewPagerItemClickInterface listener;
public ViewPagerBoundariesAdapter(Context context, ArrayList<ViewPagerItem> pagerItems, ViewPagerItemClickInterface callback) {
super();
this.pagerItems = pagerItems;
this.context = context;
this.listener = callback;
inflater = LayoutInflater.from(context);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
LinearLayout layout = (LinearLayout) inflater.inflate(R.layout.row_viewpager, container, false);
ImageView imageViewCampaign = (ImageView) layout.findViewById(R.id.imageview_campaign);
TextView textViewCampaign = (TextView) layout.findViewById(R.id.textview_campaign);
imageViewCampaign.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.onViewPagerItemClick(1);
}
});
// textViewCampaign.setText("Lorem ipsum dolor sit amet\n" + "aliquam nec nisi in lorem");
imageViewCampaign.setImageDrawable(context.getResources().getDrawable(R.drawable.nusret));
container.addView(layout);
return layout;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
((ViewPager) container).removeView((View) object);
}
@Override
public int getCount() {
return 5;
}
@Override
public boolean isViewFromObject(View view, Object obj) {
return view.equals(obj);
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:orientation="vertical">
<Android.support.v7.widget.RecyclerView
Android:id="@+id/listview_brand"
Android:layout_width="match_parent"
Android:layout_height="match_parent" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:orientation="vertical">
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_marginBottom="8dp"
Android:layout_marginLeft="8dp"
Android:orientation="horizontal">
<ImageView
Android:id="@+id/imageview_favorite"
Android:layout_width="32dp"
Android:layout_height="32dp"
Android:layout_gravity="center" />
<TextView
Android:id="@+id/textview_brand_name"
Android:layout_width="0dp"
Android:layout_height="match_parent"
Android:layout_weight="1"
Android:gravity="center_vertical"
Android:paddingLeft="8dp"
Android:text="Gucci"
Android:textSize="@dimen/standart_text_size" />
<FrameLayout
Android:layout_width="32dp"
Android:layout_height="32dp"
Android:layout_marginRight="8dp">
<ImageView
Android:id="@+id/imageview_star"
Android:layout_width="match_parent"
Android:layout_height="match_parent" />
<TextView
Android:id="@+id/textview_count"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="center"
Android:ellipsize="end"
Android:gravity="center"
Android:singleLine="true"
Android:textSize="@dimen/standart_text_size" />
</FrameLayout>
</LinearLayout>
<Android.support.v4.view.ViewPager
Android:id="@+id/pager"
Android:layout_width="match_parent"
Android:layout_height="@dimen/pager_image_and_text_height" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:orientation="vertical">
<ImageView
Android:id="@+id/imageview_campaign"
Android:layout_width="match_parent"
Android:layout_height="@dimen/parallax_image_height"
Android:layout_marginLeft="4dp"
Android:layout_marginRight="4dp"
Android:adjustViewBounds="true"
Android:scaleType="centerCrop" />
<TextView
Android:id="@+id/textview_campaign"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:paddingLeft="4dp"
Android:paddingRight="4dp"
Android:paddingTop="8dp"
Android:text="Lorem ipsum dolor sit amet
aliquam nec nisi in lorem"
Android:textSize="@dimen/standart_text_size" />
</LinearLayout>
J'ai eu le même problème et j'ai lu toutes les réponses ici. Je vais décrire comment je résous ceci.
Juste un peu de fond, j'ai un viewpager avec des onglets en haut qui affiche 3 fragments lorsque l'application démarre.
À l'intérieur de l'un des fragments se trouve une vue recyclée avec un viewpager comme l'un des éléments de la vue - appelons ce fragment A:
J'appelle cela à l'intérieur du fragment A pour définir l'adaptateur RECYCLERVIEW:
FragmentOuterAdapter fragmentOuterAdapter = new FragmentOuterAdapter(getActivity(), this ); //this here refers to Fragment A - note this as this is IMPORTANT
mRecyclerView.setAdapter(fragmentOuterAdapter);
Dans mon adaptateur RECYCLERVIEW, j'appelle ce qui suit pour créer le viewHolder:
class ViewPagerViewHolder extends RecyclerView.ViewHolder {
ViewPager viewPager;
public ViewPagerViewHolder(View view) {
super(view);
viewPager = (ViewPager) view.findViewById(R.id.viewPager);
}
}
Sous onCreateViewHolder, j'initialise la vue et ai une poignée dessus.
L'important morceau de code vient de onBindViewHolder:
FragmentManager fragmentManager = fragment.getChildFragmentManager();
((ViewPagerViewHolder) holder).viewPager.setAdapter(new SubViewFragmentPagerAdapter(fragmentManager));
L'objet fragment qui a été passé dans FragmentOuterAdapter apparaît ici où j'utilise l'objet pour getChildFragmentManager ().
Étant donné que vous utilisez l'affichage d'un fragment à l'intérieur d'un fragment PAR le viewpager, vous devez utiliser le gestionnaire de fragments enfant à la place du gestionnaire de fragments.
Cela fera fonctionner le viewpager.
Essayez de configurer votre ViewPager pour avoir une hauteur codée en dur plutôt que du contenu intégré ou du parent de correspondance. J'ai eu un problème étrange où mon écran serait vide même si mon ViewPager était rempli.
En tant que deuxième ligne, vous devez utiliser une disposition linéaire et ajouter à l'intérieur le pageur de vue ainsi que le widget tabhost qui affiche les commentaires et aime les fragments.
Vous pouvez utiliser la bibliothèque https://github.com/daimajia/AndroidSwipeLayout trouvée ici pour obtenir le même effet plus simplement.
Je pourrais fournir plus de détails si vous êtes intéressé.
La seule façon qui a fonctionné pour moi est d'utiliser quelque chose de nouveau apparu dans Android Support Library v7: utiliser Horizontal Recyclerview avec PagerSnapHelper pour obtenir des résultats similaires à ceux de ViewPager
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
recyclerview.setLayoutManager(new LinearLayoutManager(context,
LinearLayoutManager.HORIZONTAL,false));
recyclerview.setAdapter(adapter);
SnapHelper snapHelper = new PagerSnapHelper();
snapHelper.attachToRecyclerView(recyclerView);
La réponse donnée par Linh Nguyen l'a corrigée pour moi, bien que mon cas soit légèrement différent de celui de la question initiale.
Dans une activité, j'avais RecyclerView avec des lignes:
ROW1: ViewPager avec X images (layout_height="200dp"
)
ROW2: texte
ROW3: ViewPager avec Y images (layout_height="100dp"
)
...
Comme je réutilisais la même présentation pour ROW1 et ROW3, les deux ViewPagers avaient le même @+id
.
Le ViewPager dans ROW1 a bien fonctionné.
Mais ViewPager dans ROW3 se comportait comme ceci:
onCreateView()
pour la première et les deux pages environnantes/fragments de ViewPager dans ROW3).Mais ensuite, j'ai remarqué que si j'avais 5 images ou plus dans ROW3, je pouvais faire défiler les pages vides et éventuellement voir les pages 3, 4, etc. Une fois que j'ai atteint la fin, revenir aux pages 2 et 1 serait créé correctement (car ils ont été recréés).
Après avoir attribué un identifiant unique à ViewPager dans ROW3, tout a bien fonctionné.