com.gh4a.adapter.RootAdapter.java Source code

Java tutorial

Introduction

Here is the source code for com.gh4a.adapter.RootAdapter.java

Source

/*
 * Copyright 2011 Azwan Adli Abdullah
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.gh4a.adapter;

import android.content.Context;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.Filterable;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * The Root adapter.
 *
 * @param <T> the generic type
 */
public abstract class RootAdapter<T, VH extends RecyclerView.ViewHolder>
        extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements Filterable, View.OnClickListener {
    public interface OnItemClickListener<T> {
        void onItemClick(T item);
    }

    public interface OnScrolledToFooterListener {
        void onScrolledToFooter();
    }

    /**
     * The objects.
     */
    private List<T> mObjects;
    private final List<T> mUnfilteredObjects;

    /**
     * The context.
     */
    protected final Context mContext;
    private final LayoutInflater mInflater;
    private OnItemClickListener<T> mItemClickListener;
    private boolean mContextMenuSupported;

    private View mHeaderView;
    private View mFooterView;
    private OnScrolledToFooterListener mFooterListener;
    private int mHighlightPosition = -1;
    private boolean mHolderCreated = false;

    private static final int VIEW_TYPE_HEADER = 0;
    private static final int VIEW_TYPE_FOOTER = 1;
    private static final int VIEW_TYPE_ITEM = 2;

    public static final int CUSTOM_VIEW_TYPE_START = VIEW_TYPE_ITEM;

    private final Filter mFilter = new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults results = new FilterResults();
            if (TextUtils.isEmpty(constraint)) {
                results.values = mUnfilteredObjects;
                results.count = mUnfilteredObjects.size();
            } else {
                final ArrayList<T> filtered = new ArrayList<>();
                for (T object : mUnfilteredObjects) {
                    if (isFiltered(constraint, object)) {
                        filtered.add(object);
                    }
                }
                results.values = filtered;
                results.count = filtered.size();
            }
            return results;
        }

        @SuppressWarnings("unchecked")
        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            mObjects = (List<T>) results.values;
            notifyDataSetChanged();
        }
    };

    /**
     * Instantiates a new root adapter.
     *
     * @param context the context
     */
    public RootAdapter(Context context) {
        mObjects = new ArrayList<>();
        mUnfilteredObjects = new ArrayList<>();
        mContext = context;
        mInflater = LayoutInflater.from(mContext);
    }

    public void setHeaderView(View headerView) {
        mHeaderView = headerView;
        notifyDataSetChanged();
    }

    public void setFooterView(View footerView, OnScrolledToFooterListener footerListener) {
        mFooterView = footerView;
        mFooterListener = footerListener;
        notifyDataSetChanged();
    }

    public void setOnItemClickListener(OnItemClickListener<T> listener) {
        if (mHolderCreated) {
            throw new IllegalStateException("Must not set item click listener after views are bound");
        }
        mItemClickListener = listener;
    }

    public void setContextMenuSupported(boolean supported) {
        if (mHolderCreated) {
            throw new IllegalStateException("Must not set context menu state after views are bound");
        }
        mContextMenuSupported = supported;
    }

    @Override
    public int getItemCount() {
        return mObjects.size() + (mHeaderView != null ? 1 : 0) + (mFooterView != null ? 1 : 0);
    }

    @Override
    public int getItemViewType(int position) {
        int itemStart = mHeaderView != null ? 1 : 0;
        if (mHeaderView != null && position == 0) {
            return VIEW_TYPE_HEADER;
        } else if (mFooterView != null && position == itemStart + mObjects.size()) {
            return VIEW_TYPE_FOOTER;
        } else {
            int viewType = getItemViewType(getItem(position - itemStart));
            assert viewType >= CUSTOM_VIEW_TYPE_START;
            return viewType;
        }
    }

    public int getCount() {
        return mObjects.size();
    }

    public T getItem(int position) {
        return mObjects.get(position);
    }

    public T getItemFromAdapterPosition(int position) {
        return mObjects.get(position - (mHeaderView != null ? 1 : 0));
    }

    /**
     * Adds the object.
     *
     * @param object the object
     */
    public void add(T object) {
        mUnfilteredObjects.add(object);
        mObjects.add(object);
    }

    public void addAll(Collection<T> objects) {
        if (objects != null) {
            mUnfilteredObjects.addAll(objects);
            mObjects.addAll(objects);
            notifyDataSetChanged();
        }
    }

    public void remove(T object) {
        mUnfilteredObjects.remove(object);
        mObjects.remove(object);
        notifyDataSetChanged();
    }

    public void clear() {
        mUnfilteredObjects.clear();
        mObjects.clear();
        notifyDataSetChanged();
    }

    public void highlight(int position) {
        mHighlightPosition = position;
        notifyDataSetChanged();
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        mHolderCreated = true;
        switch (viewType) {
        case VIEW_TYPE_HEADER:
            return new HeaderViewHolder(mHeaderView);
        case VIEW_TYPE_FOOTER:
            return new FooterViewHolder(mFooterView);
        default:
            RecyclerView.ViewHolder holder = onCreateViewHolder(mInflater, parent, viewType);
            if (mItemClickListener != null) {
                holder.itemView.setOnClickListener(this);
                holder.itemView.setTag(holder);
            }
            if (mContextMenuSupported) {
                holder.itemView.setLongClickable(true);
            }
            return holder;
        }
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (holder instanceof FooterViewHolder) {
            if (mFooterListener != null) {
                mFooterListener.onScrolledToFooter();
            }
        } else if (!(holder instanceof HeaderViewHolder)) {
            onBindViewHolder((VH) holder, getItemFromAdapterPosition(position));
            if (position == mHighlightPosition) {
                final View v = holder.itemView;
                v.post(new Runnable() {
                    @Override
                    public void run() {
                        if (v.getBackground() != null) {
                            final int centerX = v.getWidth() / 2;
                            final int centerY = v.getHeight() / 2;
                            DrawableCompat.setHotspot(v.getBackground(), centerX, centerY);
                        }
                        v.setPressed(true);
                        v.setPressed(false);
                        mHighlightPosition = -1;
                    }
                });
            }
        }
    }

    @Override
    public void onClick(View view) {
        VH holder = (VH) view.getTag();
        int position = holder.getAdapterPosition();
        if (position != RecyclerView.NO_POSITION) {
            mItemClickListener.onItemClick(getItemFromAdapterPosition(position));
        }
    }

    protected abstract VH onCreateViewHolder(LayoutInflater inflater, ViewGroup parent, int viewType);

    protected abstract void onBindViewHolder(VH holder, T item);

    protected boolean isFiltered(CharSequence filter, T object) {
        return true;
    }

    protected int getItemViewType(T item) {
        return VIEW_TYPE_ITEM;
    }

    @Override
    public Filter getFilter() {
        return mFilter;
    }

    public boolean isCardStyle() {
        return false;
    }

    private static class HeaderViewHolder extends RecyclerView.ViewHolder {
        public HeaderViewHolder(View v) {
            super(v);
        }
    }

    private static class FooterViewHolder extends RecyclerView.ViewHolder {
        public FooterViewHolder(View v) {
            super(v);
        }
    }
}