Je conçois une vue avec plusieurs pages. Je veux que les bords des pages précédentes et suivantes soient affichés comme ci-dessous et que je mette en œuvre un balayage à deux doigts pour passer d’une page à l’autre.
J'ai essayé d'utiliser ViewPager
avec une marge de page négative comme suggéré ici mais cela ne montre qu'un des bords de l'écran, pas les deux simultanément.
Sinon, est-il possible de positionner une partie de ma vue en dehors de l'écran, puis de l'animer en lui donnant un effet de type ViewPager
?.
Comment dois-je m'y prendre? Merci !
Je me cite de n article de blog sur ce sujet :
La troisième approche vient de Dave Smith, co-auteur du livre bien connu Android Recipes. Il est allé dans une direction très différente en utilisant un conteneur personnalisé qui désactivait l'écrêtage des enfants pour afficher plusieurs pages à la fois.
Son exemple de code publié montre le tout en action. Son conteneur (
com.example.pagercontainer.PagerContainer
) enveloppe leViewPager
et appellesetClipChildren(false);
sur lui-même. Ainsi, même si leViewPager
est concentré sur une page sélectionnée, les autres pages ayant des coordonnées au-delà deViewPager
sont toujours visibles, tant que ils correspondent à laPagerContainer
. En dimensionnant leViewPager
pour qu'il soit plus petit que lePagerContainer
, leViewPager
peut redimensionner ses pages à cette taille, laissant ainsi la place à d'autres pages.PagerContainer
, cependant, doit aider un peu avec les événements tactiles, carViewPager
ne gérera que les événements de balayage sur ses propres limites visibles, en ignorant toutes les pages visibles des côtés.
J'ai une solution similaire:
Dans la fenêtre de visualisation, définissez un remplissage gauche et droit, par exemple: 20dp. Définissez également la marge de la page sur le viewpager, par exemple. la moitié du remplissage du pager. Et n'oubliez pas de désactiver le remplissage du clip.
tilePager.setPadding(defaultGap, 0, defaultGap, 0);
tilePager.setClipToPadding(false);
tilePager.setPageMargin(halfGap);
Définissez les marges intérieure et gauche pour la vue d'ensemble. Exemple xml (page_item.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"
Android:paddingLeft="20dp"
Android:paddingRight="20dp"/>
<TextView
Android:id="@+id/text1"
Android:text="Large Text"
Android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
Définissez ensuite la marge de page négative pour PageView
égale à 2 * (remplissage de la vue précédente)
int margin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20*2, getResources().getDisplayMetrics());
mViewPager.setPageMargin(-margin);
Optionnel. Définissez un remplissage à gauche pour le premier élément et un remplissage à droite au dernier élément pour masquer les bords vides. Vous pouvez le faire dans la classe de fragments PageAdapter
ou Page
.
Pour afficher un aperçu des pages gauche et droite, définissez les deux valeurs suivantes
viewpager.setClipToPadding(false)
viewpager.setPadding(left,0,right,0)
Si vous avez besoin d'espace entre deux pages dans le viewpager, ajoutez viewpager.setPageMargin (int)
Android ViewPager - Afficher l'aperçu de la page à gauche et à droite
si quelqu'un cherchait toujours une solution, j'avais personnalisé ViewPage afin de l'obtenir sans utiliser de marge négative, trouvez un exemple de projet ici https://github.com/44kksharma/Android-ViewPager-Carousel-UI it devrait fonctionner dans la plupart des cas, mais vous pouvez toujours définir la marge de la page avec mPager.setPageMargin(margin in pixel);
Téléchargez le code source à partir d'ici ( ViewPager avec les limites de page précédente et suivante )
MainActivity.Java
package com.deepshikha.viewpager;
import Android.content.Context;
import Android.content.res.Configuration;
import Android.os.Build;
import Android.support.v4.app.Fragment;
import Android.support.v4.app.FragmentActivity;
import Android.support.v4.app.FragmentManager;
import Android.support.v4.app.FragmentPagerAdapter;
import Android.support.v4.app.FragmentStatePagerAdapter;
import Android.support.v4.view.ViewPager;
import Android.support.v7.app.AppCompatActivity;
import Android.os.Bundle;
import Android.util.DisplayMetrics;
import Android.util.Log;
import Android.util.SparseArray;
import Android.view.ViewGroup;
import Java.util.ArrayList;
import Java.util.List;
public class MainActivity extends FragmentActivity {
ViewPager pager;
MyPageAdapter obj_adapter;
String str_device;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init() {
pager = (ViewPager) findViewById(R.id.viewpager);
differentDensityAndScreenSize(getApplicationContext());
List<Fragment> fragments = getFragments();
pager.setAdapter(obj_adapter);
pager.setClipToPadding(false);
if (str_device.equals("normal-hdpi")){
pager.setPadding(160, 0, 160, 0);
}else if (str_device.equals("normal-mdpi")){
pager.setPadding(160, 0, 160, 0);
}else if (str_device.equals("normal-xhdpi")){
pager.setPadding(160, 0, 160, 0);
}else if (str_device.equals("normal-xxhdpi")){
pager.setPadding(180, 0, 180, 0);
}else if (str_device.equals("normal-xxxhdpi")){
pager.setPadding(180, 0, 180, 0);
}else if (str_device.equals("normal-unknown")){
pager.setPadding(160, 0, 160, 0);
}else {
}
obj_adapter = new MyPageAdapter(getSupportFragmentManager(), fragments);
pager.setPageTransformer(true, new ExpandingViewPagerTransformer());
pager.setAdapter(obj_adapter);
}
class MyPageAdapter extends FragmentPagerAdapter {
private List<Fragment> fragments;
public MyPageAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
}
@Override
public Fragment getItem(int position) {
return this.fragments.get(position);
}
@Override
public int getCount() {
return this.fragments.size();
}
}
private List<Fragment> getFragments() {
List<Fragment> fList = new ArrayList<Fragment>();
fList.add(MyFragment.newInstance("Fragment 1",R.drawable.imags));
fList.add(MyFragment.newInstance("Fragment 2",R.drawable.image1));
fList.add(MyFragment.newInstance("Fragment 3",R.drawable.image2));
fList.add(MyFragment.newInstance("Fragment 4",R.drawable.image3));
fList.add(MyFragment.newInstance("Fragment 5",R.drawable.image4));
return fList;
}
public int differentDensityAndScreenSize(Context context) {
int value = 20;
String str = "";
if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_SMALL) {
switch (context.getResources().getDisplayMetrics().densityDpi) {
case DisplayMetrics.DENSITY_LOW:
str = "small-ldpi";
// Log.e("small 1","small-ldpi");
value = 20;
break;
case DisplayMetrics.DENSITY_MEDIUM:
str = "small-mdpi";
// Log.e("small 1","small-mdpi");
value = 20;
break;
case DisplayMetrics.DENSITY_HIGH:
str = "small-hdpi";
// Log.e("small 1","small-hdpi");
value = 20;
break;
case DisplayMetrics.DENSITY_XHIGH:
str = "small-xhdpi";
// Log.e("small 1","small-xhdpi");
value = 20;
break;
case DisplayMetrics.DENSITY_XXHIGH:
str = "small-xxhdpi";
// Log.e("small 1","small-xxhdpi");
value = 20;
break;
case DisplayMetrics.DENSITY_XXXHIGH:
str = "small-xxxhdpi";
//Log.e("small 1","small-xxxhdpi");
value = 20;
break;
case DisplayMetrics.DENSITY_TV:
str = "small-tvdpi";
// Log.e("small 1","small-tvdpi");
value = 20;
break;
default:
str = "small-unknown";
value = 20;
break;
}
} else if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_NORMAL) {
switch (context.getResources().getDisplayMetrics().densityDpi) {
case DisplayMetrics.DENSITY_LOW:
str = "normal-ldpi";
// Log.e("normal-ldpi 1","normal-ldpi");
str_device = "normal-ldpi";
value = 82;
break;
case DisplayMetrics.DENSITY_MEDIUM:
// Log.e("normal-mdpi 1","normal-mdpi");
str = "normal-mdpi";
value = 82;
str_device = "normal-mdpi";
break;
case DisplayMetrics.DENSITY_HIGH:
// Log.e("normal-hdpi 1","normal-hdpi");
str = "normal-hdpi";
str_device = "normal-hdpi";
value = 82;
break;
case DisplayMetrics.DENSITY_XHIGH:
//Log.e("normal-xhdpi 1","normal-xhdpi");
str = "normal-xhdpi";
str_device = "normal-xhdpi";
value = 90;
break;
case DisplayMetrics.DENSITY_XXHIGH:
// Log.e("normal-xxhdpi 1","normal-xxhdpi");
str = "normal-xxhdpi";
str_device = "normal-xxhdpi";
value = 96;
break;
case DisplayMetrics.DENSITY_XXXHIGH:
//Log.e("normal-xxxhdpi","normal-xxxhdpi");
str = "normal-xxxhdpi";
str_device = "normal-xxxhdpi";
value = 96;
break;
case DisplayMetrics.DENSITY_TV:
//Log.e("DENSITY_TV 1","normal-mdpi");
str = "normal-tvdpi";
str_device = "normal-tvmdpi";
value = 96;
break;
default:
// Log.e("normal-unknown","normal-unknown");
str = "normal-unknown";
str_device = "normal-unknown";
value = 82;
break;
}
} else if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE) {
switch (context.getResources().getDisplayMetrics().densityDpi) {
case DisplayMetrics.DENSITY_LOW:
str = "large-ldpi";
// Log.e("large-ldpi 1","normal-ldpi");
value = 78;
break;
case DisplayMetrics.DENSITY_MEDIUM:
str = "large-mdpi";
//Log.e("large-ldpi 1","normal-mdpi");
value = 78;
break;
case DisplayMetrics.DENSITY_HIGH:
//Log.e("large-ldpi 1","normal-hdpi");
str = "large-hdpi";
value = 78;
break;
case DisplayMetrics.DENSITY_XHIGH:
// Log.e("large-ldpi 1","normal-xhdpi");
str = "large-xhdpi";
value = 125;
break;
case DisplayMetrics.DENSITY_XXHIGH:
//Log.e("large-ldpi 1","normal-xxhdpi");
str = "large-xxhdpi";
value = 125;
break;
case DisplayMetrics.DENSITY_XXXHIGH:
// Log.e("large-ldpi 1","normal-xxxhdpi");
str = "large-xxxhdpi";
value = 125;
break;
case DisplayMetrics.DENSITY_TV:
//Log.e("large-ldpi 1","normal-tvdpi");
str = "large-tvdpi";
value = 125;
break;
default:
str = "large-unknown";
value = 78;
break;
}
} else if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE) {
switch (context.getResources().getDisplayMetrics().densityDpi) {
case DisplayMetrics.DENSITY_LOW:
// Log.e("large-ldpi 1","normal-ldpi");
str = "xlarge-ldpi";
value = 125;
break;
case DisplayMetrics.DENSITY_MEDIUM:
// Log.e("large-ldpi 1","normal-mdpi");
str = "xlarge-mdpi";
value = 125;
break;
case DisplayMetrics.DENSITY_HIGH:
//Log.e("large-ldpi 1","normal-hdpi");
str = "xlarge-hdpi";
value = 125;
break;
case DisplayMetrics.DENSITY_XHIGH:
// Log.e("large-ldpi 1","normal-hdpi");
str = "xlarge-xhdpi";
value = 125;
break;
case DisplayMetrics.DENSITY_XXHIGH:
// Log.e("large-ldpi 1","normal-xxhdpi");
str = "xlarge-xxhdpi";
value = 125;
break;
case DisplayMetrics.DENSITY_XXXHIGH:
// Log.e("large-ldpi 1","normal-xxxhdpi");
str = "xlarge-xxxhdpi";
value = 125;
break;
case DisplayMetrics.DENSITY_TV:
//Log.e("large-ldpi 1","normal-tvdpi");
str = "xlarge-tvdpi";
value = 125;
break;
default:
str = "xlarge-unknown";
value = 125;
break;
}
}
return value;
}
}
Il y a quelque temps, j'avais besoin de cette fonctionnalité et je préparais une petite bibliothèque qui utilisait RecyclerView
avec PagerSnapHelper (ajouté à la version 25.1.0 de la bibliothèque de support de la v7) au lieu du classique ViewPager
:
MetalRecyclerPagerView - vous pouvez y trouver tout le code ainsi que des exemples.
Il consiste principalement en un seul fichier de classe: MetalRecyclerViewPager.Java (et deux xmls: attrs.xml et ids.xml ).
J'espère que ça aide quelqu'un :)