public abstract class BaseActivity extends XActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        super.onCreate(savedInstanceState);
        String title=getIntent().getStringExtra("title");
        if (TextUtils.isEmpty(title))
            title=getString(R.string.app_name);
        ActionBar bar=getSupportActionBar();
        bar.setTitle(title);
        if (!title.equals(getString(R.string.app_name)))
            bar.setDisplayHomeAsUpEnabled(true);
    }

    @Override
    public void setContentView(int layoutResID) {
        super.setContentView(layoutResID);
        setStatusBar();
    }

    protected void setStatusBar() {
        XStatusBar.setColor(this, getResources().getColor(R.color.colorPrimary),0);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {
        if(item.getItemId() == android.R.id.home)
        {
            finish();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
} public class News implements Serializable {
    /**
     * 单图布局样式
     */
    public static final int TYPE_SINGLE_PICTURE = 0;
    /**
     * 无图布局样式
     */
    public static final int TYPE_NONE_PICTURE = 1;

    private int newsType;
    private String title;
    private String imageUrl;
    private String author;
    private String time;

    public News(int newsType, String title, String imageUrl, String author, String time) {
        this.newsType = newsType;
        this.title = title;
        this.imageUrl = imageUrl;
        this.author = author;
        this.time = time;
    }

    public News(int newsType, String title, String author, String time) {
        this.newsType = newsType;
        this.title = title;
        this.author = author;
        this.time = time;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }

    public String getImageUrl() {
        return imageUrl;
    }

    public void setImageUrl(String imageUrl) {
        this.imageUrl = imageUrl;
    }

    public int getNewsType() {
        return newsType;
    }

    public void setNewsType(int newsType) {
        this.newsType = newsType;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    @Override
    public String toString() {
        return "newsType=" + newsType + "\n" +
                "title =" + title + "\n" +
                "imageUrl =" + imageUrl + "\n" +
                "author =" + author + "\n" +
                "time = " + time;
    }
} public class NewDataSource {
    private static ArrayList<News> newsList;

    //测试数据
    public static ArrayList<News> getNewsList(){
        if(null==newsList || newsList.isEmpty()){
            newsList = new ArrayList<>();
            newsList.add(new News(News.TYPE_SINGLE_PICTURE,"智能手机行业正处于关键转折点，下一战场会在哪里？","https://pic.36krcnd.com/avatar/201701/17062818/1ucsedy4pdb4aqyu.jpg!heading","缪定纯•明星公司","58分钟前"));
            newsList.add(new News(News.TYPE_NONE_PICTURE,"创始团队如何保持对公司的控制权？Snapchat这里可能有一份指南","36kr","2017.02.04"));
            newsList.add(new News(News.TYPE_SINGLE_PICTURE,"创投机构回应上海政府风投补偿：返税意义更大","http://n.sinaimg.cn/tech/transform/20160126/KR43-fxnuvxc1994221.jpg","投资，职场","2017-01-16 10:36"));
            newsList.add(new News(News.TYPE_NONE_PICTURE,"上海新规：天使投资有损失可获补偿 最高补六成","段旭","2017.02.04"));
            newsList.add(new News(News.TYPE_SINGLE_PICTURE,"马云说新零售是在拯救线下 实业大佬会同意吗","https://pic.36krcnd.com/avatar/201701/12073251/vw1wo7bw0l73j8zp.jpg","早期项目","2017-01-16 10:36 "));
            newsList.add(new News(News.TYPE_NONE_PICTURE,"中国万吨巡洋舰开始下饺子，俄海军却至少还要等十年","译东西","2017.02.04"));
            newsList.add(new News(News.TYPE_NONE_PICTURE,"高管集体离职致Twitter股价开盘跳水逾6%","社交媒体","2016.02.04"));
            newsList.add(new News(News.TYPE_SINGLE_PICTURE,"传格力为推自家手机与门禁联动 员工不买难进门","http://p2.qhimg.com/t019db1294a2e7eb1db.jpg?size=600x400","前沿科技","2017-01-16 10:36"));
            newsList.add(new News(News.TYPE_SINGLE_PICTURE,"安检繁琐无用？来看看这些缴获的违禁品","http://p9.qhimg.com/t01c2084745dc313fd1.jpg","投资，职场","2013.02.04"));
            newsList.add(new News(News.TYPE_NONE_PICTURE,"清华控股将收购两家半导体制造公司","36kr","2017.02.04"));
            newsList.add(new News(News.TYPE_SINGLE_PICTURE,"雷军称小米今年目标破千亿，是实力还是吹牛皮？","http://p7.qhimg.com/t0139528269ae1ac5a0.jpg","前沿科技","2017-01-16 10:36"));
            newsList.add(new News(News.TYPE_NONE_PICTURE,"平安银行陷年终奖风波 最悲伤年终奖——1.5元","社交媒体","2017.01.04"));
            newsList.add(new News(News.TYPE_SINGLE_PICTURE,"人工智能会取代人类？别担心，你想多了","http://p7.qhimg.com/t01e82f909e7c2c350c.jpg","36kr","2017.02.04"));
        }
        return newsList;
    }
} public class GlideImageLoader implements ImageLoader {

    private Context mContext;

    public static GlideCircleTransform circleTransform;

    public GlideImageLoader(Context context) {
        this.mContext=context;
        circleTransform=new GlideCircleTransform(mContext);
    }

    @Override
    public void load(ImageView imageView, Object imageUrl) {
        Glide.with(mContext)
                .load(imageUrl)
                .crossFade()
                .into(imageView);
    }

    @Override
    public void load(ImageView imageView, Object imageUrl, int defaultImage) {
        Glide.with(mContext)
                .load(imageUrl)
                .crossFade()
                .placeholder(defaultImage)
                .into(imageView);
    }

    @Override
    public void load(ImageView imageView, Object imageUrl, Object transformation) {
        Glide.with(mContext)
                .load(imageUrl)
                .crossFade()
                .transform((BitmapTransformation) transformation)
                .into(imageView);
    }
} public class StickyHeaderAdapter implements StickyHeaderDecoration.IStickyHeaderAdapter<StickyHeaderAdapter.HeaderHolder> {

    private LayoutInflater mInflater;

    public StickyHeaderAdapter(Context context) {
        mInflater = LayoutInflater.from(context);
    }

    @Override
    public long getHeaderId(int position) {
        return position / 3;
    }

    @Override
    public HeaderHolder onCreateHeaderViewHolder(ViewGroup parent) {
        final View view = mInflater.inflate(R.layout.header_item, parent, false);
        return new HeaderHolder(view);
    }

    @Override
    public void onBindHeaderViewHolder(HeaderHolder viewholder, int position) {
        viewholder.header.setText("第"+getHeaderId(position)+"组");
    }

    class HeaderHolder extends RecyclerView.ViewHolder {
        public TextView header;

        public HeaderHolder(View itemView) {
            super(itemView);
            header = (TextView) itemView;
        }
    }
} public class GlideCircleTransform extends BitmapTransformation {
    public GlideCircleTransform(Context context) {
        super(context);
    }

    @Override
    protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
        return circleCrop(pool, toTransform);
    }

    private static Bitmap circleCrop(BitmapPool pool, Bitmap source) {
        if (source == null) return null;
        int size = Math.min(source.getWidth(), source.getHeight());
        int x = (source.getWidth() - size) / 2;
        int y = (source.getHeight() - size) / 2;
        Bitmap squared = Bitmap.createBitmap(source, x, y, size, size);
        Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888);
        if (result == null) {
            result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
        }
        Canvas canvas = new Canvas(result);
        Paint paint = new Paint();
        paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
        paint.setAntiAlias(true);
        float r = size / 2f;
        canvas.drawCircle(r, r, r, paint);
        return result;
    }

    @Override
    public String getId() {
        return getClass().getName();
    }
} public class XFrame {
    private static Context context;
    public static int screenHeight;
    public static int screenWidth;

    // #log
    public static String tag = "XFrame";
    public static boolean isDebug = true;


    public static void init(Context context) {
        XFrame.context = context;
        screenHeight = XDensityUtils.getScreenHeight();
        screenWidth = XDensityUtils.getScreenWidth();
    }

    public static XLogConfig initXLog() {
        return XLog.init();
    }

    public static XLoadingViewConfig initXLoadingView() {
        return XLoadingView.init();
    }

    public static void initXHttp(IHttpEngine httpEngine) {
        XHttp.init(httpEngine);
    }

    public static void initXImageLoader(ImageLoader loader) {
        XImage.init(loader);
    }

    public static Context getContext() {
        synchronized (XFrame.class) {
            if (XFrame.context == null)
                throw new NullPointerException("Call XFrame.init(context) within your Application onCreate() method." +
                        "Or extends XApplication");
            return XFrame.context.getApplicationContext();
        }
    }

    public static Resources getResources() {
        return XFrame.getContext().getResources();
    }

    public static String getString(@StringRes int id) {
        return getResources().getString(id);
    }

    public static Resources.Theme getTheme() {
        return XFrame.getContext().getTheme();
    }

    public static AssetManager getAssets() {
        return XFrame.getContext().getAssets();
    }

    public static Drawable getDrawable( @DrawableRes int id) {
        return XOutdatedUtils.getDrawable(id);
    }

    public static int getColor( @ColorRes int id) {
        return XOutdatedUtils.getColor(id);
    }

    public static Object getSystemService(String name){
        return XFrame.getContext().getSystemService(name);
    }

    public static Configuration getConfiguration() {
        return XFrame.getResources().getConfiguration();
    }

    public static DisplayMetrics getDisplayMetrics() {
        return XFrame.getResources().getDisplayMetrics();
    }

} public abstract class XRecyclerViewAdapter<T> extends BaseRecyclerViewAdapter<T,XViewHolder> {
    // 用来存放底部和头部View的集合  比Map要高效一些
    private SparseArray<View> mHeaderViews= new SparseArray<>();
    private SparseArray<View> mFooterViews= new SparseArray<>();
    private static int TYPE_HEADER = 0x100;
    private static int TYPE_FOOTER = 0x200;
    private static final int TYPE_LOAD_FAILED = 0x1;
    private static final int TYPE_NO_MORE = 0x2;
    private static final int TYPE_LOAD_MORE = 0x3;
    private static final int TYPE_NO_VIEW = 0x4;
    private RecyclerView mRecyclerView;
    private Context mContext;
    private View mLoadMoreView;
    private View mLoadMoreFailedView;
    private View mNoMoreView;
    private int mLoadItemType = TYPE_NO_VIEW;
    private OnLoadMoreListener onLoadMoreListener;
    private LayoutInflater inflater;
    private int layoutId;
    private boolean isLoadError = false;//标记是否加载出错
    private boolean isHaveStatesView = false;//是否有加载更多
    private OnItemClickListener onItemClickListener;
    private OnItemLongClickListener onItemLongClickListener;

    public XRecyclerViewAdapter(@NonNull RecyclerView mRecyclerView,List<T> dataLists){
        this(mRecyclerView,dataLists, -1);
    }
    public XRecyclerViewAdapter(@NonNull RecyclerView mRecyclerView, List<T> dataLists, @LayoutRes int layoutId) {
        this.mRecyclerView = mRecyclerView;
        this.dataLists = dataLists;
        this.layoutId = layoutId;
        this.mContext=mRecyclerView.getContext();
        this.inflater = LayoutInflater.from(mContext);
    }

    public RecyclerView getRecyclerView() {
        return mRecyclerView;
    }

    public Context getContext() {
        return mContext;
    }

    @Override
    public int getItemViewType(int position) {
        if (isHeaderPosition(position)) {
            return mHeaderViews.keyAt(position);
        }
        if (isLoadPosition(position)) {
            return mLoadItemType;
        }
        if (isFooterPosition(position)) {
            position = position - getHeaderCount() - getDataCount();
            return mFooterViews.keyAt(position);
        }
        position= position - getHeaderCount();
        return getItemLayoutResId(getItem(position), position);
    }

    @Override
    public XViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (isHeaderViewType(viewType)) {
            return new XViewHolder(mHeaderViews.get(viewType));
        }

        if (isFooterViewType(viewType)) {
            return new XViewHolder(mFooterViews.get(viewType));
        }
        if (viewType == TYPE_NO_MORE) {
            mNoMoreView=inflater.inflate(R.layout.adapter_no_more, mRecyclerView, false);
            return new XViewHolder(mNoMoreView);
        }
        if (viewType == TYPE_LOAD_MORE) {
            mLoadMoreView=inflater.inflate(R.layout.adapter_loading, mRecyclerView, false);
            return new XViewHolder(mLoadMoreView);
        }
        if (viewType == TYPE_LOAD_FAILED) {
            mLoadMoreFailedView=inflater.inflate(R.layout.adapter_loading_failed, mRecyclerView, false);
            return new XViewHolder(mLoadMoreFailedView);
        }
        return new XViewHolder(inflater.inflate(viewType, parent, false));
    }

    @Override
    public void onBindViewHolder(final XViewHolder holder, int position) {
        if (holder.getItemViewType() == TYPE_LOAD_FAILED) {
            mLoadMoreFailedView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (onLoadMoreListener != null) {
                        onLoadMoreListener.onRetry();
                        isLoadMore(true);
                    }
                }
            });
            return;
        }
        if (holder.getItemViewType()==TYPE_LOAD_MORE) {
            if (onLoadMoreListener != null && isHaveStatesView) {
                if (!isLoadError) {
                    onLoadMoreListener.onLoadMore();
                }
            }
            return;
        }
        if (isFooterPosition(position)||isHeaderPosition(position)) return;

        final int finalPosition = position - getHeaderCount();

        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (onItemClickListener != null) {
                    onItemClickListener.onItemClick(holder.itemView, finalPosition);
                }
            }
        });

        holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                if (onItemLongClickListener != null) {
                    return onItemLongClickListener.onItemLongClick(holder.itemView, finalPosition);
                }
                return false;
            }
        });

        bindData(holder, getItem(finalPosition), finalPosition);
    }
    protected abstract void bindData(XViewHolder holder, T data, int position);
    public int getItemLayoutResId(T data, int position){
        return layoutId;
    }
    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
        if(manager instanceof GridLayoutManager){   // 布局是GridLayoutManager所管理
            final GridLayoutManager gridLayoutManager = (GridLayoutManager) manager;
            gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    // 如果是Header、Footer的对象则占据spanCount的位置，否则就只占用1个位置
                    return (isHeaderPosition(position)||isFooterPosition(position)) ? gridLayoutManager.getSpanCount() : 1;
                }
            });
        }
    }


    @Override
    public void onViewAttachedToWindow(XViewHolder holder) {
        super.onViewAttachedToWindow(holder);
        int position = holder.getLayoutPosition();
        if (isFooterPosition(position)||isHeaderPosition(position)) {
            ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
            if (lp != null && lp instanceof StaggeredGridLayoutManager.LayoutParams) {
                StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp;
                p.setFullSpan(true);
            }
        }
    }

    @Override
    public int getItemCount() {
        return getDataCount()+ getHeaderCount() + getFooterCount()+ (isHaveStatesView ? 1 : 0);
    }

    public int getDataCount() {
        return dataLists.size();
    }

    public int getHeaderCount() {
        return mHeaderViews.size();
    }

    public int getFooterCount() {
        return mFooterViews.size();
    }

    public void isLoadMore(boolean isHaveStatesView) {
        mLoadItemType = TYPE_LOAD_MORE;
        isLoadError = false;
        this.isHaveStatesView = isHaveStatesView;
        notifyItemChanged(getItemCount());
    }

    public void showLoadError() {
        mLoadItemType = TYPE_LOAD_FAILED;
        isLoadError = true;
        isHaveStatesView = true;
        notifyItemChanged(getItemCount());
    }

    public void showLoadComplete() {
        mLoadItemType = TYPE_NO_MORE;
        isLoadError = false;
        isHaveStatesView = true;
        notifyItemChanged(getItemCount());
    }

    @Override
    public void setDataLists(List<T> datas) {
        mLoadItemType = TYPE_LOAD_MORE;
        super.setDataLists(datas);
    }

    private boolean isFooterViewType(int viewType) {
        int position = mFooterViews.indexOfKey(viewType);
        return position >= 0;
    }

    private boolean isHeaderViewType(int viewType) {
        int position = mHeaderViews.indexOfKey(viewType);
        return position >= 0;
    }

    private boolean isFooterPosition(int position) {
        return position >= (getHeaderCount() + getDataCount());
    }
    private boolean isLoadPosition(int position) {
        return position == getItemCount() -1 && isHaveStatesView;
    }
    private boolean isHeaderPosition(int position) {
        return position < getHeaderCount();
    }

    public void addHeaderView(View view) {
        int position = mHeaderViews.indexOfValue(view);
        if (position < 0) {
            mHeaderViews.put(TYPE_HEADER++, view);
        }
        notifyDataSetChanged();
    }

    public void addFooterView(View view) {
        int position = mFooterViews.indexOfValue(view);
        if (position < 0) {
            mFooterViews.put(TYPE_FOOTER++, view);
        }
        notifyDataSetChanged();
    }

    public void removeHeaderView(View view) {
        int index = mHeaderViews.indexOfValue(view);
        if (index < 0) return;
        mHeaderViews.removeAt(index);
        notifyDataSetChanged();
    }

    public void removeFooterView(View view) {
        int index = mFooterViews.indexOfValue(view);
        if (index < 0) return;
        mFooterViews.removeAt(index);
        notifyDataSetChanged();
    }

    public XRecyclerViewAdapter<T> setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) {
        this.onLoadMoreListener = onLoadMoreListener;
        return this;
    }
    public XRecyclerViewAdapter<T> setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
        return this;
    }

    public XRecyclerViewAdapter<T> setOnItemLongClickListener(OnItemLongClickListener onItemLongClickListener) {
        this.onItemLongClickListener = onItemLongClickListener;
        return this;
    }
    public interface OnLoadMoreListener {
        void onRetry();
        void onLoadMore();
    }
    public interface OnItemClickListener {
        void onItemClick(View v, int position);
    }

    public interface OnItemLongClickListener {
        boolean onItemLongClick(View v, int position);
    }

} public class XViewHolder extends RecyclerView.ViewHolder {

    private SparseArray<View> viewArray = new SparseArray<>();

    /**
     * 构造ViewHolder
     *
     * @param parent 父类容器
     * @param resId  布局资源文件id
     */
    public XViewHolder(ViewGroup parent, @LayoutRes int resId) {
        super(LayoutInflater.from(parent.getContext()).inflate(resId, parent, false));
    }

    /**
     * 构建ViewHolder
     *
     * @param view 布局View
     */
    public XViewHolder(View view) {
        super(view);
    }

    /**
     * 获取布局中的View
     *
     * @param viewId view的Id
     * @param <T>    View的类型
     * @return view
     */
    public <T extends View> T getView(@IdRes int viewId) {
        View view = viewArray.get(viewId);
        if (view == null) {
            view = itemView.findViewById(viewId);
            viewArray.put(viewId, view);
        }
        return (T) view;
    }


    public View getConvertView() {
        return itemView;
    }

    /****以下为辅助方法*****/

    /**
     * 设置TextView的值
     *
     * @param viewId
     * @param text
     * @return
     */
    public XViewHolder setText(@IdRes int viewId, String text) {
        TextView tv = getView(viewId);
        tv.setText(text);
        return this;
    }

    public XViewHolder setImageUrl(@IdRes int viewId, Object imageUrl) {
        ImageView view = getView(viewId);
        XImage.getInstance().load(view,imageUrl);
        return this;
    }

    public XViewHolder setImageUrl(@IdRes int viewId, Object imageUrl, int defaultImage) {
        ImageView view = getView(viewId);
        XImage.getInstance().load(view,imageUrl,defaultImage);
        return this;
    }

    public XViewHolder setImageUrl(@IdRes int viewId, Object imageUrl, Object transformation) {
        ImageView view = getView(viewId);
        XImage.getInstance().load(view,imageUrl,transformation);
        return this;
    }

    public XViewHolder setImageResource(@IdRes int viewId, int resId) {
        ImageView view = getView(viewId);
        view.setImageResource(resId);
        return this;
    }

    public XViewHolder setImageBitmap(@IdRes int viewId, Bitmap bitmap) {
        ImageView view = getView(viewId);
        view.setImageBitmap(bitmap);
        return this;
    }

    public XViewHolder setImageDrawable(@IdRes int viewId, Drawable drawable) {
        ImageView view = getView(viewId);
        view.setImageDrawable(drawable);
        return this;
    }

    public XViewHolder setBackgroundColor(@IdRes int viewId, int color) {
        View view = getView(viewId);
        view.setBackgroundColor(color);
        return this;
    }

    public XViewHolder setBackgroundRes(@IdRes int viewId, int backgroundRes) {
        View view = getView(viewId);
        view.setBackgroundResource(backgroundRes);
        return this;
    }

    public XViewHolder setTextColor(@IdRes int viewId, int textColor) {
        TextView view = getView(viewId);
        view.setTextColor(textColor);
        return this;
    }

    public XViewHolder setTextColorRes(@IdRes int viewId, int textColorRes) {
        TextView view = getView(viewId);
        view.setTextColor(XFrame.getResources().getColor(textColorRes));
        return this;
    }

    @SuppressLint("NewApi")
    public XViewHolder setAlpha(@IdRes int viewId, float value) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            getView(viewId).setAlpha(value);
        } else {
            // Pre-honeycomb hack to set Alpha value
            AlphaAnimation alpha = new AlphaAnimation(value, value);
            alpha.setDuration(0);
            alpha.setFillAfter(true);
            getView(viewId).startAnimation(alpha);
        }
        return this;
    }

    public XViewHolder setVisible(@IdRes int viewId, boolean visible) {
        View view = getView(viewId);
        view.setVisibility(visible ? View.VISIBLE : View.GONE);
        return this;
    }

    public XViewHolder linkify(@IdRes int viewId) {
        TextView view = getView(viewId);
        Linkify.addLinks(view, Linkify.ALL);
        return this;
    }

    public XViewHolder setTypeface(Typeface typeface, @IdRes int... viewIds) {
        for (@IdRes int viewId : viewIds) {
            TextView view = getView(viewId);
            view.setTypeface(typeface);
            view.setPaintFlags(view.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG);
        }
        return this;
    }

    public XViewHolder setProgress(@IdRes int viewId, int progress) {
        ProgressBar view = getView(viewId);
        view.setProgress(progress);
        return this;
    }

    public XViewHolder setProgress(@IdRes int viewId, int progress, int max) {
        ProgressBar view = getView(viewId);
        view.setMax(max);
        view.setProgress(progress);
        return this;
    }

    public XViewHolder setMax(@IdRes int viewId, int max) {
        ProgressBar view = getView(viewId);
        view.setMax(max);
        return this;
    }

    public XViewHolder setRating(@IdRes int viewId, float rating) {
        RatingBar view = getView(viewId);
        view.setRating(rating);
        return this;
    }

    public XViewHolder setRating(@IdRes int viewId, float rating, int max) {
        RatingBar view = getView(viewId);
        view.setMax(max);
        view.setRating(rating);
        return this;
    }

    public XViewHolder setTag(@IdRes int viewId, Object tag) {
        View view = getView(viewId);
        view.setTag(tag);
        return this;
    }

    public XViewHolder setTag(@IdRes int viewId, int key, Object tag) {
        View view = getView(viewId);
        view.setTag(key, tag);
        return this;
    }

    public XViewHolder setChecked(@IdRes int viewId, boolean checked) {
        Checkable view = (Checkable) getView(viewId);
        view.setChecked(checked);
        return this;
    }

    /**
     * 关于事件的
     */
    public XViewHolder setOnClickListener(@IdRes int viewId,
                                          View.OnClickListener listener) {
        View view = getView(viewId);
        view.setOnClickListener(listener);
        return this;
    }

    public XViewHolder setOnTouchListener(@IdRes int viewId,
                                          View.OnTouchListener listener) {
        View view = getView(viewId);
        view.setOnTouchListener(listener);
        return this;
    }

    public XViewHolder setOnLongClickListener(@IdRes int viewId,
                                              View.OnLongClickListener listener) {
        View view = getView(viewId);
        view.setOnLongClickListener(listener);
        return this;
    }


} public class DividerDecoration extends RecyclerView.ItemDecoration{
    private ColorDrawable mColorDrawable;
    private int mHeight;
    private int mPaddingLeft;
    private int mPaddingRight;
    private boolean mDrawLastItem = true;
    private boolean mDrawHeaderFooter = false;

    public DividerDecoration(int color, int height) {
        this.mColorDrawable = new ColorDrawable(color);
        this.mHeight = height;
    }
    public DividerDecoration(int color, int height, int paddingLeft, int paddingRight) {
        this.mColorDrawable = new ColorDrawable(color);
        this.mHeight = height;
        this.mPaddingLeft = paddingLeft;
        this.mPaddingRight = paddingRight;
    }

    public void setDrawLastItem(boolean mDrawLastItem) {
        this.mDrawLastItem = mDrawLastItem;
    }

    public void setDrawHeaderFooter(boolean mDrawHeaderFooter) {
        this.mDrawHeaderFooter = mDrawHeaderFooter;
    }

    /**
     * 返回条目之间的间隔，例如我们想仿照ListView一样添加分割线，那么就需要设置outRect的下边距。
     * @param outRect
     * @param view
     * @param parent
     * @param state
     */
    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        int position = parent.getChildAdapterPosition(view);
        int orientation = 0;
        int headerCount = 0,footerCount = 0;
        if (parent.getAdapter() instanceof XRecyclerViewAdapter){
            headerCount = ((XRecyclerViewAdapter) parent.getAdapter()).getHeaderCount();
            footerCount = ((XRecyclerViewAdapter) parent.getAdapter()).getFooterCount();
        }

        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof StaggeredGridLayoutManager){
            orientation = ((StaggeredGridLayoutManager) layoutManager).getOrientation();
        }else if (layoutManager instanceof GridLayoutManager){
            orientation = ((GridLayoutManager) layoutManager).getOrientation();
        }else if (layoutManager instanceof LinearLayoutManager){
            orientation = ((LinearLayoutManager) layoutManager).getOrientation();
        }

        if (position>=headerCount&&position<parent.getAdapter().getItemCount()-footerCount||mDrawHeaderFooter){
            if (orientation == OrientationHelper.VERTICAL){
                outRect.bottom = mHeight;
            }else {
                outRect.right = mHeight;
            }
        }
    }

    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {

        if (parent.getAdapter() == null){
            return;
        }

        int orientation = 0;
        int headerCount = 0,footerCount = 0,dataCount;

        if (parent.getAdapter() instanceof XRecyclerViewAdapter){
            headerCount = ((XRecyclerViewAdapter) parent.getAdapter()).getHeaderCount();
            footerCount = ((XRecyclerViewAdapter) parent.getAdapter()).getFooterCount();
            dataCount = ((XRecyclerViewAdapter) parent.getAdapter()).getDataCount();
        }else {
            dataCount = parent.getAdapter().getItemCount();
        }
        int dataStartPosition = headerCount;
        int dataEndPosition = headerCount+dataCount;


        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof StaggeredGridLayoutManager){
            orientation = ((StaggeredGridLayoutManager) layoutManager).getOrientation();
        }else if (layoutManager instanceof GridLayoutManager){
            orientation = ((GridLayoutManager) layoutManager).getOrientation();
        }else if (layoutManager instanceof LinearLayoutManager){
            orientation = ((LinearLayoutManager) layoutManager).getOrientation();
        }
        int start,end;
        if (orientation == OrientationHelper.VERTICAL){
            start = parent.getPaddingLeft() + mPaddingLeft;
            end = parent.getWidth() - parent.getPaddingRight() - mPaddingRight;
        }else {
            start = parent.getPaddingTop() + mPaddingLeft;
            end = parent.getHeight() - parent.getPaddingBottom() - mPaddingRight;
        }

        int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            View child = parent.getChildAt(i);
            int position = parent.getChildAdapterPosition(child);

            if (position>=dataStartPosition&&position<dataEndPosition-1//数据项除了最后一项
                    ||(position == dataEndPosition-1&&mDrawLastItem)//数据项最后一项
                    ||(!(position>=dataStartPosition&&position<dataEndPosition)&&mDrawHeaderFooter)//header&footer且可绘制
                    ){

                if (orientation == OrientationHelper.VERTICAL){
                    RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
                    int top = child.getBottom() + params.bottomMargin;
                    int bottom = top + mHeight;
                    mColorDrawable.setBounds(start,top,end,bottom);
                    mColorDrawable.draw(c);
                }else {
                    RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
                    int left = child.getRight() + params.rightMargin;
                    int right = left + mHeight;
                    mColorDrawable.setBounds(left,start,right,end);
                    mColorDrawable.draw(c);
                }
            }
        }
  }
} public class SpaceDecoration extends RecyclerView.ItemDecoration {

    private int space;
    private int headerCount = -1;
    private int footerCount = Integer.MAX_VALUE;
    private boolean mPaddingEdgeSide = true;
    private boolean mPaddingStart = true;
    private boolean mPaddingHeaderFooter = false;


    public SpaceDecoration(int space) {
        this.space = space ;
    }

    public void setPaddingEdgeSide(boolean mPaddingEdgeSide) {
        this.mPaddingEdgeSide = mPaddingEdgeSide;
    }

    public void setPaddingStart(boolean mPaddingStart) {
        this.mPaddingStart = mPaddingStart;
    }

    public void setPaddingHeaderFooter(boolean mPaddingHeaderFooter) {
        this.mPaddingHeaderFooter = mPaddingHeaderFooter;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        int position = parent.getChildAdapterPosition(view);
        int spanCount = 0;
        int orientation = 0;
        int spanIndex = 0;
        int headerCount = 0,footerCount = 0;
        if (parent.getAdapter() instanceof XRecyclerViewAdapter){
            headerCount = ((XRecyclerViewAdapter) parent.getAdapter()).getHeaderCount();
            footerCount = ((XRecyclerViewAdapter) parent.getAdapter()).getFooterCount();
        }

        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
         if (layoutManager instanceof StaggeredGridLayoutManager){
             orientation = ((StaggeredGridLayoutManager) layoutManager).getOrientation();
             spanCount = ((StaggeredGridLayoutManager) layoutManager).getSpanCount();
             spanIndex = ((StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams()).getSpanIndex();
        }else if (layoutManager instanceof GridLayoutManager){
             orientation = ((GridLayoutManager) layoutManager).getOrientation();
             spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
             spanIndex = ((GridLayoutManager.LayoutParams) view.getLayoutParams()).getSpanIndex();
        }else if (layoutManager instanceof LinearLayoutManager){
             orientation = ((LinearLayoutManager) layoutManager).getOrientation();
             spanCount = 1;
             spanIndex = 0;
        }

        /**
         * 普通Item的尺寸
         */
        if ((position>=headerCount&&position<parent.getAdapter().getItemCount()-footerCount)) {

            if (orientation == VERTICAL) {
                float expectedWidth = (float) (parent.getWidth() - space * (spanCount + (mPaddingEdgeSide ? 1 : -1))) / spanCount;
                float originWidth = (float) parent.getWidth() / spanCount;
                float expectedX = (mPaddingEdgeSide ? space : 0) + (expectedWidth + space) * spanIndex;
                float originX = originWidth * spanIndex;
                outRect.left = (int) (expectedX - originX);
                outRect.right = (int) (originWidth - outRect.left - expectedWidth);
                if (position - headerCount < spanCount && mPaddingStart) {
                    outRect.top = space;
                }
                outRect.bottom = space;
                return;
            } else {
                float expectedHeight = (float) (parent.getHeight() - space * (spanCount + (mPaddingEdgeSide ? 1 : -1))) / spanCount;
                float originHeight = (float) parent.getHeight() / spanCount;
                float expectedY = (mPaddingEdgeSide ? space : 0) + (expectedHeight + space) * spanIndex;
                float originY = originHeight * spanIndex;
                outRect.bottom = (int) (expectedY - originY);
                outRect.top = (int) (originHeight - outRect.bottom - expectedHeight);
                if (position - headerCount < spanCount && mPaddingStart) {
                    outRect.left = space;
                }
                outRect.right = space;
                return;
            }
        }else if (mPaddingHeaderFooter){
            if (orientation == VERTICAL){outRect.right = outRect.left = mPaddingEdgeSide ? space : 0;
                outRect.top = mPaddingStart?space : 0;
            }else { outRect.top = outRect.bottom = mPaddingEdgeSide ? space : 0;
                outRect.left = mPaddingStart?space : 0;
            }
        }

    }

} public class StickyHeaderDecoration extends RecyclerView.ItemDecoration {
    /**
     * The adapter to assist the {@link StickyHeaderDecoration} in creating and binding the header views.
     *
     * @param <T> the header view holder
     */
    public interface IStickyHeaderAdapter<T extends RecyclerView.ViewHolder> {

        /**
         * Returns the header id for the item at the given position.
         * The item in one group should return the same HeaderId.
         *
         * @param position the item position
         * @return the header id
         */
        long getHeaderId(int position);

        /**
         * Creates a new header ViewHolder.
         *
         * @param parent the header's view parent
         * @return a view holder for the created view
         */
        T onCreateHeaderViewHolder(ViewGroup parent);

        /**
         * Updates the header view to reflect the header data for the given position
         * @param viewholder the header view holder
         * @param position the header's item position
         */
        void onBindHeaderViewHolder(T viewholder, int position);
    }


    public static final long NO_HEADER_ID = -1L;

    private Map<Long, RecyclerView.ViewHolder> mHeaderCache;

    private IStickyHeaderAdapter mAdapter;

    private boolean mRenderInline;

    private boolean mIncludeHeader = false;

    /**
     * @param adapter
     *         the sticky header adapter to use
     */
    public StickyHeaderDecoration(IStickyHeaderAdapter adapter) {
        this(adapter, false);
    }

    /**
     * @param adapter
     *         the sticky header adapter to use
     */
    public StickyHeaderDecoration(IStickyHeaderAdapter adapter, boolean renderInline) {
        mAdapter = adapter;
        mHeaderCache = new HashMap<>();
        mRenderInline = renderInline;
    }

    public void setIncludeHeader(boolean mIncludeHeader) {
        this.mIncludeHeader = mIncludeHeader;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        int position = parent.getChildAdapterPosition(view);
        int headerHeight = 0;

        if (!mIncludeHeader){
            if (parent.getAdapter() instanceof XRecyclerViewAdapter){
                int headerCount = ((XRecyclerViewAdapter) parent.getAdapter()).getHeaderCount();
                int footerCount = ((XRecyclerViewAdapter) parent.getAdapter()).getFooterCount();
                int dataCount = ((XRecyclerViewAdapter) parent.getAdapter()).getDataCount();
                if (position<headerCount){
                    return;
                }
                if (position>=headerCount+dataCount){
                    return ;
                }
                if (position>=headerCount){
                    position-=headerCount;
                }

            }
        }

        if (position != RecyclerView.NO_POSITION
                && hasHeader(position)
                && showHeaderAboveItem(position)) {

            View header = getHeader(parent, position).itemView;
            headerHeight = getHeaderHeightForLayout(header);
        }

        outRect.set(0, headerHeight, 0, 0);
    }

    private boolean showHeaderAboveItem(int itemAdapterPosition) {
        if (itemAdapterPosition == 0) {
            return true;
        }
        return mAdapter.getHeaderId(itemAdapterPosition - 1) != mAdapter.getHeaderId(itemAdapterPosition);
    }

    /**
     * Clears the header view cache. Headers will be recreated and
     * rebound on list scroll after this method has been called.
     */
    public void clearHeaderCache() {
        mHeaderCache.clear();
    }

    public View findHeaderViewUnder(float x, float y) {
        for (RecyclerView.ViewHolder holder : mHeaderCache.values()) {
            final View child = holder.itemView;
            final float translationX = ViewCompat.getTranslationX(child);
            final float translationY = ViewCompat.getTranslationY(child);

            if (x >= child.getLeft() + translationX &&
                    x <= child.getRight() + translationX &&
                    y >= child.getTop() + translationY &&
                    y <= child.getBottom() + translationY) {
                return child;
            }
        }

        return null;
    }

    private boolean hasHeader(int position) {
        return mAdapter.getHeaderId(position) != NO_HEADER_ID;
    }

    private RecyclerView.ViewHolder getHeader(RecyclerView parent, int position) {
        final long key = mAdapter.getHeaderId(position);

        if (mHeaderCache.containsKey(key)) {
            return mHeaderCache.get(key);
        } else {
            final RecyclerView.ViewHolder holder = mAdapter.onCreateHeaderViewHolder(parent);
            final View header = holder.itemView;

            //noinspection unchecked
            mAdapter.onBindHeaderViewHolder(holder, position);

            int widthSpec = View.MeasureSpec.makeMeasureSpec(parent.getMeasuredWidth(), View.MeasureSpec.EXACTLY);
            int heightSpec = View.MeasureSpec.makeMeasureSpec(parent.getMeasuredHeight(), View.MeasureSpec.UNSPECIFIED);

            int childWidth = ViewGroup.getChildMeasureSpec(widthSpec,
                    parent.getPaddingLeft() + parent.getPaddingRight(), header.getLayoutParams().width);
            int childHeight = ViewGroup.getChildMeasureSpec(heightSpec,
                    parent.getPaddingTop() + parent.getPaddingBottom(), header.getLayoutParams().height);

            header.measure(childWidth, childHeight);
            header.layout(0, 0, header.getMeasuredWidth(), header.getMeasuredHeight());

            mHeaderCache.put(key, holder);

            return holder;
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onDrawOver(Canvas canvas, RecyclerView parent, RecyclerView.State state) {
        if (parent.getAdapter() == null){
            return;
        }

        final int count = parent.getChildCount();
        long previousHeaderId = -1;

        for (int layoutPos = 0; layoutPos < count; layoutPos++) {
            final View child = parent.getChildAt(layoutPos);
            int adapterPos = parent.getChildAdapterPosition(child);

            if (!mIncludeHeader){
                if (parent.getAdapter() instanceof XRecyclerViewAdapter){
                    int headerCount = ((XRecyclerViewAdapter) parent.getAdapter()).getHeaderCount();
                    int footerCount = ((XRecyclerViewAdapter) parent.getAdapter()).getFooterCount();
                    int dataCount = ((XRecyclerViewAdapter) parent.getAdapter()).getDataCount();
                    if (adapterPos<headerCount){
                        continue;
                    }
                    if (adapterPos>=headerCount+dataCount){
                        continue ;
                    }
                    if (adapterPos>=headerCount){
                        adapterPos-=headerCount;
                    }

                }
            }

            if (adapterPos != RecyclerView.NO_POSITION && hasHeader(adapterPos)) {
                long headerId = mAdapter.getHeaderId(adapterPos);

                if (headerId != previousHeaderId) {
                    previousHeaderId = headerId;
                    View header = getHeader(parent, adapterPos).itemView;
                    canvas.save();

                    final int left = child.getLeft();
                    final int top = getHeaderTop(parent, child, header, adapterPos, layoutPos);
                    canvas.translate(left, top);

                    header.setTranslationX(left);
                    header.setTranslationY(top);
                    header.draw(canvas);
                    canvas.restore();
                }
            }
        }
    }

    private int getHeaderTop(RecyclerView parent, View child, View header, int adapterPos, int layoutPos) {
        int headerHeight = getHeaderHeightForLayout(header);
        int top = ((int) child.getY()) - headerHeight;
        if (layoutPos == 0) {
            final int count = parent.getChildCount();
            final long currentId = mAdapter.getHeaderId(adapterPos);
            // find next view with header and compute the offscreen push if needed
            for (int i = 1; i < count; i++) {
                int adapterPosHere = parent.getChildAdapterPosition(parent.getChildAt(i));
                if (adapterPosHere != RecyclerView.NO_POSITION) {
                    long nextId = mAdapter.getHeaderId(adapterPosHere);
                    if (nextId != currentId) {
                        final View next = parent.getChildAt(i);
                        final int offset = ((int) next.getY()) - (headerHeight + getHeader(parent, adapterPosHere).itemView.getHeight());
                        if (offset < 0) {
                            return offset;
                        } else {
                            break;
                        }
                    }
                }
            }

            top = Math.max(0, top);
        }

        return top;
    }

    private int getHeaderHeightForLayout(View header) {
        return mRenderInline ? 0 : header.getHeight();
    }
} public class XImage implements ImageLoader {

    private static ImageLoader imageLoader;
    private static XImage xImage;

    public static void init(ImageLoader loader) {
        imageLoader = loader;
    }

    public static XImage getInstance() {
        if (imageLoader==null){
            throw new NullPointerException("Call XFrame.initXImageLoader(ImageLoader loader) within your Application onCreate() method." +
                    "Or extends XApplication");
        }
        if (xImage == null) {
            xImage = new XImage();
        }
        return xImage;
    }

    @Override
    public void load(ImageView imageView, Object imageUrl) {
        imageLoader.load(imageView, imageUrl);
    }

    @Override
    public void load(ImageView imageView, Object imageUrl, int defaultImage) {
        imageLoader.load(imageView, imageUrl, defaultImage);
    }

    @Override
    public void load(ImageView imageView, Object imageUrl, Object transformation) {
        imageLoader.load(imageView, imageUrl, transformation);
    }
}
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;
import com.bumptech.glide.Glide;
import com.youth.xf.BaseActivity;
import com.youth.xf.R;
import com.youth.xf.bean.News;
import com.youth.xf.data.NewDataSource;
import com.youth.xf.loder.GlideImageLoader;
import com.youth.xf.ui.adapter.StickyHeaderAdapter;
import com.youth.xf.view.GlideCircleTransform;
import com.youth.xframe.XFrame;
import com.youth.xframe.adapter.XRecyclerViewAdapter;
import com.youth.xframe.adapter.XViewHolder;
import com.youth.xframe.adapter.decoration.DividerDecoration;
import com.youth.xframe.adapter.decoration.SpaceDecoration;
import com.youth.xframe.adapter.decoration.StickyHeaderDecoration;
import com.youth.xframe.utils.imageload.XImage;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
package com.youth.xf.ui.demo;




public class XMultiTypeAdapterActivity extends BaseActivity {

    @Override
    public int getLayoutId() {
        return R.layout.activity_xrecycler_view_adapter;
    }

    @Override
    public void initData(Bundle savedInstanceState) {
    }

    @Override
    public void initView() {
        SwipeRefreshLayout mSwipeLayout = (SwipeRefreshLayout) findViewById(R.id.swipe);
        mSwipeLayout.setEnabled(false);
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
        recyclerView.addItemDecoration(new DividerDecoration(Color.parseColor("#f2f2f2"),15));

        //解决NestedScrollView嵌套RecycleView的滑动冲突问题
//        recyclerView.setNestedScrollingEnabled(false);

        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        final MultiTypeAdapter adapter = new MultiTypeAdapter(recyclerView, NewDataSource.getNewsList());
        recyclerView.setAdapter(adapter);

        // StickyHeader
        StickyHeaderDecoration decoration = new StickyHeaderDecoration(new StickyHeaderAdapter(this));
        decoration.setIncludeHeader(false);
        recyclerView.addItemDecoration(decoration);

        adapter.setOnItemClickListener(new XRecyclerViewAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(View v, int position) {
                //修改局部item的数据，点击那个修改哪个
                int random = new Random().nextInt(9);
                News news=NewDataSource.getNewsList().get(random);
                adapter.replace(position,news);
            }
        });
    }

    class MultiTypeAdapter extends XRecyclerViewAdapter<News> {

        public MultiTypeAdapter(@NonNull RecyclerView mRecyclerView, List<News> dataLists) {
            super(mRecyclerView, dataLists);
        }

        @Override
        public int getItemLayoutResId(News data, int position) {
            int layoutResId = -1;
            switch (data.getNewsType()){
                case News.TYPE_NONE_PICTURE:
                    layoutResId = R.layout.dome_item;
                    break;
                case News.TYPE_SINGLE_PICTURE:
                    layoutResId = R.layout.dome_image_item;
                    break;
            }
            return layoutResId;
        }

        @Override
        public void bindData(XViewHolder holder, News data, int position) {
            switch (data.getNewsType()){
                case News.TYPE_NONE_PICTURE:
                    holder.setText(R.id.text, data.getTitle());
                    break;
                case News.TYPE_SINGLE_PICTURE:
                    holder.setText(R.id.newTitle, data.getTitle())
                            .setText(R.id.newAuthor,data.getAuthor())
                            .setText(R.id.newTime,data.getTime());
                    //holder.setImageUrl(R.id.newImage,data.getImageUrl(),GlideImageLoader.circleTransform)
                    ImageView imageView= holder.getView(R.id.newImage);
                    XImage.getInstance().load(imageView,
                            data.getImageUrl(),
                            GlideImageLoader.circleTransform);