RecyclerView.Adapter不需要的空间

时间:2016-07-04 10:13:46

标签: android xml android-recyclerview android-adapter

Unwanted Space between them

所以我想删除(观光和购物)和(我的顶级图像和观光)之间不需要的空间。

观光,购物,食物和饮料,辣妹都是我的适配器的所有项目。 但由于某种原因,我的第一个项目有这个“空间”问题。

这是我的项目xml

<com.inthessaloniki.cityguide.view.SelectorRelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/fragment_poi_list_item"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:listSelector="@drawable/selector_clickable_item_bg_inverse"
  >
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <ImageView
            android:id="@+id/fragment_poi_list_item_image"
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:scaleType="fitXY"/>

    </RelativeLayout>

</com.inthessaloniki.cityguide.view.SelectorRelativeLayout>

列表的我的xml(在此布局中)

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:animateLayoutChanges="true">



    <LinearLayout
        android:id="@+id/container_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:src="@drawable/home_banner"/>

        <android.support.v7.widget.RecyclerView
            android:id="@+id/fragment_poi_list_recycler"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:scrollbars="vertical"
            android:background="@color/global_bg_front"/>
        <!--
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="New Button"
            android:id="@+id/button"
            android:background="@drawable/banner"
            android:layout_gravity="center_horizontal"/>-->



        <com.google.android.gms.ads.AdView
            android:id="@+id/fragment_poi_list_adview"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            app:adUnitId="@string/admob_unit_id_poi_list"
            app:adSize="BANNER" />

    </LinearLayout>

    <include
        layout="@layout/placeholder_progress"
        android:id="@+id/container_progress"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone" />

    <include
        layout="@layout/placeholder_offline"
        android:id="@+id/container_offline"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone" />

    <include
        layout="@layout/placeholder_empty"
        android:id="@+id/container_empty"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone" />

</FrameLayout>

我的适配器代码

public class PoiListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
{
    public static final int VIEW_TYPE_POI = 1;
    public static final int VIEW_TYPE_IMAGE_FOOTER = 2;
    public static final int VIEW_TYPE_FOOTER = 3;
    private List<PoiModel> mPoiList;
    private List<Object> mFooterList;
    private PoiViewHolder.OnItemClickListener mListener;
    private int mGridSpanCount;
    private Location mLocation;
    private boolean mAnimationEnabled = true;
    private int mAnimationPosition = -1;
    private ImageLoader mImageLoader = ImageLoader.getInstance();
    private DisplayImageOptions mDisplayImageOptions;
    private ImageLoadingListener mImageLoadingListener;


    public PoiListAdapter(List<PoiModel> poiList, List<Object> footerList, PoiViewHolder.OnItemClickListener listener, int gridSpanCount, Location location)
    {
        mPoiList = poiList;
        mFooterList = footerList;
        mListener = listener;
        mGridSpanCount = gridSpanCount;
        mLocation = location;

        // image caching options
        mDisplayImageOptions = new DisplayImageOptions.Builder()
                .showImageOnLoading(android.R.color.transparent)
                .showImageForEmptyUri(R.drawable.placeholder_photo)
                .showImageOnFail(R.drawable.placeholder_photo)
                .cacheInMemory(true)
                .cacheOnDisk(true)
                .displayer(new SimpleBitmapDisplayer())
                .build();
        mImageLoadingListener = new AnimateImageLoadingListener();
    }


    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
    {

        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        // inflate view and create view holder
        if(viewType== VIEW_TYPE_POI)
        {
            View view = inflater.inflate(R.layout.fragment_poi_list_item, parent, false);
            return new PoiViewHolder(view, mListener, mImageLoader, mDisplayImageOptions, mImageLoadingListener);
        }
        else if(viewType==VIEW_TYPE_IMAGE_FOOTER)
        {
            View view = inflater.inflate(R.layout.footer_image_layout, parent, false);
            return new ImageFooterViewHolder(view, mListener);
        }
        else if(viewType==VIEW_TYPE_FOOTER)
        {
            View view = inflater.inflate(R.layout.fragment_poi_list_footer, parent, false);
            return new FooterViewHolder(view);
        }
        else
        {
            throw new RuntimeException("There is no view type that matches the type " + viewType);
        }
    }


    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position)
    {
        // bind data
        if(viewHolder instanceof PoiViewHolder)
        {
            // entity
            PoiModel poi = mPoiList.get(getPoiPosition(position));

            // render view
            if(poi != null)
            {
                ((PoiViewHolder) viewHolder).bindData(poi, mLocation);
            }
        }
        else if(viewHolder instanceof FooterViewHolder)
        {
            // entity
            Object object = mFooterList.get(getFooterPosition(position));

            // render view
            if(object != null)
            {
                ((FooterViewHolder) viewHolder).bindData(object);
            }
        }

        // set item margins
        setItemMargins(viewHolder.itemView, position);

        // set animation
        setAnimation(viewHolder.itemView, position);
    }


    @Override
    public int getItemCount()
    {
        int size = 0;
        if(mPoiList !=null) size += mPoiList.size();
        if(mFooterList!=null) size += mFooterList.size();
        if(mFooterList!=null) size += 1; //ImageFooter
        return size;
    }


    @Override
    public int getItemViewType(int position)
    {
        int pois = mPoiList.size();
        int footers = mFooterList.size();
        int imageFooter = 1;

        if(position < pois) return VIEW_TYPE_POI;
        else if(position < pois+imageFooter) return VIEW_TYPE_IMAGE_FOOTER;
        else if(position < pois+imageFooter+footers) return VIEW_TYPE_FOOTER;
        else return -1;
    }


    public int getPoiCount()
    {
        if(mPoiList !=null) return mPoiList.size();
        return 0;
    }


    public int getFooterCount()
    {
        if(mFooterList!=null) return mFooterList.size();
        return 0;
    }


    public int getPoiPosition(int recyclerPosition)
    {
        return recyclerPosition;
    }


    public int getFooterPosition(int recyclerPosition)
    {
        return recyclerPosition - getPoiCount();
    }


    public int getRecyclerPositionByPoi(int poiPosition)
    {
        return poiPosition;
    }


    public int getRecyclerPositionByFooter(int footerPosition)
    {
        return footerPosition + getPoiCount();
    }


    public void refill(List<PoiModel> poiList, List<Object> footerList, PoiViewHolder.OnItemClickListener listener, int gridSpanCount, Location location)
    {
        mPoiList = poiList;
        mFooterList = footerList;
        mListener = listener;
        mGridSpanCount = gridSpanCount;
        mLocation = location;
        notifyDataSetChanged();
    }


    public void stop()
    {

    }


    public void setLocation(Location location)
    {
        mLocation = location;
    }


    public void setAnimationEnabled(boolean animationEnabled)
    {
        mAnimationEnabled = animationEnabled;
    }


    private void setAnimation(final View view, int position)
    {
        if(mAnimationEnabled && position>mAnimationPosition)
        {
            view.setScaleX(0f);
            view.setScaleY(0f);
            view.animate()
                    .scaleX(1f)
                    .scaleY(1f)
                    .setDuration(300)
                    .setInterpolator(new DecelerateInterpolator());

            mAnimationPosition = position;
        }
    }


    private void setItemMargins(View view, int position)
    {
        int height = (int) CityGuideApplication.getContext().getResources().getDimension(R.dimen.fragment_poi_list_recycler_item_size);
        int marginTop = 0;

        if(position<mGridSpanCount)
        {
            TypedArray a = CityGuideApplication.getContext().obtainStyledAttributes(null, new int[]{android.R.attr.actionBarSize}, 0, 0);
            marginTop = (int) a.getDimension(0, 0);
            a.recycle();

            height += marginTop;
        }

        ViewGroup.MarginLayoutParams marginParams = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
        marginParams.setMargins(0, marginTop, 0, 0);

        ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
        layoutParams.height = height;
    }


    public static final class PoiViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
    {
        private TextView nameTextView;
        private TextView distanceTextView;
        private ImageView imageView;
        private OnItemClickListener mListener;
        private ImageLoader mImageLoader;
        private DisplayImageOptions mDisplayImageOptions;
        private ImageLoadingListener mImageLoadingListener;


        public interface OnItemClickListener
        {
            public void onItemClick(View view, int position, long id, int viewType);
        }


        public PoiViewHolder(View itemView, OnItemClickListener listener, ImageLoader imageLoader, DisplayImageOptions displayImageOptions, ImageLoadingListener imageLoadingListener)
        {
            super(itemView);
            mListener = listener;
            mImageLoader = imageLoader;
            mDisplayImageOptions = displayImageOptions;
            mImageLoadingListener = imageLoadingListener;

            // set listener
            itemView.setOnClickListener(this);

            // find views
            nameTextView = (TextView) itemView.findViewById(R.id.fragment_poi_list_item_name);
            Typeface typeface = Typeface.createFromAsset(itemView.getContext().getAssets(), "fonts/nexa-light.otf");
            nameTextView.setTypeface(typeface);
            distanceTextView = (TextView) itemView.findViewById(R.id.fragment_poi_list_item_distance);
            imageView = (ImageView) itemView.findViewById(R.id.fragment_poi_list_item_image);
        }


        @Override
        public void onClick(View view)
        {
            mListener.onItemClick(view, getPosition(), getItemId(), getItemViewType());
        }


        public void bindData(PoiModel poi, Location location)
        {
            nameTextView.setText(poi.getName());
            mImageLoader.displayImage(poi.getImage(), imageView, mDisplayImageOptions, mImageLoadingListener);

            if(location!=null)
            {
                LatLng myLocation = new LatLng(location.getLatitude(), location.getLongitude());
                LatLng poiLocation = new LatLng(poi.getLatitude(), poi.getLongitude());
                String distance = LocationUtility.getDistanceString(LocationUtility.getDistance(myLocation, poiLocation), LocationUtility.isMetricSystem());
                distanceTextView.setText(distance);
                distanceTextView.setVisibility(View.VISIBLE);
            }
            else
            {
                distanceTextView.setVisibility(View.GONE);
            }
        }
    }

    public static final class ImageFooterViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        private PoiViewHolder.OnItemClickListener mListener;


        public interface OnItemClickListener {
            public void onItemClick(View view, int position, long id, int viewType);
        }


        public ImageFooterViewHolder(View itemView, PoiViewHolder.OnItemClickListener listener) {
            super(itemView);
            mListener = listener;

            // set listener
            itemView.setOnClickListener(this);
        }


        @Override
        public void onClick(View view) {
            mListener.onItemClick(view, getPosition(), getItemId(), getItemViewType());
        }


        public void bindData(PoiModel poi, Location location) {

        }
    }


    public static final class FooterViewHolder extends RecyclerView.ViewHolder
    {
        public FooterViewHolder(View itemView)
        {
            super(itemView);
        }


        public void bindData(Object object)
        {
            // do nothing
        }
    }
}

似乎无法找到问题所在。 提前谢谢!

2 个答案:

答案 0 :(得分:1)

查看PoiListAdapter#setItemMargins(View view, int position)的实施方式,每次调用方法public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position)时,都在setItemMargins

if(position<mGridSpanCount)
{
   height += marginTop;
}

考虑到public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position)可能不会被调用一次。上面的代码每次调用时都会添加一个值。

答案 1 :(得分:0)

我可以建议使用类型化适配器。我为此创建了基类:

public abstract class BaseRecyclerViewSpaceAdapter <D, T extends BaseRecyclerViewSpaceAdapter.FooterViewHolder> extends BaseRecyclerAdapter<D, BaseRecyclerViewSpaceAdapter.FooterViewHolder> {

    public static final int ITEM = 0;
    public static final int FOOTER = 1;

    private int footerHeight = 240;

    public int getFooterHeight() {
        return footerHeight;
    }

    public void setFooterHeight(int footerHeight) {
        this.footerHeight = footerHeight;
    }

    @Override
    public BaseRecyclerViewSpaceAdapter.FooterViewHolder onCreateViewHolder(ViewGroup parent, int viewType){
        if(viewType == ITEM){
            return onCreateItemViewHolder(parent, viewType);
        }else{
            View view = new View(parent.getContext());
            view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getFooterHeight()));
            return new FooterViewHolder(view);
        }
    }

    @Override
    public void onBindViewHolder(BaseRecyclerViewSpaceAdapter.FooterViewHolder holder, int position){
        if(getItemViewType(position) == ITEM){
            onBindItemViewHolder((T)holder, position);
        }
    }

    @Override
    public void onBindViewHolder(BaseRecyclerViewSpaceAdapter.FooterViewHolder holder, int position, List<Object> payloads) {
        if(getItemViewType(position) == ITEM && payloads != null && !payloads.isEmpty()){
            onBindItemViewHolder((T)holder, position, payloads);
        } else {
            super.onBindViewHolder(holder, position, payloads);
        }
    }

    @Override
    public int getItemViewType(int position) {
        return position == dataList.size() ? FOOTER : ITEM;
    }

    @Override
    public int getItemCount() {
        return dataList == null ? 0 : dataList.size() + 1; //added footer item
    }

    protected abstract void onBindItemViewHolder(T holder, int position);
    protected abstract void onBindItemViewHolder(T holder, int position, List<Object> payloads);
    public abstract T onCreateItemViewHolder(ViewGroup parent, int viewType);

    public class FooterViewHolder extends RecyclerView.ViewHolder {
        public FooterViewHolder(View view) {
            super(view);
        }
    }
}