Est-il possible de faire la ListView
horizontalement? J'ai déjà utilisé la vue Galerie, mais l'élément sélectionné se place automatiquement au centre de l'écran. Je ne veux pas l'élément sélectionné au même endroit où j'ai cliqué. Comment puis-je rectifier ce problème? Mon idée était de définir la ListView
avec défilement horizontal. Partagez votre idée?
Selon la documentation Android RecyclerView
est le nouveau moyen d'organiser les éléments dans listview et de les afficher horizontalement
Avantages:
Plus d'informations sur RecyclerView
:
Échantillon:
Il suffit d’ajouter le bloc ci-dessous pour que ListView
passe de la verticale à la verticale
Extrait de code
LinearLayoutManager layoutManager= new LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL, false);
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(layoutManager);
Paul ne prend pas la peine de corriger les bogues de sa bibliothèque ni d’accepter les corrections des utilisateurs. C'est pourquoi je suggère une autre bibliothèque qui a une fonctionnalité similaire:
https://github.com/sephiroth74/HorizontalVariableListView
Mise à jour: le 24 juillet 2013, l'auteur (sephiroth74) a publié une version entièrement réécrite basée sur le code d'Android 4.2.2 ListView. Je dois dire qu'il n'a pas toutes les erreurs que la version précédente avait et fonctionne très bien!
@Paul answer renvoie à une excellente solution, mais le code ne permet pas d'utiliser onClickListeners sur des éléments enfants (les fonctions de rappel ne sont jamais appelées). Je lutte depuis un moment pour trouver une solution et j'ai décidé de publier ici ce que vous devez modifier dans ce code (au cas où quelqu'un en aurait besoin).
Au lieu de remplacer dispatchTouchEvent
, remplacez onTouchEvent
. Utilisez le même code que dispatchTouchEvent
et supprimez la méthode (vous pouvez lire la différence entre les deux ici http://developer.Android.com/guide/topics/ui/ui-events.html#EventHandlers )
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean handled = mGesture.onTouchEvent(event);
return handled;
}
Ajoutez ensuite le code suivant qui décidera de dérober l’événement à l’élément enfant et le transmettra à notre onTouchEvent
, ou le laissera s’occuper de lui.
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch( ev.getActionMasked() ){
case MotionEvent.ACTION_DOWN:
mInitialX = ev.getX();
mInitialY = ev.getY();
return false;
case MotionEvent.ACTION_MOVE:
float deltaX = Math.abs(ev.getX() - mInitialX);
float deltaY = Math.abs(ev.getY() - mInitialY);
return ( deltaX > 5 || deltaY > 5 );
default:
return super.onInterceptTouchEvent(ev);
}
}
Enfin, n'oubliez pas de déclarer les variables dans votre classe:
private float mInitialX;
private float mInitialY;
Depuis que Google a lancé Android Support Library v7 21.0.0, vous pouvez utiliser RecyclerView pour faire défiler les éléments horizontalement. Le widget RecyclerView est une version plus avancée et plus flexible de ListView.
Pour utiliser RecyclerView, ajoutez simplement une dépendance:
com.Android.support:recyclerview-v7:23.0.1
Voici un échantillon:
public class MyActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
recyclerView.setLayoutManager(layoutManager);
MyAdapter adapter = new MyAdapter(myDataset);
recyclerView.setAdapter(adapter);
}
}
Plus d'infos sur RecyclerView:
C'est un peu (très) tard, mais je poste ceci au cas où quelqu'un viendrait plus tard.
La bibliothèque d'assistance depuis l'aperçu Android L possède un RecyclerView
qui fait exactement ce que vous voulez.
Pour le moment, vous ne pouvez l'obtenir que via le kit de développement logiciel L preview et vous devez définir votre minSdk
sur L
. Mais vous pouvez copier tous les fichiers nécessaires dans votre projet et les utiliser de cette façon jusqu'à ce que L soit officiellement sorti.
Vous pouvez télécharger les documents de prévisualisation ici .
Avertissement: L'API pour Recycler View peut changer et comporter des bogues.
Mis à jour
Le code source pour listview horizontale est:
LinearLayoutManager layoutManager
= new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
RecyclerView myList = findViewById(R.id.my_recycler_view);
myList.setLayoutManager(layoutManager);
Téléchargez le fichier jar de ici
maintenant placez-le dans votre dossier libs, faites un clic droit dessus et sélectionnez "Ajouter comme bibliothèque"
maintenant dans main.xml mettre ce code
<com.devsmart.Android.ui.HorizontalListView
Android:id="@+id/hlistview"
Android:layout_width="fill_parent"
Android:layout_height="wrap_content"
/>
maintenant dans la classe d'activité si vous voulez une liste horizontale avec des images, puis mettez ce code
HorizontalListView hListView = (HorizontalListView) findViewById(R.id.hlistview);
hListView.setAdapter(new HAdapter(this));
private class HAdapter extends BaseAdapter {
LayoutInflater inflater;
public HAdapter(Context context) {
inflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return Const.template.length;
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
HViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.listinflate, null);
holder = new HViewHolder();
convertView.setTag(holder);
} else {
holder = (HViewHolder) convertView.getTag();
}
holder.img = (ImageView) convertView.findViewById(R.id.image);
holder.img.setImageResource(Const.template[position]);
return convertView;
}
}
class HViewHolder {
ImageView img;
}
C'est en fait très simple : il suffit de faire pivoter la vue liste pour l'étendre sur le côté
mlistView.setRotation(-90);
Ensuite, lors du gonflage des enfants, cela devrait être dans la méthode getView. vous faites pivoter les enfants pour qu'ils se tiennent debout:
mylistViewchild.setRotation(90);
Edit: si votre ListView ne tient pas correctement après la rotation, placez le ListView dans cette RotateLayout comme ceci:
<com.github.rongi.rotate_layout.layout.RotateLayout
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
app:angle="90"> <!-- Specify rotate angle here -->
<ListView
Android:layout_width="match_parent"
Android:layout_height="match_parent">
</ListView>
</com.github.rongi.rotate_layout.layout.RotateLayout>
Ma solution consiste simplement à utiliser le widget ViewPager
. Elle n'est pas verrouillée par le centre Gallery
et possède des fonctionnalités intégrées pour le recyclage des vues (en tant que ListView
). Vous pouvez voir une approche similaire sur l'application Google Play, chaque fois que vous traitez avec des listes à défilement horizontal.
Il vous suffit d’étendre la variable PagerAdapter
et d’y apporter quelques modifications:
public class MyPagerAdapter extends PagerAdapter {
private Context mContext;
public MyPagerAdapter(Context context) {
this.mContext = context;
}
// As per docs, you may use views as key objects directly
// if they aren't too complex
@Override
public Object instantiateItem(ViewGroup container, int position) {
LayoutInflater inflater = LayoutInflater.from(mContext);
View view = inflater.inflate(R.layout.item, null);
container.addView(view);
return view;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
@Override
public int getCount() {
return 10;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
// Important: page takes all available width by default,
// so let's override this method to fit 5 pages within single screen
@Override
public float getPageWidth(int position) {
return 0.2f;
}
}
En conséquence, vous aurez un widget à défilement horizontal avec adaptateur, comme celui-ci:
J'ai développé une logique pour le faire sans utiliser aucune bibliothèque horizontale scrollview externe, voici la vue horizontale que j'ai réalisée et j'ai posté ma réponse ici: https://stackoverflow.com/a/33301582/5479863
Ma réponse json est la suivante:
{"searchInfo":{"status":"1","message":"Success","clist":[{"id":"1de57434-795e-49ac-0ca3-5614dacecbd4","name":"Theater","image_url":"http://52.25.198.71/miisecretory/category_images/movie.png"},{"id":"62fe1c92-2192-2ebb-7e92-5614dacad69b","name":"CNG","image_url":"http://52.25.198.71/miisecretory/category_images/cng.png"},{"id":"8060094c-df4f-5290-7983-5614dad31677","name":"Wine-shop","image_url":"http://52.25.198.71/miisecretory/category_images/beer.png"},{"id":"888a90c4-a6b0-c2e2-6b3c-561788e973f6","name":"Chemist","image_url":"http://52.25.198.71/miisecretory/category_images/chemist.png"},{"id":"a39b4ec1-943f-b800-a671-561789a57871","name":"Food","image_url":"http://52.25.198.71/miisecretory/category_images/food.png"},{"id":"c644cc53-2fce-8cbe-0715-5614da9c765f","name":"College","image_url":"http://52.25.198.71/miisecretory/category_images/college.png"},{"id":"c71e8757-072b-1bf4-5b25-5614d980ef15","name":"Hospital","image_url":"http://52.25.198.71/miisecretory/category_images/hospital.png"},{"id":"db835491-d1d2-5467-a1a1-5614d9963c94","name":"Petrol-Pumps","image_url":"http://52.25.198.71/miisecretory/category_images/petrol.png"},{"id":"f13100ca-4052-c0f4-863a-5614d9631afb","name":"ATM","image_url":"http://52.25.198.71/miisecretory/category_images/atm.png"}]}}
Fichier de mise en page:
<?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:weightSum="5">
<fragment
Android:id="@+id/map"
Android:name="com.google.Android.gms.maps.SupportMapFragment"
Android:layout_width="match_parent"
Android:layout_height="0dp"
Android:layout_weight="4" />
<HorizontalScrollView
Android:id="@+id/horizontalScroll"
Android:layout_width="match_parent"
Android:layout_height="0dp"
Android:layout_weight="1">
<LinearLayout
Android:id="@+id/ll"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:gravity="center"
Android:orientation="horizontal">
</LinearLayout>
</HorizontalScrollView>
</LinearLayout>
fichier de classe:
LinearLayout linearLayout = (LinearLayout) findViewById(R.id.ll);
for (int v = 0; v < collectionInfo.size(); v++) {
/*---------------Creating frame layout----------------------*/
FrameLayout frameLayout = new FrameLayout(ActivityMap.this);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, getPixelsToDP(90));
layoutParams.rightMargin = getPixelsToDP(10);
frameLayout.setLayoutParams(layoutParams);
/*--------------end of frame layout----------------------------*/
/*---------------Creating image view----------------------*/
final ImageView imgView = new ImageView(ActivityMap.this); //create imageview dynamically
LinearLayout.LayoutParams lpImage = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
imgView.setImageBitmap(collectionInfo.get(v).getCatImage());
imgView.setLayoutParams(lpImage);
// setting ID to retrieve at later time (same as its position)
imgView.setId(v);
imgView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// getting id which is same as its position
Log.i(TAG, "Clicked on " + collectionInfo.get(v.getId()).getCatName());
// getting selected category's data list
new GetSelectedCategoryData().execute(collectionInfo.get(v.getId()).getCatID());
}
});
/*--------------end of image view----------------------------*/
/*---------------Creating Text view----------------------*/
TextView textView = new TextView(ActivityMap.this);//create textview dynamically
textView.setText(collectionInfo.get(v).getCatName());
FrameLayout.LayoutParams lpText = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.BOTTOM | Gravity.CENTER);
// Note: LinearLayout.LayoutParams 's gravity was not working so I putted Framelayout as 3 paramater is gravity itself
textView.setTextColor(Color.parseColor("#43A047"));
textView.setLayoutParams(lpText);
/*--------------end of Text view----------------------------*/
//Adding views at appropriate places
frameLayout.addView(imgView);
frameLayout.addView(textView);
linearLayout.addView(frameLayout);
}
private int getPixelsToDP(int dp) {
float scale = getResources().getDisplayMetrics().density;
int pixels = (int) (dp * scale + 0.5f);
return pixels;
}
le truc qui marche ici est l’id que j’ai assigné à ImageView "imgView.setId (v)" et après avoir appliqué onClickListener à celui-là, je vais à nouveau chercher l’id de la vue .... j’ai également commenté dans le code que c'est facile à comprendre, J'espère que cela pourra être très utile ... Happy Coding ... :)
Vous pouvez utiliser RecyclerView dans la bibliothèque de support. RecyclerView est une version généralisée de ListView qui prend en charge:
Ce n'est pas vraiment une réponse, mais que diriez-vous d'utiliser un Vue à défilement horizontal ?
J'ai beaucoup cherché une solution à ce problème. La réponse courte est qu'il n'y a pas de bonne solution sans passer par les méthodes privées et ce genre de choses. La meilleure chose que j'ai trouvée était de le mettre en œuvre moi-même à partir de zéro en étendant AdapterView
. C'est assez misérable. Voir ma SO question sur les ListViews horizontales .
Je devais faire la même chose pour l'un de mes projets et j'ai fini par écrire le mien. Je l'ai appelé HorzListView fait maintenant partie de ma bibliothèque open source Aniqroid.
http://aniqroid.sileria.com/doc/api/ (recherchez des téléchargements en bas ou utilisez un projet de code Google pour voir plus d'options de téléchargement: http://code.google.com/p/ aniqroid/téléchargements/liste )
La documentation de la classe est la suivante: http://aniqroid.sileria.com/doc/api/com/sileria/Android/view/HorzListView.html
Pour mon application, j'utilise un HorizontalScrollView contenant LinearLayout à l'intérieur, dont l'orientation est définie sur horizontal. Afin d'ajouter des images à l'intérieur, je crée ImageViews dans l'activité et les ajoute à mon LinearLayout. Par exemple:
<HorizontalScrollView
Android:id="@+id/photo_scroll"
Android:layout_width="wrap_content"
Android:layout_height="0dp"
Android:layout_weight="1"
Android:scrollbars="horizontal"
Android:visibility="gone">
<LinearLayout
Android:id="@+id/imageview_holder"
Android:layout_width="wrap_content"
Android:orientation="horizontal"
Android:layout_height="match_parent">
</LinearLayout>
</HorizontalScrollView>
Cela fonctionne parfaitement pour moi. Dans l'activité, tout ce que j'ai à faire est quelque chose comme le code ci-dessous:
LinearLayout imgViewHolder = findViewById(R.id.imageview_holder);
ImageView img1 = new ImageView(getApplicationContext());
//set bitmap
//set img1 layout params
imgViewHolder.add(img1);
ImageView img2 = new ImageView(getApplicationContext());
//set bitmap
//set img2 layout params
imgViewHolder.add(img2);
Comme je l'ai dit, cela fonctionne pour moi et j'espère que cela aidera également quelqu'un qui cherche à atteindre cet objectif.
vous pouvez toujours créer dynamiquement vos vues de texte, etc., et définir vos onclicklisteners comme vous le feriez avec un adaptateur
HorizontialListView ne peut pas fonctionner lorsque les données de l'adaptateur sont impliquées dans un autre thread. Tout fonctionne à 100% sur le thread d'interface utilisateur. C'est un gros problème en multithread. Je pense qu'utiliser HorizontialListView n'est pas la meilleure solution à votre problème.HorzListView est un meilleur moyen.Vous venez de remplacer votre précédente Galerie par HorzListView.Vous n'avez pas besoin de modifier le code de l'adaptateur.Ensuite, tout se déroule comme vous le souhaitez.Voir https://stackoverflow.com/a/12339708/1525777 à propos de HorzListView.
J'avais utilisé lien listview horizontal dans mon projet et j'ai obtenu de bons résultats. J'avais utilisé devsmart library au début, mais cela me posait quelques problèmes. Donc, meilleure façon d'utiliser lien de liste horizontale car il a récupéré mes problèmes et j'ai récemment lancé mon application sur Google PlayStore en utilisant cette bibliothèque et j'ai obtenu une bonne réponse des utilisateurs. Je vous recommande donc d'utiliser la même bibliothèque que celle mentionnée ci-dessus pour afficher listview horizontalement. Prendre plaisir :)
Il existe une excellente bibliothèque pour cela, appelée TwoWayView , il est très facile à mettre en œuvre. Il suffit d'inclure la bibliothèque de projet dans votre espace de travail et de l'ajouter en tant que projet de bibliothèque à votre projet d'origine, puis de suivre les étapes suivantes: à l'origine mentionné ici :
Premièrement, ajoutons un style indiquant l’orientation de ListView (horizontal ou vertical) dans (res/values / styles.xml):
<style name="TwoWayView">
<item name="Android:orientation">horizontal</item>
</style>
Ensuite,
Dans votre mise en page XML, utilisez le code suivant pour ajouter le TwoWayView:
<org.lucasr.twowayview.TwoWayView
xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:tools="http://schemas.Android.com/tools"
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:id="@+id/lvItems"
style="@style/TwoWayView"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:drawSelectorOnTop="false"
tools:context=".MainActivity" />
et finalement, déclarez-le et traitez-le comme n'importe quel ListView
régulier:
TwoWayView lvTest = (TwoWayView) findViewById(R.id.lvItems);
Toutes les méthodes de ListView
fonctionneront ici comme d’habitude, mais j’ai remarqué une seule différence: lorsque vous définissez le mode de choix, la méthode setChoiceMode
ne prend pas une valeur int
mais une valeur de enum
appelée ChoiceMode
, donc list_view.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
sera lvTest.setChoiceMode(ChoiceMode.SINGLE); // or MULTIPLE or NONE
.