2015-10-21 12 views
18

Tôi đang cố gắng chụp RecyclerView với chiều cao StaggeredGridLayout và đặt chiều cao cố định bằng cách đo chiều cao và đặt chiều cao động. Tôi đang ghi đè số onMeasure() nhưng không phải lúc nào cũng có vẻ chính xác. Tôi muốn nói nó hoạt động khoảng 50% thời gian. 50% thời gian còn lại để đo. Tôi nghĩ rằng nó đã làm với khi văn bản kết thúc tốt đẹp trong view_tile_small.xml, nhưng tôi không chắc chắn.Tự động đặt chiều cao cố định cho chế độ xem lưới so le

Fragment

public class AtTheMuseumFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener{ 

     //Odds n Ends Variables 
     private MapFragment mapFragment; 
     private FragmentTransaction fragmentTransaction; 
     private User user = new User(); 
     private MuseumCollection museumCollection; 
     private Context context; 

     //Story Grid Adapter Variables 
     private AtTheMuseumAdapter nearMeAdapter; 
     private TileFactory tileFactory; 

     //Interfaces 
     private OnFragmentChangeListener changeListener; 

     @Bind(R.id.stories_list_view) RecyclerView storiesListView; 
     @Bind(R.id.swipe_container) SwipeRefreshLayout swipeRefreshLayout; 

     public static AtTheMuseumFragment newInstance(MuseumCollection museumCollection) { 
      AtTheMuseumFragment fragment = new AtTheMuseumFragment(); 
      Bundle args = new Bundle(); 
      fragment.setArguments(args); 
      return fragment; 
     } 

     public AtTheMuseumFragment() { 
      // Required empty public constructor 
     } 

     @Override 
     public void onCreate(Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 
      museumCollection = ((MainActivity) getActivity()).getMuseumCollection(); 
      context = getActivity().getApplicationContext(); 
      tileFactory = new TileFactory(); 
     } 

     @Override 
     public View onCreateView(LayoutInflater inflater, ViewGroup container, 
           Bundle savedInstanceState) { 

      View view = inflater.inflate(R.layout.fragment_museum, container, false); 
      ButterKnife.bind(this, view); 

      //Sets up the layoutManager to the Mason View 
      storiesListView.setLayoutManager(new MeasuredStaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)); 

      //Sets up The map 
      try{ 
       fragmentTransaction = getChildFragmentManager().beginTransaction(); 
       mapFragment = MapFragment.newInstance(MapFragment.MUSEUM); 
       fragmentTransaction.add(R.id.museum_map, mapFragment).commit(); 
      }catch (Exception e){ 
       Log.d("Map - Initial Inflate:", e.getMessage()); 
      } 


      //Sets up the swipe to refresh jawn 
      swipeRefreshLayout.setOnRefreshListener(this); 
      setNearMeAdapter(); 

      return view; 
     } 

     @Override 
     public void onResume(){ 
      super.onResume(); 
     } 

     @Override 
     public void onAttach(Activity activity) { 
      super.onAttach(activity); 
      try { 
       changeListener = (OnFragmentChangeListener) activity; 
      } catch (ClassCastException e) { 
       throw new ClassCastException(activity.toString() 
         + " must implement OnFragmentInteractionListener"); 
      } 
     } 

     @Override 
     public void onDetach() { 
      super.onDetach(); 
      changeListener = null; 
     } 

     /** 
     * Loads the adapter once the data is ready 
     * 
     */ 

     public void setNearMeAdapter(){ 
      List<MuseumObject> newList = museumCollection.getObjectsNearUser(User.position, 4); 
      List<Tile> tiles = tileFactory.createAtMuseumFeed(newList, true); 
      nearMeAdapter = new AtTheMuseumAdapter(context, tiles, getActivity()); 
      storiesListView.setAdapter(nearMeAdapter); 
     } 

     /** 
     * Refreshes Adapter with new data 
     * 
     */ 

     public void refreshNearMeAdapter(){ 
      //TODO CHANGE THIS TO LOCATION BASED WHEN TIME IS RIGHT - Peter 
      //nearMeAdapter.setNewData(MuseumCollection.getObjectsNearUser(User.position, 4)); 
      List<MuseumObject> newList = museumCollection.getRandomOrder(); 
      nearMeAdapter.setNewData(tileFactory.createAtMuseumFeed(newList,false)); 
     } 

     /** 
     * Adds past data to the Adapter 
     * 
     */ 

     public void loadPastObjects(){ 
      //TODO MAKE THIS NOT ONLY LOAD RANDOM DATA - Peter 
      List<MuseumObject> newList = museumCollection.getRandomOrder(); 
      nearMeAdapter.addNewData(tileFactory.createAtMuseumFeed(newList, false)); 
      nearMeAdapter.notifyDataSetChanged(); 
     } 

     @Override 
     public void onRefresh() { 
      user.updateUserLocation(); 
      refreshNearMeAdapter(); 
      mapFragment.refreshMap(museumCollection.getObjectFeed()); 
      swipeRefreshLayout.setRefreshing(false); 
     } 

     public interface OnFragmentChangeListener { 
      void onFragmentChange(String fragment); 
     } 

     @OnClick(R.id.explore_map) 
     public void exploreMap(){ 
      changeListener.onFragmentChange("map"); 
     } 

     @OnClick(R.id.load_more) 
     public void loadMore(){ 
      loadPastObjects(); 
     } 

    } 

MeasuredStaggeredGridLayoutManager

public class MeasuredStaggeredGridLayoutManager extends StaggeredGridLayoutManager { 

    public MeasuredStaggeredGridLayoutManager(int spanCount, int orientation) { 
     super(spanCount, orientation); 
    } 

    private int[] mMeasuredDimension = new int[2]; 

    @Override 
    public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, 
          int widthSpec, int heightSpec) { 
     final int widthMode = View.MeasureSpec.getMode(widthSpec); 
     final int heightMode = View.MeasureSpec.getMode(heightSpec); 
     final int widthSize = View.MeasureSpec.getSize(widthSpec); 
     final int heightSize = View.MeasureSpec.getSize(heightSpec); 
     int width = 0; 
     int height = 0; 
     int heightR = 0; 
     int heightL = 0; 
     for (int i = 0; i < getItemCount(); i++) { 
      measureScrapChild(recycler, i, 
        View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), 
        View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), 
        mMeasuredDimension); 

      if (getOrientation() == HORIZONTAL) { 
       width = width + mMeasuredDimension[0]; 
       if (i == 0) { 
        height = mMeasuredDimension[1]; 
       } 
      } else { 

       if(i % 2 == 0){ 
        heightL += mMeasuredDimension[1]; 
       }else{ 
        heightR += mMeasuredDimension[1]; 
       } 

       if (i == 0) { 
        width = mMeasuredDimension[0]; 
       } 
      } 
     } 
     switch (widthMode) { 
      case View.MeasureSpec.EXACTLY: 
       width = widthSize; 
      case View.MeasureSpec.AT_MOST: 
      case View.MeasureSpec.UNSPECIFIED: 
     } 

     switch (heightMode) { 
      case View.MeasureSpec.EXACTLY: 
       height = heightSize; 
      case View.MeasureSpec.AT_MOST: 
      case View.MeasureSpec.UNSPECIFIED: 
     } 

     if(heightL != 0 || heightR != 0){ 
      height = (heightL > heightR) ? heightL : heightR; 
     } 

     //TODO come up with a better way to fix the slightly wrong height 
     // must be not accounting for padding or margin or something - Peter 
     height += (20 * (getItemCount()/2)) + 5; 

     setMeasuredDimension(width, height); 
    } 

    private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec, 
            int heightSpec, int[] measuredDimension) { 
     View view = recycler.getViewForPosition(position); 
     if (view != null) { 
      RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams(); 
      int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec, 
        getPaddingLeft() + getPaddingRight(), p.width); 
      int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec, 
        getPaddingTop() + getPaddingBottom(), p.height); 
      view.measure(childWidthSpec, childHeightSpec); 
      measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin; 
      measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin; 
      recycler.recycleView(view); 
     } 
    } 
} 

AtTheMuseumAdapter

public class AtTheMuseumAdapter extends RecyclerView.Adapter<AtTheMuseumAdapter.MuseumStoriesViewHolder> { 

    private List<Tile> tiles; 
    private LayoutInflater inflater; 
    private AdapterCallback mListener; 



    private Context context; 

    public AtTheMuseumAdapter(Context context, List<Tile> tiles, Activity activity) { 
     this.tiles = tiles; 
     this.context = context; 
     inflater = LayoutInflater.from(this.context); 

     //Sets up interface between Stock Adapter and Fragment 
     try { 
      this.mListener = ((AdapterCallback) activity); 
     } catch (ClassCastException e) { 
      throw new ClassCastException("Fragment must implement AdapterCallback."); 
     } 
    } 

    @Override 
    public MuseumStoriesViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { 
     View view = inflater.inflate(R.layout.view_tile_small, viewGroup, false); 
     MuseumStoriesViewHolder holder = new MuseumStoriesViewHolder(view); 

     return holder; 
    } 

    @Override 
    public void onBindViewHolder(MuseumStoriesViewHolder holder, int position) { 
     Tile currentTile = tiles.get(position); 

     holder.title.setText(currentTile.getTitle()); 
     holder.desc.setText(currentTile.getDescription()); 
     holder.type.setText(currentTile.getObjectTypeName()); 


     //Using Picasso since it handles caching and all that jazz 
     Picasso.with(context) 
       .load(currentTile.getImg()) 
       .into(holder.img); 
    } 

    @Override 
    public int getItemCount() { 
     return tiles.size(); 
    } 

    public void setNewData(List<Tile> newItems){ 
     tiles = newItems; 
     notifyDataSetChanged(); 
    } 

    public void addNewData(final List<Tile> newItems){ 
     tiles.addAll(newItems); 
     notifyDataSetChanged(); 
    } 

    class MuseumStoriesViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { 

     public TextView type,title,desc; 
     public ImageView img; 

     public MuseumStoriesViewHolder(View itemView) { 
      super(itemView); 
      //Tried Butterknife, but it doesn't seem like it was working in the view holder. - Peter 
      type = (TextView) itemView.findViewById(R.id.small_box_type); 
      title = (TextView) itemView.findViewById(R.id.small_box_title); 
      desc = (TextView) itemView.findViewById(R.id.small_box_desc); 
      img = (ImageView) itemView.findViewById(R.id.small_box_image); 

      itemView.setOnClickListener(this); 
     } 

     @Override 
     public void onClick(View view) { 
      Tile t = tiles.get(getPosition()); 
      switch (t.getObjectTypeName()){ 
       case Tile.OBJECT_NAME: 
        mListener.onObjectClick(t.getObjectID()); 
        break; 
       case Tile.TOUR_NAME: 
        mListener.onTourCLick(t.getTourID()); 
        break; 
       case Tile.STORY_NAME: 
        mListener.onStoryClick(t.getObjectID(), t.getStoryID()); 
        break; 

      } 
     } 

    } 

    public interface AdapterCallback { 
     public void onObjectClick(String objectID); 
     public void onStoryClick(String objectID, String storyID); 
     public void onTourCLick(String tourID); 
    } 

} 

view_tile_small.xml

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:layout_margin="@dimen/margin_small" 
    android:background="@color/small_box_background_color"> 

    <FrameLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content"> 

     <!--TODO Make layout_height wrap contenet --> 
     <ImageView 
      android:id="@+id/small_box_image" 
      android:layout_width="match_parent" 
      android:layout_height="150dp" 
      android:adjustViewBounds="true" 
      android:scaleType="centerCrop" 
      android:maxHeight="150dp" 
      android:background="@color/transparent"/> 

     <ImageView 
      android:layout_width="35dp" 
      android:layout_height="35dp" 
      android:layout_gravity="right" 
      android:src="@drawable/abc_btn_rating_star_off_mtrl_alpha" 
      /> 

     <TextView 
      android:id="@+id/small_box_type" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_marginStart="@dimen/margin_normal" 
      android:paddingBottom="@dimen/margin_normal" 
      android:textSize="@dimen/font_small" 
      android:textColor="@color/font_white" 
      android:background="@drawable/small_box_text_bottom_border" 
      android:layout_gravity="bottom" 
      android:text="Object Story" 
      /> 

    </FrameLayout> 

    <TextView 
     android:id="@+id/small_box_title" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_marginLeft="@dimen/margin_larger" 
     android:layout_marginBottom="@dimen/margin_normal" 
     android:layout_marginRight="@dimen/margin_larger" 
     android:layout_marginTop="@dimen/margin_larger" 
     android:textSize="@dimen/font_large" 
     android:textColor="@color/font_black" 
     android:text="Sample Text Here" 
    /> 

    <TextView 
     android:id="@+id/small_box_desc" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_marginLeft="@dimen/margin_larger" 
     android:layout_marginBottom="@dimen/margin_larger" 
     android:textSize="@dimen/font_normal" 
     android:textColor="@color/font_black" 
     android:textStyle="italic" 
     android:text="Sample Text Here" 
    /> 



</LinearLayout> 

fragment_museum

<android.support.v4.widget.SwipeRefreshLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    tools:context="com.bluecadet.android.nasm.ui.AtTheMuseumFragment" 
    android:id="@+id/swipe_container" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 

    <ScrollView 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:layout_marginBottom="100dp"> 

     <LinearLayout 
      android:orientation="vertical" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:background="#FFFFFF" 
      android:descendantFocusability="blocksDescendants" 
      > 

      <TextView 
       android:id="@+id/museum_header" 
       style="@style/header" 
       android:text="@string/museum_header" 
       android:layout_margin="@dimen/margin_larger" 
       android:elevation="8dp" 
       /> 

      <FrameLayout 
       android:layout_width="match_parent" 
       android:layout_height="275dp" 
       android:elevation="2dp" 
       > 

       <FrameLayout 
        android:id="@+id/museum_map" 
        android:layout_height="fill_parent" 
        android:layout_width="match_parent" 
        /> 

       <include 
        layout="@layout/view_explore_map" /> 

      </FrameLayout> 

      <android.support.v7.widget.RecyclerView 
       android:id="@+id/stories_list_view" 
       xmlns:android="http://schemas.android.com/apk/res/android" 
       android:orientation="vertical" 
       android:layout_width="match_parent" 
       android:layout_height="wrap_content" 
       android:layout_marginBottom="@dimen/margin_normal" 
       android:layout_marginLeft="@dimen/margin_small" 
       android:layout_marginRight="@dimen/margin_small" 
       android:layout_marginTop="@dimen/margin_normal" 
       android:stretchMode="columnWidth" 
       /> 

      <Button 
       android:id="@+id/load_more" 
       style="@style/home_button" 
       android:gravity="center" 
       android:text="@string/button_load_more" 
      /> 

     </LinearLayout> 
    </ScrollView> 
</android.support.v4.widget.SwipeRefreshLayout> 

đang ViewTreeObserver Tôi đang chơi với bây giờ. Đó là trong Fragment.

mTopStoriesListView.setLayoutManager(new NewMeasuredStaggeredLayoutManager(2, StaggeredGridLayoutManager.VERTICAL, mTopStoriesListView)); 
    mTopStoriesListView.setNestedScrollingEnabled(false); 

    //Testing Issue 54 
    final ViewTreeObserver viewTreeObserver = mTopStoriesListView.getViewTreeObserver(); 
    if (viewTreeObserver.isAlive()) { 
     viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 
      @Override 
      public void onGlobalLayout() { 
       mTopStoriesListView.getViewTreeObserver().removeOnGlobalLayoutListener(this); 
       int l = 0,r = 0; 
       for(int i = 0 ; i < mNearMeAdapter.getItemCount(); i++){ 
        int h = mTopStoriesListView.getLayoutManager().findViewByPosition(i).getHeight(); 
        ViewGroup.MarginLayoutParams layout = (ViewGroup.MarginLayoutParams) mTopStoriesListView.getLayoutManager() 
          .findViewByPosition(i).getLayoutParams(); 

        int t = layout.topMargin; 
        int b = layout.bottomMargin; 
        if(i % 2 == 0){ 
         l += h + t + b; 
        }else{ 
         r += h + t + b; 
        } 
       } 
       int viewHeight = (l > r) ? l : r; 
       mTopStoriesListView.getLayoutParams().height = viewHeight; 
       Log.d("TAG", String.valueOf(viewHeight)); 
      } 
     }); 
    } 
    //END TEST 
+0

Bạn có nhận được bất kỳ giải pháp cho điều này ? Tôi có cùng một vấn đề –

+0

Không, tôi không có. Tôi đã có ý nghĩa để thử các giải pháp dưới đây, nhưng lỗi đã được đưa vào ổ ghi lại cho thời gian là do những câu chuyện quan trọng hơn. Tôi nên cố gắng một lần nữa để giải quyết nó vào ngày mai. –

+0

Ok mát bệnh cố gắng để làm cho nó hoạt động và gửi một giải pháp nếu tôi sửa chữa nó .. sẽ đánh giá cao nếu bạn làm như vậy nếu bạn nhận được nó;) –

Trả lời

5

Bạn đã xem ViewTreeObserver chưa?

Tôi có một vấn đề tương tự trên một dự án trôi qua và tôi đã tìm thấy nó đáng tin cậy hơn onMesure để tự động được tính Layout

Bạn có thể đi qua nó tại đây: http://developer.android.com/reference/android/view/ViewTreeObserver.html

+0

Không, tôi chưa xem xét điều đó. Tôi sẽ xem xét nó sau ngày hôm nay. Cảm ơn đã giúp đỡ! –

+0

Cuối cùng tôi đã có thể quay lại vấn đề này ... Vậy làm thế nào tôi có thể sử dụng 'ViewTreeObserver' để đo từng khung nhìn bên trong' RecyclerView'? Tôi thấy các ví dụ về đo lường một lượt xem, nhưng không xem các lượt xem từ bên trong bộ điều hợp. –

Các vấn đề liên quan