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
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 đề –
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. –
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ó;) –