6

Ich versuche, mehrere ViewPagers in eine ScrollView aufzublasen, wobei jede ViewPager einen FragmentStatePagerAdapter verwendet.Lazy loading ViewPagers in einer ScrollView

Die ViewPager bestehen aus Fragmenten mit drei ImageViews für jede Seite.

Ich benutze UniversalImageLoader für das asynchrone Laden der Bilder, aber ich kann nicht eine faule Last zu arbeiten.

Das Problem ist, wenn meine app aufblähenden sagen 10 ViewPagers mit 3 ImageViews für jede TripplePosterFragment1, und weitere 10 ViewPagers mit 3 ImageViews für TripplePosterFragment2 seit den mPager.setOffscreenPageLimit(1) Tritte in.

Seine insgesamt 60 Asynchron-Anfragen Brennen lässt während meiner progressLayout ist sichtbar.

Mein MainFragment mit folgenden Methode:

private void renderSubCarousels(ArrayList<Carousel> carousels) { 

    LayoutInflater mInflater = (LayoutInflater)getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 

    int i = 1; 

    LinearLayout subCarouselLayout = (LinearLayout) mScrollView.findViewById(R.id.index_subcategory_carousel_container); 

    for (final Carousel carousel : carousels) { 

     RelativeLayout carouselWrapper = (RelativeLayout) mInflater.inflate(R.layout.main_pager_layout, null); 
     LinearLayout mContainer = (LinearLayout) carouselWrapper.findViewById(R.id.main_pager_container); 
     mContainer.setId(Constants.BASEID_LINEARLAYOUT + i); 

     ViewPager mPager = (ViewPager) mContainer.findViewById(R.id.main_pager); 
     mPager.setId(Constants.BASEID_VIEWPAGER + i); 
     mPager.setAdapter(new PagerPosterAdapter(getFragmentManager(),Constants.TRIPLE_POSTERS, carousel)); 
     subCarouselLayout.addView(carouselWrapper); 
     i++; 
    } 
    progressLayout.setVisibility(View.GONE); 
} 

Mein FragmentStatePagerAdapter:

public class PagerPosterAdapter extends FragmentStatePagerAdapter { 
    private int mPageSize; 
    private Carousel mCarousel; 

    public PagerPosterAdapter(FragmentManager fm, int pageSize, Carousel carousel) { 
     super(fm); 
     this.mPageSize = pageSize; 
     this.mCarousel = carousel; 
    } 

    @Override 
    public int getCount() { 
     int maxPageIndex = (int) Math.ceil((float) mCarousel.getAssets().size()/mPageSize);  
     return maxPageIndex; 
    } 

    @Override 
    public Fragment getItem(int position) { 
     ArrayList<Asset> assets = mCarousel.getAssets(); 
     int from = position*mPageSize; 
     int to = (position+1)*(mPageSize); 
     if(to > assets.size()-1) 
      to = assets.size(); 

     return (TripplePosterFragment.newInstance(assets.subList(from, to))); 
    } 
} 

Die TripplePosterFragment wo das Image Rendering passiert:

private void initViews() { 

    ImageView mFirstImageView = (ImageView) mLinearLayout.findViewById(R.id.first_pager_poster);   
    ImageView mSecondImageView = (ImageView)mLinearLayout.findViewById(R.id.second_pager_poster); 
    ImageView mThirdImageView = (ImageView)mLinearLayout.findViewById(R.id.third_pager_poster); 

    for(int i = 0;i < assets.size(); i++){ 

     ImageView image = null; 

     switch(i){ 
     case 0: 
      image = (ImageView) mLinearLayout.findViewById(R.id.first_pager_poster); 
      break;  
     case 1: 
      image = (ImageView) mLinearLayout.findViewById(R.id.second_pager_poster); 
       break; 
     case 2: 
      image = (ImageView) mLinearLayout.findViewById(R.id.third_pager_poster); 
      break; 
     default: 
      continue; 
     } 

     //The ScrollView in MainFragment 

     CustomScrollView mParentScrollView = (CustomScrollView)getActivity().findViewById(R.id.index_scrollviewparent); 

     Rect scrollBounds = new Rect(); 
     mParentScrollView.getHitRect(scrollBounds); 
     if (image.getLocalVisibleRect(scrollBounds)) { 
      // Any portion of the imageView, even a single pixel, is within the visible window 
      ImageLoader.getInstance().displayImage(assets.get(i).getPoster(), image); 
      System.out.println("Im within"); 
     else { 
      // NONE of the imageView is within the visible window 
      System.out.println("Im NOT within"); 
     } 
    } 
} 

ich überprüfen müssen, wenn die Bilder sichtbar und laden Sie sie, wenn sie sind. Aber System.out.println("Im NOT within"); ist in der Log gespammt. Ich bin mir sicher, dass es einen ähnlichen Weg gibt, aber ich brauche Hilfe.

Ich habe versucht, eine schnelle Annäherung in einem Listview viel von dem Fleisch zu tun, aber es ist nicht optimal, zumindest nach einigen Lesen, ViewPager inside ListView

UPDATE

Samt Kernfrage nach wie vor, aber Verwenden eines neuen Ansatzes HorizontalListViews instad von Pagern.

ListViews scheint wie der Weg zu gehen. Wenn Sie ArrayAdapter verwenden, um eine reguläre vertikale ListView mit mehreren zu füllen, lädt die Lazy die Bilder vertikal für jede neue Zeile und horizontal für jedes Bild innerhalb, wie vorgesehen.

Problem: Horizontale Positionen sind verloren. Die horizontalAdapter wird von einer wiederverwerteten Ansicht auf den nächsten Listeneintrag vererbt. Diese Positionen das neue Listenelement, wo die wiederverwertete Liste Element war.

public View getView(int position, View convertView, ViewGroup parent) { 
    final ViewHolder holder; 
    View view = convertView; 

    if (view == null) { 
     holder = new ViewHolder(); 
     view = mInflater.inflate(R.layout.carousel_frame_layout, null); 
     holder.carouselList = (HListView) view.findViewById(R.id.hListView); 
     view.setTag(holder); 
    } 
    else { 
     holder = (ViewHolder) view.getTag(); 
    } 
    Carousel mCarousel = mData.get(position); 

    // Problem: Re-uses adapters from convertview 
    if (holder.carouselList.getAdapter() == null) { 
     SubCategoryCarouselAdapter horizontalAdapter = new SubCategoryCarouselAdapter(mContext, mCarousel.getAssets()); 
     holder.carouselList.setAdapter(horizontalAdapter); 
    } else { 
     ((SubCategoryCarouselAdapter) holder.carouselList.getAdapter()).update(mCarousel.getAssets()); 
    } 

    return view; 
} 

Die Lösung könnte die inneren horizontalAdapter zu einer bestimmten Listenposition Position zu speichern sein, aber ich weiß nicht, wie dies zu tun ist, wenn die HListView selbst zurückgeführt wird.

UPDATE 3

eine funktionierende Lösung für HListViews gefunden. Aber ich muss noch testen, ob das für ViewPagers funktioniert.

Seine Lazy laden Bilder sowohl horizontal als auch vertikal bei Verwendung addHeaderView auf Eltern ListView für jeden inneren HListView. Ich habe HorizontalVariableListView zusammen mit UniversalImageLoader für die Karussells verwendet.

LayoutInflater mInflater = (LayoutInflater) getActivity().getSystemService 
      (Context.LAYOUT_INFLATER_SERVICE); 

for (final Carousel carousel : carousels) { 
    View carouselWrapper = mInflater.inflate(R.layout.carousel_sub_category_layout, null); 
    listView.addHeaderView(carouselWrapper); 
    listView.setAdapter(null); 

    HListView horizontalList = (HListView) carouselWrapper.findViewById(R.id.hListView); 
    SubCategoryCarouselAdapter mAdapter = new SubCategoryCarouselAdapter(getActivity(), carousel.getAssets()); 
    horizontalList.setAdapter(mAdapter); 
} 

Antwort

1

Könnten Sie einen Haltepunkt an

if (image.getLocalVisibleRect(scrollBounds)) { 

und sehen, welche Eigenschaften (Breite/Höhe/Position) Bild und scrollBounds haben?

Auch wenn ist

private void initViews() { 

genannt?

2

Warum nicht ein ListView anstelle von ScrollView verwenden? Es hat eine Funktion zum Recyclen von Ansichten, so dass das Laden nur für diejenigen Pager beginnt, die gerade auf dem Bildschirm sichtbar sind. Andernfalls sollten Sie Ihre ScrollView ableiten, um zu prüfen, ob der Pager gerade sichtbar ist.

+0

Ja, es scheint so zu sein. Ich kann das Recycling von View und Adaptern nicht zum Laufen bringen. Ich habe weg von Pagern bewegt und stattdessen HorizontalListViews verwendet. Es hat jedoch das gleiche Verhalten, wenn alle Bilder in einer ScrollView geladen werden. Wie Sie bereits gesagt haben, werden die HorizontalListViews wiederverwendet, aber auch die Adapter, die an jede wiederverwendbare Ansicht gebunden sind. Meine Antwort wurde aktualisiert! – Rob

+0

Ich kann zwei folgende Lösungen vorschlagen: 1) speichern Sie Ihre Adapter in der Liste und erhalten Sie den benötigten Adapter durch seine Position (eigentlich glaube ich nicht, dass es eine gute Idee ist, da es in Bezug auf Speicher nicht wirksam ist) 2) add ein Zeiger auf Ihr Karussell (ich nehme an, es hat die Liste der Daten angezeigt werden) Klasse, die auf die aktive Position zeigen und dann SubCategoryCarouselAdapter Konstruktor ändern, um diesen Zeiger zu bekommen und die entsprechende Position (ich denke, dass dieser Weg ist Weg besser als die erste, wie für den Zeiger kann es nur ein int Wert sein, der die Nummer der Seite anzeigt) – Chaosit

+0

Zumindest sollte dies funktionieren, falls Ihre HListView paginiert wird wie der ViewPager – Chaosit