com.hippo.easyrecyclerview.EasyRecyclerView

Here are the examples of the java api com.hippo.easyrecyclerview.EasyRecyclerView taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.

57 Examples 7

19 Source : HistoryScene.java
with Apache License 2.0
from xiaojieonly

@Override
public boolean onItemLongClick(EasyRecyclerView parent, View view, int position, long id) {
    final Context context = getContext2();
    final MainActivity activity = getActivity2();
    if (null == context || null == activity || null == mLazyList) {
        return false;
    }
    final GalleryInfo gi = mLazyList.get(position);
    new AlertDialog.Builder(context).setreplacedle(EhUtils.getSuitablereplacedle(gi)).sereplacedems(R.array.gallery_list_menu_entries, new DialogInterface.OnClickListener() {

        @Override
        public void onClick(DialogInterface dialog, int which) {
            switch(which) {
                case // Download
                0:
                    CommonOperations.startDownload(activity, gi, false);
                    break;
                case // Favorites
                1:
                    CommonOperations.addToFavorites(activity, gi, new addToFavoriteListener(context, activity.getStageId(), getTag()));
                    break;
            }
        }
    }).show();
    return true;
}

19 Source : GalleryInfoScene.java
with Apache License 2.0
from xiaojieonly

public final clreplaced GalleryInfoScene extends ToolbarScene implements EasyRecyclerView.OnItemClickListener {

    public static final String KEY_GALLERY_DETAIL = "gallery_detail";

    public static final String KEY_KEYS = "keys";

    public static final String KEY_VALUES = "values";

    private static final int INDEX_URL = 3;

    private static final int INDEX_PARENT = 10;

    /*---------------
     Whole life cycle
     ---------------*/
    @Nullable
    private ArrayList<String> mKeys;

    @Nullable
    private ArrayList<String> mValues;

    @Nullable
    private EasyRecyclerView mRecyclerView;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState == null) {
            onInit();
        } else {
            onRestore(savedInstanceState);
        }
    }

    private void handlerArgs(Bundle args) {
        if (args == null) {
            return;
        }
        GalleryDetail gd = args.getParcelable(KEY_GALLERY_DETAIL);
        if (gd == null) {
            return;
        }
        if (mKeys == null || mValues == null) {
            return;
        }
        Resources resources = getResources2();
        replacedertUtils.replacedertNotNull(resources);
        mKeys.add(resources.getString(R.string.header_key));
        mValues.add(resources.getString(R.string.header_value));
        mKeys.add(resources.getString(R.string.key_gid));
        mValues.add(Long.toString(gd.gid));
        mKeys.add(resources.getString(R.string.key_token));
        mValues.add(gd.token);
        mKeys.add(resources.getString(R.string.key_url));
        mValues.add(EhUrl.getGalleryDetailUrl(gd.gid, gd.token));
        mKeys.add(resources.getString(R.string.key_replacedle));
        mValues.add(gd.replacedle);
        mKeys.add(resources.getString(R.string.key_replacedle_jpn));
        mValues.add(gd.replacedleJpn);
        mKeys.add(resources.getString(R.string.key_thumb));
        mValues.add(gd.thumb);
        mKeys.add(resources.getString(R.string.key_category));
        mValues.add(EhUtils.getCategory(gd.category));
        mKeys.add(resources.getString(R.string.key_uploader));
        mValues.add(gd.uploader);
        mKeys.add(resources.getString(R.string.key_posted));
        mValues.add(gd.posted);
        mKeys.add(resources.getString(R.string.key_parent));
        mValues.add(gd.parent);
        mKeys.add(resources.getString(R.string.key_visible));
        mValues.add(gd.visible);
        mKeys.add(resources.getString(R.string.key_language));
        mValues.add(gd.language);
        mKeys.add(resources.getString(R.string.key_pages));
        mValues.add(Integer.toString(gd.pages));
        mKeys.add(resources.getString(R.string.key_size));
        mValues.add(gd.size);
        mKeys.add(resources.getString(R.string.key_favorite_count));
        mValues.add(Integer.toString(gd.favoriteCount));
        mKeys.add(resources.getString(R.string.key_favorited));
        mValues.add(Boolean.toString(gd.isFavorited));
        mKeys.add(resources.getString(R.string.key_rating_count));
        mValues.add(Integer.toString(gd.ratingCount));
        mKeys.add(resources.getString(R.string.key_rating));
        mValues.add(Float.toString(gd.rating));
        mKeys.add(resources.getString(R.string.key_torrents));
        mValues.add(Integer.toString(gd.torrentCount));
        mKeys.add(resources.getString(R.string.key_torrent_url));
        mValues.add(gd.torrentUrl);
        mKeys.add(resources.getString(R.string.favorite_name));
        mValues.add(gd.favoriteName);
    }

    protected void onInit() {
        mKeys = new ArrayList<>();
        mValues = new ArrayList<>();
        handlerArgs(getArguments());
    }

    protected void onRestore(@NonNull Bundle savedInstanceState) {
        mKeys = savedInstanceState.getStringArrayList(KEY_KEYS);
        mValues = savedInstanceState.getStringArrayList(KEY_VALUES);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putStringArrayList(KEY_KEYS, mKeys);
        outState.putStringArrayList(KEY_VALUES, mValues);
    }

    @SuppressWarnings("deprecation")
    @Nullable
    @Override
    public View onCreateView3(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.scene_gallery_info, container, false);
        Context context = getContext2();
        replacedertUtils.replacedertNotNull(context);
        mRecyclerView = (EasyRecyclerView) ViewUtils.$$(view, R.id.recycler_view);
        InfoAdapter adapter = new InfoAdapter();
        mRecyclerView.setAdapter(adapter);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(context, RecyclerView.VERTICAL, false));
        LinearDividerItemDecoration decoration = new LinearDividerItemDecoration(LinearDividerItemDecoration.VERTICAL, AttrResources.getAttrColor(context, R.attr.dividerColor), LayoutUtils.dp2pix(context, 1));
        decoration.setPadding(context.getResources().getDimensionPixelOffset(R.dimen.keyline_margin));
        mRecyclerView.addItemDecoration(decoration);
        mRecyclerView.setSelector(Ripple.generateRippleDrawable(context, !AttrResources.getAttrBoolean(context, R.attr.isLightTheme), new ColorDrawable(Color.TRANSPARENT)));
        mRecyclerView.setClipToPadding(false);
        mRecyclerView.setHasFixedSize(true);
        mRecyclerView.setOnItemClickListener(this);
        return view;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        setreplacedle(R.string.gallery_info);
        setNavigationIcon(R.drawable.v_arrow_left_dark_x24);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (null != mRecyclerView) {
            mRecyclerView.stopScroll();
            mRecyclerView = null;
        }
    }

    @Override
    public boolean onItemClick(EasyRecyclerView parent, View view, int position, long id) {
        Context context = getContext2();
        if (null != context && 0 != position && null != mValues) {
            if (position == INDEX_PARENT) {
                UrlOpener.openUrl(context, mValues.get(position), true);
            } else {
                ClipboardManager cmb = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
                cmb.setPrimaryClip(ClipData.newPlainText(null, mValues.get(position)));
                if (position == INDEX_URL) {
                    // Save it to avoid detect the gallery
                    Settings.putClipboardTextHashCode(mValues.get(position).hashCode());
                }
                showTip(R.string.copied_to_clipboard, LENGTH_SHORT);
            }
            return true;
        } else {
            return false;
        }
    }

    @Override
    public void onNavigationClick() {
        onBackPressed();
    }

    private static clreplaced InfoHolder extends RecyclerView.ViewHolder {

        private final TextView key;

        private final TextView value;

        public InfoHolder(View itemView) {
            super(itemView);
            key = (TextView) itemView.findViewById(R.id.key);
            value = (TextView) itemView.findViewById(R.id.value);
        }
    }

    private clreplaced InfoAdapter extends RecyclerView.Adapter<InfoHolder> {

        private static final int TYPE_HEADER = 0;

        private static final int TYPE_DATA = 1;

        private final LayoutInflater mInflater;

        public InfoAdapter() {
            mInflater = getLayoutInflater2();
            replacedertUtils.replacedertNotNull(mInflater);
        }

        @Override
        public int gereplacedemViewType(int position) {
            if (position == 0) {
                return TYPE_HEADER;
            } else {
                return TYPE_DATA;
            }
        }

        @Override
        public InfoHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            return new InfoHolder(mInflater.inflate(viewType == TYPE_HEADER ? R.layout.item_gallery_info_header : R.layout.item_gallery_info_data, parent, false));
        }

        @Override
        public void onBindViewHolder(InfoHolder holder, int position) {
            if (mKeys != null && mValues != null) {
                holder.key.setText(mKeys.get(position));
                holder.value.setText(mValues.get(position));
                holder.itemView.setEnabled(position != 0);
            }
        }

        @Override
        public int gereplacedemCount() {
            return mKeys == null || mValues == null ? 0 : Math.min(mKeys.size(), mValues.size());
        }
    }
}

19 Source : GalleryInfoScene.java
with Apache License 2.0
from xiaojieonly

@Override
public boolean onItemClick(EasyRecyclerView parent, View view, int position, long id) {
    Context context = getContext2();
    if (null != context && 0 != position && null != mValues) {
        if (position == INDEX_PARENT) {
            UrlOpener.openUrl(context, mValues.get(position), true);
        } else {
            ClipboardManager cmb = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
            cmb.setPrimaryClip(ClipData.newPlainText(null, mValues.get(position)));
            if (position == INDEX_URL) {
                // Save it to avoid detect the gallery
                Settings.putClipboardTextHashCode(mValues.get(position).hashCode());
            }
            showTip(R.string.copied_to_clipboard, LENGTH_SHORT);
        }
        return true;
    } else {
        return false;
    }
}

19 Source : GalleryCommentsScene.java
with Apache License 2.0
from xiaojieonly

@Override
public boolean onItemClick(EasyRecyclerView parent, View view, int position, long id) {
    MainActivity activity = getActivity2();
    if (null == activity) {
        return false;
    }
    RecyclerView.ViewHolder holder = parent.getChildViewHolder(view);
    if (holder instanceof ActualCommentHolder) {
        ActualCommentHolder commentHolder = (ActualCommentHolder) holder;
        ClickableSpan span = commentHolder.comment.getCurrentSpan();
        commentHolder.comment.clearCurrentSpan();
        if (span instanceof URLSpan) {
            UrlOpener.openUrl(activity, ((URLSpan) span).getURL(), true);
        } else {
            showCommentDialog(position);
        }
    } else if (holder instanceof MoreCommentHolder && !mRefreshingComments && mAdapter != null) {
        mRefreshingComments = true;
        mShowAllComments = true;
        mAdapter.notifyItemChanged(position);
        String url = getGalleryDetailUrl();
        if (url != null) {
            // Request
            EhRequest request = new EhRequest().setMethod(EhClient.METHOD_GET_GALLERY_DETAIL).setArgs(url).setCallback(new RefreshCommentListener(activity, activity.getStageId(), getTag()));
            EhApplication.getEhClient(activity).execute(request);
        }
    }
    return true;
}

19 Source : ExcludedLanguagesActivity.java
with Apache License 2.0
from xiaojieonly

public clreplaced ExcludedLanguagesActivity extends ToolbarActivity implements View.OnClickListener {

    private static final String KEY_SELECTIONS = "selections";

    private static final int ROW_COUNT = 17;

    private static final int[] LANGUAGE_STR_IDS = { R.string.language_replacedanese, R.string.language_english, R.string.language_chinese, R.string.language_dutch, R.string.language_french, R.string.language_german, R.string.language_hungarian, R.string.language_italian, R.string.language_korean, R.string.language_polish, R.string.language_portuguese, R.string.language_russian, R.string.language_spanish, R.string.language_thai, R.string.language_vietnamese, R.string.language_na, R.string.language_other };

    private static final String[] LANGUAGES = { EhConfig.replacedANESE_ORIGINAL, EhConfig.replacedANESE_TRANSLATED, EhConfig.replacedANESE_REWRITE, EhConfig.ENGLISH_ORIGINAL, EhConfig.ENGLISH_TRANSLATED, EhConfig.ENGLISH_REWRITE, EhConfig.CHINESE_ORIGINAL, EhConfig.CHINESE_TRANSLATED, EhConfig.CHINESE_REWRITE, EhConfig.DUTCH_ORIGINAL, EhConfig.DUTCH_TRANSLATED, EhConfig.DUTCH_REWRITE, EhConfig.FRENCH_ORIGINAL, EhConfig.FRENCH_TRANSLATED, EhConfig.FRENCH_REWRITE, EhConfig.GERMAN_ORIGINAL, EhConfig.GERMAN_TRANSLATED, EhConfig.GERMAN_REWRITE, EhConfig.HUNGARIAN_ORIGINAL, EhConfig.HUNGARIAN_TRANSLATED, EhConfig.HUNGARIAN_REWRITE, EhConfig.ITALIAN_ORIGINAL, EhConfig.ITALIAN_TRANSLATED, EhConfig.ITALIAN_REWRITE, EhConfig.KOREAN_ORIGINAL, EhConfig.KOREAN_TRANSLATED, EhConfig.KOREAN_REWRITE, EhConfig.POLISH_ORIGINAL, EhConfig.POLISH_TRANSLATED, EhConfig.POLISH_REWRITE, EhConfig.PORTUGUESE_ORIGINAL, EhConfig.PORTUGUESE_TRANSLATED, EhConfig.PORTUGUESE_REWRITE, EhConfig.RUSSIAN_ORIGINAL, EhConfig.RUSSIAN_TRANSLATED, EhConfig.RUSSIAN_REWRITE, EhConfig.SPANISH_ORIGINAL, EhConfig.SPANISH_TRANSLATED, EhConfig.SPANISH_REWRITE, EhConfig.THAI_ORIGINAL, EhConfig.THAI_TRANSLATED, EhConfig.THAI_REWRITE, EhConfig.VIETNAMESE_ORIGINAL, EhConfig.VIETNAMESE_TRANSLATED, EhConfig.VIETNAMESE_REWRITE, EhConfig.NA_ORIGINAL, EhConfig.NA_TRANSLATED, EhConfig.NA_REWRITE, EhConfig.OTHER_ORIGINAL, EhConfig.OTHER_TRANSLATED, EhConfig.OTHER_REWRITE };

    private final boolean[][] mSelections = new boolean[ROW_COUNT][3];

    /*---------------
     Whole life cycle
     ---------------*/
    @Nullable
    private View mCancel;

    @Nullable
    private View mOk;

    @Nullable
    private View mSelectAll;

    @Nullable
    private View mDeselectAll;

    @Nullable
    private View mInvertSelection;

    @Nullable
    private EasyRecyclerView mRecyclerView;

    @Nullable
    private LanguageAdapter mAdapter;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.scene_excluded_languages);
        setNavigationIcon(R.drawable.v_arrow_left_dark_x24);
        if (null == savedInstanceState) {
            onInit();
        } else {
            onRestore(savedInstanceState);
        }
        mCancel = ViewUtils.$$(this, R.id.cancel);
        mOk = ViewUtils.$$(this, R.id.ok);
        mSelectAll = ViewUtils.$$(this, R.id.select_all);
        mDeselectAll = ViewUtils.$$(this, R.id.deselect_all);
        mInvertSelection = ViewUtils.$$(this, R.id.invert_selection);
        mRecyclerView = (EasyRecyclerView) ViewUtils.$$(this, R.id.recycler_view);
        mRecyclerView.setHasFixedSize(true);
        mRecyclerView.setClipToPadding(false);
        mAdapter = new LanguageAdapter();
        mRecyclerView.setAdapter(mAdapter);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        mCancel.setOnClickListener(this);
        mOk.setOnClickListener(this);
        mSelectAll.setOnClickListener(this);
        mDeselectAll.setOnClickListener(this);
        mInvertSelection.setOnClickListener(this);
        boolean isDarkTheme = !AttrResources.getAttrBoolean(this, R.attr.isLightTheme);
        Ripple.addRipple(mCancel, isDarkTheme);
        Ripple.addRipple(mOk, isDarkTheme);
        Ripple.addRipple(mSelectAll, isDarkTheme);
        Ripple.addRipple(mDeselectAll, isDarkTheme);
        Ripple.addRipple(mInvertSelection, isDarkTheme);
    }

    private boolean isDecimal(String str) {
        int length = str.length();
        // "" is not decimal
        if (length <= 0) {
            return false;
        }
        for (int i = 0; i < length; i++) {
            char ch = str.charAt(i);
            if (ch < '0' || ch > '9') {
                return false;
            }
        }
        return true;
    }

    private void onInit() {
        String excludedLanguages = Settings.getExcludedLanguages();
        if (null == excludedLanguages) {
            return;
        }
        String[] languages = excludedLanguages.split("x");
        int iLength = languages.length;
        int jLength = LANGUAGES.length;
        for (int i = 0, j = 0; i < iLength; i++) {
            String language = languages[i];
            if (!isDecimal(language)) {
                continue;
            }
            for (; j < jLength; j++) {
                String pattern = LANGUAGES[j];
                if (pattern.equals(language)) {
                    // Get it
                    int row = j / 3;
                    int column = j % 3;
                    mSelections[row][column] = true;
                    break;
                }
            }
        }
    }

    private long saveSelectionsToLong() {
        boolean[][] selections = mSelections;
        long value = 0;
        for (int i = 0; i < ROW_COUNT; i++) {
            for (int j = 0; j < 3; j++) {
                if (selections[i][j]) {
                    value |= 1 << (i * 3 + j);
                }
            }
        }
        return value;
    }

    private void restoreSelectionsFromLong(long value) {
        boolean[][] selections = mSelections;
        for (int i = 0; i < ROW_COUNT; i++) {
            for (int j = 0; j < 3; j++) {
                selections[i][j] = 0 != ((value >>> (i * 3 + j)) & 1);
            }
        }
    }

    private void onRestore(@NonNull Bundle savedInstanceState) {
        restoreSelectionsFromLong(savedInstanceState.getLong(KEY_SELECTIONS));
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putLong(KEY_SELECTIONS, saveSelectionsToLong());
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mCancel = null;
        mOk = null;
        mSelectAll = null;
        mDeselectAll = null;
        mInvertSelection = null;
        mRecyclerView = null;
        mAdapter = null;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch(item.gereplacedemId()) {
            case android.R.id.home:
                finish();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public void onClick(View v) {
        if (null == mAdapter) {
            return;
        }
        if (v == mCancel) {
            finish();
        } else if (v == mOk) {
            StringBuilder sb = new StringBuilder();
            int i = 0;
            boolean first = true;
            for (boolean[] selections : mSelections) {
                for (boolean b : selections) {
                    if (b) {
                        if (!first) {
                            sb.append("x");
                        } else {
                            first = false;
                        }
                        sb.append(LANGUAGES[i]);
                    }
                    i++;
                }
            }
            String excludedLanguages = sb.toString();
            Settings.putExcludedLanguages(excludedLanguages);
            finish();
        } else if (v == mSelectAll) {
            for (boolean[] selections : mSelections) {
                int length = selections.length;
                for (int i = 0; i < length; i++) {
                    selections[i] = true;
                }
            }
            mAdapter.notifyDataSetChanged();
        } else if (v == mDeselectAll) {
            for (boolean[] selections : mSelections) {
                int length = selections.length;
                for (int i = 0; i < length; i++) {
                    selections[i] = false;
                }
            }
            mAdapter.notifyDataSetChanged();
        } else if (v == mInvertSelection) {
            for (boolean[] selections : mSelections) {
                int length = selections.length;
                for (int i = 0; i < length; i++) {
                    selections[i] = !selections[i];
                }
            }
            mAdapter.notifyDataSetChanged();
        }
    }

    private clreplaced LanguageHolder extends RecyclerView.ViewHolder implements SensitiveCheckBox.OnCheckedChangeListener {

        public TextView language;

        public SensitiveCheckBox original;

        public SensitiveCheckBox translated;

        public SensitiveCheckBox rewrite;

        public LanguageHolder(View itemView) {
            super(itemView);
            ViewGroup viewGroup = (ViewGroup) itemView;
            language = (TextView) viewGroup.getChildAt(0);
            original = (SensitiveCheckBox) viewGroup.getChildAt(1);
            translated = (SensitiveCheckBox) viewGroup.getChildAt(2);
            rewrite = (SensitiveCheckBox) viewGroup.getChildAt(3);
            original.setOnCheckedChangeListener(this);
            translated.setOnCheckedChangeListener(this);
            rewrite.setOnCheckedChangeListener(this);
        }

        @Override
        public void onCheckedChanged(SensitiveCheckBox view, boolean isChecked, boolean fromUser) {
            if (fromUser) {
                int row = getAdapterPosition();
                if (row < 0) {
                    return;
                }
                int column;
                if (view == original) {
                    column = 0;
                } else if (view == translated) {
                    column = 1;
                } else {
                    column = 2;
                }
                mSelections[row][column] = !mSelections[row][column];
            }
        }
    }

    private clreplaced LanguageAdapter extends RecyclerView.Adapter<LanguageHolder> {

        @Override
        public LanguageHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            return new LanguageHolder(getLayoutInflater().inflate(R.layout.item_excluded_languages, parent, false));
        }

        @Override
        public void onBindViewHolder(LanguageHolder holder, int position) {
            holder.language.setText(LANGUAGE_STR_IDS[position]);
            boolean[] selections = mSelections[position];
            holder.original.setChecked(selections[0]);
            holder.translated.setChecked(selections[1]);
            holder.rewrite.setChecked(selections[2]);
        }

        @Override
        public int gereplacedemCount() {
            return ROW_COUNT;
        }
    }
}

19 Source : GalleryInfoScene.java
with Apache License 2.0
from NuclearVGA

public final clreplaced GalleryInfoScene extends ToolbarScene {

    public static final String KEY_GALLERY_DETAIL = "gallery_detail";

    public static final String KEY_KEYS = "keys";

    public static final String KEY_VALUES = "values";

    private static final int INDEX_URL = 3;

    private static final int INDEX_PARENT = 10;

    /*---------------
     Whole life cycle
     ---------------*/
    @Nullable
    private ArrayList<String> mKeys;

    @Nullable
    private ArrayList<String> mValues;

    @Nullable
    private EasyRecyclerView mRecyclerView;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState == null) {
            onInit();
        } else {
            onRestore(savedInstanceState);
        }
    }

    private void handlerArgs(Bundle args) {
        if (args == null) {
            return;
        }
        GalleryDetail gd = args.getParcelable(KEY_GALLERY_DETAIL);
        if (gd == null) {
            return;
        }
        if (mKeys == null || mValues == null) {
            return;
        }
        Resources resources = getResources2();
        replacedertUtils.replacedertNotNull(resources);
        mKeys.add(resources.getString(R.string.header_key));
        mValues.add(resources.getString(R.string.header_value));
        mKeys.add(resources.getString(R.string.key_gid));
        mValues.add(Long.toString(gd.gid));
        mKeys.add(resources.getString(R.string.key_token));
        mValues.add(gd.token);
        mKeys.add(resources.getString(R.string.key_url));
        mValues.add(EhUrl.getGalleryDetailUrl(gd.gid, gd.token));
        mKeys.add(resources.getString(R.string.key_replacedle));
        mValues.add(gd.replacedle);
        mKeys.add(resources.getString(R.string.key_replacedle_jpn));
        mValues.add(gd.replacedleJpn);
        mKeys.add(resources.getString(R.string.key_thumb));
        mValues.add(gd.thumb);
        mKeys.add(resources.getString(R.string.key_category));
        mValues.add(EhUtils.getCategory(gd.category));
        mKeys.add(resources.getString(R.string.key_uploader));
        mValues.add(gd.uploader);
        mKeys.add(resources.getString(R.string.key_posted));
        mValues.add(gd.posted);
        mKeys.add(resources.getString(R.string.key_parent));
        mValues.add(gd.parent);
        mKeys.add(resources.getString(R.string.key_visible));
        mValues.add(gd.visible);
        mKeys.add(resources.getString(R.string.key_language));
        mValues.add(gd.language);
        mKeys.add(resources.getString(R.string.key_pages));
        mValues.add(Integer.toString(gd.pages));
        mKeys.add(resources.getString(R.string.key_size));
        mValues.add(gd.size);
        mKeys.add(resources.getString(R.string.key_favorite_count));
        mValues.add(Integer.toString(gd.favoriteCount));
        mKeys.add(resources.getString(R.string.key_favorited));
        mValues.add(Boolean.toString(gd.isFavorited));
        mKeys.add(resources.getString(R.string.key_rating_count));
        mValues.add(Integer.toString(gd.ratingCount));
        mKeys.add(resources.getString(R.string.key_rating));
        mValues.add(Float.toString(gd.rating));
        mKeys.add(resources.getString(R.string.key_torrents));
        mValues.add(Integer.toString(gd.torrentCount));
        mKeys.add(resources.getString(R.string.key_torrent_url));
        mValues.add(gd.torrentUrl);
        mKeys.add(resources.getString(R.string.favorite_name));
        mValues.add(gd.favoriteName);
    }

    protected void onInit() {
        mKeys = new ArrayList<>();
        mValues = new ArrayList<>();
        handlerArgs(getArguments());
    }

    protected void onRestore(@NonNull Bundle savedInstanceState) {
        mKeys = savedInstanceState.getStringArrayList(KEY_KEYS);
        mValues = savedInstanceState.getStringArrayList(KEY_VALUES);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putStringArrayList(KEY_KEYS, mKeys);
        outState.putStringArrayList(KEY_VALUES, mValues);
    }

    @Override
    public View onCreateView3(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.scene_gallery_info, container, false);
        Context context = getContext2();
        replacedertUtils.replacedertNotNull(context);
        mRecyclerView = (EasyRecyclerView) ViewUtils.$$(view, R.id.recycler_view);
        InfoAdapter adapter = new InfoAdapter();
        mRecyclerView.setAdapter(adapter);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(context, RecyclerView.VERTICAL, false));
        LinearDividerItemDecoration decoration = new LinearDividerItemDecoration(LinearDividerItemDecoration.VERTICAL, AttrResources.getAttrColor(context, R.attr.dividerColor), LayoutUtils.dp2pix(context, 1));
        decoration.setPadding(context.getResources().getDimensionPixelOffset(R.dimen.keyline_margin));
        mRecyclerView.addItemDecoration(decoration);
        // mRecyclerView.setSelector(Ripple.generateRippleDrawable(context, !AttrResources.getAttrBoolean(context, R.attr.isLightTheme), new ColorDrawable(Color.TRANSPARENT)));
        mRecyclerView.setClipToPadding(false);
        mRecyclerView.setHasFixedSize(true);
        // mRecyclerView.setOnItemClickListener(this);
        return view;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        setreplacedle(R.string.gallery_info);
        setNavigationIcon(R.drawable.v_arrow_left_dark_x24);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (null != mRecyclerView) {
            mRecyclerView.stopScroll();
            mRecyclerView = null;
        }
    }

    public boolean onItemClick(int position) {
        Context context = getContext2();
        if (null != context && 0 != position && null != mValues) {
            if (position == INDEX_PARENT) {
                UrlOpener.openUrl(context, mValues.get(position), true);
            } else {
                ClipboardManager cmb = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
                cmb.setPrimaryClip(ClipData.newPlainText(null, mValues.get(position)));
                if (position == INDEX_URL) {
                    // Save it to avoid detect the gallery
                    Settings.putClipboardTextHashCode(mValues.get(position).hashCode());
                }
                showTip(R.string.copied_to_clipboard, LENGTH_SHORT);
            }
            return true;
        } else {
            return false;
        }
    }

    @Override
    public void onNavigationClick() {
        onBackPressed();
    }

    private static clreplaced InfoHolder extends RecyclerView.ViewHolder {

        private final TextView key;

        private final TextView value;

        public InfoHolder(View itemView) {
            super(itemView);
            key = itemView.findViewById(R.id.key);
            value = itemView.findViewById(R.id.value);
        }
    }

    private clreplaced InfoAdapter extends RecyclerView.Adapter<InfoHolder> {

        private static final int TYPE_HEADER = 0;

        private static final int TYPE_DATA = 1;

        private final LayoutInflater mInflater;

        public InfoAdapter() {
            mInflater = getLayoutInflater2();
            replacedertUtils.replacedertNotNull(mInflater);
        }

        @Override
        public int gereplacedemViewType(int position) {
            if (position == 0) {
                return TYPE_HEADER;
            } else {
                return TYPE_DATA;
            }
        }

        @Override
        public InfoHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            return new InfoHolder(mInflater.inflate(viewType == TYPE_HEADER ? R.layout.item_gallery_info_header : R.layout.item_gallery_info_data, parent, false));
        }

        @Override
        public void onBindViewHolder(InfoHolder holder, int position) {
            if (mKeys != null && mValues != null) {
                holder.key.setText(mKeys.get(position));
                holder.value.setText(mValues.get(position));
                holder.itemView.setEnabled(position != 0);
                holder.itemView.setOnClickListener(v -> onItemClick(position));
            }
        }

        @Override
        public int gereplacedemCount() {
            return mKeys == null || mValues == null ? 0 : Math.min(mKeys.size(), mValues.size());
        }
    }
}

19 Source : GalleryCommentsScene.java
with Apache License 2.0
from NuclearVGA

public boolean onItemClick(EasyRecyclerView parent, View view, int position) {
    MainActivity activity = getActivity2();
    if (null == activity) {
        return false;
    }
    RecyclerView.ViewHolder holder = parent.getChildViewHolder(view);
    if (holder instanceof ActualCommentHolder) {
        ActualCommentHolder commentHolder = (ActualCommentHolder) holder;
        ClickableSpan span = commentHolder.comment.getCurrentSpan();
        commentHolder.comment.clearCurrentSpan();
        if (span instanceof URLSpan) {
            UrlOpener.openUrl(activity, ((URLSpan) span).getURL(), true);
        } else {
            showCommentDialog(position);
        }
    } else if (holder instanceof MoreCommentHolder && !mRefreshingComments && mAdapter != null) {
        mRefreshingComments = true;
        mShowAllComments = true;
        mAdapter.notifyItemChanged(position);
        String url = getGalleryDetailUrl();
        if (url != null) {
            // Request
            EhRequest request = new EhRequest().setMethod(EhClient.METHOD_GET_GALLERY_DETAIL).setArgs(url).setCallback(new RefreshCommentListener(activity, activity.getStageId(), getTag()));
            EhApplication.getEhClient(activity).execute(request);
        }
    }
    return true;
}

19 Source : GalleryInfoScene.java
with Apache License 2.0
from duzhaokun123

public final clreplaced GalleryInfoScene extends ToolbarScene {

    public static final String KEY_GALLERY_DETAIL = "gallery_detail";

    public static final String KEY_KEYS = "keys";

    public static final String KEY_VALUES = "values";

    private static final int INDEX_URL = 3;

    private static final int INDEX_PARENT = 10;

    /*---------------
     Whole life cycle
     ---------------*/
    @Nullable
    private ArrayList<String> mKeys;

    @Nullable
    private ArrayList<String> mValues;

    @Nullable
    private EasyRecyclerView mRecyclerView;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState == null) {
            onInit();
        } else {
            onRestore(savedInstanceState);
        }
    }

    private void handlerArgs(Bundle args) {
        if (args == null) {
            return;
        }
        GalleryDetail gd = args.getParcelable(KEY_GALLERY_DETAIL);
        if (gd == null) {
            return;
        }
        if (mKeys == null || mValues == null) {
            return;
        }
        mKeys.add(getString(R.string.header_key));
        mValues.add(getString(R.string.header_value));
        mKeys.add(getString(R.string.key_gid));
        mValues.add(Long.toString(gd.gid));
        mKeys.add(getString(R.string.key_token));
        mValues.add(gd.token);
        mKeys.add(getString(R.string.key_url));
        mValues.add(EhUrl.getGalleryDetailUrl(gd.gid, gd.token));
        mKeys.add(getString(R.string.key_replacedle));
        mValues.add(gd.replacedle);
        mKeys.add(getString(R.string.key_replacedle_jpn));
        mValues.add(gd.replacedleJpn);
        mKeys.add(getString(R.string.key_thumb));
        mValues.add(gd.thumb);
        mKeys.add(getString(R.string.key_category));
        mValues.add(EhUtils.getCategory(gd.category));
        mKeys.add(getString(R.string.key_uploader));
        mValues.add(gd.uploader);
        mKeys.add(getString(R.string.key_posted));
        mValues.add(gd.posted);
        mKeys.add(getString(R.string.key_parent));
        mValues.add(gd.parent);
        mKeys.add(getString(R.string.key_visible));
        mValues.add(gd.visible);
        mKeys.add(getString(R.string.key_language));
        mValues.add(gd.language);
        mKeys.add(getString(R.string.key_pages));
        mValues.add(Integer.toString(gd.pages));
        mKeys.add(getString(R.string.key_size));
        mValues.add(gd.size);
        mKeys.add(getString(R.string.key_favorite_count));
        mValues.add(Integer.toString(gd.favoriteCount));
        mKeys.add(getString(R.string.key_favorited));
        mValues.add(Boolean.toString(gd.isFavorited));
        mKeys.add(getString(R.string.key_rating_count));
        mValues.add(Integer.toString(gd.ratingCount));
        mKeys.add(getString(R.string.key_rating));
        mValues.add(Float.toString(gd.rating));
        mKeys.add(getString(R.string.key_torrents));
        mValues.add(Integer.toString(gd.torrentCount));
        mKeys.add(getString(R.string.key_torrent_url));
        mValues.add(gd.torrentUrl);
        mKeys.add(getString(R.string.favorite_name));
        mValues.add(gd.favoriteName);
    }

    protected void onInit() {
        mKeys = new ArrayList<>();
        mValues = new ArrayList<>();
        handlerArgs(getArguments());
    }

    protected void onRestore(@NonNull Bundle savedInstanceState) {
        mKeys = savedInstanceState.getStringArrayList(KEY_KEYS);
        mValues = savedInstanceState.getStringArrayList(KEY_VALUES);
    }

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putStringArrayList(KEY_KEYS, mKeys);
        outState.putStringArrayList(KEY_VALUES, mValues);
    }

    @Override
    public View onCreateViewWithToolbar(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.scene_gallery_info, container, false);
        Context context = getContext();
        replacedertUtils.replacedertNotNull(context);
        mRecyclerView = (EasyRecyclerView) ViewUtils.$$(view, R.id.recycler_view);
        InfoAdapter adapter = new InfoAdapter();
        mRecyclerView.setAdapter(adapter);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(context, RecyclerView.VERTICAL, false));
        LinearDividerItemDecoration decoration = new LinearDividerItemDecoration(LinearDividerItemDecoration.VERTICAL, AttrResources.getAttrColor(context, R.attr.dividerColor), LayoutUtils.dp2pix(context, 1));
        decoration.setPadding(context.getResources().getDimensionPixelOffset(R.dimen.keyline_margin));
        mRecyclerView.addItemDecoration(decoration);
        mRecyclerView.setClipToPadding(false);
        mRecyclerView.setHasFixedSize(true);
        return view;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        setreplacedle(R.string.gallery_info);
        setNavigationIcon(R.drawable.v_arrow_left_dark_x24);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (null != mRecyclerView) {
            mRecyclerView.stopScroll();
            mRecyclerView = null;
        }
    }

    public boolean onItemClick(int position) {
        Context context = getContext();
        if (null != context && 0 != position && null != mValues) {
            if (position == INDEX_PARENT) {
                UrlOpener.openUrl(context, mValues.get(position), true);
            } else {
                ClipboardUtil.addTextToClipboard(mValues.get(position));
                if (position == INDEX_URL) {
                    // Save it to avoid detect the gallery
                    Settings.putClipboardTextHashCode(mValues.get(position).hashCode());
                }
                showTip(R.string.copied_to_clipboard, LENGTH_SHORT);
            }
            return true;
        } else {
            return false;
        }
    }

    @Override
    public void onNavigationClick() {
        onBackPressed();
    }

    private static clreplaced InfoHolder extends RecyclerView.ViewHolder {

        private final TextView key;

        private final TextView value;

        public InfoHolder(View itemView) {
            super(itemView);
            key = itemView.findViewById(R.id.key);
            value = itemView.findViewById(R.id.value);
        }
    }

    private clreplaced InfoAdapter extends RecyclerView.Adapter<InfoHolder> {

        private static final int TYPE_HEADER = 0;

        private static final int TYPE_DATA = 1;

        private final LayoutInflater mInflater;

        public InfoAdapter() {
            mInflater = getLayoutInflater();
            replacedertUtils.replacedertNotNull(mInflater);
        }

        @Override
        public int gereplacedemViewType(int position) {
            if (position == 0) {
                return TYPE_HEADER;
            } else {
                return TYPE_DATA;
            }
        }

        @NonNull
        @Override
        public InfoHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            return new InfoHolder(mInflater.inflate(viewType == TYPE_HEADER ? R.layout.item_gallery_info_header : R.layout.item_gallery_info_data, parent, false));
        }

        @Override
        public void onBindViewHolder(@NonNull InfoHolder holder, int position) {
            if (mKeys != null && mValues != null) {
                holder.key.setText(mKeys.get(position));
                holder.value.setText(mValues.get(position));
                holder.itemView.setEnabled(position != 0);
                holder.itemView.setOnClickListener(v -> onItemClick(position));
            }
        }

        @Override
        public int gereplacedemCount() {
            return mKeys == null || mValues == null ? 0 : Math.min(mKeys.size(), mValues.size());
        }
    }

    @Override
    public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
        Insets insets1 = insets.getInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.ime());
        v.setPadding(insets1.left, 0, insets1.right, 0);
        View statusBarBackground = v.findViewById(R.id.status_bar_background);
        statusBarBackground.getLayoutParams().height = insets1.top;
        statusBarBackground.setBackgroundColor(AttrResources.getAttrColor(requireContext(), R.attr.colorPrimaryDark));
        if (mRecyclerView != null) {
            int keyline_margin = getResources().getDimensionPixelOffset(R.dimen.keyline_margin);
            mRecyclerView.setPadding(mRecyclerView.getPaddingLeft(), mRecyclerView.getPaddingTop(), mRecyclerView.getPaddingRight(), keyline_margin + insets1.bottom);
        }
        return WindowInsetsCompat.CONSUMED;
    }
}

19 Source : HistoryScene.java
with Apache License 2.0
from axlecho

@Override
public boolean onItemLongClick(EasyRecyclerView parent, View view, int position, long id) {
    final Context context = getContext2();
    final MainActivity activity = getActivity2();
    if (null == context || null == activity || null == mLazyList) {
        return false;
    }
    final GalleryInfo gi = mLazyList.get(position);
    new AlertDialog.Builder(context).setreplacedle(EhUtils.getSuitablereplacedle(gi)).sereplacedems(R.array.gallery_list_menu_entries, (dialog, which) -> {
        switch(which) {
            case // Download
            0:
                CommonOperations.startDownload(activity, gi, false);
                break;
            case // Favorites
            1:
                CommonOperations.addToFavorites(activity, gi);
                showTip(R.string.add_to_favorite_success, LENGTH_SHORT);
                break;
        }
    }).show();
    return true;
}

19 Source : GalleryInfoScene.java
with Apache License 2.0
from axlecho

public final clreplaced GalleryInfoScene extends ToolbarScene implements EasyRecyclerView.OnItemClickListener {

    public static final String KEY_GALLERY_DETAIL = "gallery_detail";

    public static final String KEY_KEYS = "keys";

    public static final String KEY_VALUES = "values";

    /*---------------
     Whole life cycle
     ---------------*/
    @Nullable
    private ArrayList<String> mKeys;

    @Nullable
    private ArrayList<String> mValues;

    @Nullable
    private EasyRecyclerView mRecyclerView;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState == null) {
            onInit();
        } else {
            onRestore(savedInstanceState);
        }
    }

    private void handlerArgs(Bundle args) {
        if (args == null) {
            return;
        }
        GalleryDetail gd = args.getParcelable(KEY_GALLERY_DETAIL);
        if (gd == null) {
            return;
        }
        if (mKeys == null || mValues == null) {
            return;
        }
        Resources resources = getResources2();
        replacedertUtils.replacedertNotNull(resources);
        mKeys.add(resources.getString(R.string.header_key));
        mValues.add(resources.getString(R.string.header_value));
        mKeys.add(resources.getString(R.string.key_gid));
        mValues.add(gd.gid);
        mKeys.add(resources.getString(R.string.key_token));
        mValues.add(gd.token);
        mKeys.add(resources.getString(R.string.key_url));
        mValues.add(EhUrl.getGalleryDetailUrl(gd.gid, gd.token));
        mKeys.add(resources.getString(R.string.key_replacedle));
        mValues.add(gd.replacedle);
        mKeys.add(resources.getString(R.string.key_replacedle_jpn));
        mValues.add(gd.replacedleJpn);
        mKeys.add(resources.getString(R.string.key_thumb));
        mValues.add(gd.thumb);
        mKeys.add(resources.getString(R.string.key_category));
        mValues.add(EhUtils.getCategory(gd.category));
        mKeys.add(resources.getString(R.string.key_uploader));
        mValues.add(gd.uploader);
        mKeys.add(resources.getString(R.string.key_posted));
        mValues.add(gd.posted);
        mKeys.add(resources.getString(R.string.key_rating));
        mValues.add(Float.toString(gd.rating));
        mKeys.add(resources.getString(R.string.favorite_name));
        mValues.add(gd.favoriteName);
    }

    protected void onInit() {
        mKeys = new ArrayList<>();
        mValues = new ArrayList<>();
        handlerArgs(getArguments());
    }

    protected void onRestore(@NonNull Bundle savedInstanceState) {
        mKeys = savedInstanceState.getStringArrayList(KEY_KEYS);
        mValues = savedInstanceState.getStringArrayList(KEY_VALUES);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putStringArrayList(KEY_KEYS, mKeys);
        outState.putStringArrayList(KEY_VALUES, mValues);
    }

    @SuppressWarnings("deprecation")
    @Nullable
    @Override
    public View onCreateView3(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.scene_gallery_info, container, false);
        Context context = getContext2();
        replacedertUtils.replacedertNotNull(context);
        mRecyclerView = (EasyRecyclerView) ViewUtils.$$(view, R.id.recycler_view);
        InfoAdapter adapter = new InfoAdapter();
        mRecyclerView.setAdapter(adapter);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(context, RecyclerView.VERTICAL, false));
        LinearDividerItemDecoration decoration = new LinearDividerItemDecoration(LinearDividerItemDecoration.VERTICAL, AttrResources.getAttrColor(context, R.attr.dividerColor), LayoutUtils.dp2pix(context, 1));
        decoration.setPadding(context.getResources().getDimensionPixelOffset(R.dimen.keyline_margin));
        mRecyclerView.addItemDecoration(decoration);
        mRecyclerView.setSelector(Ripple.generateRippleDrawable(context, !AttrResources.getAttrBoolean(context, R.attr.isLightTheme), new ColorDrawable(Color.TRANSPARENT)));
        mRecyclerView.setClipToPadding(false);
        mRecyclerView.setHasFixedSize(true);
        mRecyclerView.setOnItemClickListener(this);
        return view;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        setreplacedle(R.string.gallery_info);
        setNavigationIcon(R.drawable.v_arrow_left_dark_x24);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (null != mRecyclerView) {
            mRecyclerView.stopScroll();
            mRecyclerView = null;
        }
    }

    @Override
    public boolean onItemClick(EasyRecyclerView parent, View view, int position, long id) {
        Context context = getContext2();
        if (null != context && 0 != position && null != mValues) {
            ClipboardManager cmb = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
            cmb.setPrimaryClip(ClipData.newPlainText(null, mValues.get(position)));
            if (position == 3) {
                // Save it to avoid detect the gallery
                Settings.putClipboardTextHashCode(mValues.get(position).hashCode());
            }
            showTip(R.string.copied_to_clipboard, LENGTH_SHORT);
            return true;
        } else {
            return false;
        }
    }

    @Override
    public void onNavigationClick() {
        onBackPressed();
    }

    private static clreplaced InfoHolder extends RecyclerView.ViewHolder {

        private final TextView key;

        private final TextView value;

        public InfoHolder(View itemView) {
            super(itemView);
            key = (TextView) itemView.findViewById(R.id.key);
            value = (TextView) itemView.findViewById(R.id.value);
        }
    }

    private clreplaced InfoAdapter extends RecyclerView.Adapter<InfoHolder> {

        private static final int TYPE_HEADER = 0;

        private static final int TYPE_DATA = 1;

        private final LayoutInflater mInflater;

        public InfoAdapter() {
            mInflater = getLayoutInflater2();
            replacedertUtils.replacedertNotNull(mInflater);
        }

        @Override
        public int gereplacedemViewType(int position) {
            if (position == 0) {
                return TYPE_HEADER;
            } else {
                return TYPE_DATA;
            }
        }

        @Override
        public InfoHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            return new InfoHolder(mInflater.inflate(viewType == TYPE_HEADER ? R.layout.item_gallery_info_header : R.layout.item_gallery_info_data, parent, false));
        }

        @Override
        public void onBindViewHolder(InfoHolder holder, int position) {
            if (mKeys != null && mValues != null) {
                holder.key.setText(mKeys.get(position));
                holder.value.setText(mValues.get(position));
                holder.itemView.setEnabled(position != 0);
            }
        }

        @Override
        public int gereplacedemCount() {
            return mKeys == null || mValues == null ? 0 : Math.min(mKeys.size(), mValues.size());
        }
    }
}

19 Source : GalleryCommentsScene.java
with Apache License 2.0
from axlecho

@Override
public boolean onItemClick(EasyRecyclerView parent, View view, int position, long id) {
    Activity activity = getActivity2();
    if (null == activity) {
        return false;
    }
    RecyclerView.ViewHolder holder = parent.getChildViewHolder(view);
    if (holder instanceof CommentHolder) {
        CommentHolder commentHolder = (CommentHolder) holder;
        ClickableSpan span = commentHolder.comment.getCurrentSpan();
        commentHolder.comment.clearCurrentSpan();
        if (span instanceof URLSpan) {
            UrlOpener.openUrl(activity, ((URLSpan) span).getURL(), true);
            return true;
        }
    }
    showCommentDialog(position);
    return true;
}

19 Source : PluginsActivity.java
with Apache License 2.0
from axlecho

@Override
public boolean onItemClick(EasyRecyclerView easyRecyclerView, View view, int position, long id) {
    return true;
}

18 Source : DirExplorer.java
with Apache License 2.0
from xiaojieonly

@Override
public boolean onItemClick(EasyRecyclerView parent, View view, int position, long id) {
    File file = mFiles.get(position);
    if (file == PARENT_DIR) {
        file = mCurrentFile.getParentFile();
    }
    setCurrentFile(file);
    return true;
}

18 Source : ContentLayout.java
with Apache License 2.0
from xiaojieonly

public clreplaced ContentLayout extends FrameLayout {

    private ProgressView mProgressView;

    private TextView mTipView;

    private ViewGroup mContentView;

    private RefreshLayout mRefreshLayout;

    private EasyRecyclerView mRecyclerView;

    private FastScroller mFastScroller;

    private ContentHelper mContentHelper;

    private int mRecyclerViewOriginTop;

    private int mRecyclerViewOriginBottom;

    public ContentLayout(Context context) {
        super(context);
        init(context);
    }

    public ContentLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public ContentLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        LayoutInflater.from(context).inflate(R.layout.widget_content_layout, this);
        mProgressView = (ProgressView) findViewById(R.id.progress);
        mTipView = (TextView) findViewById(R.id.tip);
        mContentView = (ViewGroup) findViewById(R.id.content_view);
        mRefreshLayout = (RefreshLayout) mContentView.findViewById(R.id.refresh_layout);
        mFastScroller = (FastScroller) mContentView.findViewById(R.id.fast_scroller);
        mRecyclerView = (EasyRecyclerView) mRefreshLayout.findViewById(R.id.recycler_view);
        mFastScroller.attachToRecyclerView(mRecyclerView);
        HandlerDrawable drawable = new HandlerDrawable();
        drawable.setColor(AttrResources.getAttrColor(context, R.attr.widgetColorThemeAccent));
        mFastScroller.setHandlerDrawable(drawable);
        mRefreshLayout.setHeaderColorSchemeResources(R.color.loading_indicator_red, R.color.loading_indicator_purple, R.color.loading_indicator_blue, R.color.loading_indicator_cyan, R.color.loading_indicator_green, R.color.loading_indicator_yellow);
        mRefreshLayout.setFooterColorSchemeResources(R.color.loading_indicator_red, R.color.loading_indicator_blue, R.color.loading_indicator_green, R.color.loading_indicator_orange);
        mRecyclerViewOriginTop = mRecyclerView.getPaddingTop();
        mRecyclerViewOriginBottom = mRecyclerView.getPaddingBottom();
    }

    @NonNull
    public EasyRecyclerView getRecyclerView() {
        return mRecyclerView;
    }

    public FastScroller getFastScroller() {
        return mFastScroller;
    }

    public RefreshLayout getRefreshLayout() {
        return mRefreshLayout;
    }

    public void setHelper(ContentHelper helper) {
        mContentHelper = helper;
        helper.init(this);
    }

    public void showFastScroll() {
        if (!mFastScroller.isAttached()) {
            mFastScroller.attachToRecyclerView(mRecyclerView);
        }
    }

    public void hideFastScroll() {
        mFastScroller.detachedFromRecyclerView();
    }

    public void setFitPaddingTop(int fitPaddingTop) {
        // RecyclerView
        mRecyclerView.setPadding(mRecyclerView.getPaddingLeft(), mRecyclerViewOriginTop + fitPaddingTop, mRecyclerView.getPaddingRight(), mRecyclerView.getPaddingBottom());
        // RefreshLayout
        // TODO
        mRefreshLayout.setProgressViewOffset(false, fitPaddingTop, fitPaddingTop + LayoutUtils.dp2pix(getContext(), 32));
    }

    public void setFitPaddingBottom(int fitPaddingBottom) {
        // RecyclerView
        mRecyclerView.setPadding(mRecyclerView.getPaddingLeft(), mRecyclerView.getPaddingTop(), mRecyclerView.getPaddingRight(), mRecyclerViewOriginBottom + fitPaddingBottom);
    }

    @Override
    protected Parcelable onSaveInstanceState() {
        return mContentHelper.saveInstanceState(super.onSaveInstanceState());
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        super.onRestoreInstanceState(mContentHelper.restoreInstanceState(state));
    }

    public abstract static clreplaced ContentHelper<E extends Parcelable> implements ViewTransition.OnShowViewListener {

        private static final String TAG = ContentHelper.clreplaced.getSimpleName();

        private static final int CHECK_DUPLICATE_RANGE = 50;

        private static final String KEY_SUPER = "super";

        private static final String KEY_SHOWN_VIEW = "shown_view";

        private static final String KEY_TIP = "tip";

        private static final String KEY_DATA = "data";

        private static final String KEY_NEXT_ID = "next_id";

        private static final String KEY_PAGE_DIVIDER = "page_divider";

        private static final String KEY_START_PAGE = "start_page";

        private static final String KEY_END_PAGE = "end_page";

        private static final String KEY_PAGES = "pages";

        public static final int TYPE_REFRESH = 0;

        public static final int TYPE_PRE_PAGE = 1;

        public static final int TYPE_PRE_PAGE_KEEP_POS = 2;

        public static final int TYPE_NEXT_PAGE = 3;

        public static final int TYPE_NEXT_PAGE_KEEP_POS = 4;

        public static final int TYPE_SOMEWHERE = 5;

        public static final int TYPE_REFRESH_PAGE = 6;

        public static final int REFRESH_TYPE_HEADER = 0;

        public static final int REFRESH_TYPE_FOOTER = 1;

        public static final int REFRESH_TYPE_PROGRESS_VIEW = 2;

        private ProgressView mProgressView;

        private TextView mTipView;

        private ViewGroup mContentView;

        private RefreshLayout mRefreshLayout;

        private EasyRecyclerView mRecyclerView;

        private ViewTransition mViewTransition;

        /**
         * Store data
         */
        private ArrayList<E> mData = new ArrayList<>();

        /**
         * Generate task id
         */
        private final IntIdGenerator mIdGenerator = new IntIdGenerator();

        /**
         * Store the page divider index
         *
         * For example, the data contain page 3, page 4, page 5,
         * page 3 size is 7, page 4 size is 8, page 5 size is 9,
         * so <code>mPageDivider</code> contain 7, 15, 24.
         */
        private IntList mPageDivider = new IntList();

        /**
         * The first page in <code>mData</code>
         */
        private int mStartPage;

        /**
         * The last page + 1 in <code>mData</code>
         */
        private int mEndPage;

        /**
         * The available page count.
         */
        private int mPages;

        private int mNextPage;

        private int mCurrentTaskId;

        private int mCurrentTaskType;

        private int mCurrentTaskPage;

        private int mNextPageScrollSize;

        private String mEmptyString = "No hint";

        private final RecyclerView.OnScrollListener mOnScrollListener = new RecyclerView.OnScrollListener() {

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                if (!mRefreshLayout.isRefreshing() && mRefreshLayout.isAlmostBottom() && mEndPage < mPages) {
                    // Get next page
                    mRefreshLayout.setFooterRefreshing(true);
                    mOnRefreshListener.onFooterRefresh();
                }
            }
        };

        private final RefreshLayout.OnRefreshListener mOnRefreshListener = new RefreshLayout.OnRefreshListener() {

            @Override
            public void onHeaderRefresh() {
                if (mStartPage > 0) {
                    mCurrentTaskId = mIdGenerator.nextId();
                    mCurrentTaskType = TYPE_PRE_PAGE_KEEP_POS;
                    mCurrentTaskPage = mStartPage - 1;
                    getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
                } else {
                    doRefresh();
                }
            }

            @Override
            public void onFooterRefresh() {
                if (mEndPage < mPages) {
                    // Get next page
                    // Fill pages before NextPage with empty list
                    while (mNextPage > mEndPage && mEndPage < mPages) {
                        mCurrentTaskId = mIdGenerator.nextId();
                        mCurrentTaskType = TYPE_NEXT_PAGE_KEEP_POS;
                        mCurrentTaskPage = mEndPage;
                        onGetPageData(mCurrentTaskId, mPages, mNextPage, Collections.emptyList());
                    }
                    mCurrentTaskId = mIdGenerator.nextId();
                    mCurrentTaskType = TYPE_NEXT_PAGE_KEEP_POS;
                    mCurrentTaskPage = mEndPage;
                    getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
                } else if (mEndPage == mPages) {
                    // Refresh last page
                    mCurrentTaskId = mIdGenerator.nextId();
                    mCurrentTaskType = TYPE_REFRESH_PAGE;
                    mCurrentTaskPage = mEndPage - 1;
                    getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
                } else {
                    Log.e(TAG, "Try to footer refresh, but mEndPage = " + mEndPage + ", mPages = " + mPages);
                    mRefreshLayout.setFooterRefreshing(false);
                }
            }
        };

        private final LayoutManagerUtils.OnScrollToPositionListener mOnScrollToPositionListener = opsition -> ContentHelper.this.onScrollToPosition(opsition);

        // private final LayoutManagerUtils.OnScrollToPositionListener mOnScrollToPositionListener =
        // new LayoutManagerUtils.OnScrollToPositionListener() {
        // @Override
        // public void onScrollToPosition(int position) {
        // ContentHelper.this.onScrollToPosition(position);
        // }
        // };
        private void init(ContentLayout contentLayout) {
            mNextPageScrollSize = LayoutUtils.dp2pix(contentLayout.getContext(), 48);
            mProgressView = contentLayout.mProgressView;
            mTipView = contentLayout.mTipView;
            mContentView = contentLayout.mContentView;
            mRefreshLayout = contentLayout.mRefreshLayout;
            mRecyclerView = contentLayout.mRecyclerView;
            Drawable drawable = DrawableManager.getVectorDrawable(getContext(), R.drawable.big_sad_pandroid);
            drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
            mTipView.setCompoundDrawables(null, drawable, null, null);
            mViewTransition = new ViewTransition(mContentView, mProgressView, mTipView);
            mViewTransition.setOnShowViewListener(this);
            mRecyclerView.addOnScrollListener(mOnScrollListener);
            mRefreshLayout.setOnRefreshListener(mOnRefreshListener);
            mTipView.setOnClickListener(// 刷新页面
            v -> refresh());
        // mTipView.setOnClickListener(new OnClickListener() {
        // @Override
        // public void onClick(View v) {
        // refresh();
        // }
        // });
        }

        /**
         * Call {@link #onGetPageData(int, int, int, List)} when get data
         *
         * @param taskId task id
         * @param page the page to get
         */
        protected abstract void getPageData(int taskId, int type, int page);

        protected abstract Context getContext();

        protected abstract void notifyDataSetChanged();

        protected abstract void notifyItemRangeRemoved(int positionStart, int itemCount);

        protected abstract void notifyItemRangeInserted(int positionStart, int itemCount);

        protected void onScrollToPosition(int postion) {
        }

        @Override
        public void onShowView(View hiddenView, View shownView) {
        }

        public int getShownViewIndex() {
            return mViewTransition.getShownViewIndex();
        }

        public void setRefreshLayoutEnable(boolean enable) {
            mRefreshLayout.setEnabled(enable);
        }

        public void setEnable(boolean enable) {
            mRefreshLayout.setEnabled(enable);
        }

        public void setEmptyString(String str) {
            mEmptyString = str;
        }

        public List<E> getData() {
            return mData;
        }

        /**
         * @throws IndexOutOfBoundsException
         *                if {@code location < 0 || location >= size()}
         */
        public E getDataAt(int location) {
            return mData.get(location);
        }

        @Nullable
        public E getDataAtEx(int location) {
            if (location >= 0 && location < mData.size()) {
                return mData.get(location);
            } else {
                return null;
            }
        }

        public int size() {
            return mData.size();
        }

        public boolean isCurrentTask(int taskId) {
            return mCurrentTaskId == taskId;
        }

        public int getPages() {
            return mPages;
        }

        public void addAt(int index, E data) {
            mData.add(index, data);
            onAddData(data);
            for (int i = 0, n = mPageDivider.size(); i < n; i++) {
                int divider = mPageDivider.get(i);
                if (index < divider) {
                    mPageDivider.set(i, divider + 1);
                }
            }
            notifyItemRangeInserted(index, 1);
        }

        public void removeAt(int index) {
            E data = mData.remove(index);
            onRemoveData(data);
            for (int i = 0, n = mPageDivider.size(); i < n; i++) {
                int divider = mPageDivider.get(i);
                if (index < divider) {
                    mPageDivider.set(i, divider - 1);
                }
            }
            notifyItemRangeRemoved(index, 1);
        }

        protected abstract boolean isDuplicate(E d1, E d2);

        private void removeDuplicateData(List<E> data, int start, int end) {
            start = Math.max(0, start);
            end = Math.min(mData.size(), end);
            for (Iterator<E> iterator = data.iterator(); iterator.hasNext(); ) {
                E d = iterator.next();
                for (int i = start; i < end; i++) {
                    if (isDuplicate(d, mData.get(i))) {
                        iterator.remove();
                        break;
                    }
                }
            }
        }

        protected void onAddData(E data) {
        }

        protected void onAddData(List<E> data) {
        }

        protected void onRemoveData(E data) {
        }

        protected void onRemoveData(List<E> data) {
        }

        protected void onClearData() {
        }

        public void onGetPageData(int taskId, int pages, int nextPage, List<E> data) {
            if (mCurrentTaskId == taskId) {
                int dataSize;
                switch(mCurrentTaskType) {
                    case TYPE_REFRESH:
                        mStartPage = 0;
                        mEndPage = 1;
                        mPages = pages;
                        mNextPage = nextPage;
                        mPageDivider.clear();
                        mPageDivider.add(data.size());
                        if (data.isEmpty()) {
                            mData.clear();
                            onClearData();
                            notifyDataSetChanged();
                            if (true || mEndPage >= mPages) {
                                // Not found
                                // Ui change, show empty string
                                mRefreshLayout.setHeaderRefreshing(false);
                                mRefreshLayout.setFooterRefreshing(false);
                                showEmptyString();
                            } else {
                                // Ui change, show progress bar
                                mRefreshLayout.setHeaderRefreshing(false);
                                mRefreshLayout.setFooterRefreshing(false);
                                showProgressBar();
                                // Get next page
                                mCurrentTaskId = mIdGenerator.nextId();
                                mCurrentTaskType = TYPE_NEXT_PAGE_KEEP_POS;
                                mCurrentTaskPage = mEndPage;
                                getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
                            }
                        } else {
                            mData.clear();
                            onClearData();
                            mData.addAll(data);
                            onAddData(data);
                            notifyDataSetChanged();
                            // Ui change, show content
                            mRefreshLayout.setHeaderRefreshing(false);
                            mRefreshLayout.setFooterRefreshing(false);
                            showContent();
                            // RecyclerView scroll
                            if (mRecyclerView.isAttachedToWindow()) {
                                mRecyclerView.stopScroll();
                                LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), 0, 0);
                                onScrollToPosition(0);
                            }
                        }
                        break;
                    case TYPE_PRE_PAGE:
                    case TYPE_PRE_PAGE_KEEP_POS:
                        removeDuplicateData(data, 0, CHECK_DUPLICATE_RANGE);
                        dataSize = data.size();
                        for (int i = 0, n = mPageDivider.size(); i < n; i++) {
                            mPageDivider.set(i, mPageDivider.get(i) + dataSize);
                        }
                        mPageDivider.add(0, dataSize);
                        mStartPage--;
                        mPages = Math.max(mEndPage, pages);
                        // replacedert mStartPage >= 0
                        if (data.isEmpty()) {
                            if (true || mStartPage <= 0) {
                                // OK, that's all
                                if (mData.isEmpty()) {
                                    // Ui change, show empty string
                                    mRefreshLayout.setHeaderRefreshing(false);
                                    mRefreshLayout.setFooterRefreshing(false);
                                    showEmptyString();
                                } else {
                                    // Ui change, show content
                                    mRefreshLayout.setHeaderRefreshing(false);
                                    mRefreshLayout.setFooterRefreshing(false);
                                    showContent();
                                    if (mCurrentTaskType == TYPE_PRE_PAGE && mRecyclerView.isAttachedToWindow()) {
                                        // RecyclerView scroll, to top
                                        mRecyclerView.stopScroll();
                                        LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), 0, 0);
                                        onScrollToPosition(0);
                                    }
                                }
                            } else {
                                // Keep UI
                                // Get previous
                                mCurrentTaskId = mIdGenerator.nextId();
                                // Keep mCurrentTaskType
                                mCurrentTaskPage = mStartPage - 1;
                                getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
                            }
                        } else {
                            mData.addAll(0, data);
                            onAddData(data);
                            notifyItemRangeInserted(0, data.size());
                            // Ui change, show content
                            mRefreshLayout.setHeaderRefreshing(false);
                            mRefreshLayout.setFooterRefreshing(false);
                            showContent();
                            if (mRecyclerView.isAttachedToWindow()) {
                                // RecyclerView scroll
                                if (mCurrentTaskType == TYPE_PRE_PAGE_KEEP_POS) {
                                    mRecyclerView.stopScroll();
                                    LayoutManagerUtils.scrollToPositionProperly(mRecyclerView.getLayoutManager(), getContext(), dataSize - 1, mOnScrollToPositionListener);
                                } else {
                                    mRecyclerView.stopScroll();
                                    LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), 0, 0);
                                    onScrollToPosition(0);
                                }
                            }
                        }
                        break;
                    case TYPE_NEXT_PAGE:
                    case TYPE_NEXT_PAGE_KEEP_POS:
                        removeDuplicateData(data, mData.size() - CHECK_DUPLICATE_RANGE, mData.size());
                        dataSize = data.size();
                        int oldDataSize = mData.size();
                        mPageDivider.add(oldDataSize + dataSize);
                        mEndPage++;
                        mNextPage = nextPage;
                        mPages = Math.max(mEndPage, pages);
                        if (data.isEmpty()) {
                            if (true || mEndPage >= mPages) {
                                // OK, that's all
                                if (mData.isEmpty()) {
                                    // Ui change, show empty string
                                    mRefreshLayout.setHeaderRefreshing(false);
                                    mRefreshLayout.setFooterRefreshing(false);
                                    showEmptyString();
                                } else {
                                    // Ui change, show content
                                    mRefreshLayout.setHeaderRefreshing(false);
                                    mRefreshLayout.setFooterRefreshing(false);
                                    showContent();
                                    if (mCurrentTaskType == TYPE_NEXT_PAGE && mRecyclerView.isAttachedToWindow()) {
                                        // RecyclerView scroll
                                        mRecyclerView.stopScroll();
                                        LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), oldDataSize, 0);
                                        onScrollToPosition(oldDataSize);
                                    }
                                }
                            } else {
                                // Keep UI
                                // Get next page
                                mCurrentTaskId = mIdGenerator.nextId();
                                // Keep mCurrentTaskType
                                mCurrentTaskPage = mEndPage;
                                getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
                            }
                        } else {
                            mData.addAll(data);
                            onAddData(data);
                            notifyItemRangeInserted(oldDataSize, dataSize);
                            // Ui change, show content
                            mRefreshLayout.setHeaderRefreshing(false);
                            mRefreshLayout.setFooterRefreshing(false);
                            showContent();
                            if (mRecyclerView.isAttachedToWindow()) {
                                if (mCurrentTaskType == TYPE_NEXT_PAGE_KEEP_POS) {
                                    mRecyclerView.stopScroll();
                                    mRecyclerView.smoothScrollBy(0, mNextPageScrollSize);
                                } else {
                                    mRecyclerView.stopScroll();
                                    LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), oldDataSize, 0);
                                    onScrollToPosition(oldDataSize);
                                }
                            }
                        }
                        break;
                    case TYPE_SOMEWHERE:
                        mStartPage = mCurrentTaskPage;
                        mEndPage = mCurrentTaskPage + 1;
                        mNextPage = nextPage;
                        mPages = pages;
                        mPageDivider.clear();
                        mPageDivider.add(data.size());
                        if (data.isEmpty()) {
                            mData.clear();
                            onClearData();
                            notifyDataSetChanged();
                            if (true || mEndPage >= mPages) {
                                // Not found
                                // Ui change, show empty string
                                mRefreshLayout.setHeaderRefreshing(false);
                                mRefreshLayout.setFooterRefreshing(false);
                                showEmptyString();
                            } else {
                                // Ui change, show progress bar
                                mRefreshLayout.setHeaderRefreshing(false);
                                mRefreshLayout.setFooterRefreshing(false);
                                showProgressBar();
                                // Get next page
                                mCurrentTaskId = mIdGenerator.nextId();
                                mCurrentTaskType = TYPE_NEXT_PAGE_KEEP_POS;
                                mCurrentTaskPage = mEndPage;
                                getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
                            }
                        } else {
                            mData.clear();
                            onClearData();
                            mData.addAll(data);
                            onAddData(data);
                            notifyDataSetChanged();
                            // Ui change, show content
                            mRefreshLayout.setHeaderRefreshing(false);
                            mRefreshLayout.setFooterRefreshing(false);
                            showContent();
                            if (mRecyclerView.isAttachedToWindow()) {
                                // RecyclerView scroll
                                mRecyclerView.stopScroll();
                                LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), 0, 0);
                                onScrollToPosition(0);
                            }
                        }
                        break;
                    case TYPE_REFRESH_PAGE:
                        if (mCurrentTaskPage < mStartPage || mCurrentTaskPage >= mEndPage) {
                            Log.e(TAG, "TYPE_REFRESH_PAGE, but mCurrentTaskPage = " + mCurrentTaskPage + ", mStartPage = " + mStartPage + ", mEndPage = " + mEndPage);
                            break;
                        }
                        if (mCurrentTaskPage == mEndPage - 1) {
                            mNextPage = nextPage;
                        }
                        mPages = Math.max(mEndPage, pages);
                        int oldIndexStart = mCurrentTaskPage == mStartPage ? 0 : mPageDivider.get(mCurrentTaskPage - mStartPage - 1);
                        int oldIndexEnd = mPageDivider.get(mCurrentTaskPage - mStartPage);
                        List<E> toRemove = mData.subList(oldIndexStart, oldIndexEnd);
                        onRemoveData(toRemove);
                        toRemove.clear();
                        removeDuplicateData(data, oldIndexStart - CHECK_DUPLICATE_RANGE, oldIndexStart + CHECK_DUPLICATE_RANGE);
                        int newIndexStart = oldIndexStart;
                        int newIndexEnd = newIndexStart + data.size();
                        mData.addAll(oldIndexStart, data);
                        onAddData(data);
                        notifyDataSetChanged();
                        for (int i = mCurrentTaskPage - mStartPage, n = mPageDivider.size(); i < n; i++) {
                            mPageDivider.set(i, mPageDivider.get(i) - oldIndexEnd + newIndexEnd);
                        }
                        if (mData.isEmpty()) {
                            // Ui change, show empty string
                            mRefreshLayout.setHeaderRefreshing(false);
                            mRefreshLayout.setFooterRefreshing(false);
                            showEmptyString();
                        } else {
                            // Ui change, show content
                            mRefreshLayout.setHeaderRefreshing(false);
                            mRefreshLayout.setFooterRefreshing(false);
                            showContent();
                            // RecyclerView scroll
                            if (newIndexEnd > oldIndexEnd && newIndexEnd > 0 && mRecyclerView.isAttachedToWindow()) {
                                mRecyclerView.stopScroll();
                                LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), newIndexEnd - 1, 0);
                                onScrollToPosition(newIndexEnd - 1);
                            }
                        }
                        break;
                }
            }
        }

        public void onGetException(int taskId, Exception e) {
            if (mCurrentTaskId == taskId) {
                mRefreshLayout.setHeaderRefreshing(false);
                mRefreshLayout.setFooterRefreshing(false);
                String readableError;
                if (e != null) {
                    e.printStackTrace();
                    readableError = ExceptionUtils.getReadableString(e);
                } else {
                    readableError = getContext().getString(R.string.error_unknown);
                }
                if (mViewTransition.getShownViewIndex() == 0) {
                    Toast.makeText(getContext(), readableError, Toast.LENGTH_SHORT).show();
                } else {
                    showText(readableError);
                }
            }
        }

        public void showContent() {
            mViewTransition.showView(0);
        }

        private boolean isContentShowing() {
            return mViewTransition.getShownViewIndex() == 0;
        }

        public void showProgressBar() {
            showProgressBar(true);
        }

        public void showProgressBar(boolean animation) {
            mViewTransition.showView(1, animation);
        }

        public void showText(CharSequence text) {
            mTipView.setText(text);
            mViewTransition.showView(2);
        }

        public void showEmptyString() {
            showText(mEmptyString);
        }

        /**
         * Be carefull
         */
        public void doGetData(int type, int page, int refreshType) {
            switch(refreshType) {
                default:
                case REFRESH_TYPE_HEADER:
                    showContent();
                    mRefreshLayout.setFooterRefreshing(false);
                    mRefreshLayout.setHeaderRefreshing(true);
                    break;
                case REFRESH_TYPE_FOOTER:
                    showContent();
                    mRefreshLayout.setHeaderRefreshing(false);
                    mRefreshLayout.setFooterRefreshing(true);
                    break;
                case REFRESH_TYPE_PROGRESS_VIEW:
                    showProgressBar();
                    mRefreshLayout.setHeaderRefreshing(false);
                    mRefreshLayout.setFooterRefreshing(false);
                    break;
            }
            mCurrentTaskId = mIdGenerator.nextId();
            mCurrentTaskType = type;
            mCurrentTaskPage = page;
            getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
        }

        private void doRefresh() {
            mCurrentTaskId = mIdGenerator.nextId();
            mCurrentTaskType = TYPE_REFRESH;
            mCurrentTaskPage = 0;
            getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
        }

        /**
         * Lisk {@link #refresh()}, but no animation when show progress bar
         */
        public void firstRefresh() {
            showProgressBar(false);
            doRefresh();
        }

        /**
         * Show progress bar first, than do refresh
         */
        public void refresh() {
            showProgressBar();
            doRefresh();
        }

        private void cancelCurrentTask() {
            mCurrentTaskId = mIdGenerator.nextId();
            mRefreshLayout.setHeaderRefreshing(false);
            mRefreshLayout.setFooterRefreshing(false);
        }

        private int getPageStart(int page) {
            if (mStartPage == page) {
                return 0;
            } else {
                return mPageDivider.get(page - mStartPage - 1);
            }
        }

        private int getPageEnd(int page) {
            return mPageDivider.get(page - mStartPage);
        }

        private int getPageForPosition(int position) {
            if (position < 0) {
                return -1;
            }
            IntList pageDivider = mPageDivider;
            for (int i = 0, n = pageDivider.size(); i < n; i++) {
                if (position < pageDivider.get(i)) {
                    return i + mStartPage;
                }
            }
            return -1;
        }

        public int getPageForTop() {
            return getPageForPosition(LayoutManagerUtils.getFirstVisibleItemPosition(mRecyclerView.getLayoutManager()));
        }

        public int getPageForBottom() {
            return getPageForPosition(LayoutManagerUtils.getLastVisibleItemPosition(mRecyclerView.getLayoutManager()));
        }

        public boolean canGoTo() {
            return isContentShowing();
        }

        /**
         * Check range first!
         *
         * @param page the target page
         * @throws IndexOutOfBoundsException
         */
        public void goTo(int page) throws IndexOutOfBoundsException {
            if (page < 0 || page >= mPages) {
                throw new IndexOutOfBoundsException("Page count is " + mPages + ", page is " + page);
            } else if (page >= mStartPage && page < mEndPage) {
                cancelCurrentTask();
                int position = getPageStart(page);
                mRecyclerView.stopScroll();
                LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), position, 0);
                onScrollToPosition(position);
            } else if (page == mStartPage - 1) {
                mRefreshLayout.setFooterRefreshing(false);
                mRefreshLayout.setHeaderRefreshing(true);
                mCurrentTaskId = mIdGenerator.nextId();
                mCurrentTaskType = TYPE_PRE_PAGE;
                mCurrentTaskPage = page;
                getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
            } else if (page == mEndPage) {
                mRefreshLayout.setHeaderRefreshing(false);
                mRefreshLayout.setFooterRefreshing(true);
                mCurrentTaskId = mIdGenerator.nextId();
                mCurrentTaskType = TYPE_NEXT_PAGE;
                mCurrentTaskPage = page;
                getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
            } else {
                mRefreshLayout.setFooterRefreshing(false);
                mRefreshLayout.setHeaderRefreshing(true);
                mCurrentTaskId = mIdGenerator.nextId();
                mCurrentTaskType = TYPE_SOMEWHERE;
                mCurrentTaskPage = page;
                getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
            }
        }

        private int mSavedDataId = IntIdGenerator.INVALID_ID;

        protected Parcelable saveInstanceState(Parcelable superState) {
            Bundle bundle = new Bundle();
            bundle.putParcelable(KEY_SUPER, superState);
            int shownView = mViewTransition.getShownViewIndex();
            bundle.putInt(KEY_SHOWN_VIEW, shownView);
            bundle.putString(KEY_TIP, mTipView.getText().toString());
            // TODO It's a bad design
            EhApplication app = (EhApplication) getContext().getApplicationContext();
            if (mSavedDataId != IntIdGenerator.INVALID_ID) {
                app.removeGlobalStuff(mSavedDataId);
                mSavedDataId = IntIdGenerator.INVALID_ID;
            }
            mSavedDataId = app.putGlobalStuff(mData);
            bundle.putInt(KEY_DATA, mSavedDataId);
            bundle.putInt(KEY_NEXT_ID, mIdGenerator.nextId());
            bundle.putParcelable(KEY_PAGE_DIVIDER, mPageDivider);
            bundle.putInt(KEY_START_PAGE, mStartPage);
            bundle.putInt(KEY_END_PAGE, mEndPage);
            bundle.putInt(KEY_PAGES, mPages);
            return bundle;
        }

        protected Parcelable restoreInstanceState(Parcelable state) {
            if (state instanceof Bundle) {
                Bundle bundle = (Bundle) state;
                mViewTransition.showView(bundle.getInt(KEY_SHOWN_VIEW), false);
                mTipView.setText(bundle.getString(KEY_TIP));
                mSavedDataId = bundle.getInt(KEY_DATA);
                ArrayList<E> newData = null;
                EhApplication app = (EhApplication) getContext().getApplicationContext();
                if (mSavedDataId != IntIdGenerator.INVALID_ID) {
                    newData = (ArrayList<E>) app.removeGlobalStuff(mSavedDataId);
                    mSavedDataId = IntIdGenerator.INVALID_ID;
                    if (newData != null) {
                        mData = newData;
                    }
                }
                mIdGenerator.setNextId(bundle.getInt(KEY_NEXT_ID));
                mPageDivider = bundle.getParcelable(KEY_PAGE_DIVIDER);
                mStartPage = bundle.getInt(KEY_START_PAGE);
                mEndPage = bundle.getInt(KEY_END_PAGE);
                mPages = bundle.getInt(KEY_PAGES);
                notifyDataSetChanged();
                if (newData == null) {
                    mPageDivider.clear();
                    mStartPage = 0;
                    mEndPage = 0;
                    mPages = 0;
                    firstRefresh();
                }
                return bundle.getParcelable(KEY_SUPER);
            } else {
                return state;
            }
        }
    }
}

18 Source : HistoryScene.java
with Apache License 2.0
from xiaojieonly

@Override
public boolean onItemClick(EasyRecyclerView parent, View view, int position, long id) {
    if (null == mLazyList) {
        return false;
    }
    Bundle args = new Bundle();
    args.putString(GalleryDetailScene.KEY_ACTION, GalleryDetailScene.ACTION_GALLERY_INFO);
    args.putParcelable(GalleryDetailScene.KEY_GALLERY_INFO, mLazyList.get(position));
    Announcer announcer = new Announcer(GalleryDetailScene.clreplaced).setArgs(args);
    View thumb;
    if (null != (thumb = view.findViewById(R.id.thumb))) {
        announcer.setTranHelper(new EnterGalleryDetailTransaction(thumb));
    }
    startScene(announcer);
    return true;
}

18 Source : GalleryPreviewsScene.java
with Apache License 2.0
from xiaojieonly

public clreplaced GalleryPreviewsScene extends ToolbarScene implements EasyRecyclerView.OnItemClickListener {

    public static final String KEY_GALLERY_INFO = "gallery_info";

    private final static String KEY_HAS_FIRST_REFRESH = "has_first_refresh";

    /*---------------
     Whole life cycle
     ---------------*/
    @Nullable
    private EhClient mClient;

    @Nullable
    private GalleryInfo mGalleryInfo;

    /*---------------
     View life cycle
     ---------------*/
    @Nullable
    private EasyRecyclerView mRecyclerView;

    @Nullable
    private GalleryPreviewAdapter mAdapter;

    @Nullable
    private GalleryPreviewHelper mHelper;

    private boolean mHasFirstRefresh = false;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Context context = getContext2();
        replacedertUtils.replacedertNotNull(context);
        mClient = EhApplication.getEhClient(context);
        if (savedInstanceState == null) {
            onInit();
        } else {
            onRestore(savedInstanceState);
        }
    }

    private void onInit() {
        Bundle args = getArguments();
        if (args == null) {
            return;
        }
        mGalleryInfo = args.getParcelable(KEY_GALLERY_INFO);
    }

    private void onRestore(@NonNull Bundle savedInstanceState) {
        mGalleryInfo = savedInstanceState.getParcelable(KEY_GALLERY_INFO);
        mHasFirstRefresh = savedInstanceState.getBoolean(KEY_HAS_FIRST_REFRESH);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        boolean hasFirstRefresh;
        if (mHelper != null && 1 == mHelper.getShownViewIndex()) {
            hasFirstRefresh = false;
        } else {
            hasFirstRefresh = mHasFirstRefresh;
        }
        outState.putBoolean(KEY_HAS_FIRST_REFRESH, hasFirstRefresh);
        outState.putParcelable(KEY_GALLERY_INFO, mGalleryInfo);
    }

    @Nullable
    @Override
    public View onCreateView3(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        ContentLayout contentLayout = (ContentLayout) inflater.inflate(R.layout.scene_gallery_previews, container, false);
        contentLayout.hideFastScroll();
        mRecyclerView = contentLayout.getRecyclerView();
        Context context = getContext2();
        replacedertUtils.replacedertNotNull(context);
        Resources resources = context.getResources();
        mAdapter = new GalleryPreviewAdapter();
        mRecyclerView.setAdapter(mAdapter);
        int columnWidth = resources.getDimensionPixelOffset(Settings.getThumbSizeResId());
        AutoGridLayoutManager layoutManager = new AutoGridLayoutManager(context, columnWidth);
        layoutManager.setStrategy(AutoGridLayoutManager.STRATEGY_SUITABLE_SIZE);
        mRecyclerView.setLayoutManager(layoutManager);
        mRecyclerView.setClipToPadding(false);
        mRecyclerView.setOnItemClickListener(this);
        int padding = LayoutUtils.dp2pix(context, 4);
        MarginItemDecoration decoration = new MarginItemDecoration(padding, padding, padding, padding, padding);
        mRecyclerView.addItemDecoration(decoration);
        decoration.applyPaddings(mRecyclerView);
        mHelper = new GalleryPreviewHelper();
        contentLayout.setHelper(mHelper);
        // Only refresh for the first time
        if (!mHasFirstRefresh) {
            mHasFirstRefresh = true;
            mHelper.firstRefresh();
        }
        return contentLayout;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (null != mHelper) {
            if (1 == mHelper.getShownViewIndex()) {
                mHasFirstRefresh = false;
            }
        }
        if (null != mRecyclerView) {
            mRecyclerView.stopScroll();
            mRecyclerView = null;
        }
        mAdapter = null;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        setreplacedle(R.string.gallery_previews);
        setNavigationIcon(R.drawable.v_arrow_left_dark_x24);
    }

    @Override
    public int getMenuResId() {
        return R.menu.scene_gallery_previews;
    }

    @Override
    public boolean onMenuItemClick(MenuItem item) {
        Context context = getContext2();
        if (null == context) {
            return false;
        }
        int id = item.gereplacedemId();
        switch(id) {
            case R.id.action_go_to:
                if (mHelper == null) {
                    return true;
                }
                int pages = mHelper.getPages();
                if (pages > 0 && mHelper.canGoTo()) {
                    GoToDialogHelper helper = new GoToDialogHelper(pages, mHelper.getPageForTop());
                    AlertDialog dialog = new AlertDialog.Builder(context).setreplacedle(R.string.go_to).setView(R.layout.dialog_go_to).setPositiveButton(android.R.string.ok, null).create();
                    dialog.show();
                    helper.setDialog(dialog);
                }
                return true;
        }
        return false;
    }

    @Override
    public void onNavigationClick() {
        onBackPressed();
    }

    @Override
    public boolean onItemClick(EasyRecyclerView parent, View view, int position, long id) {
        Context context = getContext2();
        if (null != context && null != mHelper && null != mGalleryInfo) {
            GalleryPreview p = mHelper.getDataAtEx(position);
            if (p != null) {
                Intent intent = new Intent(context, GalleryActivity.clreplaced);
                intent.setAction(GalleryActivity.ACTION_EH);
                intent.putExtra(GalleryActivity.KEY_GALLERY_INFO, mGalleryInfo);
                intent.putExtra(GalleryActivity.KEY_PAGE, p.getPosition());
                startActivity(intent);
            }
        }
        return true;
    }

    private clreplaced GalleryPreviewHolder extends RecyclerView.ViewHolder {

        public LoadImageView image;

        public TextView text;

        public GalleryPreviewHolder(View itemView) {
            super(itemView);
            image = (LoadImageView) itemView.findViewById(R.id.image);
            text = (TextView) itemView.findViewById(R.id.text);
        }
    }

    private clreplaced GalleryPreviewAdapter extends RecyclerView.Adapter<GalleryPreviewHolder> {

        private final LayoutInflater mInflater;

        public GalleryPreviewAdapter() {
            mInflater = getLayoutInflater2();
            replacedertUtils.replacedertNotNull(mInflater);
        }

        @Override
        public GalleryPreviewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            return new GalleryPreviewHolder(mInflater.inflate(R.layout.item_gallery_preview, parent, false));
        }

        @Override
        @SuppressLint("SetTextI18n")
        public void onBindViewHolder(GalleryPreviewHolder holder, int position) {
            if (null != mHelper) {
                GalleryPreview preview = mHelper.getDataAtEx(position);
                if (preview != null) {
                    preview.load(holder.image);
                    holder.text.setText(Integer.toString(preview.getPosition() + 1));
                }
            }
        }

        @Override
        public int gereplacedemCount() {
            return mHelper != null ? mHelper.size() : 0;
        }
    }

    private clreplaced GalleryPreviewHelper extends ContentLayout.ContentHelper<GalleryPreview> {

        @Override
        protected void getPageData(final int taskId, int type, int page) {
            MainActivity activity = getActivity2();
            if (null == activity || null == mClient || null == mGalleryInfo) {
                onGetException(taskId, new EhException(getString(R.string.error_cannot_find_gallery)));
                return;
            }
            String url = EhUrl.getGalleryDetailUrl(mGalleryInfo.gid, mGalleryInfo.token, page, false);
            EhRequest request = new EhRequest();
            request.setMethod(EhClient.METHOD_GET_PREVIEW_SET);
            request.setCallback(new GetPreviewSetListener(getContext(), activity.getStageId(), getTag(), taskId));
            request.setArgs(url);
            mClient.execute(request);
        }

        @Override
        protected Context getContext() {
            return GalleryPreviewsScene.this.getContext2();
        }

        @Override
        protected void notifyDataSetChanged() {
            if (mAdapter != null) {
                mAdapter.notifyDataSetChanged();
            }
        }

        @Override
        protected void notifyItemRangeRemoved(int positionStart, int itemCount) {
            if (mAdapter != null) {
                mAdapter.notifyItemRangeRemoved(positionStart, itemCount);
            }
        }

        @Override
        protected void notifyItemRangeInserted(int positionStart, int itemCount) {
            if (mAdapter != null) {
                mAdapter.notifyItemRangeInserted(positionStart, itemCount);
            }
        }

        @Override
        protected boolean isDuplicate(GalleryPreview d1, GalleryPreview d2) {
            return false;
        }
    }

    private void onGetPreviewSetSuccess(Pair<PreviewSet, Integer> result, int taskId) {
        if (null != mHelper && mHelper.isCurrentTask(taskId) && null != mGalleryInfo) {
            PreviewSet previewSet = result.first;
            int size = previewSet.size();
            ArrayList<GalleryPreview> list = new ArrayList<>(size);
            for (int i = 0; i < size; i++) {
                list.add(previewSet.getGalleryPreview(mGalleryInfo.gid, i));
            }
            mHelper.onGetPageData(taskId, result.second, 0, list);
        }
    }

    private void onGetPreviewSetFailure(Exception e, int taskId) {
        if (mHelper != null && mHelper.isCurrentTask(taskId)) {
            mHelper.onGetException(taskId, e);
        }
    }

    private static clreplaced GetPreviewSetListener extends EhCallback<GalleryPreviewsScene, Pair<PreviewSet, Integer>> {

        private final int mTaskId;

        public GetPreviewSetListener(Context context, int stageId, String sceneTag, int taskId) {
            super(context, stageId, sceneTag);
            mTaskId = taskId;
        }

        @Override
        public void onSuccess(Pair<PreviewSet, Integer> result) {
            GalleryPreviewsScene scene = getScene();
            if (scene != null) {
                scene.onGetPreviewSetSuccess(result, mTaskId);
            }
        }

        @Override
        public void onFailure(Exception e) {
            GalleryPreviewsScene scene = getScene();
            if (scene != null) {
                scene.onGetPreviewSetFailure(e, mTaskId);
            }
        }

        @Override
        public void onCancel() {
        }

        @Override
        public boolean isInstance(SceneFragment scene) {
            return scene instanceof GalleryPreviewsScene;
        }
    }

    private clreplaced GoToDialogHelper implements View.OnClickListener, DialogInterface.OnDismissListener {

        private final int mPages;

        private final int mCurrentPage;

        @Nullable
        private Slider mSlider;

        @Nullable
        private Dialog mDialog;

        private GoToDialogHelper(int pages, int currentPage) {
            mPages = pages;
            mCurrentPage = currentPage;
        }

        public void setDialog(@NonNull AlertDialog dialog) {
            mDialog = dialog;
            ((TextView) ViewUtils.$$(dialog, R.id.start)).setText(String.format(Locale.US, "%d", 1));
            ((TextView) ViewUtils.$$(dialog, R.id.end)).setText(String.format(Locale.US, "%d", mPages));
            mSlider = (Slider) ViewUtils.$$(dialog, R.id.slider);
            mSlider.setRange(1, mPages);
            mSlider.setProgress(mCurrentPage + 1);
            dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(this);
            dialog.setOnDismissListener(this);
        }

        @Override
        public void onClick(View v) {
            if (null == mSlider) {
                return;
            }
            int page = mSlider.getProgress() - 1;
            if (page >= 0 && page < mPages && mHelper != null) {
                mHelper.goTo(page);
                if (mDialog != null) {
                    mDialog.dismiss();
                    mDialog = null;
                }
            } else {
                showTip(R.string.error_out_of_range, LENGTH_LONG);
            }
        }

        @Override
        public void onDismiss(DialogInterface dialog) {
            mDialog = null;
            mSlider = null;
        }
    }
}

18 Source : HostsActivity.java
with Apache License 2.0
from xiaojieonly

public clreplaced HostsActivity extends ToolbarActivity implements EasyRecyclerView.OnItemClickListener, View.OnClickListener {

    private static final String DIALOG_TAG_ADD_HOST = AddHostDialogFragment.clreplaced.getName();

    private static final String DIALOG_TAG_EDIT_HOST = EditHostDialogFragment.clreplaced.getName();

    private static final String KEY_HOST = "com.hippo.ehviewer.ui.HostsActivity.HOST";

    private static final String KEY_IP = "com.hippo.ehviewer.ui.HostsActivity.IP";

    private Hosts hosts;

    private List<Pair<String, String>> data;

    private EasyRecyclerView recyclerView;

    private View tip;

    private HostsAdapter adapter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        hosts = EhApplication.getHosts(this);
        data = hosts.getAll();
        setContentView(R.layout.activity_hosts);
        setNavigationIcon(R.drawable.v_arrow_left_dark_x24);
        recyclerView = findViewById(R.id.recycler_view);
        tip = findViewById(R.id.tip);
        FloatingActionButton fab = findViewById(R.id.fab);
        adapter = new HostsAdapter();
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(this, RecyclerView.VERTICAL, false));
        LinearDividerItemDecoration decoration = new LinearDividerItemDecoration(LinearDividerItemDecoration.VERTICAL, AttrResources.getAttrColor(this, R.attr.dividerColor), LayoutUtils.dp2pix(this, 1));
        decoration.setShowLastDivider(true);
        recyclerView.addItemDecoration(decoration);
        recyclerView.setSelector(Ripple.generateRippleDrawable(this, !AttrResources.getAttrBoolean(this, R.attr.isLightTheme), new ColorDrawable(Color.TRANSPARENT)));
        recyclerView.setHasFixedSize(true);
        recyclerView.setOnItemClickListener(this);
        recyclerView.setPadding(recyclerView.getPaddingLeft(), recyclerView.getPaddingTop(), recyclerView.getPaddingRight(), recyclerView.getPaddingBottom() + getResources().getDimensionPixelOffset(R.dimen.gallery_padding_bottom_fab));
        fab.setOnClickListener(this);
        recyclerView.setVisibility(data.isEmpty() ? View.GONE : View.VISIBLE);
        tip.setVisibility(data.isEmpty() ? View.VISIBLE : View.GONE);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch(item.gereplacedemId()) {
            case android.R.id.home:
                finish();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public boolean onItemClick(EasyRecyclerView easyRecyclerView, View view, int position, long id) {
        Pair<String, String> pair = data.get(position);
        Bundle args = new Bundle();
        args.putString(KEY_HOST, pair.first);
        args.putString(KEY_IP, pair.second);
        DialogFragment fragment = new EditHostDialogFragment();
        fragment.setArguments(args);
        fragment.show(getSupportFragmentManager(), DIALOG_TAG_EDIT_HOST);
        return true;
    }

    @Override
    public void onClick(View v) {
        new AddHostDialogFragment().show(getSupportFragmentManager(), DIALOG_TAG_ADD_HOST);
    }

    private void notifyHostsChanges() {
        data = hosts.getAll();
        recyclerView.setVisibility(data.isEmpty() ? View.GONE : View.VISIBLE);
        tip.setVisibility(data.isEmpty() ? View.VISIBLE : View.GONE);
        adapter.notifyDataSetChanged();
    }

    private clreplaced HostsHolder extends RecyclerView.ViewHolder {

        public final TextView host;

        public final TextView ip;

        public HostsHolder(View itemView) {
            super(itemView);
            host = itemView.findViewById(R.id.host);
            ip = itemView.findViewById(R.id.ip);
        }
    }

    private clreplaced HostsAdapter extends RecyclerView.Adapter<HostsHolder> {

        private final LayoutInflater inflater = getLayoutInflater();

        @NonNull
        @Override
        public HostsHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            return new HostsHolder(inflater.inflate(R.layout.item_hosts, parent, false));
        }

        @Override
        public void onBindViewHolder(@NonNull HostsHolder holder, int position) {
            Pair<String, String> pair = data.get(position);
            holder.host.setText(pair.first);
            holder.ip.setText(pair.second);
        }

        @Override
        public int gereplacedemCount() {
            return data.size();
        }
    }

    public abstract static clreplaced HostDialogFragment extends DialogFragment {

        private TextView host;

        private TextView ip;

        @NonNull
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_hosts, null, false);
            host = view.findViewById(R.id.host);
            ip = view.findViewById(R.id.ip);
            Bundle arguments = getArguments();
            if (savedInstanceState == null && arguments != null) {
                host.setText(arguments.getString(KEY_HOST));
                ip.setText(arguments.getString(KEY_IP));
            }
            AlertDialog.Builder builder = new AlertDialog.Builder(getContext()).setView(view);
            onCreateDialogBuilder(builder);
            AlertDialog dialog = builder.create();
            dialog.setOnShowListener(d -> onCreateDialog((AlertDialog) d));
            return dialog;
        }

        protected abstract void onCreateDialogBuilder(AlertDialog.Builder builder);

        protected abstract void onCreateDialog(AlertDialog dialog);

        protected void put(AlertDialog dialog) {
            TextView host = dialog.findViewById(R.id.host);
            TextView ip = dialog.findViewById(R.id.ip);
            String hostString = host.getText().toString().trim().toLowerCase(Locale.US);
            String ipString = ip.getText().toString().trim();
            if (!Hosts.isValidHost(hostString)) {
                TextInputLayout hostInputLayout = dialog.findViewById(R.id.host_input_layout);
                hostInputLayout.setError(getContext().getString(R.string.invalid_host));
                return;
            }
            if (!Hosts.isValidIp(ipString)) {
                TextInputLayout ipInputLayout = dialog.findViewById(R.id.ip_input_layout);
                ipInputLayout.setError(getContext().getString(R.string.invalid_ip));
                return;
            }
            HostsActivity activity = (HostsActivity) dialog.getOwnerActivity();
            activity.hosts.put(hostString, ipString);
            activity.notifyHostsChanges();
            dialog.dismiss();
        }

        protected void delete(AlertDialog dialog) {
            TextView host = dialog.findViewById(R.id.host);
            String hostString = host.getText().toString().trim().toLowerCase(Locale.US);
            HostsActivity activity = (HostsActivity) dialog.getOwnerActivity();
            activity.hosts.delete(hostString);
            activity.notifyHostsChanges();
            dialog.dismiss();
        }
    }

    public static clreplaced AddHostDialogFragment extends HostDialogFragment {

        @Override
        protected void onCreateDialogBuilder(AlertDialog.Builder builder) {
            builder.setreplacedle(R.string.add_host);
            builder.setPositiveButton(R.string.add_host_add, null);
        }

        @Override
        protected void onCreateDialog(AlertDialog dialog) {
            dialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> put(dialog));
        }
    }

    public static clreplaced EditHostDialogFragment extends HostDialogFragment {

        @Override
        protected void onCreateDialogBuilder(AlertDialog.Builder builder) {
            builder.setreplacedle(R.string.edit_host);
            builder.setPositiveButton(R.string.edit_host_confirm, null);
            builder.setNegativeButton(R.string.edit_host_delete, null);
        }

        @Override
        protected void onCreateDialog(AlertDialog dialog) {
            dialog.findViewById(R.id.host_input_layout).setEnabled(false);
            dialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> put(dialog));
            dialog.getButton(DialogInterface.BUTTON_NEGATIVE).setOnClickListener(v -> delete(dialog));
        }
    }
}

18 Source : FilterActivity.java
with Apache License 2.0
from xiaojieonly

public clreplaced FilterActivity extends ToolbarActivity {

    @Nullable
    private EasyRecyclerView mRecyclerView;

    @Nullable
    private ViewTransition mViewTransition;

    @Nullable
    private FilterAdapter mAdapter;

    @Nullable
    private FilterList mFilterList;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_filter);
        setNavigationIcon(R.drawable.v_arrow_left_dark_x24);
        mFilterList = new FilterList();
        mRecyclerView = (EasyRecyclerView) ViewUtils.$$(this, R.id.recycler_view);
        TextView tip = (TextView) ViewUtils.$$(this, R.id.tip);
        mViewTransition = new ViewTransition(mRecyclerView, tip);
        Drawable drawable = DrawableManager.getVectorDrawable(this, R.drawable.big_filter);
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        tip.setCompoundDrawables(null, drawable, null, null);
        mAdapter = new FilterAdapter();
        mRecyclerView.setAdapter(mAdapter);
        mRecyclerView.setClipToPadding(false);
        mRecyclerView.setClipChildren(false);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        mRecyclerView.hasFixedSize();
        mRecyclerView.sereplacedemAnimator(null);
        updateView(false);
    }

    private void updateView(boolean animation) {
        if (null == mViewTransition) {
            return;
        }
        if (null == mFilterList || 0 == mFilterList.size()) {
            mViewTransition.showView(1, animation);
        } else {
            mViewTransition.showView(0, animation);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mRecyclerView = null;
        mViewTransition = null;
        mAdapter = null;
        mFilterList = null;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        getMenuInflater().inflate(R.menu.activity_filter, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch(item.gereplacedemId()) {
            case android.R.id.home:
                finish();
                return true;
            case R.id.action_add:
                showAddFilterDialog();
                return true;
            case R.id.action_tip:
                showTipDialog();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    private void showTipDialog() {
        new AlertDialog.Builder(this).setreplacedle(R.string.filter).setMessage(R.string.filter_tip).show();
    }

    private void showAddFilterDialog() {
        AlertDialog dialog = new AlertDialog.Builder(this).setreplacedle(R.string.add_filter).setView(R.layout.dialog_add_filter).setPositiveButton(R.string.add, null).show();
        AddFilterDialogHelper helper = new AddFilterDialogHelper();
        helper.setDialog(dialog);
    }

    private void showDeleteFilterDialog(final Filter filter) {
        String message = getString(R.string.delete_filter, filter.text);
        new AlertDialog.Builder(this).setMessage(message).setPositiveButton(R.string.delete, (dialog, which) -> {
            if (DialogInterface.BUTTON_POSITIVE != which || null == mFilterList) {
                return;
            }
            mFilterList.delete(filter);
            if (null != mAdapter) {
                mAdapter.notifyDataSetChanged();
            }
            updateView(true);
        }).show();
    }

    private clreplaced AddFilterDialogHelper implements View.OnClickListener {

        @Nullable
        private AlertDialog mDialog;

        @Nullable
        private Spinner mSpinner;

        @Nullable
        private TextInputLayout mInputLayout;

        @Nullable
        private EditText mEditText;

        public void setDialog(AlertDialog dialog) {
            mDialog = dialog;
            mSpinner = (Spinner) ViewUtils.$$(dialog, R.id.spinner);
            mInputLayout = (TextInputLayout) ViewUtils.$$(dialog, R.id.text_input_layout);
            mEditText = mInputLayout.getEditText();
            View button = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
            if (null != button) {
                button.setOnClickListener(this);
            }
        }

        @Override
        public void onClick(View v) {
            if (null == mFilterList || null == mDialog || null == mSpinner || null == mInputLayout || null == mEditText) {
                return;
            }
            String text = mEditText.getText().toString().trim();
            if (TextUtils.isEmpty(text)) {
                mInputLayout.setError(getString(R.string.text_is_empty));
                return;
            } else {
                mInputLayout.setError(null);
            }
            int mode = mSpinner.getSelectedItemPosition();
            Filter filter = new Filter();
            filter.mode = mode;
            filter.text = text;
            mFilterList.add(filter);
            if (null != mAdapter) {
                mAdapter.notifyDataSetChanged();
            }
            updateView(true);
            mDialog.dismiss();
            mDialog = null;
            mSpinner = null;
            mInputLayout = null;
            mEditText = null;
        }
    }

    private clreplaced FilterHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        private final TextView text;

        private final ImageView icon;

        public FilterHolder(View itemView) {
            super(itemView);
            text = (TextView) ViewUtils.$$(itemView, R.id.text);
            icon = itemView.findViewById(R.id.icon);
            if (null != icon) {
                icon.setOnClickListener(this);
            }
            // click on the filter text to enable/disable it
            text.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            int position = getAdapterPosition();
            if (position < 0 || null == mFilterList) {
                return;
            }
            Filter filter = mFilterList.get(position);
            if (FilterList.MODE_HEADER != filter.mode) {
                if (v instanceof ImageView) {
                    showDeleteFilterDialog(filter);
                } else if (v instanceof TextView) {
                    mFilterList.trigger(filter);
                    // for updating delete line on filter text
                    mAdapter.notifyItemChanged(getAdapterPosition());
                }
            }
        }
    }

    private clreplaced FilterAdapter extends RecyclerView.Adapter<FilterHolder> {

        private static final int TYPE_ITEM = 0;

        private static final int TYPE_HEADER = 1;

        @Override
        public int gereplacedemViewType(int position) {
            if (null == mFilterList) {
                return TYPE_ITEM;
            }
            if (mFilterList.get(position).mode == FilterList.MODE_HEADER) {
                return TYPE_HEADER;
            } else {
                return TYPE_ITEM;
            }
        }

        @Override
        public FilterHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            int layoutId;
            switch(viewType) {
                default:
                case TYPE_ITEM:
                    layoutId = R.layout.item_filter;
                    break;
                case TYPE_HEADER:
                    layoutId = R.layout.item_filter_header;
                    break;
            }
            FilterHolder holder = new FilterHolder(getLayoutInflater().inflate(layoutId, parent, false));
            if (R.layout.item_filter == layoutId) {
                holder.icon.setImageDrawable(DrawableManager.getVectorDrawable(FilterActivity.this, R.drawable.v_delete_x24));
            }
            return holder;
        }

        @Override
        public void onBindViewHolder(FilterHolder holder, int position) {
            if (null == mFilterList) {
                return;
            }
            Filter filter = mFilterList.get(position);
            if (FilterList.MODE_HEADER == filter.mode) {
                holder.text.setText(filter.text);
            } else {
                holder.text.setText(filter.text);
                // add a delete line if the filter is disabled
                if (!filter.enable) {
                    holder.text.setPaintFlags(holder.text.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
                } else {
                    holder.text.setPaintFlags(holder.text.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG));
                }
            }
        }

        @Override
        public int gereplacedemCount() {
            return null != mFilterList ? mFilterList.size() : 0;
        }
    }

    private clreplaced FilterList {

        public static final int MODE_HEADER = -1;

        private final EhFilter mEhFilter;

        private final List<Filter> mreplacedleFilterList;

        private final List<Filter> mUploaderFilterList;

        private final List<Filter> mTagFilterList;

        private final List<Filter> mTagNamespaceFilterList;

        private Filter mreplacedleHeader;

        private Filter mUploaderHeader;

        private Filter mTagHeader;

        private Filter mTagNamespaceHeader;

        public FilterList() {
            mEhFilter = EhFilter.getInstance();
            mreplacedleFilterList = mEhFilter.getreplacedleFilterList();
            mUploaderFilterList = mEhFilter.getUploaderFilterList();
            mTagFilterList = mEhFilter.getTagFilterList();
            mTagNamespaceFilterList = mEhFilter.getTagNamespaceFilterList();
        }

        public int size() {
            int count = 0;
            int size = mreplacedleFilterList.size();
            count += 0 == size ? 0 : size + 1;
            size = mUploaderFilterList.size();
            count += 0 == size ? 0 : size + 1;
            size = mTagFilterList.size();
            count += 0 == size ? 0 : size + 1;
            size = mTagNamespaceFilterList.size();
            count += 0 == size ? 0 : size + 1;
            return count;
        }

        private Filter getreplacedleHeader() {
            if (null == mreplacedleHeader) {
                mreplacedleHeader = new Filter();
                mreplacedleHeader.mode = MODE_HEADER;
                mreplacedleHeader.text = getString(R.string.filter_replacedle);
            }
            return mreplacedleHeader;
        }

        private Filter getUploaderHeader() {
            if (null == mUploaderHeader) {
                mUploaderHeader = new Filter();
                mUploaderHeader.mode = MODE_HEADER;
                mUploaderHeader.text = getString(R.string.filter_uploader);
            }
            return mUploaderHeader;
        }

        private Filter getTagHeader() {
            if (null == mTagHeader) {
                mTagHeader = new Filter();
                mTagHeader.mode = MODE_HEADER;
                mTagHeader.text = getString(R.string.filter_tag);
            }
            return mTagHeader;
        }

        private Filter getTagNamespaceHeader() {
            if (null == mTagNamespaceHeader) {
                mTagNamespaceHeader = new Filter();
                mTagNamespaceHeader.mode = MODE_HEADER;
                mTagNamespaceHeader.text = getString(R.string.filter_tag_namespace);
            }
            return mTagNamespaceHeader;
        }

        public Filter get(int index) {
            int size = mreplacedleFilterList.size();
            if (0 != size) {
                if (index == 0) {
                    return getreplacedleHeader();
                } else if (index <= size) {
                    return mreplacedleFilterList.get(index - 1);
                } else {
                    index -= size + 1;
                }
            }
            size = mUploaderFilterList.size();
            if (0 != size) {
                if (index == 0) {
                    return getUploaderHeader();
                } else if (index <= size) {
                    return mUploaderFilterList.get(index - 1);
                } else {
                    index -= size + 1;
                }
            }
            size = mTagFilterList.size();
            if (0 != size) {
                if (index == 0) {
                    return getTagHeader();
                } else if (index <= size) {
                    return mTagFilterList.get(index - 1);
                } else {
                    index -= size + 1;
                }
            }
            size = mTagNamespaceFilterList.size();
            if (0 != size) {
                if (index == 0) {
                    return getTagNamespaceHeader();
                } else if (index <= size) {
                    return mTagNamespaceFilterList.get(index - 1);
                } else {
                    index -= size + 1;
                }
            }
            throw new IndexOutOfBoundsException();
        }

        public void add(Filter filter) {
            mEhFilter.addFilter(filter);
        }

        public void delete(Filter filter) {
            mEhFilter.deleteFilter(filter);
        }

        public void trigger(Filter filter) {
            mEhFilter.triggerFilter(filter);
        }
    }
}

18 Source : BlackListActivity.java
with Apache License 2.0
from xiaojieonly

public clreplaced BlackListActivity extends ToolbarActivity {

    @Nullable
    private EasyRecyclerView mRecyclerView;

    @Nullable
    private ViewTransition mViewTransition;

    @Nullable
    private BlackListAdapter mAdapter;

    @Nullable
    private BlackListList mblackListList;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_blacklist);
        setNavigationIcon(R.drawable.v_arrow_left_dark_x24);
        mblackListList = new BlackListList();
        mRecyclerView = (EasyRecyclerView) ViewUtils.$$(this, R.id.recycler_view1);
        TextView tip = (TextView) ViewUtils.$$(this, R.id.tip);
        mViewTransition = new ViewTransition(mRecyclerView, tip);
        Drawable drawable = DrawableManager.getVectorDrawable(this, R.drawable.big_filter);
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        tip.setCompoundDrawables(null, drawable, null, null);
        mAdapter = new BlackListAdapter();
        mRecyclerView.setAdapter(mAdapter);
        mRecyclerView.setClipToPadding(false);
        mRecyclerView.setClipChildren(false);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        mRecyclerView.hasFixedSize();
        mRecyclerView.sereplacedemAnimator(null);
        updateView(false);
    }

    private void updateView(boolean animation) {
        if (null == mViewTransition) {
            return;
        }
        if (null == mblackListList || 0 == mblackListList.size()) {
            mViewTransition.showView(1, animation);
        } else {
            mViewTransition.showView(0, animation);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mRecyclerView = null;
        mViewTransition = null;
        mAdapter = null;
        mblackListList = null;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        getMenuInflater().inflate(R.menu.activity_blick_list, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch(item.gereplacedemId()) {
            case android.R.id.home:
                finish();
                return true;
            case R.id.action_add:
                showAddBlackListDialog();
                return true;
            case R.id.action_tip:
                showTipDialog();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    private void showTipDialog() {
        new AlertDialog.Builder(this).setreplacedle(R.string.blacklist).setMessage(R.string.blacklist_tip).show();
    }

    private void showAddBlackListDialog() {
        AlertDialog dialog = new AlertDialog.Builder(this).setreplacedle(R.string.add_blacklist).setView(R.layout.dialog_add_blacklist).setPositiveButton(R.string.add, null).show();
        AddBlackListDialogHelper helper = new AddBlackListDialogHelper();
        helper.setDialog(dialog);
    }

    private void showDeleteBlackListDialog(final BlackList blackList) {
        String message = getString(R.string.delete_blacklist, blackList.badgayname);
        new AlertDialog.Builder(this).setMessage(message).setPositiveButton(R.string.delete, (dialog, which) -> {
            if (DialogInterface.BUTTON_POSITIVE != which || null == mblackListList) {
                return;
            }
            mblackListList.delete(blackList);
            if (null != mAdapter) {
                mAdapter.notifyDataSetChanged();
            }
            updateView(true);
        }).show();
    }

    private clreplaced AddBlackListDialogHelper implements View.OnClickListener {

        @Nullable
        private AlertDialog mDialog;

        @Nullable
        private Spinner mSpinner;

        @Nullable
        private TextInputLayout mInputLayout;

        @Nullable
        private EditText mEditText;

        public void setDialog(AlertDialog dialog) {
            mDialog = dialog;
            mSpinner = (Spinner) ViewUtils.$$(dialog, R.id.spinner);
            mInputLayout = (TextInputLayout) ViewUtils.$$(dialog, R.id.text_inputreason_layout);
            mEditText = mInputLayout.getEditText();
            View button = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
            if (null != button) {
                button.setOnClickListener(this);
            }
        }

        @Override
        public void onClick(View v) {
            if (null == mblackListList || null == mDialog || null == mSpinner || null == mInputLayout || null == mEditText) {
                return;
            }
            String text = mEditText.getText().toString().trim();
            if (TextUtils.isEmpty(text)) {
                mInputLayout.setError(getString(R.string.text_is_empty));
                return;
            } else {
                mInputLayout.setError(null);
            }
            int mode = mSpinner.getSelectedItemPosition();
            BlackList blackList = new BlackList();
            blackList.badgayname = text;
            blackList.add_time = TimeUtils.getTimeNow();
            blackList.angrywith = "/手动添加/";
            blackList.mode = 1;
            mblackListList.add(blackList);
            if (null != mAdapter) {
                mAdapter.notifyDataSetChanged();
            }
            updateView(true);
            mDialog.dismiss();
            mDialog = null;
            mSpinner = null;
            mInputLayout = null;
            mEditText = null;
        }
    }

    private clreplaced BlackListHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        private final TextView text;

        private final ImageView icon;

        public BlackListHolder(View itemView) {
            super(itemView);
            text = (TextView) ViewUtils.$$(itemView, R.id.text);
            icon = itemView.findViewById(R.id.icon);
            if (null != icon) {
                icon.setOnClickListener(this);
            }
            // click on the blacklist text to enable/disable it
            text.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            int position = getAdapterPosition();
            if (position < 0 || null == mblackListList) {
                return;
            }
            BlackList blackList = mblackListList.get(position);
            if (v instanceof ImageView) {
                showDeleteBlackListDialog(blackList);
            } else if (v instanceof TextView) {
                mAdapter.notifyItemChanged(getAdapterPosition());
            }
        }
    }

    private clreplaced BlackListAdapter extends RecyclerView.Adapter<BlackListHolder> {

        private static final int TYPE_ITEM = 0;

        private static final int TYPE_HEADER = 1;

        @Override
        public int gereplacedemViewType(int position) {
            if (null == mblackListList) {
                return TYPE_ITEM;
            }
            if (mblackListList.get(position).mode == BlackListList.MODE_HEADER) {
                return TYPE_HEADER;
            } else {
                return TYPE_ITEM;
            }
        }

        @Override
        public BlackListHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            int layoutId;
            switch(viewType) {
                default:
                case TYPE_ITEM:
                    layoutId = R.layout.item_blacklist;
                    break;
                case TYPE_HEADER:
                    layoutId = R.layout.item_blacklist_header;
                    break;
            }
            BlackListHolder holder = new BlackListHolder(getLayoutInflater().inflate(layoutId, parent, false));
            if (R.layout.item_blacklist == layoutId) {
                holder.icon.setImageDrawable(DrawableManager.getVectorDrawable(BlackListActivity.this, R.drawable.v_delete_x24));
            }
            return holder;
        }

        @Override
        public void onBindViewHolder(BlackListHolder holder, int position) {
            if (null == mblackListList) {
                return;
            }
            BlackList blackList = mblackListList.get(position);
            if (BlackListList.MODE_HEADER == blackList.mode) {
                holder.text.setText(blackList.badgayname);
            } else {
                holder.text.setText(blackList.badgayname);
                holder.text.setPaintFlags(holder.text.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG));
            }
        }

        @Override
        public int gereplacedemCount() {
            return null != mblackListList ? mblackListList.size() : 0;
        }
    }

    private clreplaced BlackListList {

        public static final int MODE_HEADER = -1;

        private List<BlackList> mreplacedleBlackList;

        private BlackList mreplacedleHeader;

        public BlackListList() {
            mreplacedleBlackList = EhDB.getAllBlackList();
        }

        public int size() {
            int count = 0;
            int size = mreplacedleBlackList.size();
            count += 0 == size ? 0 : size + 1;
            return count;
        }

        private BlackList getreplacedleHeader() {
            if (null == mreplacedleHeader) {
                mreplacedleHeader = new BlackList();
                mreplacedleHeader.mode = MODE_HEADER;
                mreplacedleHeader.badgayname = getString(R.string.blacklist_id);
            }
            return mreplacedleHeader;
        }

        public BlackList get(int index) {
            int size = mreplacedleBlackList.size();
            if (0 != size) {
                if (index == 0) {
                    return getreplacedleHeader();
                } else if (index <= size) {
                    return mreplacedleBlackList.get(index - 1);
                } else {
                    index -= size + 1;
                }
            }
            throw new IndexOutOfBoundsException();
        }

        public void add(BlackList blackList) {
            EhDB.insertBlackList(blackList);
            mreplacedleBlackList.add(blackList);
        }

        public void delete(BlackList blackList) {
            EhDB.deleteBlackList(blackList);
            mreplacedleBlackList.remove(blackList);
        }
    }
}

18 Source : ContentLayout.java
with Apache License 2.0
from NuclearVGA

public clreplaced ContentLayout extends FrameLayout {

    private ProgressView mProgressView;

    private TextView mTipView;

    private ViewGroup mContentView;

    private RefreshLayout mRefreshLayout;

    private EasyRecyclerView mRecyclerView;

    private FastScroller mFastScroller;

    private ContentHelper<?> mContentHelper;

    private int mRecyclerViewOriginTop;

    private int mRecyclerViewOriginBottom;

    public ContentLayout(Context context) {
        super(context);
        init(context);
    }

    public ContentLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public ContentLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        LayoutInflater.from(context).inflate(R.layout.widget_content_layout, this);
        mProgressView = findViewById(R.id.progress);
        mTipView = findViewById(R.id.tip);
        mContentView = findViewById(R.id.content_view);
        mRefreshLayout = mContentView.findViewById(R.id.refresh_layout);
        mFastScroller = mContentView.findViewById(R.id.fast_scroller);
        mRecyclerView = mRefreshLayout.findViewById(R.id.recycler_view);
        mFastScroller.attachToRecyclerView(mRecyclerView);
        HandlerDrawable drawable = new HandlerDrawable();
        drawable.setColor(AttrResources.getAttrColor(context, R.attr.widgetColorThemeAccent));
        mFastScroller.setHandlerDrawable(drawable);
        mRefreshLayout.setHeaderColorSchemeResources(R.color.loading_indicator_red, R.color.loading_indicator_purple, R.color.loading_indicator_blue, R.color.loading_indicator_cyan, R.color.loading_indicator_green, R.color.loading_indicator_yellow);
        mRefreshLayout.setFooterColorSchemeResources(R.color.loading_indicator_red, R.color.loading_indicator_blue, R.color.loading_indicator_green, R.color.loading_indicator_orange);
        mRecyclerViewOriginTop = mRecyclerView.getPaddingTop();
        mRecyclerViewOriginBottom = mRecyclerView.getPaddingBottom();
    }

    @NonNull
    public EasyRecyclerView getRecyclerView() {
        return mRecyclerView;
    }

    public FastScroller getFastScroller() {
        return mFastScroller;
    }

    public RefreshLayout getRefreshLayout() {
        return mRefreshLayout;
    }

    public void setHelper(ContentHelper<?> helper) {
        mContentHelper = helper;
        helper.init(this);
    }

    public void showFastScroll() {
        if (!mFastScroller.isAttached()) {
            mFastScroller.attachToRecyclerView(mRecyclerView);
        }
    }

    public void hideFastScroll() {
        mFastScroller.detachedFromRecyclerView();
    }

    public void setFitPaddingTop(int fitPaddingTop) {
        // RecyclerView
        mRecyclerView.setPadding(mRecyclerView.getPaddingLeft(), mRecyclerViewOriginTop + fitPaddingTop, mRecyclerView.getPaddingRight(), mRecyclerView.getPaddingBottom());
        // RefreshLayout
        // TODO
        mRefreshLayout.setHeaderProgressViewOffset(true, 0, fitPaddingTop + LayoutUtils.dp2pix(getContext(), 32));
    }

    public void setFitPaddingBottom(int fitPaddingBottom) {
        // RecyclerView
        mRecyclerView.setPadding(mRecyclerView.getPaddingLeft(), mRecyclerView.getPaddingTop(), mRecyclerView.getPaddingRight(), mRecyclerViewOriginBottom + fitPaddingBottom);
    }

    @Override
    protected Parcelable onSaveInstanceState() {
        return mContentHelper.saveInstanceState(super.onSaveInstanceState());
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        super.onRestoreInstanceState(mContentHelper.restoreInstanceState(state));
    }

    public abstract static clreplaced ContentHelper<E extends Parcelable> implements ViewTransition.OnShowViewListener {

        public static final int TYPE_REFRESH = 0;

        public static final int TYPE_PRE_PAGE = 1;

        public static final int TYPE_PRE_PAGE_KEEP_POS = 2;

        public static final int TYPE_NEXT_PAGE = 3;

        public static final int TYPE_NEXT_PAGE_KEEP_POS = 4;

        public static final int TYPE_SOMEWHERE = 5;

        public static final int TYPE_REFRESH_PAGE = 6;

        public static final int REFRESH_TYPE_HEADER = 0;

        public static final int REFRESH_TYPE_FOOTER = 1;

        public static final int REFRESH_TYPE_PROGRESS_VIEW = 2;

        private static final String TAG = ContentHelper.clreplaced.getSimpleName();

        private static final int CHECK_DUPLICATE_RANGE = 50;

        private static final String KEY_SUPER = "super";

        private static final String KEY_SHOWN_VIEW = "shown_view";

        private static final String KEY_TIP = "tip";

        private static final String KEY_DATA = "data";

        private static final String KEY_NEXT_ID = "next_id";

        private static final String KEY_PAGE_DIVIDER = "page_divider";

        private static final String KEY_START_PAGE = "start_page";

        private static final String KEY_END_PAGE = "end_page";

        private static final String KEY_PAGES = "pages";

        /**
         * Generate task id
         */
        private final IntIdGenerator mIdGenerator = new IntIdGenerator();

        private final LayoutManagerUtils.OnScrollToPositionListener mOnScrollToPositionListener = new LayoutManagerUtils.OnScrollToPositionListener() {

            @Override
            public void onScrollToPosition(int position) {
                ContentHelper.this.onScrollToPosition(position);
            }
        };

        private ProgressView mProgressView;

        private TextView mTipView;

        private ViewGroup mContentView;

        private RefreshLayout mRefreshLayout;

        private EasyRecyclerView mRecyclerView;

        private ViewTransition mViewTransition;

        /**
         * Store data
         */
        private ArrayList<E> mData = new ArrayList<>();

        /**
         * Store the page divider index
         * <p>
         * For example, the data contain page 3, page 4, page 5,
         * page 3 size is 7, page 4 size is 8, page 5 size is 9,
         * so <code>mPageDivider</code> contain 7, 15, 24.
         */
        private IntList mPageDivider = new IntList();

        /**
         * The first page in <code>mData</code>
         */
        private int mStartPage;

        /**
         * The last page + 1 in <code>mData</code>
         */
        private int mEndPage;

        /**
         * The available page count.
         */
        private int mPages;

        private int mNextPage;

        private int mCurrentTaskId;

        private int mCurrentTaskType;

        private int mCurrentTaskPage;

        private int mNextPageScrollSize;

        private String mEmptyString = "No hint";

        private final RefreshLayout.OnRefreshListener mOnRefreshListener = new RefreshLayout.OnRefreshListener() {

            @Override
            public void onHeaderRefresh() {
                if (mStartPage > 0) {
                    mCurrentTaskId = mIdGenerator.nextId();
                    mCurrentTaskType = TYPE_PRE_PAGE_KEEP_POS;
                    mCurrentTaskPage = mStartPage - 1;
                    getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
                } else {
                    doRefresh();
                }
            }

            @Override
            public void onFooterRefresh() {
                if (mEndPage < mPages) {
                    // Get next page
                    // Fill pages before NextPage with empty list
                    while (mNextPage > mEndPage && mEndPage < mPages) {
                        mCurrentTaskId = mIdGenerator.nextId();
                        mCurrentTaskType = TYPE_NEXT_PAGE_KEEP_POS;
                        mCurrentTaskPage = mEndPage;
                        onGetPageData(mCurrentTaskId, mPages, mNextPage, Collections.emptyList());
                    }
                    mCurrentTaskId = mIdGenerator.nextId();
                    mCurrentTaskType = TYPE_NEXT_PAGE_KEEP_POS;
                    mCurrentTaskPage = mEndPage;
                    getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
                } else if (mEndPage == mPages) {
                    // Refresh last page
                    mCurrentTaskId = mIdGenerator.nextId();
                    mCurrentTaskType = TYPE_REFRESH_PAGE;
                    mCurrentTaskPage = mEndPage - 1;
                    getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
                } else {
                    Log.e(TAG, "Try to footer refresh, but mEndPage = " + mEndPage + ", mPages = " + mPages);
                    mRefreshLayout.setFooterRefreshing(false);
                }
            }
        };

        private final RecyclerView.OnScrollListener mOnScrollListener = new RecyclerView.OnScrollListener() {

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                if (!mRefreshLayout.isRefreshing() && mRefreshLayout.isAlmostBottom() && mEndPage < mPages) {
                    // Get next page
                    mRefreshLayout.setFooterRefreshing(true);
                    mOnRefreshListener.onFooterRefresh();
                }
            }
        };

        private int mSavedDataId = IntIdGenerator.INVALID_ID;

        private void init(ContentLayout contentLayout) {
            mNextPageScrollSize = LayoutUtils.dp2pix(contentLayout.getContext(), 48);
            mProgressView = contentLayout.mProgressView;
            mTipView = contentLayout.mTipView;
            mContentView = contentLayout.mContentView;
            mRefreshLayout = contentLayout.mRefreshLayout;
            mRecyclerView = contentLayout.mRecyclerView;
            Drawable drawable = DrawableManager.getVectorDrawable(getContext(), R.drawable.big_sad_pandroid);
            drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
            mTipView.setCompoundDrawables(null, drawable, null, null);
            mViewTransition = new ViewTransition(mContentView, mProgressView, mTipView);
            mViewTransition.setOnShowViewListener(this);
            mRecyclerView.addOnScrollListener(mOnScrollListener);
            mRefreshLayout.setOnRefreshListener(mOnRefreshListener);
            mTipView.setOnClickListener(v -> refresh());
        }

        /**
         * Call {@link #onGetPageData(int, int, int, List)} when get data
         *
         * @param taskId task id
         * @param page   the page to get
         */
        protected abstract void getPageData(int taskId, int type, int page);

        protected abstract Context getContext();

        protected abstract void notifyDataSetChanged();

        protected abstract void notifyItemRangeRemoved(int positionStart, int itemCount);

        protected abstract void notifyItemRangeInserted(int positionStart, int itemCount);

        protected void onScrollToPosition(int postion) {
        }

        @Override
        public void onShowView(View hiddenView, View shownView) {
        }

        public int getShownViewIndex() {
            return mViewTransition.getShownViewIndex();
        }

        public void setRefreshLayoutEnable(boolean enable) {
            mRefreshLayout.setEnabled(enable);
        }

        public void setEnable(boolean enable) {
            mRefreshLayout.setEnabled(enable);
        }

        public void setEmptyString(String str) {
            mEmptyString = str;
        }

        public List<E> getData() {
            return mData;
        }

        /**
         * @throws IndexOutOfBoundsException if {@code location < 0 || location >= size()}
         */
        public E getDataAt(int location) {
            return mData.get(location);
        }

        @Nullable
        public E getDataAtEx(int location) {
            if (location >= 0 && location < mData.size()) {
                return mData.get(location);
            } else {
                return null;
            }
        }

        public int size() {
            return mData.size();
        }

        public boolean isCurrentTask(int taskId) {
            return mCurrentTaskId == taskId;
        }

        public int getPages() {
            return mPages;
        }

        public void addAt(int index, E data) {
            mData.add(index, data);
            onAddData(data);
            for (int i = 0, n = mPageDivider.size(); i < n; i++) {
                int divider = mPageDivider.get(i);
                if (index < divider) {
                    mPageDivider.set(i, divider + 1);
                }
            }
            notifyItemRangeInserted(index, 1);
        }

        public void removeAt(int index) {
            E data = mData.remove(index);
            onRemoveData(data);
            for (int i = 0, n = mPageDivider.size(); i < n; i++) {
                int divider = mPageDivider.get(i);
                if (index < divider) {
                    mPageDivider.set(i, divider - 1);
                }
            }
            notifyItemRangeRemoved(index, 1);
        }

        protected abstract boolean isDuplicate(E d1, E d2);

        private void removeDuplicateData(List<E> data, int start, int end) {
            start = Math.max(0, start);
            end = Math.min(mData.size(), end);
            for (Iterator<E> iterator = data.iterator(); iterator.hasNext(); ) {
                E d = iterator.next();
                for (int i = start; i < end; i++) {
                    if (isDuplicate(d, mData.get(i))) {
                        iterator.remove();
                        break;
                    }
                }
            }
        }

        protected void onAddData(E data) {
        }

        protected void onAddData(List<E> data) {
        }

        protected void onRemoveData(E data) {
        }

        protected void onRemoveData(List<E> data) {
        }

        protected void onClearData() {
        }

        public void onGetPageData(int taskId, int pages, int nextPage, List<E> data) {
            if (mCurrentTaskId == taskId) {
                int dataSize;
                switch(mCurrentTaskType) {
                    case TYPE_REFRESH:
                        mStartPage = 0;
                        mEndPage = 1;
                        mPages = pages;
                        mNextPage = nextPage;
                        mPageDivider.clear();
                        mPageDivider.add(data.size());
                        if (data.isEmpty()) {
                            mData.clear();
                            onClearData();
                            notifyDataSetChanged();
                            if (true || mEndPage >= mPages) {
                                // Not found
                                // Ui change, show empty string
                                mRefreshLayout.setHeaderRefreshing(false);
                                mRefreshLayout.setFooterRefreshing(false);
                                showEmptyString();
                            } else {
                                // Ui change, show progress bar
                                mRefreshLayout.setHeaderRefreshing(false);
                                mRefreshLayout.setFooterRefreshing(false);
                                showProgressBar();
                                // Get next page
                                mCurrentTaskId = mIdGenerator.nextId();
                                mCurrentTaskType = TYPE_NEXT_PAGE_KEEP_POS;
                                mCurrentTaskPage = mEndPage;
                                getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
                            }
                        } else {
                            mData.clear();
                            onClearData();
                            mData.addAll(data);
                            onAddData(data);
                            notifyDataSetChanged();
                            // Ui change, show content
                            mRefreshLayout.setHeaderRefreshing(false);
                            mRefreshLayout.setFooterRefreshing(false);
                            showContent();
                            // RecyclerView scroll
                            if (mRecyclerView.isAttachedToWindow()) {
                                mRecyclerView.stopScroll();
                                LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), 0, 0);
                                onScrollToPosition(0);
                            }
                        }
                        break;
                    case TYPE_PRE_PAGE:
                    case TYPE_PRE_PAGE_KEEP_POS:
                        removeDuplicateData(data, 0, CHECK_DUPLICATE_RANGE);
                        dataSize = data.size();
                        for (int i = 0, n = mPageDivider.size(); i < n; i++) {
                            mPageDivider.set(i, mPageDivider.get(i) + dataSize);
                        }
                        mPageDivider.add(0, dataSize);
                        mStartPage--;
                        mPages = Math.max(mEndPage, pages);
                        // replacedert mStartPage >= 0
                        if (data.isEmpty()) {
                            if (true || mStartPage <= 0) {
                                // OK, that's all
                                if (mData.isEmpty()) {
                                    // Ui change, show empty string
                                    mRefreshLayout.setHeaderRefreshing(false);
                                    mRefreshLayout.setFooterRefreshing(false);
                                    showEmptyString();
                                } else {
                                    // Ui change, show content
                                    mRefreshLayout.setHeaderRefreshing(false);
                                    mRefreshLayout.setFooterRefreshing(false);
                                    showContent();
                                    if (mCurrentTaskType == TYPE_PRE_PAGE && mRecyclerView.isAttachedToWindow()) {
                                        // RecyclerView scroll, to top
                                        mRecyclerView.stopScroll();
                                        LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), 0, 0);
                                        onScrollToPosition(0);
                                    }
                                }
                            } else {
                                // Keep UI
                                // Get previous
                                mCurrentTaskId = mIdGenerator.nextId();
                                // Keep mCurrentTaskType
                                mCurrentTaskPage = mStartPage - 1;
                                getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
                            }
                        } else {
                            mData.addAll(0, data);
                            onAddData(data);
                            notifyItemRangeInserted(0, data.size());
                            // Ui change, show content
                            mRefreshLayout.setHeaderRefreshing(false);
                            mRefreshLayout.setFooterRefreshing(false);
                            showContent();
                            if (mRecyclerView.isAttachedToWindow()) {
                                // RecyclerView scroll
                                if (mCurrentTaskType == TYPE_PRE_PAGE_KEEP_POS) {
                                    mRecyclerView.stopScroll();
                                    LayoutManagerUtils.scrollToPositionProperly(mRecyclerView.getLayoutManager(), getContext(), dataSize - 1, mOnScrollToPositionListener);
                                } else {
                                    mRecyclerView.stopScroll();
                                    LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), 0, 0);
                                    onScrollToPosition(0);
                                }
                            }
                        }
                        break;
                    case TYPE_NEXT_PAGE:
                    case TYPE_NEXT_PAGE_KEEP_POS:
                        removeDuplicateData(data, mData.size() - CHECK_DUPLICATE_RANGE, mData.size());
                        dataSize = data.size();
                        int oldDataSize = mData.size();
                        mPageDivider.add(oldDataSize + dataSize);
                        mEndPage++;
                        mNextPage = nextPage;
                        mPages = Math.max(mEndPage, pages);
                        if (data.isEmpty()) {
                            if (true || mEndPage >= mPages) {
                                // OK, that's all
                                if (mData.isEmpty()) {
                                    // Ui change, show empty string
                                    mRefreshLayout.setHeaderRefreshing(false);
                                    mRefreshLayout.setFooterRefreshing(false);
                                    showEmptyString();
                                } else {
                                    // Ui change, show content
                                    mRefreshLayout.setHeaderRefreshing(false);
                                    mRefreshLayout.setFooterRefreshing(false);
                                    showContent();
                                    if (mCurrentTaskType == TYPE_NEXT_PAGE && mRecyclerView.isAttachedToWindow()) {
                                        // RecyclerView scroll
                                        mRecyclerView.stopScroll();
                                        LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), oldDataSize, 0);
                                        onScrollToPosition(oldDataSize);
                                    }
                                }
                            } else {
                                // Keep UI
                                // Get next page
                                mCurrentTaskId = mIdGenerator.nextId();
                                // Keep mCurrentTaskType
                                mCurrentTaskPage = mEndPage;
                                getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
                            }
                        } else {
                            mData.addAll(data);
                            onAddData(data);
                            notifyItemRangeInserted(oldDataSize, dataSize);
                            // Ui change, show content
                            mRefreshLayout.setHeaderRefreshing(false);
                            mRefreshLayout.setFooterRefreshing(false);
                            showContent();
                            if (mRecyclerView.isAttachedToWindow()) {
                                if (mCurrentTaskType == TYPE_NEXT_PAGE_KEEP_POS) {
                                    mRecyclerView.stopScroll();
                                    mRecyclerView.smoothScrollBy(0, mNextPageScrollSize);
                                } else {
                                    mRecyclerView.stopScroll();
                                    LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), oldDataSize, 0);
                                    onScrollToPosition(oldDataSize);
                                }
                            }
                        }
                        break;
                    case TYPE_SOMEWHERE:
                        mStartPage = mCurrentTaskPage;
                        mEndPage = mCurrentTaskPage + 1;
                        mNextPage = nextPage;
                        mPages = pages;
                        mPageDivider.clear();
                        mPageDivider.add(data.size());
                        if (data.isEmpty()) {
                            mData.clear();
                            onClearData();
                            notifyDataSetChanged();
                            if (true || mEndPage >= mPages) {
                                // Not found
                                // Ui change, show empty string
                                mRefreshLayout.setHeaderRefreshing(false);
                                mRefreshLayout.setFooterRefreshing(false);
                                showEmptyString();
                            } else {
                                // Ui change, show progress bar
                                mRefreshLayout.setHeaderRefreshing(false);
                                mRefreshLayout.setFooterRefreshing(false);
                                showProgressBar();
                                // Get next page
                                mCurrentTaskId = mIdGenerator.nextId();
                                mCurrentTaskType = TYPE_NEXT_PAGE_KEEP_POS;
                                mCurrentTaskPage = mEndPage;
                                getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
                            }
                        } else {
                            mData.clear();
                            onClearData();
                            mData.addAll(data);
                            onAddData(data);
                            notifyDataSetChanged();
                            // Ui change, show content
                            mRefreshLayout.setHeaderRefreshing(false);
                            mRefreshLayout.setFooterRefreshing(false);
                            showContent();
                            if (mRecyclerView.isAttachedToWindow()) {
                                // RecyclerView scroll
                                mRecyclerView.stopScroll();
                                LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), 0, 0);
                                onScrollToPosition(0);
                            }
                        }
                        break;
                    case TYPE_REFRESH_PAGE:
                        if (mCurrentTaskPage < mStartPage || mCurrentTaskPage >= mEndPage) {
                            Log.e(TAG, "TYPE_REFRESH_PAGE, but mCurrentTaskPage = " + mCurrentTaskPage + ", mStartPage = " + mStartPage + ", mEndPage = " + mEndPage);
                            break;
                        }
                        if (mCurrentTaskPage == mEndPage - 1) {
                            mNextPage = nextPage;
                        }
                        mPages = Math.max(mEndPage, pages);
                        int oldIndexStart = mCurrentTaskPage == mStartPage ? 0 : mPageDivider.get(mCurrentTaskPage - mStartPage - 1);
                        int oldIndexEnd = mPageDivider.get(mCurrentTaskPage - mStartPage);
                        List<E> toRemove = mData.subList(oldIndexStart, oldIndexEnd);
                        onRemoveData(toRemove);
                        toRemove.clear();
                        removeDuplicateData(data, oldIndexStart - CHECK_DUPLICATE_RANGE, oldIndexStart + CHECK_DUPLICATE_RANGE);
                        int newIndexStart = oldIndexStart;
                        int newIndexEnd = newIndexStart + data.size();
                        mData.addAll(oldIndexStart, data);
                        onAddData(data);
                        notifyDataSetChanged();
                        for (int i = mCurrentTaskPage - mStartPage, n = mPageDivider.size(); i < n; i++) {
                            mPageDivider.set(i, mPageDivider.get(i) - oldIndexEnd + newIndexEnd);
                        }
                        if (mData.isEmpty()) {
                            // Ui change, show empty string
                            mRefreshLayout.setHeaderRefreshing(false);
                            mRefreshLayout.setFooterRefreshing(false);
                            showEmptyString();
                        } else {
                            // Ui change, show content
                            mRefreshLayout.setHeaderRefreshing(false);
                            mRefreshLayout.setFooterRefreshing(false);
                            showContent();
                            // RecyclerView scroll
                            if (newIndexEnd > oldIndexEnd && newIndexEnd > 0 && mRecyclerView.isAttachedToWindow()) {
                                mRecyclerView.stopScroll();
                                LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), newIndexEnd - 1, 0);
                                onScrollToPosition(newIndexEnd - 1);
                            }
                        }
                        break;
                }
            }
        }

        public void onGetException(int taskId, Exception e) {
            if (mCurrentTaskId == taskId) {
                mRefreshLayout.setHeaderRefreshing(false);
                mRefreshLayout.setFooterRefreshing(false);
                String readableError;
                if (e != null) {
                    e.printStackTrace();
                    readableError = ExceptionUtils.getReadableString(e);
                } else {
                    readableError = getContext().getString(R.string.error_unknown);
                }
                if (mViewTransition.getShownViewIndex() == 0) {
                    Toast.makeText(getContext(), readableError, Toast.LENGTH_SHORT).show();
                } else {
                    showText(readableError);
                }
            }
        }

        public void showContent() {
            mViewTransition.showView(0);
        }

        private boolean isContentShowing() {
            return mViewTransition.getShownViewIndex() == 0;
        }

        public void showProgressBar() {
            showProgressBar(true);
        }

        public void showProgressBar(boolean animation) {
            mViewTransition.showView(1, animation);
        }

        public void showText(CharSequence text) {
            mTipView.setText(text);
            mViewTransition.showView(2);
        }

        public void showEmptyString() {
            showText(mEmptyString);
        }

        /**
         * Be carefull
         */
        public void doGetData(int type, int page, int refreshType) {
            switch(refreshType) {
                default:
                case REFRESH_TYPE_HEADER:
                    showContent();
                    mRefreshLayout.setFooterRefreshing(false);
                    mRefreshLayout.setHeaderRefreshing(true);
                    break;
                case REFRESH_TYPE_FOOTER:
                    showContent();
                    mRefreshLayout.setHeaderRefreshing(false);
                    mRefreshLayout.setFooterRefreshing(true);
                    break;
                case REFRESH_TYPE_PROGRESS_VIEW:
                    showProgressBar();
                    mRefreshLayout.setHeaderRefreshing(false);
                    mRefreshLayout.setFooterRefreshing(false);
                    break;
            }
            mCurrentTaskId = mIdGenerator.nextId();
            mCurrentTaskType = type;
            mCurrentTaskPage = page;
            getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
        }

        private void doRefresh() {
            mCurrentTaskId = mIdGenerator.nextId();
            mCurrentTaskType = TYPE_REFRESH;
            mCurrentTaskPage = 0;
            getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
        }

        /**
         * Lisk {@link #refresh()}, but no animation when show progress bar
         */
        public void firstRefresh() {
            showProgressBar(false);
            doRefresh();
        }

        /**
         * Show progress bar first, than do refresh
         */
        public void refresh() {
            showProgressBar();
            doRefresh();
        }

        private void cancelCurrentTask() {
            mCurrentTaskId = mIdGenerator.nextId();
            mRefreshLayout.setHeaderRefreshing(false);
            mRefreshLayout.setFooterRefreshing(false);
        }

        private int getPageStart(int page) {
            if (mStartPage == page) {
                return 0;
            } else {
                return mPageDivider.get(page - mStartPage - 1);
            }
        }

        private int getPageEnd(int page) {
            return mPageDivider.get(page - mStartPage);
        }

        private int getPageForPosition(int position) {
            if (position < 0) {
                return -1;
            }
            IntList pageDivider = mPageDivider;
            for (int i = 0, n = pageDivider.size(); i < n; i++) {
                if (position < pageDivider.get(i)) {
                    return i + mStartPage;
                }
            }
            return -1;
        }

        public int getPageForTop() {
            return getPageForPosition(LayoutManagerUtils.getFirstVisibleItemPosition(mRecyclerView.getLayoutManager()));
        }

        public int getPageForBottom() {
            return getPageForPosition(LayoutManagerUtils.getLastVisibleItemPosition(mRecyclerView.getLayoutManager()));
        }

        public boolean canGoTo() {
            return isContentShowing();
        }

        /**
         * Check range first!
         *
         * @param page the target page
         * @throws IndexOutOfBoundsException
         */
        public void goTo(int page) throws IndexOutOfBoundsException {
            if (page < 0 || page >= mPages) {
                throw new IndexOutOfBoundsException("Page count is " + mPages + ", page is " + page);
            } else if (page >= mStartPage && page < mEndPage) {
                cancelCurrentTask();
                int position = getPageStart(page);
                mRecyclerView.stopScroll();
                LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), position, 0);
                onScrollToPosition(position);
            } else if (page == mStartPage - 1) {
                mRefreshLayout.setFooterRefreshing(false);
                mRefreshLayout.setHeaderRefreshing(true);
                mCurrentTaskId = mIdGenerator.nextId();
                mCurrentTaskType = TYPE_PRE_PAGE;
                mCurrentTaskPage = page;
                getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
            } else if (page == mEndPage) {
                mRefreshLayout.setHeaderRefreshing(false);
                mRefreshLayout.setFooterRefreshing(true);
                mCurrentTaskId = mIdGenerator.nextId();
                mCurrentTaskType = TYPE_NEXT_PAGE;
                mCurrentTaskPage = page;
                getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
            } else {
                mRefreshLayout.setFooterRefreshing(false);
                mRefreshLayout.setHeaderRefreshing(true);
                mCurrentTaskId = mIdGenerator.nextId();
                mCurrentTaskType = TYPE_SOMEWHERE;
                mCurrentTaskPage = page;
                getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
            }
        }

        protected Parcelable saveInstanceState(Parcelable superState) {
            Bundle bundle = new Bundle();
            bundle.putParcelable(KEY_SUPER, superState);
            int shownView = mViewTransition.getShownViewIndex();
            bundle.putInt(KEY_SHOWN_VIEW, shownView);
            bundle.putString(KEY_TIP, mTipView.getText().toString());
            // TODO It's a bad design
            EhApplication app = (EhApplication) getContext().getApplicationContext();
            if (mSavedDataId != IntIdGenerator.INVALID_ID) {
                app.removeGlobalStuff(mSavedDataId);
                mSavedDataId = IntIdGenerator.INVALID_ID;
            }
            mSavedDataId = app.putGlobalStuff(mData);
            bundle.putInt(KEY_DATA, mSavedDataId);
            bundle.putInt(KEY_NEXT_ID, mIdGenerator.nextId());
            bundle.putParcelable(KEY_PAGE_DIVIDER, mPageDivider);
            bundle.putInt(KEY_START_PAGE, mStartPage);
            bundle.putInt(KEY_END_PAGE, mEndPage);
            bundle.putInt(KEY_PAGES, mPages);
            return bundle;
        }

        protected Parcelable restoreInstanceState(Parcelable state) {
            if (state instanceof Bundle) {
                Bundle bundle = (Bundle) state;
                mViewTransition.showView(bundle.getInt(KEY_SHOWN_VIEW), false);
                mTipView.setText(bundle.getString(KEY_TIP));
                mSavedDataId = bundle.getInt(KEY_DATA);
                ArrayList<E> newData = null;
                EhApplication app = (EhApplication) getContext().getApplicationContext();
                if (mSavedDataId != IntIdGenerator.INVALID_ID) {
                    newData = (ArrayList<E>) app.removeGlobalStuff(mSavedDataId);
                    mSavedDataId = IntIdGenerator.INVALID_ID;
                    if (newData != null) {
                        mData = newData;
                    }
                }
                mIdGenerator.setNextId(bundle.getInt(KEY_NEXT_ID));
                mPageDivider = bundle.getParcelable(KEY_PAGE_DIVIDER);
                mStartPage = bundle.getInt(KEY_START_PAGE);
                mEndPage = bundle.getInt(KEY_END_PAGE);
                mPages = bundle.getInt(KEY_PAGES);
                notifyDataSetChanged();
                if (newData == null) {
                    mPageDivider.clear();
                    mStartPage = 0;
                    mEndPage = 0;
                    mPages = 0;
                    firstRefresh();
                }
                return bundle.getParcelable(KEY_SUPER);
            } else {
                return state;
            }
        }
    }
}

18 Source : GalleryPreviewsScene.java
with Apache License 2.0
from NuclearVGA

public clreplaced GalleryPreviewsScene extends ToolbarScene {

    public static final String KEY_GALLERY_INFO = "gallery_info";

    private final static String KEY_HAS_FIRST_REFRESH = "has_first_refresh";

    /*---------------
     Whole life cycle
     ---------------*/
    @Nullable
    private EhClient mClient;

    @Nullable
    private GalleryInfo mGalleryInfo;

    /*---------------
     View life cycle
     ---------------*/
    @Nullable
    private EasyRecyclerView mRecyclerView;

    @Nullable
    private GalleryPreviewAdapter mAdapter;

    @Nullable
    private GalleryPreviewHelper mHelper;

    private boolean mHasFirstRefresh = false;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Context context = getContext2();
        replacedertUtils.replacedertNotNull(context);
        mClient = EhApplication.getEhClient(context);
        if (savedInstanceState == null) {
            onInit();
        } else {
            onRestore(savedInstanceState);
        }
    }

    private void onInit() {
        Bundle args = getArguments();
        if (args == null) {
            return;
        }
        mGalleryInfo = args.getParcelable(KEY_GALLERY_INFO);
    }

    private void onRestore(@NonNull Bundle savedInstanceState) {
        mGalleryInfo = savedInstanceState.getParcelable(KEY_GALLERY_INFO);
        mHasFirstRefresh = savedInstanceState.getBoolean(KEY_HAS_FIRST_REFRESH);
    }

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        boolean hasFirstRefresh;
        if (mHelper != null && 1 == mHelper.getShownViewIndex()) {
            hasFirstRefresh = false;
        } else {
            hasFirstRefresh = mHasFirstRefresh;
        }
        outState.putBoolean(KEY_HAS_FIRST_REFRESH, hasFirstRefresh);
        outState.putParcelable(KEY_GALLERY_INFO, mGalleryInfo);
    }

    @Nullable
    @Override
    public View onCreateView3(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        ContentLayout contentLayout = (ContentLayout) inflater.inflate(R.layout.scene_gallery_previews, container, false);
        contentLayout.hideFastScroll();
        mRecyclerView = contentLayout.getRecyclerView();
        Context context = getContext2();
        replacedertUtils.replacedertNotNull(context);
        Resources resources = context.getResources();
        mAdapter = new GalleryPreviewAdapter();
        mRecyclerView.setAdapter(mAdapter);
        int columnWidth = resources.getDimensionPixelOffset(Settings.getThumbSizeResId());
        AutoGridLayoutManager layoutManager = new AutoGridLayoutManager(context, columnWidth);
        layoutManager.setStrategy(AutoGridLayoutManager.STRATEGY_SUITABLE_SIZE);
        mRecyclerView.setLayoutManager(layoutManager);
        mRecyclerView.setClipToPadding(false);
        int padding = LayoutUtils.dp2pix(context, 4);
        MarginItemDecoration decoration = new MarginItemDecoration(padding, padding, padding, padding, padding);
        mRecyclerView.addItemDecoration(decoration);
        decoration.applyPaddings(mRecyclerView);
        mHelper = new GalleryPreviewHelper();
        contentLayout.setHelper(mHelper);
        // Only refresh for the first time
        if (!mHasFirstRefresh) {
            mHasFirstRefresh = true;
            mHelper.firstRefresh();
        }
        return contentLayout;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (null != mHelper) {
            if (1 == mHelper.getShownViewIndex()) {
                mHasFirstRefresh = false;
            }
        }
        if (null != mRecyclerView) {
            mRecyclerView.stopScroll();
            mRecyclerView = null;
        }
        mAdapter = null;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        setreplacedle(R.string.gallery_previews);
        setNavigationIcon(R.drawable.v_arrow_left_dark_x24);
    }

    @Override
    public int getMenuResId() {
        return R.menu.scene_gallery_previews;
    }

    @Override
    public boolean onMenuItemClick(MenuItem item) {
        Context context = getContext2();
        if (null == context) {
            return false;
        }
        int id = item.gereplacedemId();
        if (id == R.id.action_go_to) {
            if (mHelper == null) {
                return true;
            }
            int pages = mHelper.getPages();
            if (pages > 0 && mHelper.canGoTo()) {
                GoToDialogHelper helper = new GoToDialogHelper(pages, mHelper.getPageForTop());
                AlertDialog dialog = new MaterialAlertDialogBuilder(context).setreplacedle(R.string.go_to).setView(R.layout.dialog_go_to).setPositiveButton(android.R.string.ok, null).create();
                dialog.show();
                helper.setDialog(dialog);
            }
            return true;
        }
        return false;
    }

    @Override
    public void onNavigationClick() {
        onBackPressed();
    }

    public boolean onItemClick(int position) {
        Context context = getContext2();
        if (null != context && null != mHelper && null != mGalleryInfo) {
            GalleryPreview p = mHelper.getDataAtEx(position);
            if (p != null) {
                Intent intent = new Intent(context, GalleryActivity.clreplaced);
                intent.setAction(GalleryActivity.ACTION_EH);
                intent.putExtra(GalleryActivity.KEY_GALLERY_INFO, mGalleryInfo);
                intent.putExtra(GalleryActivity.KEY_PAGE, p.getPosition());
                startActivity(intent);
            }
        }
        return true;
    }

    private void onGetPreviewSetSuccess(Pair<PreviewSet, Integer> result, int taskId) {
        if (null != mHelper && mHelper.isCurrentTask(taskId) && null != mGalleryInfo) {
            PreviewSet previewSet = result.first;
            int size = previewSet.size();
            ArrayList<GalleryPreview> list = new ArrayList<>(size);
            for (int i = 0; i < size; i++) {
                list.add(previewSet.getGalleryPreview(mGalleryInfo.gid, i));
            }
            mHelper.onGetPageData(taskId, result.second, 0, list);
        }
    }

    private void onGetPreviewSetFailure(Exception e, int taskId) {
        if (mHelper != null && mHelper.isCurrentTask(taskId)) {
            mHelper.onGetException(taskId, e);
        }
    }

    private static clreplaced GetPreviewSetListener extends EhCallback<GalleryPreviewsScene, Pair<PreviewSet, Integer>> {

        private final int mTaskId;

        public GetPreviewSetListener(Context context, int stageId, String sceneTag, int taskId) {
            super(context, stageId, sceneTag);
            mTaskId = taskId;
        }

        @Override
        public void onSuccess(Pair<PreviewSet, Integer> result) {
            GalleryPreviewsScene scene = getScene();
            if (scene != null) {
                scene.onGetPreviewSetSuccess(result, mTaskId);
            }
        }

        @Override
        public void onFailure(Exception e) {
            GalleryPreviewsScene scene = getScene();
            if (scene != null) {
                scene.onGetPreviewSetFailure(e, mTaskId);
            }
        }

        @Override
        public void onCancel() {
        }

        @Override
        public boolean isInstance(SceneFragment scene) {
            return scene instanceof GalleryPreviewsScene;
        }
    }

    private static clreplaced GalleryPreviewHolder extends RecyclerView.ViewHolder {

        public LoadImageView image;

        public TextView text;

        public GalleryPreviewHolder(View itemView) {
            super(itemView);
            image = itemView.findViewById(R.id.image);
            text = itemView.findViewById(R.id.text);
        }
    }

    private clreplaced GalleryPreviewAdapter extends RecyclerView.Adapter<GalleryPreviewHolder> {

        private final LayoutInflater mInflater;

        public GalleryPreviewAdapter() {
            mInflater = getLayoutInflater2();
            replacedertUtils.replacedertNotNull(mInflater);
        }

        @NonNull
        @Override
        public GalleryPreviewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            return new GalleryPreviewHolder(mInflater.inflate(R.layout.item_gallery_preview, parent, false));
        }

        @Override
        @SuppressLint("SetTextI18n")
        public void onBindViewHolder(@NonNull GalleryPreviewHolder holder, int position) {
            if (null != mHelper) {
                GalleryPreview preview = mHelper.getDataAtEx(position);
                if (preview != null) {
                    preview.load(holder.image);
                    holder.text.setText(Integer.toString(preview.getPosition() + 1));
                }
            }
            holder.itemView.setOnClickListener(v -> onItemClick(position));
        }

        @Override
        public int gereplacedemCount() {
            return mHelper != null ? mHelper.size() : 0;
        }
    }

    private clreplaced GalleryPreviewHelper extends ContentLayout.ContentHelper<GalleryPreview> {

        @Override
        protected void getPageData(final int taskId, int type, int page) {
            MainActivity activity = getActivity2();
            if (null == activity || null == mClient || null == mGalleryInfo) {
                onGetException(taskId, new EhException(getString(R.string.error_cannot_find_gallery)));
                return;
            }
            String url = EhUrl.getGalleryDetailUrl(mGalleryInfo.gid, mGalleryInfo.token, page, false);
            EhRequest request = new EhRequest();
            request.setMethod(EhClient.METHOD_GET_PREVIEW_SET);
            request.setCallback(new GetPreviewSetListener(getContext(), activity.getStageId(), getTag(), taskId));
            request.setArgs(url);
            mClient.execute(request);
        }

        @Override
        protected Context getContext() {
            return GalleryPreviewsScene.this.getContext2();
        }

        @Override
        protected void notifyDataSetChanged() {
            if (mAdapter != null) {
                mAdapter.notifyDataSetChanged();
            }
        }

        @Override
        protected void notifyItemRangeRemoved(int positionStart, int itemCount) {
            if (mAdapter != null) {
                mAdapter.notifyItemRangeRemoved(positionStart, itemCount);
            }
        }

        @Override
        protected void notifyItemRangeInserted(int positionStart, int itemCount) {
            if (mAdapter != null) {
                mAdapter.notifyItemRangeInserted(positionStart, itemCount);
            }
        }

        @Override
        protected boolean isDuplicate(GalleryPreview d1, GalleryPreview d2) {
            return false;
        }
    }

    private clreplaced GoToDialogHelper implements View.OnClickListener, DialogInterface.OnDismissListener {

        private final int mPages;

        private final int mCurrentPage;

        @Nullable
        private Slider mSlider;

        @Nullable
        private Dialog mDialog;

        private GoToDialogHelper(int pages, int currentPage) {
            mPages = pages;
            mCurrentPage = currentPage;
        }

        public void setDialog(@NonNull AlertDialog dialog) {
            mDialog = dialog;
            ((TextView) ViewUtils.$$(dialog, R.id.start)).setText(String.format(Locale.US, "%d", 1));
            ((TextView) ViewUtils.$$(dialog, R.id.end)).setText(String.format(Locale.US, "%d", mPages));
            mSlider = (Slider) ViewUtils.$$(dialog, R.id.slider);
            mSlider.setRange(1, mPages);
            mSlider.setProgress(mCurrentPage + 1);
            dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(this);
            dialog.setOnDismissListener(this);
        }

        @Override
        public void onClick(View v) {
            if (null == mSlider) {
                return;
            }
            int page = mSlider.getProgress() - 1;
            if (page >= 0 && page < mPages && mHelper != null) {
                mHelper.goTo(page);
                if (mDialog != null) {
                    mDialog.dismiss();
                    mDialog = null;
                }
            } else {
                showTip(R.string.error_out_of_range, LENGTH_LONG);
            }
        }

        @Override
        public void onDismiss(DialogInterface dialog) {
            mDialog = null;
            mSlider = null;
        }
    }
}

18 Source : HostsActivity.java
with Apache License 2.0
from NuclearVGA

public clreplaced HostsActivity extends ToolbarActivity implements View.OnClickListener {

    private static final String DIALOG_TAG_ADD_HOST = AddHostDialogFragment.clreplaced.getName();

    private static final String DIALOG_TAG_EDIT_HOST = EditHostDialogFragment.clreplaced.getName();

    private static final String KEY_HOST = "com.hippo.ehviewer.ui.HostsActivity.HOST";

    private static final String KEY_IP = "com.hippo.ehviewer.ui.HostsActivity.IP";

    private Hosts hosts;

    private List<Pair<String, String>> data;

    private EasyRecyclerView recyclerView;

    private View tip;

    private HostsAdapter adapter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        hosts = EhApplication.getHosts(this);
        data = hosts.getAll();
        setContentView(R.layout.activity_hosts);
        setreplacedle(R.string.hosts);
        setNavigationIcon(R.drawable.v_arrow_left_dark_x24);
        recyclerView = findViewById(R.id.recycler_view);
        tip = findViewById(R.id.tip);
        FloatingActionButton fab = findViewById(R.id.fab);
        adapter = new HostsAdapter();
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(this, RecyclerView.VERTICAL, false));
        LinearDividerItemDecoration decoration = new LinearDividerItemDecoration(LinearDividerItemDecoration.VERTICAL, AttrResources.getAttrColor(this, R.attr.dividerColor), LayoutUtils.dp2pix(this, 1));
        decoration.setShowLastDivider(true);
        recyclerView.addItemDecoration(decoration);
        // recyclerView.setSelector(Ripple.generateRippleDrawable(this, !AttrResources.getAttrBoolean(this, R.attr.isLightTheme), new ColorDrawable(Color.TRANSPARENT)));
        recyclerView.setHasFixedSize(true);
        // recyclerView.setOnItemClickListener(this);
        recyclerView.setPadding(recyclerView.getPaddingLeft(), recyclerView.getPaddingTop(), recyclerView.getPaddingRight(), recyclerView.getPaddingBottom() + getResources().getDimensionPixelOffset(R.dimen.gallery_padding_bottom_fab));
        fab.setOnClickListener(this);
        recyclerView.setVisibility(data.isEmpty() ? View.GONE : View.VISIBLE);
        tip.setVisibility(data.isEmpty() ? View.VISIBLE : View.GONE);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch(item.gereplacedemId()) {
            case android.R.id.home:
                finish();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    public boolean onItemClick(int position) {
        Pair<String, String> pair = data.get(position);
        Bundle args = new Bundle();
        args.putString(KEY_HOST, pair.first);
        args.putString(KEY_IP, pair.second);
        DialogFragment fragment = new EditHostDialogFragment();
        fragment.setArguments(args);
        fragment.show(getSupportFragmentManager(), DIALOG_TAG_EDIT_HOST);
        return true;
    }

    @Override
    public void onClick(View v) {
        new AddHostDialogFragment().show(getSupportFragmentManager(), DIALOG_TAG_ADD_HOST);
    }

    private void notifyHostsChanges() {
        data = hosts.getAll();
        recyclerView.setVisibility(data.isEmpty() ? View.GONE : View.VISIBLE);
        tip.setVisibility(data.isEmpty() ? View.VISIBLE : View.GONE);
        adapter.notifyDataSetChanged();
    }

    public abstract static clreplaced HostDialogFragment extends DialogFragment {

        private TextView host;

        private TextView ip;

        @NonNull
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_hosts, null, false);
            host = view.findViewById(R.id.host);
            ip = view.findViewById(R.id.ip);
            Bundle arguments = getArguments();
            if (savedInstanceState == null && arguments != null) {
                host.setText(arguments.getString(KEY_HOST));
                ip.setText(arguments.getString(KEY_IP));
            }
            AlertDialog.Builder builder = new MaterialAlertDialogBuilder(requireContext()).setView(view);
            onCreateDialogBuilder(builder);
            AlertDialog dialog = builder.create();
            dialog.setOnShowListener(d -> onCreateDialog((AlertDialog) d));
            return dialog;
        }

        protected abstract void onCreateDialogBuilder(AlertDialog.Builder builder);

        protected abstract void onCreateDialog(AlertDialog dialog);

        protected void put(AlertDialog dialog) {
            TextView host = dialog.findViewById(R.id.host);
            TextView ip = dialog.findViewById(R.id.ip);
            String hostString = host.getText().toString().trim().toLowerCase(Locale.US);
            String ipString = ip.getText().toString().trim();
            if (!Hosts.isValidHost(hostString)) {
                TextInputLayout hostInputLayout = dialog.findViewById(R.id.host_input_layout);
                hostInputLayout.setError(getContext().getString(R.string.invalid_host));
                return;
            }
            if (!Hosts.isValidIp(ipString)) {
                TextInputLayout ipInputLayout = dialog.findViewById(R.id.ip_input_layout);
                ipInputLayout.setError(getContext().getString(R.string.invalid_ip));
                return;
            }
            HostsActivity activity = (HostsActivity) dialog.getOwnerActivity();
            activity.hosts.put(hostString, ipString);
            activity.notifyHostsChanges();
            dialog.dismiss();
        }

        protected void delete(AlertDialog dialog) {
            TextView host = dialog.findViewById(R.id.host);
            String hostString = host.getText().toString().trim().toLowerCase(Locale.US);
            HostsActivity activity = (HostsActivity) dialog.getOwnerActivity();
            activity.hosts.delete(hostString);
            activity.notifyHostsChanges();
            dialog.dismiss();
        }
    }

    public static clreplaced AddHostDialogFragment extends HostDialogFragment {

        @Override
        protected void onCreateDialogBuilder(AlertDialog.Builder builder) {
            builder.setreplacedle(R.string.add_host);
            builder.setPositiveButton(R.string.add_host_add, null);
            builder.setNegativeButton(android.R.string.cancel, null);
        }

        @Override
        protected void onCreateDialog(AlertDialog dialog) {
            dialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> put(dialog));
        }
    }

    public static clreplaced EditHostDialogFragment extends HostDialogFragment {

        @Override
        protected void onCreateDialogBuilder(AlertDialog.Builder builder) {
            builder.setreplacedle(R.string.edit_host);
            builder.setPositiveButton(R.string.edit_host_confirm, null);
            builder.setNegativeButton(R.string.edit_host_delete, null);
        }

        @Override
        protected void onCreateDialog(AlertDialog dialog) {
            dialog.findViewById(R.id.host_input_layout).setEnabled(false);
            dialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> put(dialog));
            dialog.getButton(DialogInterface.BUTTON_NEGATIVE).setOnClickListener(v -> delete(dialog));
        }
    }

    private clreplaced HostsHolder extends RecyclerView.ViewHolder {

        public final TextView host;

        public final TextView ip;

        public HostsHolder(View itemView) {
            super(itemView);
            host = itemView.findViewById(R.id.host);
            ip = itemView.findViewById(R.id.ip);
        }
    }

    private clreplaced HostsAdapter extends RecyclerView.Adapter<HostsHolder> {

        private final LayoutInflater inflater = getLayoutInflater();

        @NonNull
        @Override
        public HostsHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            return new HostsHolder(inflater.inflate(R.layout.item_hosts, parent, false));
        }

        @Override
        public void onBindViewHolder(@NonNull HostsHolder holder, int position) {
            Pair<String, String> pair = data.get(position);
            holder.host.setText(pair.first);
            holder.ip.setText(pair.second);
            holder.itemView.setOnClickListener(v -> onItemClick(position));
        }

        @Override
        public int gereplacedemCount() {
            return data.size();
        }
    }
}

18 Source : FilterActivity.java
with Apache License 2.0
from NuclearVGA

public clreplaced FilterActivity extends ToolbarActivity {

    @Nullable
    private EasyRecyclerView mRecyclerView;

    @Nullable
    private ViewTransition mViewTransition;

    @Nullable
    private FilterAdapter mAdapter;

    @Nullable
    private FilterList mFilterList;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_filter);
        setreplacedle(R.string.filter);
        setNavigationIcon(R.drawable.v_arrow_left_dark_x24);
        mFilterList = new FilterList();
        mRecyclerView = (EasyRecyclerView) ViewUtils.$$(this, R.id.recycler_view);
        TextView tip = (TextView) ViewUtils.$$(this, R.id.tip);
        mViewTransition = new ViewTransition(mRecyclerView, tip);
        Drawable drawable = DrawableManager.getVectorDrawable(this, R.drawable.big_filter);
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        tip.setCompoundDrawables(null, drawable, null, null);
        mAdapter = new FilterAdapter();
        mRecyclerView.setAdapter(mAdapter);
        mRecyclerView.setClipToPadding(false);
        mRecyclerView.setClipChildren(false);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        mRecyclerView.hasFixedSize();
        mRecyclerView.sereplacedemAnimator(null);
        updateView(false);
    }

    private void updateView(boolean animation) {
        if (null == mViewTransition) {
            return;
        }
        if (null == mFilterList || 0 == mFilterList.size()) {
            mViewTransition.showView(1, animation);
        } else {
            mViewTransition.showView(0, animation);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mRecyclerView = null;
        mViewTransition = null;
        mAdapter = null;
        mFilterList = null;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        getMenuInflater().inflate(R.menu.activity_filter, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch(item.gereplacedemId()) {
            case android.R.id.home:
                finish();
                return true;
            case R.id.action_add:
                showAddFilterDialog();
                return true;
            case R.id.action_tip:
                showTipDialog();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    private void showTipDialog() {
        new MaterialAlertDialogBuilder(this).setreplacedle(R.string.filter).setMessage(R.string.filter_tip).show();
    }

    private void showAddFilterDialog() {
        AlertDialog dialog = new MaterialAlertDialogBuilder(this).setreplacedle(R.string.add_filter).setView(R.layout.dialog_add_filter).setPositiveButton(R.string.add, null).setNegativeButton(android.R.string.cancel, null).show();
        AddFilterDialogHelper helper = new AddFilterDialogHelper();
        helper.setDialog(dialog);
    }

    private void showDeleteFilterDialog(final Filter filter) {
        String message = getString(R.string.delete_filter, filter.text);
        new MaterialAlertDialogBuilder(this).setMessage(message).setPositiveButton(R.string.delete, (dialog, which) -> {
            if (DialogInterface.BUTTON_POSITIVE != which || null == mFilterList) {
                return;
            }
            mFilterList.delete(filter);
            if (null != mAdapter) {
                mAdapter.notifyDataSetChanged();
            }
            updateView(true);
        }).setNegativeButton(android.R.string.cancel, null).show();
    }

    private clreplaced AddFilterDialogHelper implements View.OnClickListener {

        @Nullable
        private AlertDialog mDialog;

        @Nullable
        private Spinner mSpinner;

        @Nullable
        private TextInputLayout mInputLayout;

        @Nullable
        private EditText mEditText;

        public void setDialog(AlertDialog dialog) {
            mDialog = dialog;
            mSpinner = (Spinner) ViewUtils.$$(dialog, R.id.spinner);
            mInputLayout = (TextInputLayout) ViewUtils.$$(dialog, R.id.text_input_layout);
            mEditText = mInputLayout.getEditText();
            View button = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
            if (null != button) {
                button.setOnClickListener(this);
            }
        }

        @Override
        public void onClick(View v) {
            if (null == mFilterList || null == mDialog || null == mSpinner || null == mInputLayout || null == mEditText) {
                return;
            }
            String text = mEditText.getText().toString().trim();
            if (TextUtils.isEmpty(text)) {
                mInputLayout.setError(getString(R.string.text_is_empty));
                return;
            } else {
                mInputLayout.setError(null);
            }
            int mode = mSpinner.getSelectedItemPosition();
            Filter filter = new Filter();
            filter.mode = mode;
            filter.text = text;
            mFilterList.add(filter);
            if (null != mAdapter) {
                mAdapter.notifyDataSetChanged();
            }
            updateView(true);
            mDialog.dismiss();
            mDialog = null;
            mSpinner = null;
            mInputLayout = null;
            mEditText = null;
        }
    }

    private clreplaced FilterHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        private final TextView text;

        private final ImageView icon;

        public FilterHolder(View itemView) {
            super(itemView);
            text = (TextView) ViewUtils.$$(itemView, R.id.text);
            icon = itemView.findViewById(R.id.icon);
            if (null != icon) {
                icon.setOnClickListener(this);
            }
            // click on the filter text to enable/disable it
            text.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            int position = getAdapterPosition();
            if (position < 0 || null == mFilterList) {
                return;
            }
            Filter filter = mFilterList.get(position);
            if (FilterList.MODE_HEADER != filter.mode) {
                if (v instanceof ImageView) {
                    showDeleteFilterDialog(filter);
                } else if (v instanceof TextView) {
                    mFilterList.trigger(filter);
                    // for updating delete line on filter text
                    mAdapter.notifyItemChanged(getAdapterPosition());
                }
            }
        }
    }

    private clreplaced FilterAdapter extends RecyclerView.Adapter<FilterHolder> {

        private static final int TYPE_ITEM = 0;

        private static final int TYPE_HEADER = 1;

        @Override
        public int gereplacedemViewType(int position) {
            if (null == mFilterList) {
                return TYPE_ITEM;
            }
            if (mFilterList.get(position).mode == FilterList.MODE_HEADER) {
                return TYPE_HEADER;
            } else {
                return TYPE_ITEM;
            }
        }

        @Override
        public FilterHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            int layoutId;
            switch(viewType) {
                default:
                case TYPE_ITEM:
                    layoutId = R.layout.item_filter;
                    break;
                case TYPE_HEADER:
                    layoutId = R.layout.item_filter_header;
                    break;
            }
            FilterHolder holder = new FilterHolder(getLayoutInflater().inflate(layoutId, parent, false));
            if (R.layout.item_filter == layoutId) {
                holder.icon.setImageDrawable(DrawableManager.getVectorDrawable(FilterActivity.this, R.drawable.v_delete_x24));
            }
            return holder;
        }

        @Override
        public void onBindViewHolder(FilterHolder holder, int position) {
            if (null == mFilterList) {
                return;
            }
            Filter filter = mFilterList.get(position);
            if (FilterList.MODE_HEADER == filter.mode) {
                holder.text.setText(filter.text);
            } else {
                holder.text.setText(filter.text);
                // add a delete line if the filter is disabled
                if (!filter.enable) {
                    holder.text.setPaintFlags(holder.text.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
                } else {
                    holder.text.setPaintFlags(holder.text.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG));
                }
            }
        }

        @Override
        public int gereplacedemCount() {
            return null != mFilterList ? mFilterList.size() : 0;
        }
    }

    private clreplaced FilterList {

        public static final int MODE_HEADER = -1;

        private final EhFilter mEhFilter;

        private final List<Filter> mreplacedleFilterList;

        private final List<Filter> mUploaderFilterList;

        private final List<Filter> mTagFilterList;

        private final List<Filter> mTagNamespaceFilterList;

        private Filter mreplacedleHeader;

        private Filter mUploaderHeader;

        private Filter mTagHeader;

        private Filter mTagNamespaceHeader;

        public FilterList() {
            mEhFilter = EhFilter.getInstance();
            mreplacedleFilterList = mEhFilter.getreplacedleFilterList();
            mUploaderFilterList = mEhFilter.getUploaderFilterList();
            mTagFilterList = mEhFilter.getTagFilterList();
            mTagNamespaceFilterList = mEhFilter.getTagNamespaceFilterList();
        }

        public int size() {
            int count = 0;
            int size = mreplacedleFilterList.size();
            count += 0 == size ? 0 : size + 1;
            size = mUploaderFilterList.size();
            count += 0 == size ? 0 : size + 1;
            size = mTagFilterList.size();
            count += 0 == size ? 0 : size + 1;
            size = mTagNamespaceFilterList.size();
            count += 0 == size ? 0 : size + 1;
            return count;
        }

        private Filter getreplacedleHeader() {
            if (null == mreplacedleHeader) {
                mreplacedleHeader = new Filter();
                mreplacedleHeader.mode = MODE_HEADER;
                mreplacedleHeader.text = getString(R.string.filter_replacedle);
            }
            return mreplacedleHeader;
        }

        private Filter getUploaderHeader() {
            if (null == mUploaderHeader) {
                mUploaderHeader = new Filter();
                mUploaderHeader.mode = MODE_HEADER;
                mUploaderHeader.text = getString(R.string.filter_uploader);
            }
            return mUploaderHeader;
        }

        private Filter getTagHeader() {
            if (null == mTagHeader) {
                mTagHeader = new Filter();
                mTagHeader.mode = MODE_HEADER;
                mTagHeader.text = getString(R.string.filter_tag);
            }
            return mTagHeader;
        }

        private Filter getTagNamespaceHeader() {
            if (null == mTagNamespaceHeader) {
                mTagNamespaceHeader = new Filter();
                mTagNamespaceHeader.mode = MODE_HEADER;
                mTagNamespaceHeader.text = getString(R.string.filter_tag_namespace);
            }
            return mTagNamespaceHeader;
        }

        public Filter get(int index) {
            int size = mreplacedleFilterList.size();
            if (0 != size) {
                if (index == 0) {
                    return getreplacedleHeader();
                } else if (index <= size) {
                    return mreplacedleFilterList.get(index - 1);
                } else {
                    index -= size + 1;
                }
            }
            size = mUploaderFilterList.size();
            if (0 != size) {
                if (index == 0) {
                    return getUploaderHeader();
                } else if (index <= size) {
                    return mUploaderFilterList.get(index - 1);
                } else {
                    index -= size + 1;
                }
            }
            size = mTagFilterList.size();
            if (0 != size) {
                if (index == 0) {
                    return getTagHeader();
                } else if (index <= size) {
                    return mTagFilterList.get(index - 1);
                } else {
                    index -= size + 1;
                }
            }
            size = mTagNamespaceFilterList.size();
            if (0 != size) {
                if (index == 0) {
                    return getTagNamespaceHeader();
                } else if (index <= size) {
                    return mTagNamespaceFilterList.get(index - 1);
                } else {
                    index -= size + 1;
                }
            }
            throw new IndexOutOfBoundsException();
        }

        public void add(Filter filter) {
            mEhFilter.addFilter(filter);
        }

        public void delete(Filter filter) {
            mEhFilter.deleteFilter(filter);
        }

        public void trigger(Filter filter) {
            mEhFilter.triggerFilter(filter);
        }
    }
}

18 Source : ContentLayout.java
with Apache License 2.0
from axlecho

public clreplaced ContentLayout extends FrameLayout {

    private ProgressView mProgressView;

    private TextView mTipView;

    private ViewGroup mContentView;

    private RefreshLayout mRefreshLayout;

    private EasyRecyclerView mRecyclerView;

    private FastScroller mFastScroller;

    private ContentHelper mContentHelper;

    private int mRecyclerViewOriginTop;

    private int mRecyclerViewOriginBottom;

    public ContentLayout(Context context) {
        super(context);
        init(context);
    }

    public ContentLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public ContentLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        LayoutInflater.from(context).inflate(R.layout.widget_content_layout, this);
        mProgressView = (ProgressView) findViewById(R.id.progress);
        mTipView = (TextView) findViewById(R.id.tip);
        mContentView = (ViewGroup) findViewById(R.id.content_view);
        mRefreshLayout = (RefreshLayout) mContentView.findViewById(R.id.refresh_layout);
        mFastScroller = (FastScroller) mContentView.findViewById(R.id.fast_scroller);
        mRecyclerView = (EasyRecyclerView) mRefreshLayout.findViewById(R.id.recycler_view);
        mFastScroller.attachToRecyclerView(mRecyclerView);
        HandlerDrawable drawable = new HandlerDrawable();
        drawable.setColor(AttrResources.getAttrColor(context, R.attr.widgetColorThemeAccent));
        mFastScroller.setHandlerDrawable(drawable);
        mRefreshLayout.setHeaderColorSchemeResources(R.color.loading_indicator_red, R.color.loading_indicator_purple, R.color.loading_indicator_blue, R.color.loading_indicator_cyan, R.color.loading_indicator_green, R.color.loading_indicator_yellow);
        mRefreshLayout.setFooterColorSchemeResources(R.color.loading_indicator_red, R.color.loading_indicator_blue, R.color.loading_indicator_green, R.color.loading_indicator_orange);
        mRecyclerViewOriginTop = mRecyclerView.getPaddingTop();
        mRecyclerViewOriginBottom = mRecyclerView.getPaddingBottom();
    }

    @NonNull
    public EasyRecyclerView getRecyclerView() {
        return mRecyclerView;
    }

    public FastScroller getFastScroller() {
        return mFastScroller;
    }

    public RefreshLayout getRefreshLayout() {
        return mRefreshLayout;
    }

    public void setHelper(ContentHelper helper) {
        mContentHelper = helper;
        helper.init(this);
    }

    public void showFastScroll() {
        if (!mFastScroller.isAttached()) {
            mFastScroller.attachToRecyclerView(mRecyclerView);
        }
    }

    public void hideFastScroll() {
        mFastScroller.detachedFromRecyclerView();
    }

    public void setFitPaddingTop(int fitPaddingTop) {
        // RecyclerView
        mRecyclerView.setPadding(mRecyclerView.getPaddingLeft(), mRecyclerViewOriginTop + fitPaddingTop, mRecyclerView.getPaddingRight(), mRecyclerView.getPaddingBottom());
        // RefreshLayout
        // TODO
        mRefreshLayout.setProgressViewOffset(false, fitPaddingTop, fitPaddingTop + LayoutUtils.dp2pix(getContext(), 32));
    }

    public void setFitPaddingBottom(int fitPaddingBottom) {
        // RecyclerView
        mRecyclerView.setPadding(mRecyclerView.getPaddingLeft(), mRecyclerView.getPaddingTop(), mRecyclerView.getPaddingRight(), mRecyclerViewOriginBottom + fitPaddingBottom);
    }

    @Override
    protected Parcelable onSaveInstanceState() {
        return mContentHelper.saveInstanceState(super.onSaveInstanceState());
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        super.onRestoreInstanceState(mContentHelper.restoreInstanceState(state));
    }

    public abstract static clreplaced ContentHelper<E extends Parcelable> implements ViewTransition.OnShowViewListener {

        private static final String TAG = ContentHelper.clreplaced.getSimpleName();

        private static final int CHECK_DUPLICATE_RANGE = 50;

        private static final String KEY_SUPER = "super";

        private static final String KEY_SHOWN_VIEW = "shown_view";

        private static final String KEY_TIP = "tip";

        private static final String KEY_DATA = "data";

        private static final String KEY_NEXT_ID = "next_id";

        private static final String KEY_PAGE_DIVIDER = "page_divider";

        private static final String KEY_START_PAGE = "start_page";

        private static final String KEY_END_PAGE = "end_page";

        private static final String KEY_PAGES = "pages";

        public static final int TYPE_REFRESH = 0;

        public static final int TYPE_PRE_PAGE = 1;

        public static final int TYPE_PRE_PAGE_KEEP_POS = 2;

        public static final int TYPE_NEXT_PAGE = 3;

        public static final int TYPE_NEXT_PAGE_KEEP_POS = 4;

        public static final int TYPE_SOMEWHERE = 5;

        public static final int TYPE_REFRESH_PAGE = 6;

        public static final int REFRESH_TYPE_HEADER = 0;

        public static final int REFRESH_TYPE_FOOTER = 1;

        public static final int REFRESH_TYPE_PROGRESS_VIEW = 2;

        private ProgressView mProgressView;

        private TextView mTipView;

        private ViewGroup mContentView;

        private RefreshLayout mRefreshLayout;

        private EasyRecyclerView mRecyclerView;

        private ViewTransition mViewTransition;

        private OnClickListener refreshListener = v -> refresh();

        private OnClickListener loginListener = new OnClickListener() {

            @Override
            public void onClick(View v) {
                // login
                Announcer announcer = new Announcer(SignInScene.clreplaced);
                startScene(announcer);
                mTipView.setOnClickListener(refreshListener);
            }
        };

        public void startScene(Announcer announcer) {
            Context activity = getContext();
            if (activity instanceof StageActivity) {
                ((StageActivity) activity).startScene(announcer);
            }
        }

        /**
         * Store data
         */
        private ArrayList<E> mData = new ArrayList<>();

        /**
         * Generate task id
         */
        private final IntIdGenerator mIdGenerator = new IntIdGenerator();

        /**
         * Store the page divider index
         * <p>
         * For example, the data contain page 3, page 4, page 5,
         * page 3 size is 7, page 4 size is 8, page 5 size is 9,
         * so <code>mPageDivider</code> contain 7, 15, 24.
         */
        private IntList mPageDivider = new IntList();

        /**
         * The first page in <code>mData</code>
         */
        private int mStartPage;

        /**
         * The last page + 1 in <code>mData</code>
         */
        private int mEndPage;

        /**
         * The available page count.
         */
        private int mPages;

        private int mNextPage;

        private int mCurrentTaskId;

        private int mCurrentTaskType;

        private int mCurrentTaskPage;

        private int mNextPageScrollSize;

        private String mEmptyString = "No hint";

        private final RecyclerView.OnScrollListener mOnScrollListener = new RecyclerView.OnScrollListener() {

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                if (!mRefreshLayout.isRefreshing() && mRefreshLayout.isAlmostBottom() && mEndPage < mPages) {
                    // Get next page
                    mRefreshLayout.setFooterRefreshing(true);
                    mOnRefreshListener.onFooterRefresh();
                }
            }
        };

        private final RefreshLayout.OnRefreshListener mOnRefreshListener = new RefreshLayout.OnRefreshListener() {

            @Override
            public void onHeaderRefresh() {
                if (mStartPage > 0) {
                    mCurrentTaskId = mIdGenerator.nextId();
                    mCurrentTaskType = TYPE_PRE_PAGE_KEEP_POS;
                    mCurrentTaskPage = mStartPage - 1;
                    getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
                } else {
                    doRefresh();
                }
            }

            @Override
            public void onFooterRefresh() {
                if (mEndPage < mPages) {
                    // Get next page
                    // Fill pages before NextPage with empty list
                    while (mNextPage > mEndPage && mEndPage < mPages) {
                        mCurrentTaskId = mIdGenerator.nextId();
                        mCurrentTaskType = TYPE_NEXT_PAGE_KEEP_POS;
                        mCurrentTaskPage = mEndPage;
                        onGetPageData(mCurrentTaskId, mPages, mNextPage, Collections.emptyList());
                    }
                    mCurrentTaskId = mIdGenerator.nextId();
                    mCurrentTaskType = TYPE_NEXT_PAGE_KEEP_POS;
                    mCurrentTaskPage = mEndPage;
                    getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
                } else if (mEndPage == mPages) {
                    // Refresh last page
                    mCurrentTaskId = mIdGenerator.nextId();
                    mCurrentTaskType = TYPE_REFRESH_PAGE;
                    mCurrentTaskPage = mEndPage - 1;
                    getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
                } else {
                    Log.e(TAG, "Try to footer refresh, but mEndPage = " + mEndPage + ", mPages = " + mPages);
                    mRefreshLayout.setFooterRefreshing(false);
                }
            }
        };

        private final LayoutManagerUtils.OnScrollToPositionListener mOnScrollToPositionListener = new LayoutManagerUtils.OnScrollToPositionListener() {

            @Override
            public void onScrollToPosition(int position) {
                ContentHelper.this.onScrollToPosition(position);
            }
        };

        private void init(ContentLayout contentLayout) {
            mNextPageScrollSize = LayoutUtils.dp2pix(contentLayout.getContext(), 48);
            mProgressView = contentLayout.mProgressView;
            mTipView = contentLayout.mTipView;
            mContentView = contentLayout.mContentView;
            mRefreshLayout = contentLayout.mRefreshLayout;
            mRecyclerView = contentLayout.mRecyclerView;
            Drawable drawable = DrawableManager.getVectorDrawable(getContext(), R.drawable.big_sad_pandroid);
            drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
            mTipView.setCompoundDrawables(null, drawable, null, null);
            mViewTransition = new ViewTransition(mContentView, mProgressView, mTipView);
            mViewTransition.setOnShowViewListener(this);
            mRecyclerView.addOnScrollListener(mOnScrollListener);
            mRefreshLayout.setOnRefreshListener(mOnRefreshListener);
            mTipView.setOnClickListener(refreshListener);
        }

        /**
         * Call {@link #onGetPageData(int, int, int, List)} when get data
         *
         * @param taskId task id
         * @param page   the page to get
         */
        protected abstract void getPageData(int taskId, int type, int page);

        protected abstract Context getContext();

        protected abstract void notifyDataSetChanged();

        protected abstract void notifyItemRangeRemoved(int positionStart, int itemCount);

        protected abstract void notifyItemRangeInserted(int positionStart, int itemCount);

        protected void onScrollToPosition(int postion) {
        }

        @Override
        public void onShowView(View hiddenView, View shownView) {
        }

        public int getShownViewIndex() {
            return mViewTransition.getShownViewIndex();
        }

        public void setRefreshLayoutEnable(boolean enable) {
            mRefreshLayout.setEnabled(enable);
        }

        public void setEnable(boolean enable) {
            mRefreshLayout.setEnabled(enable);
        }

        public void setEmptyString(String str) {
            mEmptyString = str;
        }

        public List<E> getData() {
            return mData;
        }

        /**
         * @throws IndexOutOfBoundsException if {@code location < 0 || location >= size()}
         */
        public E getDataAt(int location) {
            return mData.get(location);
        }

        @Nullable
        public E getDataAtEx(int location) {
            if (location >= 0 && location < mData.size()) {
                return mData.get(location);
            } else {
                return null;
            }
        }

        public int size() {
            return mData.size();
        }

        public boolean isCurrentTask(int taskId) {
            return mCurrentTaskId == taskId;
        }

        public int getPages() {
            return mPages;
        }

        public void addAt(int index, E data) {
            mData.add(index, data);
            onAddData(data);
            for (int i = 0, n = mPageDivider.size(); i < n; i++) {
                int divider = mPageDivider.get(i);
                if (index < divider) {
                    mPageDivider.set(i, divider + 1);
                }
            }
            notifyItemRangeInserted(index, 1);
        }

        public void removeAt(int index) {
            E data = mData.remove(index);
            onRemoveData(data);
            for (int i = 0, n = mPageDivider.size(); i < n; i++) {
                int divider = mPageDivider.get(i);
                if (index < divider) {
                    mPageDivider.set(i, divider - 1);
                }
            }
            notifyItemRangeRemoved(index, 1);
        }

        protected abstract boolean isDuplicate(E d1, E d2);

        private void removeDuplicateData(List<E> data, int start, int end) {
            start = Math.max(0, start);
            end = Math.min(mData.size(), end);
            for (Iterator<E> iterator = data.iterator(); iterator.hasNext(); ) {
                E d = iterator.next();
                for (int i = start; i < end; i++) {
                    if (isDuplicate(d, mData.get(i))) {
                        iterator.remove();
                        break;
                    }
                }
            }
        }

        protected void onAddData(E data) {
        }

        protected void onAddData(List<E> data) {
        }

        protected void onRemoveData(E data) {
        }

        protected void onRemoveData(List<E> data) {
        }

        protected void onClearData() {
        }

        public void onGetPageData(int taskId, int pages, int nextPage, List<E> data) {
            if (mCurrentTaskId == taskId) {
                int dataSize;
                switch(mCurrentTaskType) {
                    case TYPE_REFRESH:
                        mStartPage = 0;
                        mEndPage = 1;
                        mPages = pages;
                        mNextPage = nextPage;
                        mPageDivider.clear();
                        mPageDivider.add(data.size());
                        if (data.isEmpty()) {
                            mData.clear();
                            onClearData();
                            notifyDataSetChanged();
                            if (true || mEndPage >= mPages) {
                                // Not found
                                // Ui change, show empty string
                                mRefreshLayout.setHeaderRefreshing(false);
                                mRefreshLayout.setFooterRefreshing(false);
                                showEmptyString();
                            } else {
                                // Ui change, show progress bar
                                mRefreshLayout.setHeaderRefreshing(false);
                                mRefreshLayout.setFooterRefreshing(false);
                                showProgressBar();
                                // Get next page
                                mCurrentTaskId = mIdGenerator.nextId();
                                mCurrentTaskType = TYPE_NEXT_PAGE_KEEP_POS;
                                mCurrentTaskPage = mEndPage;
                                getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
                            }
                        } else {
                            mData.clear();
                            onClearData();
                            mData.addAll(data);
                            onAddData(data);
                            notifyDataSetChanged();
                            // Ui change, show content
                            mRefreshLayout.setHeaderRefreshing(false);
                            mRefreshLayout.setFooterRefreshing(false);
                            showContent();
                            // RecyclerView scroll
                            if (mRecyclerView.isAttachedToWindow()) {
                                mRecyclerView.stopScroll();
                                LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), 0, 0);
                                onScrollToPosition(0);
                            }
                        }
                        break;
                    case TYPE_PRE_PAGE:
                    case TYPE_PRE_PAGE_KEEP_POS:
                        removeDuplicateData(data, 0, CHECK_DUPLICATE_RANGE);
                        dataSize = data.size();
                        for (int i = 0, n = mPageDivider.size(); i < n; i++) {
                            mPageDivider.set(i, mPageDivider.get(i) + dataSize);
                        }
                        mPageDivider.add(0, dataSize);
                        mStartPage--;
                        mPages = Math.max(mEndPage, pages);
                        // replacedert mStartPage >= 0
                        if (data.isEmpty()) {
                            if (true || mStartPage <= 0) {
                                // OK, that's all
                                if (mData.isEmpty()) {
                                    // Ui change, show empty string
                                    mRefreshLayout.setHeaderRefreshing(false);
                                    mRefreshLayout.setFooterRefreshing(false);
                                    showEmptyString();
                                } else {
                                    // Ui change, show content
                                    mRefreshLayout.setHeaderRefreshing(false);
                                    mRefreshLayout.setFooterRefreshing(false);
                                    showContent();
                                    if (mCurrentTaskType == TYPE_PRE_PAGE && mRecyclerView.isAttachedToWindow()) {
                                        // RecyclerView scroll, to top
                                        mRecyclerView.stopScroll();
                                        LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), 0, 0);
                                        onScrollToPosition(0);
                                    }
                                }
                            } else {
                                // Keep UI
                                // Get previous
                                mCurrentTaskId = mIdGenerator.nextId();
                                // Keep mCurrentTaskType
                                mCurrentTaskPage = mStartPage - 1;
                                getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
                            }
                        } else {
                            mData.addAll(0, data);
                            onAddData(data);
                            notifyItemRangeInserted(0, data.size());
                            // Ui change, show content
                            mRefreshLayout.setHeaderRefreshing(false);
                            mRefreshLayout.setFooterRefreshing(false);
                            showContent();
                            if (mRecyclerView.isAttachedToWindow()) {
                                // RecyclerView scroll
                                if (mCurrentTaskType == TYPE_PRE_PAGE_KEEP_POS) {
                                    mRecyclerView.stopScroll();
                                    LayoutManagerUtils.scrollToPositionProperly(mRecyclerView.getLayoutManager(), getContext(), dataSize - 1, mOnScrollToPositionListener);
                                } else {
                                    mRecyclerView.stopScroll();
                                    LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), 0, 0);
                                    onScrollToPosition(0);
                                }
                            }
                        }
                        break;
                    case TYPE_NEXT_PAGE:
                    case TYPE_NEXT_PAGE_KEEP_POS:
                        removeDuplicateData(data, mData.size() - CHECK_DUPLICATE_RANGE, mData.size());
                        dataSize = data.size();
                        int oldDataSize = mData.size();
                        mPageDivider.add(oldDataSize + dataSize);
                        mEndPage++;
                        mNextPage = nextPage;
                        mPages = Math.max(mEndPage, pages);
                        if (data.isEmpty()) {
                            if (true || mEndPage >= mPages) {
                                // OK, that's all
                                if (mData.isEmpty()) {
                                    // Ui change, show empty string
                                    mRefreshLayout.setHeaderRefreshing(false);
                                    mRefreshLayout.setFooterRefreshing(false);
                                    showEmptyString();
                                } else {
                                    // Ui change, show content
                                    mRefreshLayout.setHeaderRefreshing(false);
                                    mRefreshLayout.setFooterRefreshing(false);
                                    showContent();
                                    if (mCurrentTaskType == TYPE_NEXT_PAGE && mRecyclerView.isAttachedToWindow()) {
                                        // RecyclerView scroll
                                        mRecyclerView.stopScroll();
                                        LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), oldDataSize, 0);
                                        onScrollToPosition(oldDataSize);
                                    }
                                }
                            } else {
                                // Keep UI
                                // Get next page
                                mCurrentTaskId = mIdGenerator.nextId();
                                // Keep mCurrentTaskType
                                mCurrentTaskPage = mEndPage;
                                getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
                            }
                        } else {
                            mData.addAll(data);
                            onAddData(data);
                            notifyItemRangeInserted(oldDataSize, dataSize);
                            // Ui change, show content
                            mRefreshLayout.setHeaderRefreshing(false);
                            mRefreshLayout.setFooterRefreshing(false);
                            showContent();
                            if (mRecyclerView.isAttachedToWindow()) {
                                if (mCurrentTaskType == TYPE_NEXT_PAGE_KEEP_POS) {
                                    mRecyclerView.stopScroll();
                                    mRecyclerView.smoothScrollBy(0, mNextPageScrollSize);
                                } else {
                                    mRecyclerView.stopScroll();
                                    LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), oldDataSize, 0);
                                    onScrollToPosition(oldDataSize);
                                }
                            }
                        }
                        break;
                    case TYPE_SOMEWHERE:
                        mStartPage = mCurrentTaskPage;
                        mEndPage = mCurrentTaskPage + 1;
                        mNextPage = nextPage;
                        mPages = pages;
                        mPageDivider.clear();
                        mPageDivider.add(data.size());
                        if (data.isEmpty()) {
                            mData.clear();
                            onClearData();
                            notifyDataSetChanged();
                            if (true || mEndPage >= mPages) {
                                // Not found
                                // Ui change, show empty string
                                mRefreshLayout.setHeaderRefreshing(false);
                                mRefreshLayout.setFooterRefreshing(false);
                                showEmptyString();
                            } else {
                                // Ui change, show progress bar
                                mRefreshLayout.setHeaderRefreshing(false);
                                mRefreshLayout.setFooterRefreshing(false);
                                showProgressBar();
                                // Get next page
                                mCurrentTaskId = mIdGenerator.nextId();
                                mCurrentTaskType = TYPE_NEXT_PAGE_KEEP_POS;
                                mCurrentTaskPage = mEndPage;
                                getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
                            }
                        } else {
                            mData.clear();
                            onClearData();
                            mData.addAll(data);
                            onAddData(data);
                            notifyDataSetChanged();
                            // Ui change, show content
                            mRefreshLayout.setHeaderRefreshing(false);
                            mRefreshLayout.setFooterRefreshing(false);
                            showContent();
                            if (mRecyclerView.isAttachedToWindow()) {
                                // RecyclerView scroll
                                mRecyclerView.stopScroll();
                                LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), 0, 0);
                                onScrollToPosition(0);
                            }
                        }
                        break;
                    case TYPE_REFRESH_PAGE:
                        if (mCurrentTaskPage < mStartPage || mCurrentTaskPage >= mEndPage) {
                            Log.e(TAG, "TYPE_REFRESH_PAGE, but mCurrentTaskPage = " + mCurrentTaskPage + ", mStartPage = " + mStartPage + ", mEndPage = " + mEndPage);
                            break;
                        }
                        if (mCurrentTaskPage == mEndPage - 1) {
                            mNextPage = nextPage;
                        }
                        mPages = Math.max(mEndPage, pages);
                        int oldIndexStart = mCurrentTaskPage == mStartPage ? 0 : mPageDivider.get(mCurrentTaskPage - mStartPage - 1);
                        int oldIndexEnd = mPageDivider.get(mCurrentTaskPage - mStartPage);
                        List<E> toRemove = mData.subList(oldIndexStart, oldIndexEnd);
                        onRemoveData(toRemove);
                        toRemove.clear();
                        removeDuplicateData(data, oldIndexStart - CHECK_DUPLICATE_RANGE, oldIndexStart + CHECK_DUPLICATE_RANGE);
                        int newIndexStart = oldIndexStart;
                        int newIndexEnd = newIndexStart + data.size();
                        mData.addAll(oldIndexStart, data);
                        onAddData(data);
                        notifyDataSetChanged();
                        for (int i = mCurrentTaskPage - mStartPage, n = mPageDivider.size(); i < n; i++) {
                            mPageDivider.set(i, mPageDivider.get(i) - oldIndexEnd + newIndexEnd);
                        }
                        if (mData.isEmpty()) {
                            // Ui change, show empty string
                            mRefreshLayout.setHeaderRefreshing(false);
                            mRefreshLayout.setFooterRefreshing(false);
                            showEmptyString();
                        } else {
                            // Ui change, show content
                            mRefreshLayout.setHeaderRefreshing(false);
                            mRefreshLayout.setFooterRefreshing(false);
                            showContent();
                            // RecyclerView scroll
                            if (newIndexEnd > oldIndexEnd && newIndexEnd > 0 && mRecyclerView.isAttachedToWindow()) {
                                mRecyclerView.stopScroll();
                                LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), newIndexEnd - 1, 0);
                                onScrollToPosition(newIndexEnd - 1);
                            }
                        }
                        break;
                }
            }
        }

        public void onGetException(int taskId, Exception e) {
            if (mCurrentTaskId == taskId) {
                mRefreshLayout.setHeaderRefreshing(false);
                mRefreshLayout.setFooterRefreshing(false);
                String readableError;
                if (e != null) {
                    e.printStackTrace();
                    if (e instanceof HttpException && ((HttpException) e).code() == 401) {
                        // do login
                        mTipView.setOnClickListener(loginListener);
                    }
                    readableError = ExceptionUtils.getReadableString(e);
                } else {
                    readableError = getContext().getString(R.string.error_unknown);
                }
                if (mViewTransition.getShownViewIndex() == 0) {
                    Toast.makeText(getContext(), readableError, Toast.LENGTH_SHORT).show();
                } else {
                    showText(readableError);
                }
            }
        }

        public void showContent() {
            mViewTransition.showView(0);
        }

        private boolean isContentShowing() {
            return mViewTransition.getShownViewIndex() == 0;
        }

        public void showProgressBar() {
            showProgressBar(true);
        }

        public void showProgressBar(boolean animation) {
            mViewTransition.showView(1, animation);
        }

        public void showText(CharSequence text) {
            mTipView.setText(text);
            mViewTransition.showView(2);
        }

        public void showEmptyString() {
            showText(mEmptyString);
        }

        /**
         * Be carefull
         */
        public void doGetData(int type, int page, int refreshType) {
            switch(refreshType) {
                default:
                case REFRESH_TYPE_HEADER:
                    showContent();
                    mRefreshLayout.setFooterRefreshing(false);
                    mRefreshLayout.setHeaderRefreshing(true);
                    break;
                case REFRESH_TYPE_FOOTER:
                    showContent();
                    mRefreshLayout.setHeaderRefreshing(false);
                    mRefreshLayout.setFooterRefreshing(true);
                    break;
                case REFRESH_TYPE_PROGRESS_VIEW:
                    showProgressBar();
                    mRefreshLayout.setHeaderRefreshing(false);
                    mRefreshLayout.setFooterRefreshing(false);
                    break;
            }
            mCurrentTaskId = mIdGenerator.nextId();
            mCurrentTaskType = type;
            mCurrentTaskPage = page;
            getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
        }

        private void doRefresh() {
            mCurrentTaskId = mIdGenerator.nextId();
            mCurrentTaskType = TYPE_REFRESH;
            mCurrentTaskPage = 0;
            getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
        }

        /**
         * Lisk {@link #refresh()}, but no animation when show progress bar
         */
        public void firstRefresh() {
            showProgressBar(false);
            doRefresh();
        }

        /**
         * Show progress bar first, than do refresh
         */
        public void refresh() {
            showProgressBar();
            doRefresh();
        }

        private void cancelCurrentTask() {
            mCurrentTaskId = mIdGenerator.nextId();
            mRefreshLayout.setHeaderRefreshing(false);
            mRefreshLayout.setFooterRefreshing(false);
        }

        private int getPageStart(int page) {
            if (mStartPage == page) {
                return 0;
            } else {
                return mPageDivider.get(page - mStartPage - 1);
            }
        }

        private int getPageEnd(int page) {
            return mPageDivider.get(page - mStartPage);
        }

        private int getPageForPosition(int position) {
            if (position < 0) {
                return -1;
            }
            IntList pageDivider = mPageDivider;
            for (int i = 0, n = pageDivider.size(); i < n; i++) {
                if (position < pageDivider.get(i)) {
                    return i + mStartPage;
                }
            }
            return -1;
        }

        public int getPageForTop() {
            return getPageForPosition(LayoutManagerUtils.getFirstVisibleItemPosition(mRecyclerView.getLayoutManager()));
        }

        public int getPageForBottom() {
            return getPageForPosition(LayoutManagerUtils.getLastVisibleItemPosition(mRecyclerView.getLayoutManager()));
        }

        public boolean canGoTo() {
            return isContentShowing();
        }

        /**
         * Check range first!
         *
         * @param page the target page
         * @throws IndexOutOfBoundsException
         */
        public void goTo(int page) throws IndexOutOfBoundsException {
            if (page < 0 || page >= mPages) {
                throw new IndexOutOfBoundsException("Page count is " + mPages + ", page is " + page);
            } else if (page >= mStartPage && page < mEndPage) {
                cancelCurrentTask();
                int position = getPageStart(page);
                mRecyclerView.stopScroll();
                LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), position, 0);
                onScrollToPosition(position);
            } else if (page == mStartPage - 1) {
                mRefreshLayout.setFooterRefreshing(false);
                mRefreshLayout.setHeaderRefreshing(true);
                mCurrentTaskId = mIdGenerator.nextId();
                mCurrentTaskType = TYPE_PRE_PAGE;
                mCurrentTaskPage = page;
                getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
            } else if (page == mEndPage) {
                mRefreshLayout.setHeaderRefreshing(false);
                mRefreshLayout.setFooterRefreshing(true);
                mCurrentTaskId = mIdGenerator.nextId();
                mCurrentTaskType = TYPE_NEXT_PAGE;
                mCurrentTaskPage = page;
                getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
            } else {
                mRefreshLayout.setFooterRefreshing(false);
                mRefreshLayout.setHeaderRefreshing(true);
                mCurrentTaskId = mIdGenerator.nextId();
                mCurrentTaskType = TYPE_SOMEWHERE;
                mCurrentTaskPage = page;
                getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
            }
        }

        private int mSavedDataId = IntIdGenerator.INVALID_ID;

        protected Parcelable saveInstanceState(Parcelable superState) {
            Bundle bundle = new Bundle();
            bundle.putParcelable(KEY_SUPER, superState);
            int shownView = mViewTransition.getShownViewIndex();
            bundle.putInt(KEY_SHOWN_VIEW, shownView);
            bundle.putString(KEY_TIP, mTipView.getText().toString());
            // TODO It's a bad design
            EhApplication app = (EhApplication) getContext().getApplicationContext();
            if (mSavedDataId != IntIdGenerator.INVALID_ID) {
                app.removeGlobalStuff(mSavedDataId);
                mSavedDataId = IntIdGenerator.INVALID_ID;
            }
            mSavedDataId = app.putGlobalStuff(mData);
            bundle.putInt(KEY_DATA, mSavedDataId);
            bundle.putInt(KEY_NEXT_ID, mIdGenerator.nextId());
            bundle.putParcelable(KEY_PAGE_DIVIDER, mPageDivider);
            bundle.putInt(KEY_START_PAGE, mStartPage);
            bundle.putInt(KEY_END_PAGE, mEndPage);
            bundle.putInt(KEY_PAGES, mPages);
            return bundle;
        }

        protected Parcelable restoreInstanceState(Parcelable state) {
            if (state instanceof Bundle) {
                Bundle bundle = (Bundle) state;
                mViewTransition.showView(bundle.getInt(KEY_SHOWN_VIEW), false);
                mTipView.setText(bundle.getString(KEY_TIP));
                mSavedDataId = bundle.getInt(KEY_DATA);
                ArrayList<E> newData = null;
                EhApplication app = (EhApplication) getContext().getApplicationContext();
                if (mSavedDataId != IntIdGenerator.INVALID_ID) {
                    newData = (ArrayList<E>) app.removeGlobalStuff(mSavedDataId);
                    mSavedDataId = IntIdGenerator.INVALID_ID;
                    if (newData != null) {
                        mData = newData;
                    }
                }
                mIdGenerator.setNextId(bundle.getInt(KEY_NEXT_ID));
                mPageDivider = bundle.getParcelable(KEY_PAGE_DIVIDER);
                mStartPage = bundle.getInt(KEY_START_PAGE);
                mEndPage = bundle.getInt(KEY_END_PAGE);
                mPages = bundle.getInt(KEY_PAGES);
                notifyDataSetChanged();
                if (newData == null) {
                    mPageDivider.clear();
                    mStartPage = 0;
                    mEndPage = 0;
                    mPages = 0;
                    firstRefresh();
                }
                return bundle.getParcelable(KEY_SUPER);
            } else {
                return state;
            }
        }
    }
}

18 Source : HistoryScene.java
with Apache License 2.0
from axlecho

public clreplaced HistoryScene extends ToolbarScene implements EasyRecyclerView.OnItemClickListener, EasyRecyclerView.OnItemLongClickListener {

    /*---------------
     View life cycle
     ---------------*/
    @Nullable
    private EasyRecyclerView mRecyclerView;

    @Nullable
    private ViewTransition mViewTransition;

    @Nullable
    private RecyclerView.Adapter<?> mAdapter;

    @Nullable
    private LazyList<HistoryInfo> mLazyList;

    @Override
    public int getNavCheckedItem() {
        return R.id.nav_history;
    }

    @Nullable
    @Override
    public View onCreateView3(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.scene_history, container, false);
        View content = ViewUtils.$$(view, R.id.content);
        mRecyclerView = (EasyRecyclerView) ViewUtils.$$(content, R.id.recycler_view);
        FastScroller fastScroller = (FastScroller) ViewUtils.$$(content, R.id.fast_scroller);
        TextView tip = (TextView) ViewUtils.$$(view, R.id.tip);
        mViewTransition = new ViewTransition(content, tip);
        Context context = getContext2();
        replacedertUtils.replacedertNotNull(context);
        Resources resources = context.getResources();
        Drawable drawable = DrawableManager.getVectorDrawable(context, R.drawable.big_history);
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        tip.setCompoundDrawables(null, drawable, null, null);
        RecyclerViewTouchActionGuardManager guardManager = new RecyclerViewTouchActionGuardManager();
        guardManager.setInterceptVerticalScrollingWhileAnimationRunning(true);
        guardManager.setEnabled(true);
        RecyclerViewSwipeManager swipeManager = new RecyclerViewSwipeManager();
        mAdapter = new HistoryAdapter();
        mAdapter.setHreplacedtableIds(true);
        mAdapter = swipeManager.createWrappedAdapter(mAdapter);
        mRecyclerView.setAdapter(mAdapter);
        final GeneralItemAnimator animator = new SwipeDismissItemAnimator();
        animator.setSupportsChangeAnimations(false);
        mRecyclerView.sereplacedemAnimator(animator);
        AutoStaggeredGridLayoutManager layoutManager = new AutoStaggeredGridLayoutManager(0, StaggeredGridLayoutManager.VERTICAL);
        layoutManager.setColumnSize(resources.getDimensionPixelOffset(Settings.getDetailSizeResId()));
        layoutManager.setStrategy(AutoStaggeredGridLayoutManager.STRATEGY_MIN_SIZE);
        mRecyclerView.setLayoutManager(layoutManager);
        mRecyclerView.setSelector(Ripple.generateRippleDrawable(context, !AttrResources.getAttrBoolean(context, R.attr.isLightTheme), new ColorDrawable(Color.TRANSPARENT)));
        mRecyclerView.setDrawSelectorOnTop(true);
        mRecyclerView.setClipToPadding(false);
        mRecyclerView.setOnItemClickListener(this);
        mRecyclerView.setOnItemLongClickListener(this);
        int interval = resources.getDimensionPixelOffset(R.dimen.gallery_list_interval);
        int paddingH = resources.getDimensionPixelOffset(R.dimen.gallery_list_margin_h);
        int paddingV = resources.getDimensionPixelOffset(R.dimen.gallery_list_margin_v);
        MarginItemDecoration decoration = new MarginItemDecoration(interval, paddingH, paddingV, paddingH, paddingV);
        mRecyclerView.addItemDecoration(decoration);
        decoration.applyPaddings(mRecyclerView);
        guardManager.attachRecyclerView(mRecyclerView);
        swipeManager.attachRecyclerView(mRecyclerView);
        fastScroller.attachToRecyclerView(mRecyclerView);
        HandlerDrawable handlerDrawable = new HandlerDrawable();
        handlerDrawable.setColor(AttrResources.getAttrColor(context, R.attr.widgetColorThemeAccent));
        fastScroller.setHandlerDrawable(handlerDrawable);
        updateLazyList();
        updateView(false);
        return view;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        setreplacedle(R.string.history);
        setNavigationIcon(R.drawable.v_arrow_left_dark_x24);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (null != mLazyList) {
            mLazyList.close();
            mLazyList = null;
            if (mAdapter != null) {
                mAdapter.notifyDataSetChanged();
            }
        }
        if (null != mRecyclerView) {
            mRecyclerView.stopScroll();
            mRecyclerView = null;
        }
        mViewTransition = null;
        mAdapter = null;
    }

    // Remember to notify
    private void updateLazyList() {
        LazyList<HistoryInfo> lazyList = EhDB.getHistoryLazyList();
        if (mLazyList != null) {
            mLazyList.close();
        }
        mLazyList = lazyList;
    }

    private void updateView(boolean animation) {
        if (null == mAdapter || null == mViewTransition) {
            return;
        }
        if (mAdapter.gereplacedemCount() == 0) {
            mViewTransition.showView(1, animation);
        } else {
            mViewTransition.showView(0, animation);
        }
    }

    @Override
    public void onNavigationClick() {
        onBackPressed();
    }

    @Override
    public int getMenuResId() {
        return R.menu.scene_history;
    }

    private void showClearAllDialog() {
        new AlertDialog.Builder(getContext2()).setMessage(R.string.clear_all_history).setPositiveButton(R.string.clear_all, new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (DialogInterface.BUTTON_POSITIVE != which || null == mAdapter) {
                    return;
                }
                EhDB.clearHistoryInfo();
                updateLazyList();
                mAdapter.notifyDataSetChanged();
                updateView(true);
            }
        }).show();
    }

    @Override
    public boolean onMenuItemClick(MenuItem item) {
        // Skip when in choice mode
        Context context = getContext2();
        if (null == context) {
            return false;
        }
        int id = item.gereplacedemId();
        switch(id) {
            case R.id.action_clear_all:
                {
                    showClearAllDialog();
                    return true;
                }
        }
        return false;
    }

    @Override
    public boolean onItemClick(EasyRecyclerView parent, View view, int position, long id) {
        if (null == mLazyList) {
            return false;
        }
        Bundle args = new Bundle();
        args.putString(GalleryDetailScene.KEY_ACTION, GalleryDetailScene.ACTION_GALLERY_INFO);
        args.putParcelable(GalleryDetailScene.KEY_GALLERY_INFO, new GalleryInfo(mLazyList.get(position)));
        Announcer announcer = new Announcer(GalleryDetailScene.clreplaced).setArgs(args);
        View thumb;
        if (null != (thumb = view.findViewById(R.id.thumb))) {
            announcer.setTranHelper(new EnterGalleryDetailTransaction(thumb));
        }
        startScene(announcer);
        return true;
    }

    @Override
    public boolean onItemLongClick(EasyRecyclerView parent, View view, int position, long id) {
        final Context context = getContext2();
        final MainActivity activity = getActivity2();
        if (null == context || null == activity || null == mLazyList) {
            return false;
        }
        final GalleryInfo gi = mLazyList.get(position);
        new AlertDialog.Builder(context).setreplacedle(EhUtils.getSuitablereplacedle(gi)).sereplacedems(R.array.gallery_list_menu_entries, (dialog, which) -> {
            switch(which) {
                case // Download
                0:
                    CommonOperations.startDownload(activity, gi, false);
                    break;
                case // Favorites
                1:
                    CommonOperations.addToFavorites(activity, gi);
                    showTip(R.string.add_to_favorite_success, LENGTH_SHORT);
                    break;
            }
        }).show();
        return true;
    }

    private clreplaced HistoryHolder extends AbstractSwipeableItemViewHolder {

        public final View card;

        public final LoadImageView thumb;

        public final TextView replacedle;

        public final TextView uploader;

        public final SimpleRatingView rating;

        public final TextView category;

        public final TextView posted;

        public final TextView simpleLanguage;

        public final TextView source;

        public HistoryHolder(View itemView) {
            super(itemView);
            card = itemView.findViewById(R.id.card);
            thumb = (LoadImageView) itemView.findViewById(R.id.thumb);
            replacedle = (TextView) itemView.findViewById(R.id.replacedle);
            uploader = (TextView) itemView.findViewById(R.id.uploader);
            rating = (SimpleRatingView) itemView.findViewById(R.id.rating);
            category = (TextView) itemView.findViewById(R.id.category);
            posted = (TextView) itemView.findViewById(R.id.posted);
            simpleLanguage = (TextView) itemView.findViewById(R.id.simple_language);
            source = itemView.findViewById(R.id.source_bg);
        }

        @Override
        public View getSwipeableContainerView() {
            return card;
        }
    }

    private clreplaced HistoryAdapter extends RecyclerView.Adapter<HistoryHolder> implements SwipeableItemAdapter<HistoryHolder> {

        private final LayoutInflater mInflater;

        private final int mListThumbWidth;

        private final int mListThumbHeight;

        public HistoryAdapter() {
            mInflater = getLayoutInflater2();
            View calculator = mInflater.inflate(R.layout.item_gallery_list_thumb_height, null);
            ViewUtils.measureView(calculator, 1024, ViewGroup.LayoutParams.WRAP_CONTENT);
            mListThumbHeight = calculator.getMeasuredHeight();
            mListThumbWidth = mListThumbHeight * 2 / 3;
        }

        @Override
        public long gereplacedemId(int position) {
            if (null == mLazyList) {
                return super.gereplacedemId(position);
            } else {
                return position;
            }
        }

        @Override
        public HistoryHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            HistoryHolder holder = new HistoryHolder(mInflater.inflate(R.layout.item_history, parent, false));
            ViewGroup.LayoutParams lp = holder.thumb.getLayoutParams();
            lp.width = mListThumbWidth;
            lp.height = mListThumbHeight;
            holder.thumb.setLayoutParams(lp);
            return holder;
        }

        @Override
        public void onBindViewHolder(HistoryHolder holder, int position) {
            if (null == mLazyList) {
                return;
            }
            GalleryInfo gi = mLazyList.get(position);
            holder.thumb.load(EhCacheKeyFactory.getThumbKey(gi.gid), gi.thumb);
            holder.replacedle.setText(EhUtils.getSuitablereplacedle(gi));
            holder.uploader.setText(gi.uploader);
            holder.rating.setRating(gi.rating);
            TextView category = holder.category;
            String newCategoryText = EhUtils.getCategory(gi.category);
            if (!newCategoryText.equals(category.getText())) {
                category.setText(newCategoryText);
                category.setBackgroundColor(EhUtils.getCategoryColor(gi.category));
            }
            holder.posted.setText(gi.posted);
            holder.simpleLanguage.setText(gi.simpleLanguage);
            // Update transition name
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                String gid = gi.gid;
                ViewCompat.setTransitionName(holder.thumb, TransitionNameFactory.getThumbTransitionName(gid));
            }
            holder.rating.setVisibility(View.INVISIBLE);
            holder.category.setVisibility(View.INVISIBLE);
            holder.source.setText(gi.source);
        }

        @Override
        public int gereplacedemCount() {
            return null != mLazyList ? mLazyList.size() : 0;
        }

        @Override
        public int onGetSwipeReactionType(HistoryHolder holder, int position, int x, int y) {
            return SwipeableItemConstants.REACTION_CAN_SWIPE_LEFT;
        }

        @Override
        public void onSwipeItemStarted(HistoryHolder holder, int position) {
        }

        @Override
        public void onSetSwipeBackground(HistoryHolder holder, int position, int type) {
        }

        @Override
        public SwipeResultAction onSwipeItem(HistoryHolder holder, int position, int result) {
            switch(result) {
                case SwipeableItemConstants.RESULT_SWIPED_LEFT:
                    return new SwipeResultActionClear(position);
                case SwipeableItemConstants.RESULT_SWIPED_RIGHT:
                case SwipeableItemConstants.RESULT_CANCELED:
                default:
                    return new SwipeResultActionDefault();
            }
        }
    }

    private clreplaced SwipeResultActionClear extends SwipeResultActionRemoveItem {

        private final int mPosition;

        protected SwipeResultActionClear(int position) {
            mPosition = position;
        }

        @Override
        protected void onPerformAction() {
            super.onPerformAction();
            if (null == mLazyList || null == mAdapter) {
                return;
            }
            HistoryInfo info = mLazyList.get(mPosition);
            EhDB.deleteHistoryInfo(info);
            updateLazyList();
            mAdapter.notifyDataSetChanged();
            updateView(true);
        }
    }
}

18 Source : HistoryScene.java
with Apache License 2.0
from axlecho

@Override
public boolean onItemClick(EasyRecyclerView parent, View view, int position, long id) {
    if (null == mLazyList) {
        return false;
    }
    Bundle args = new Bundle();
    args.putString(GalleryDetailScene.KEY_ACTION, GalleryDetailScene.ACTION_GALLERY_INFO);
    args.putParcelable(GalleryDetailScene.KEY_GALLERY_INFO, new GalleryInfo(mLazyList.get(position)));
    Announcer announcer = new Announcer(GalleryDetailScene.clreplaced).setArgs(args);
    View thumb;
    if (null != (thumb = view.findViewById(R.id.thumb))) {
        announcer.setTranHelper(new EnterGalleryDetailTransaction(thumb));
    }
    startScene(announcer);
    return true;
}

18 Source : GalleryInfoScene.java
with Apache License 2.0
from axlecho

@Override
public boolean onItemClick(EasyRecyclerView parent, View view, int position, long id) {
    Context context = getContext2();
    if (null != context && 0 != position && null != mValues) {
        ClipboardManager cmb = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
        cmb.setPrimaryClip(ClipData.newPlainText(null, mValues.get(position)));
        if (position == 3) {
            // Save it to avoid detect the gallery
            Settings.putClipboardTextHashCode(mValues.get(position).hashCode());
        }
        showTip(R.string.copied_to_clipboard, LENGTH_SHORT);
        return true;
    } else {
        return false;
    }
}

18 Source : PluginsActivity.java
with Apache License 2.0
from axlecho

public clreplaced PluginsActivity extends ToolbarActivity implements EasyRecyclerView.OnItemClickListener, View.OnClickListener {

    private List<MHPlugin> data;

    private EasyRecyclerView recyclerView;

    private View tip;

    private PluginsAdapter adapter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        data = MHPluginManager.Companion.getINSTANCE().plugins();
        setContentView(R.layout.activity_plugins);
        setNavigationIcon(R.drawable.v_arrow_left_dark_x24);
        recyclerView = findViewById(R.id.recycler_view);
        tip = findViewById(R.id.tip);
        FloatingActionButton fab = findViewById(R.id.fab);
        adapter = new PluginsAdapter();
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(this, RecyclerView.VERTICAL, false));
        LinearDividerItemDecoration decoration = new LinearDividerItemDecoration(LinearDividerItemDecoration.VERTICAL, AttrResources.getAttrColor(this, R.attr.dividerColor), LayoutUtils.dp2pix(this, 1));
        decoration.setShowLastDivider(true);
        recyclerView.addItemDecoration(decoration);
        recyclerView.setSelector(Ripple.generateRippleDrawable(this, !AttrResources.getAttrBoolean(this, R.attr.isLightTheme), new ColorDrawable(Color.TRANSPARENT)));
        recyclerView.setHasFixedSize(true);
        recyclerView.setOnItemClickListener(this);
        recyclerView.setPadding(recyclerView.getPaddingLeft(), recyclerView.getPaddingTop(), recyclerView.getPaddingRight(), recyclerView.getPaddingBottom() + getResources().getDimensionPixelOffset(R.dimen.gallery_padding_bottom_fab));
        fab.setOnClickListener(this);
        recyclerView.setVisibility(data.isEmpty() ? View.GONE : View.VISIBLE);
        tip.setVisibility(data.isEmpty() ? View.VISIBLE : View.GONE);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch(item.gereplacedemId()) {
            case android.R.id.home:
                finish();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public boolean onItemClick(EasyRecyclerView easyRecyclerView, View view, int position, long id) {
        return true;
    }

    @Override
    public void onClick(View v) {
        importData(this);
    }

    private void notifyHostsChanges() {
        data = MHPluginManager.Companion.getINSTANCE().plugins();
        recyclerView.setVisibility(data.isEmpty() ? View.GONE : View.VISIBLE);
        tip.setVisibility(data.isEmpty() ? View.VISIBLE : View.GONE);
        adapter.notifyDataSetChanged();
    }

    private clreplaced HostsHolder extends RecyclerView.ViewHolder {

        public final TextView host;

        public final Switch enable;

        public final View view;

        public HostsHolder(View itemView) {
            super(itemView);
            host = itemView.findViewById(R.id.host);
            enable = itemView.findViewById(R.id.enable);
            view = itemView;
        }
    }

    private clreplaced PluginsAdapter extends RecyclerView.Adapter<HostsHolder> {

        private final LayoutInflater inflater = getLayoutInflater();

        @NonNull
        @Override
        public HostsHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            return new HostsHolder(inflater.inflate(R.layout.item_plugin, parent, false));
        }

        @Override
        public void onBindViewHolder(@NonNull HostsHolder holder, int position) {
            MHPlugin plugin = data.get(position);
            holder.host.setText(plugin.getName());
            holder.enable.setChecked(plugin.isEnable());
            holder.enable.setOnClickListener((view) -> {
                plugin.setEnable(!plugin.isEnable());
                MHPluginManager.Companion.getINSTANCE().savePlugin(plugin);
                notifyItemChanged(position);
            });
            holder.view.setOnClickListener((view) -> {
                plugin.setEnable(!plugin.isEnable());
                MHPluginManager.Companion.getINSTANCE().savePlugin(plugin);
                notifyItemChanged(position);
            });
        }

        @Override
        public int gereplacedemCount() {
            return data.size();
        }
    }

    private static void importData(final Context context) {
        final File dir = AppConfig.getExternalDataPlugins();
        if (null == dir) {
            Toast.makeText(context, R.string.cant_get_data_dir, Toast.LENGTH_SHORT).show();
            return;
        }
        final String[] files = dir.list();
        if (null == files || files.length <= 0) {
            Toast.makeText(context, R.string.cant_find_any_data, Toast.LENGTH_SHORT).show();
            return;
        }
        Arrays.sort(files);
        new AlertDialog.Builder(context).sereplacedems(files, (dialog, which) -> {
            File file = new File(dir, files[which]);
            try {
                MHPlugin plugin = MHPluginManager.Companion.getINSTANCE().parserPlugin(file.getAbsolutePath());
                MHPluginManager.Companion.getINSTANCE().savePlugin(plugin);
            } catch (Exception e) {
                Toast.makeText(context, e.getMessage(), Toast.LENGTH_SHORT).show();
                return;
            }
            Toast.makeText(context, R.string.add_plugin_successful, Toast.LENGTH_SHORT).show();
        }).show();
    }
}

17 Source : QuickSearchScene.java
with Apache License 2.0
from xiaojieonly

public final clreplaced QuickSearchScene extends ToolbarScene {

    /*---------------
     Whole life cycle
     ---------------*/
    @Nullable
    private List<QuickSearch> mQuickSearchList;

    /*---------------
     View life cycle
     ---------------*/
    @Nullable
    private EasyRecyclerView mRecyclerView;

    @Nullable
    private ViewTransition mViewTransition;

    @Nullable
    private RecyclerView.Adapter mAdapter;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mQuickSearchList = EhDB.getAllQuickSearch();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mQuickSearchList = null;
    }

    @SuppressWarnings("deprecation")
    @Nullable
    @Override
    public View onCreateView3(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.scene_label_list, container, false);
        mRecyclerView = (EasyRecyclerView) ViewUtils.$$(view, R.id.recycler_view);
        TextView tip = (TextView) ViewUtils.$$(view, R.id.tip);
        mViewTransition = new ViewTransition(mRecyclerView, tip);
        Context context = getContext2();
        replacedertUtils.replacedertNotNull(context);
        Drawable drawable = DrawableManager.getVectorDrawable(context, R.drawable.big_search);
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        tip.setCompoundDrawables(null, drawable, null, null);
        tip.setText(R.string.no_quick_search);
        // drag & drop manager
        RecyclerViewDragDropManager dragDropManager = new RecyclerViewDragDropManager();
        dragDropManager.setDraggingItemShadowDrawable((NinePatchDrawable) context.getResources().getDrawable(R.drawable.shadow_8dp));
        RecyclerView.Adapter adapter = new QuickSearchAdapter();
        adapter.setHreplacedtableIds(true);
        // wrap for dragging
        adapter = dragDropManager.createWrappedAdapter(adapter);
        mAdapter = adapter;
        final GeneralItemAnimator animator = new DraggableItemAnimator();
        mRecyclerView.setLayoutManager(new LinearLayoutManager(context));
        mRecyclerView.setAdapter(adapter);
        mRecyclerView.sereplacedemAnimator(animator);
        dragDropManager.attachRecyclerView(mRecyclerView);
        updateView();
        return view;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        setreplacedle(R.string.quick_search);
        setNavigationIcon(R.drawable.v_arrow_left_dark_x24);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (null != mRecyclerView) {
            mRecyclerView.stopScroll();
            mRecyclerView = null;
        }
        mViewTransition = null;
    }

    @Override
    public void onNavigationClick() {
        onBackPressed();
    }

    private void updateView() {
        if (mViewTransition != null) {
            if (mQuickSearchList != null && mQuickSearchList.size() > 0) {
                mViewTransition.showView(0);
            } else {
                mViewTransition.showView(1);
            }
        }
    }

    private clreplaced QuickSearchHolder extends AbstractDraggableItemViewHolder implements View.OnClickListener {

        public final TextView label;

        public final View dragHandler;

        public final View delete;

        public QuickSearchHolder(View itemView) {
            super(itemView);
            label = (TextView) ViewUtils.$$(itemView, R.id.label);
            dragHandler = ViewUtils.$$(itemView, R.id.drag_handler);
            delete = ViewUtils.$$(itemView, R.id.delete);
            delete.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            int position = getAdapterPosition();
            Context context = getContext2();
            if (position == RecyclerView.NO_POSITION || mQuickSearchList == null) {
                return;
            }
            final QuickSearch quickSearch = mQuickSearchList.get(position);
            new AlertDialog.Builder(context).setreplacedle(R.string.delete_quick_search_replacedle).setMessage(getString(R.string.delete_quick_search_message, quickSearch.name)).setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {
                    EhDB.deleteQuickSearch(quickSearch);
                    mQuickSearchList.remove(position);
                }
            }).setOnDismissListener(new DialogInterface.OnDismissListener() {

                @Override
                public void onDismiss(DialogInterface dialog) {
                    if (null != mAdapter) {
                        mAdapter.notifyDataSetChanged();
                    }
                    updateView();
                }
            }).show();
        }
    }

    private clreplaced QuickSearchAdapter extends RecyclerView.Adapter<QuickSearchHolder> implements DraggableItemAdapter<QuickSearchHolder> {

        private final LayoutInflater mInflater;

        public QuickSearchAdapter() {
            mInflater = getLayoutInflater2();
            replacedertUtils.replacedertNotNull(mInflater);
        }

        @Override
        public QuickSearchHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            return new QuickSearchHolder(mInflater.inflate(R.layout.item_quick_search, parent, false));
        }

        @Override
        public void onBindViewHolder(QuickSearchHolder holder, int position) {
            if (mQuickSearchList != null) {
                holder.label.setText(mQuickSearchList.get(position).name);
            }
        }

        @Override
        public long gereplacedemId(int position) {
            return mQuickSearchList != null ? mQuickSearchList.get(position).getId() : 0;
        }

        @Override
        public int gereplacedemCount() {
            return mQuickSearchList != null ? mQuickSearchList.size() : 0;
        }

        @Override
        public boolean onCheckCanStartDrag(QuickSearchHolder holder, int position, int x, int y) {
            return ViewUtils.isViewUnder(holder.dragHandler, x, y, 0);
        }

        @Override
        public ItemDraggableRange onGereplacedemDraggableRange(QuickSearchHolder holder, int position) {
            return null;
        }

        @Override
        public void onMoveItem(int fromPosition, int toPosition) {
            if (fromPosition == toPosition) {
                return;
            }
            if (null == mQuickSearchList) {
                return;
            }
            EhDB.moveQuickSearch(fromPosition, toPosition);
            final QuickSearch item = mQuickSearchList.remove(fromPosition);
            mQuickSearchList.add(toPosition, item);
        }

        @Override
        public boolean onCheckCanDrop(int draggingPosition, int dropPosition) {
            return true;
        }

        @Override
        public void onItemDragStarted(int position) {
        }

        @Override
        public void onItemDragFinished(int fromPosition, int toPosition, boolean result) {
        }
    }
}

17 Source : HistoryScene.java
with Apache License 2.0
from xiaojieonly

public clreplaced HistoryScene extends ToolbarScene implements EasyRecyclerView.OnItemClickListener, EasyRecyclerView.OnItemLongClickListener {

    /*---------------
     View life cycle
     ---------------*/
    @Nullable
    private EasyRecyclerView mRecyclerView;

    @Nullable
    private ViewTransition mViewTransition;

    @Nullable
    private RecyclerView.Adapter<?> mAdapter;

    @Nullable
    private LazyList<HistoryInfo> mLazyList;

    @Override
    public int getNavCheckedItem() {
        return R.id.nav_history;
    }

    @Nullable
    @Override
    public View onCreateView3(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.scene_history, container, false);
        View content = ViewUtils.$$(view, R.id.content);
        mRecyclerView = (EasyRecyclerView) ViewUtils.$$(content, R.id.recycler_view);
        FastScroller fastScroller = (FastScroller) ViewUtils.$$(content, R.id.fast_scroller);
        TextView tip = (TextView) ViewUtils.$$(view, R.id.tip);
        mViewTransition = new ViewTransition(content, tip);
        Context context = getContext2();
        replacedertUtils.replacedertNotNull(context);
        Resources resources = context.getResources();
        Drawable drawable = DrawableManager.getVectorDrawable(context, R.drawable.big_history);
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        tip.setCompoundDrawables(null, drawable, null, null);
        RecyclerViewTouchActionGuardManager guardManager = new RecyclerViewTouchActionGuardManager();
        guardManager.setInterceptVerticalScrollingWhileAnimationRunning(true);
        guardManager.setEnabled(true);
        RecyclerViewSwipeManager swipeManager = new RecyclerViewSwipeManager();
        mAdapter = new HistoryAdapter();
        mAdapter.setHreplacedtableIds(true);
        mAdapter = swipeManager.createWrappedAdapter(mAdapter);
        mRecyclerView.setAdapter(mAdapter);
        final GeneralItemAnimator animator = new SwipeDismissItemAnimator();
        animator.setSupportsChangeAnimations(false);
        mRecyclerView.sereplacedemAnimator(animator);
        AutoStaggeredGridLayoutManager layoutManager = new AutoStaggeredGridLayoutManager(0, StaggeredGridLayoutManager.VERTICAL);
        layoutManager.setColumnSize(resources.getDimensionPixelOffset(Settings.getDetailSizeResId()));
        layoutManager.setStrategy(AutoStaggeredGridLayoutManager.STRATEGY_MIN_SIZE);
        mRecyclerView.setLayoutManager(layoutManager);
        mRecyclerView.setSelector(Ripple.generateRippleDrawable(context, !AttrResources.getAttrBoolean(context, R.attr.isLightTheme), new ColorDrawable(Color.TRANSPARENT)));
        mRecyclerView.setDrawSelectorOnTop(true);
        mRecyclerView.setClipToPadding(false);
        mRecyclerView.setOnItemClickListener(this);
        mRecyclerView.setOnItemLongClickListener(this);
        int interval = resources.getDimensionPixelOffset(R.dimen.gallery_list_interval);
        int paddingH = resources.getDimensionPixelOffset(R.dimen.gallery_list_margin_h);
        int paddingV = resources.getDimensionPixelOffset(R.dimen.gallery_list_margin_v);
        MarginItemDecoration decoration = new MarginItemDecoration(interval, paddingH, paddingV, paddingH, paddingV);
        mRecyclerView.addItemDecoration(decoration);
        decoration.applyPaddings(mRecyclerView);
        guardManager.attachRecyclerView(mRecyclerView);
        swipeManager.attachRecyclerView(mRecyclerView);
        fastScroller.attachToRecyclerView(mRecyclerView);
        HandlerDrawable handlerDrawable = new HandlerDrawable();
        handlerDrawable.setColor(AttrResources.getAttrColor(context, R.attr.widgetColorThemeAccent));
        fastScroller.setHandlerDrawable(handlerDrawable);
        updateLazyList();
        updateView(false);
        return view;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        setreplacedle(R.string.history);
        setNavigationIcon(R.drawable.v_arrow_left_dark_x24);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (null != mLazyList) {
            mLazyList.close();
            mLazyList = null;
            if (mAdapter != null) {
                mAdapter.notifyDataSetChanged();
            }
        }
        if (null != mRecyclerView) {
            mRecyclerView.stopScroll();
            mRecyclerView = null;
        }
        mViewTransition = null;
        mAdapter = null;
    }

    // Remember to notify
    private void updateLazyList() {
        LazyList<HistoryInfo> lazyList = EhDB.getHistoryLazyList();
        if (mLazyList != null) {
            mLazyList.close();
        }
        mLazyList = lazyList;
    }

    private void updateView(boolean animation) {
        if (null == mAdapter || null == mViewTransition) {
            return;
        }
        if (mAdapter.gereplacedemCount() == 0) {
            mViewTransition.showView(1, animation);
        } else {
            mViewTransition.showView(0, animation);
        }
    }

    @Override
    public void onNavigationClick() {
        onBackPressed();
    }

    @Override
    public int getMenuResId() {
        return R.menu.scene_history;
    }

    private void showClearAllDialog() {
        new AlertDialog.Builder(getContext2()).setMessage(R.string.clear_all_history).setPositiveButton(R.string.clear_all, new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (DialogInterface.BUTTON_POSITIVE != which || null == mAdapter) {
                    return;
                }
                EhDB.clearHistoryInfo();
                updateLazyList();
                mAdapter.notifyDataSetChanged();
                updateView(true);
            }
        }).show();
    }

    @Override
    public boolean onMenuItemClick(MenuItem item) {
        // Skip when in choice mode
        Context context = getContext2();
        if (null == context) {
            return false;
        }
        int id = item.gereplacedemId();
        switch(id) {
            case R.id.action_clear_all:
                {
                    showClearAllDialog();
                    return true;
                }
        }
        return false;
    }

    @Override
    public boolean onItemClick(EasyRecyclerView parent, View view, int position, long id) {
        if (null == mLazyList) {
            return false;
        }
        Bundle args = new Bundle();
        args.putString(GalleryDetailScene.KEY_ACTION, GalleryDetailScene.ACTION_GALLERY_INFO);
        args.putParcelable(GalleryDetailScene.KEY_GALLERY_INFO, mLazyList.get(position));
        Announcer announcer = new Announcer(GalleryDetailScene.clreplaced).setArgs(args);
        View thumb;
        if (null != (thumb = view.findViewById(R.id.thumb))) {
            announcer.setTranHelper(new EnterGalleryDetailTransaction(thumb));
        }
        startScene(announcer);
        return true;
    }

    @Override
    public boolean onItemLongClick(EasyRecyclerView parent, View view, int position, long id) {
        final Context context = getContext2();
        final MainActivity activity = getActivity2();
        if (null == context || null == activity || null == mLazyList) {
            return false;
        }
        final GalleryInfo gi = mLazyList.get(position);
        new AlertDialog.Builder(context).setreplacedle(EhUtils.getSuitablereplacedle(gi)).sereplacedems(R.array.gallery_list_menu_entries, new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                switch(which) {
                    case // Download
                    0:
                        CommonOperations.startDownload(activity, gi, false);
                        break;
                    case // Favorites
                    1:
                        CommonOperations.addToFavorites(activity, gi, new addToFavoriteListener(context, activity.getStageId(), getTag()));
                        break;
                }
            }
        }).show();
        return true;
    }

    private clreplaced HistoryHolder extends AbstractSwipeableItemViewHolder {

        public final View card;

        public final LoadImageView thumb;

        public final TextView replacedle;

        public final TextView uploader;

        public final SimpleRatingView rating;

        public final TextView category;

        public final TextView posted;

        public final TextView simpleLanguage;

        public HistoryHolder(View itemView) {
            super(itemView);
            card = itemView.findViewById(R.id.card);
            thumb = (LoadImageView) itemView.findViewById(R.id.thumb);
            replacedle = (TextView) itemView.findViewById(R.id.replacedle);
            uploader = (TextView) itemView.findViewById(R.id.uploader);
            rating = (SimpleRatingView) itemView.findViewById(R.id.rating);
            category = (TextView) itemView.findViewById(R.id.category);
            posted = (TextView) itemView.findViewById(R.id.posted);
            simpleLanguage = (TextView) itemView.findViewById(R.id.simple_language);
        }

        @Override
        public View getSwipeableContainerView() {
            return card;
        }
    }

    private clreplaced HistoryAdapter extends RecyclerView.Adapter<HistoryHolder> implements SwipeableItemAdapter<HistoryHolder> {

        private final LayoutInflater mInflater;

        private final int mListThumbWidth;

        private final int mListThumbHeight;

        public HistoryAdapter() {
            mInflater = getLayoutInflater2();
            View calculator = mInflater.inflate(R.layout.item_gallery_list_thumb_height, null);
            ViewUtils.measureView(calculator, 1024, ViewGroup.LayoutParams.WRAP_CONTENT);
            mListThumbHeight = calculator.getMeasuredHeight();
            mListThumbWidth = mListThumbHeight * 2 / 3;
        }

        @Override
        public long gereplacedemId(int position) {
            if (null == mLazyList) {
                return super.gereplacedemId(position);
            } else {
                return mLazyList.get(position).gid;
            }
        }

        @Override
        public HistoryHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            HistoryHolder holder = new HistoryHolder(mInflater.inflate(R.layout.item_history, parent, false));
            ViewGroup.LayoutParams lp = holder.thumb.getLayoutParams();
            lp.width = mListThumbWidth;
            lp.height = mListThumbHeight;
            holder.thumb.setLayoutParams(lp);
            return holder;
        }

        @Override
        public void onBindViewHolder(HistoryHolder holder, int position) {
            if (null == mLazyList) {
                return;
            }
            GalleryInfo gi = mLazyList.get(position);
            holder.thumb.load(EhCacheKeyFactory.getThumbKey(gi.gid), gi.thumb);
            holder.replacedle.setText(EhUtils.getSuitablereplacedle(gi));
            holder.uploader.setText(gi.uploader);
            holder.rating.setRating(gi.rating);
            TextView category = holder.category;
            String newCategoryText = EhUtils.getCategory(gi.category);
            if (!newCategoryText.equals(category.getText())) {
                category.setText(newCategoryText);
                category.setBackgroundColor(EhUtils.getCategoryColor(gi.category));
            }
            holder.posted.setText(gi.posted);
            holder.simpleLanguage.setText(gi.simpleLanguage);
            // Update transition name
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                long gid = gi.gid;
                ViewCompat.setTransitionName(holder.thumb, TransitionNameFactory.getThumbTransitionName(gid));
            }
        }

        @Override
        public int gereplacedemCount() {
            return null != mLazyList ? mLazyList.size() : 0;
        }

        @Override
        public int onGetSwipeReactionType(HistoryHolder holder, int position, int x, int y) {
            return SwipeableItemConstants.REACTION_CAN_SWIPE_LEFT;
        }

        @Override
        public void onSwipeItemStarted(HistoryHolder holder, int position) {
        }

        @Override
        public void onSetSwipeBackground(HistoryHolder holder, int position, int type) {
        }

        @Override
        public SwipeResultAction onSwipeItem(HistoryHolder holder, int position, int result) {
            switch(result) {
                case SwipeableItemConstants.RESULT_SWIPED_LEFT:
                    return new SwipeResultActionClear(position);
                case SwipeableItemConstants.RESULT_SWIPED_RIGHT:
                case SwipeableItemConstants.RESULT_CANCELED:
                default:
                    return new SwipeResultActionDefault();
            }
        }
    }

    private clreplaced SwipeResultActionClear extends SwipeResultActionRemoveItem {

        private final int mPosition;

        protected SwipeResultActionClear(int position) {
            mPosition = position;
        }

        @Override
        protected void onPerformAction() {
            super.onPerformAction();
            if (null == mLazyList || null == mAdapter) {
                return;
            }
            HistoryInfo info = mLazyList.get(mPosition);
            EhDB.deleteHistoryInfo(info);
            updateLazyList();
            mAdapter.notifyDataSetChanged();
            updateView(true);
        }
    }

    private static clreplaced addToFavoriteListener extends EhCallback<HistoryScene, Void> {

        public addToFavoriteListener(Context context, int stageId, String sceneTag) {
            super(context, stageId, sceneTag);
        }

        @Override
        public void onSuccess(Void result) {
            showTip(R.string.add_to_favorite_success, LENGTH_SHORT);
        }

        @Override
        public void onFailure(Exception e) {
            showTip(R.string.add_to_favorite_failure, LENGTH_LONG);
        }

        @Override
        public void onCancel() {
        }

        @Override
        public boolean isInstance(SceneFragment scene) {
            return scene instanceof HistoryScene;
        }
    }
}

17 Source : GalleryPreviewsScene.java
with Apache License 2.0
from xiaojieonly

@Override
public boolean onItemClick(EasyRecyclerView parent, View view, int position, long id) {
    Context context = getContext2();
    if (null != context && null != mHelper && null != mGalleryInfo) {
        GalleryPreview p = mHelper.getDataAtEx(position);
        if (p != null) {
            Intent intent = new Intent(context, GalleryActivity.clreplaced);
            intent.setAction(GalleryActivity.ACTION_EH);
            intent.putExtra(GalleryActivity.KEY_GALLERY_INFO, mGalleryInfo);
            intent.putExtra(GalleryActivity.KEY_PAGE, p.getPosition());
            startActivity(intent);
        }
    }
    return true;
}

17 Source : GalleryCommentsScene.java
with Apache License 2.0
from xiaojieonly

/**
 * 画廊评论对象
 */
public final clreplaced GalleryCommentsScene extends ToolbarScene implements EasyRecyclerView.OnItemClickListener, View.OnClickListener {

    public static final String TAG = GalleryCommentsScene.clreplaced.getSimpleName();

    public static final String KEY_API_UID = "api_uid";

    public static final String KEY_API_KEY = "api_key";

    public static final String KEY_GID = "gid";

    public static final String KEY_TOKEN = "token";

    public static final String KEY_COMMENT_LIST = "comment_list";

    private long mApiUid;

    private String mApiKey;

    private long mGid;

    private String mToken;

    @Nullable
    private GalleryCommentList mCommentList;

    @Nullable
    private EasyRecyclerView mRecyclerView;

    @Nullable
    private FabLayout mFabLayout;

    @Nullable
    private FloatingActionButton mFab;

    @Nullable
    private View mEditPanel;

    @Nullable
    private ImageView mSendImage;

    @Nullable
    private EditText mEditText;

    @Nullable
    private CommentAdapter mAdapter;

    @Nullable
    private ViewTransition mViewTransition;

    private Drawable mSendDrawable;

    private Drawable mPencilDrawable;

    private long mCommentId;

    private boolean mInAnimation = false;

    private boolean mShowAllComments = false;

    private boolean mRefreshingComments = false;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState == null) {
            onInit();
        } else {
            onRestore(savedInstanceState);
        }
    }

    private void handleArgs(Bundle args) {
        if (args == null) {
            return;
        }
        mApiUid = args.getLong(KEY_API_UID, -1L);
        mApiKey = args.getString(KEY_API_KEY);
        mGid = args.getLong(KEY_GID, -1L);
        mToken = args.getString(KEY_TOKEN, null);
        mCommentList = args.getParcelable(KEY_COMMENT_LIST);
        mShowAllComments = mCommentList != null && !mCommentList.hasMore;
    }

    private void onInit() {
        handleArgs(getArguments());
    }

    private void onRestore(@NonNull Bundle savedInstanceState) {
        mApiUid = savedInstanceState.getLong(KEY_API_UID, -1L);
        mApiKey = savedInstanceState.getString(KEY_API_KEY);
        mGid = savedInstanceState.getLong(KEY_GID, -1L);
        mToken = savedInstanceState.getString(KEY_TOKEN, null);
        mCommentList = savedInstanceState.getParcelable(KEY_COMMENT_LIST);
        mShowAllComments = mCommentList != null && !mCommentList.hasMore;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putLong(KEY_API_UID, mApiUid);
        outState.putString(KEY_API_KEY, mApiKey);
        outState.putLong(KEY_GID, mGid);
        outState.putString(KEY_TOKEN, mToken);
        outState.putParcelable(KEY_COMMENT_LIST, mCommentList);
    }

    /**
     * 评论详情页创建
     * @param inflater
     * @param container
     * @param savedInstanceState
     * @return
     */
    @Nullable
    @Override
    public View onCreateView3(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.scene_gallery_comments, container, false);
        mRecyclerView = (EasyRecyclerView) ViewUtils.$$(view, R.id.recycler_view);
        TextView tip = (TextView) ViewUtils.$$(view, R.id.tip);
        mEditPanel = ViewUtils.$$(view, R.id.edit_panel);
        mSendImage = (ImageView) ViewUtils.$$(mEditPanel, R.id.send);
        mEditText = (EditText) ViewUtils.$$(mEditPanel, R.id.edit_text);
        mFabLayout = (FabLayout) ViewUtils.$$(view, R.id.fab_layout);
        mFab = (FloatingActionButton) ViewUtils.$$(view, R.id.fab);
        Context context = getContext2();
        replacedertUtils.replacedertNotNull(context);
        Resources resources = context.getResources();
        int paddingBottomFab = resources.getDimensionPixelOffset(R.dimen.gallery_padding_bottom_fab);
        Drawable drawable = DrawableManager.getVectorDrawable(context, R.drawable.big_sad_pandroid);
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        tip.setCompoundDrawables(null, drawable, null, null);
        mSendDrawable = DrawableManager.getVectorDrawable(context, R.drawable.v_send_dark_x24);
        mPencilDrawable = DrawableManager.getVectorDrawable(context, R.drawable.v_pencil_dark_x24);
        mAdapter = new CommentAdapter();
        mRecyclerView.setAdapter(mAdapter);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(context, RecyclerView.VERTICAL, false));
        LinearDividerItemDecoration decoration = new LinearDividerItemDecoration(LinearDividerItemDecoration.VERTICAL, AttrResources.getAttrColor(context, R.attr.dividerColor), LayoutUtils.dp2pix(context, 1));
        decoration.setShowLastDivider(true);
        mRecyclerView.addItemDecoration(decoration);
        mRecyclerView.setSelector(Ripple.generateRippleDrawable(context, !AttrResources.getAttrBoolean(context, R.attr.isLightTheme), new ColorDrawable(Color.TRANSPARENT)));
        mRecyclerView.setHasFixedSize(true);
        mRecyclerView.setOnItemClickListener(this);
        mRecyclerView.setPadding(mRecyclerView.getPaddingLeft(), mRecyclerView.getPaddingTop(), mRecyclerView.getPaddingRight(), mRecyclerView.getPaddingBottom() + paddingBottomFab);
        // Cancel change animator
        RecyclerView.ItemAnimator itemAnimator = mRecyclerView.gereplacedemAnimator();
        if (itemAnimator instanceof DefaulreplacedemAnimator) {
            ((DefaulreplacedemAnimator) itemAnimator).setSupportsChangeAnimations(false);
        }
        mSendImage.setOnClickListener(this);
        mFab.setOnClickListener(this);
        addAboveSnackView(mEditPanel);
        addAboveSnackView(mFabLayout);
        mViewTransition = new ViewTransition(mRecyclerView, tip);
        updateView(false);
        return view;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (null != mRecyclerView) {
            mRecyclerView.stopScroll();
            mRecyclerView = null;
        }
        if (null != mEditPanel) {
            removeAboveSnackView(mEditPanel);
            mEditPanel = null;
        }
        if (null != mFabLayout) {
            removeAboveSnackView(mFabLayout);
            mFabLayout = null;
        }
        mFab = null;
        mSendImage = null;
        mEditText = null;
        mAdapter = null;
        mViewTransition = null;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        setreplacedle(R.string.gallery_comments);
        setNavigationIcon(R.drawable.v_arrow_left_dark_x24);
    }

    @Override
    public void onNavigationClick() {
        onBackPressed();
    }

    private void voteComment(long id, int vote) {
        Context context = getContext2();
        MainActivity activity = getActivity2();
        if (null == context || null == activity) {
            return;
        }
        EhRequest request = new EhRequest().setMethod(EhClient.METHOD_VOTE_COMMENT).setArgs(mApiUid, mApiKey, mGid, mToken, id, vote).setCallback(new VoteCommentListener(context, activity.getStageId(), getTag()));
        EhApplication.getEhClient(context).execute(request);
    }

    private clreplaced InfoHolder extends RecyclerView.ViewHolder {

        private final TextView key;

        private final TextView value;

        public InfoHolder(View itemView) {
            super(itemView);
            key = (TextView) ViewUtils.$$(itemView, R.id.key);
            value = (TextView) ViewUtils.$$(itemView, R.id.value);
        }
    }

    @SuppressLint("InflateParams")
    public void showVoteStatusDialog(Context context, String voteStatus) {
        String[] temp = StringUtils.split(voteStatus, ',');
        final int length = temp.length;
        final String[] userArray = new String[length];
        final String[] voteArray = new String[length];
        for (int i = 0; i < length; i++) {
            String str = StringUtils.trim(temp[i]);
            int index = str.lastIndexOf(' ');
            if (index < 0) {
                Log.d(TAG, "Something wrong happened about vote state");
                userArray[i] = str;
                voteArray[i] = "";
            } else {
                userArray[i] = StringUtils.trim(str.substring(0, index));
                voteArray[i] = StringUtils.trim(str.substring(index + 1));
            }
        }
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        context = builder.getContext();
        final LayoutInflater inflater = LayoutInflater.from(context);
        EasyRecyclerView rv = (EasyRecyclerView) inflater.inflate(R.layout.dialog_recycler_view, null);
        rv.setAdapter(new RecyclerView.Adapter<InfoHolder>() {

            @Override
            public InfoHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                return new InfoHolder(inflater.inflate(R.layout.item_drawer_favorites, parent, false));
            }

            @Override
            public void onBindViewHolder(InfoHolder holder, int position) {
                holder.key.setText(userArray[position]);
                holder.value.setText(voteArray[position]);
            }

            @Override
            public int gereplacedemCount() {
                return length;
            }
        });
        rv.setLayoutManager(new LinearLayoutManager(context));
        LinearDividerItemDecoration decoration = new LinearDividerItemDecoration(LinearDividerItemDecoration.VERTICAL, AttrResources.getAttrColor(context, R.attr.dividerColor), LayoutUtils.dp2pix(context, 1));
        decoration.setPadding(ResourcesUtils.getAttrDimensionPixelOffset(context, R.attr.dialogPreferredPadding));
        rv.addItemDecoration(decoration);
        rv.setSelector(Ripple.generateRippleDrawable(context, !AttrResources.getAttrBoolean(context, R.attr.isLightTheme), new ColorDrawable(Color.TRANSPARENT)));
        rv.setClipToPadding(false);
        builder.setView(rv).show();
    }

    private void showCommentDialog(int position) {
        final Context context = getContext2();
        if (context == null || mCommentList == null || mCommentList.comments == null || position >= mCommentList.comments.length || position < 0) {
            return;
        }
        final GalleryComment comment = mCommentList.comments[position];
        List<String> menu = new ArrayList<>();
        final IntList menuId = new IntList();
        Resources resources = context.getResources();
        menu.add(resources.getString(R.string.copy_comment_text));
        menuId.add(R.id.copy);
        menu.add(resources.getString(R.string.join_in_blacklist));
        menuId.add(R.id.join_blacklist);
        if (comment.editable) {
            menu.add(resources.getString(R.string.edit_comment));
            menuId.add(R.id.edit_comment);
        }
        if (comment.voteUpAble) {
            menu.add(resources.getString(comment.voteUpEd ? R.string.cancel_vote_up : R.string.vote_up));
            menuId.add(R.id.vote_up);
        }
        if (comment.voteDownAble) {
            menu.add(resources.getString(comment.voteDownEd ? R.string.cancel_vote_down : R.string.vote_down));
            menuId.add(R.id.vote_down);
        }
        if (!TextUtils.isEmpty(comment.voteState)) {
            menu.add(resources.getString(R.string.check_vote_status));
            menuId.add(R.id.check_vote_status);
        }
        new AlertDialog.Builder(context).sereplacedems(menu.toArray(new String[menu.size()]), new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (which < 0 || which >= menuId.size()) {
                    return;
                }
                int id = menuId.get(which);
                switch(id) {
                    case R.id.copy:
                        ClipboardManager cmb = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
                        cmb.setPrimaryClip(ClipData.newPlainText(null, comment.comment));
                        showTip(R.string.copied_to_clipboard, LENGTH_SHORT);
                        break;
                    case R.id.vote_up:
                        voteComment(comment.id, 1);
                        break;
                    case R.id.vote_down:
                        voteComment(comment.id, -1);
                        break;
                    case R.id.check_vote_status:
                        showVoteStatusDialog(context, comment.voteState);
                        break;
                    case R.id.edit_comment:
                        prepareEditComment(comment.id);
                        if (!mInAnimation && mEditPanel != null && mEditPanel.getVisibility() != View.VISIBLE) {
                            showEditPanel(true);
                        }
                        break;
                    case R.id.join_blacklist:
                        EhDB.insertBlackList(BlackListUtils.parseBlacklist(comment));
                        mCommentList.DeleteComment(position);
                        mAdapter.notifyDataSetChanged();
                        updateView(true);
                        break;
                }
            }
        }).show();
    }

    @Override
    public boolean onItemClick(EasyRecyclerView parent, View view, int position, long id) {
        MainActivity activity = getActivity2();
        if (null == activity) {
            return false;
        }
        RecyclerView.ViewHolder holder = parent.getChildViewHolder(view);
        if (holder instanceof ActualCommentHolder) {
            ActualCommentHolder commentHolder = (ActualCommentHolder) holder;
            ClickableSpan span = commentHolder.comment.getCurrentSpan();
            commentHolder.comment.clearCurrentSpan();
            if (span instanceof URLSpan) {
                UrlOpener.openUrl(activity, ((URLSpan) span).getURL(), true);
            } else {
                showCommentDialog(position);
            }
        } else if (holder instanceof MoreCommentHolder && !mRefreshingComments && mAdapter != null) {
            mRefreshingComments = true;
            mShowAllComments = true;
            mAdapter.notifyItemChanged(position);
            String url = getGalleryDetailUrl();
            if (url != null) {
                // Request
                EhRequest request = new EhRequest().setMethod(EhClient.METHOD_GET_GALLERY_DETAIL).setArgs(url).setCallback(new RefreshCommentListener(activity, activity.getStageId(), getTag()));
                EhApplication.getEhClient(activity).execute(request);
            }
        }
        return true;
    }

    private void updateView(boolean animation) {
        if (null == mViewTransition) {
            return;
        }
        if (mCommentList == null || mCommentList.comments == null || mCommentList.comments.length <= 0) {
            mViewTransition.showView(1, animation);
        } else {
            mViewTransition.showView(0, animation);
        }
    }

    private void prepareNewComment() {
        mCommentId = 0;
        if (mSendImage != null) {
            mSendImage.setImageDrawable(mSendDrawable);
        }
    }

    private void prepareEditComment(long commentId) {
        mCommentId = commentId;
        if (mSendImage != null) {
            mSendImage.setImageDrawable(mPencilDrawable);
        }
    }

    private void showEditPanelWithAnimation() {
        if (null == mFab || null == mEditPanel) {
            return;
        }
        mInAnimation = true;
        mFab.setTranslationX(0.0f);
        mFab.setTranslationY(0.0f);
        mFab.setScaleX(1.0f);
        mFab.setScaleY(1.0f);
        int fabEndX = mEditPanel.getLeft() + (mEditPanel.getWidth() / 2) - (mFab.getWidth() / 2);
        int fabEndY = mEditPanel.getTop() + (mEditPanel.getHeight() / 2) - (mFab.getHeight() / 2);
        mFab.animate().x(fabEndX).y(fabEndY).scaleX(0.0f).scaleY(0.0f).setInterpolator(AnimationUtils.SLOW_FAST_SLOW_INTERPOLATOR).setDuration(300L).setListener(new SimpleAnimatorListener() {

            @Override
            public void onAnimationEnd(Animator animation) {
                if (null == mFab || null == mEditPanel) {
                    return;
                }
                ((View) mFab).setVisibility(View.INVISIBLE);
                mEditPanel.setVisibility(View.VISIBLE);
                int halfW = mEditPanel.getWidth() / 2;
                int halfH = mEditPanel.getHeight() / 2;
                Animator animator = ViewAnimationUtils.createCircularReveal(mEditPanel, halfW, halfH, 0, (float) Math.hypot(halfW, halfH)).setDuration(300L);
                animator.addListener(new SimpleAnimatorListener() {

                    @Override
                    public void onAnimationEnd(Animator a) {
                        mInAnimation = false;
                    }
                });
                animator.start();
            }
        }).start();
    }

    private void showEditPanel(boolean animation) {
        if (animation) {
            showEditPanelWithAnimation();
        } else {
            if (null == mFab || null == mEditPanel) {
                return;
            }
            ((View) mFab).setVisibility(View.INVISIBLE);
            mEditPanel.setVisibility(View.VISIBLE);
        }
    }

    private void hideEditPanelWithAnimation() {
        if (null == mFab || null == mEditPanel) {
            return;
        }
        mInAnimation = true;
        int halfW = mEditPanel.getWidth() / 2;
        int halfH = mEditPanel.getHeight() / 2;
        Animator animator = ViewAnimationUtils.createCircularReveal(mEditPanel, halfW, halfH, (float) Math.hypot(halfW, halfH), 0.0f).setDuration(300L);
        animator.addListener(new SimpleAnimatorListener() {

            @Override
            public void onAnimationEnd(Animator a) {
                if (null == mFab || null == mEditPanel) {
                    return;
                }
                if (Looper.myLooper() != Looper.getMainLooper()) {
                    // Some devices may run this block in non-UI thread.
                    // It might be a bug of Android OS.
                    // Check it here to avoid crash.
                    return;
                }
                mEditPanel.setVisibility(View.GONE);
                ((View) mFab).setVisibility(View.VISIBLE);
                int fabStartX = mEditPanel.getLeft() + (mEditPanel.getWidth() / 2) - (mFab.getWidth() / 2);
                int fabStartY = mEditPanel.getTop() + (mEditPanel.getHeight() / 2) - (mFab.getHeight() / 2);
                mFab.setX(fabStartX);
                mFab.setY(fabStartY);
                mFab.setScaleX(0.0f);
                mFab.setScaleY(0.0f);
                mFab.setRotation(-45.0f);
                mFab.animate().translationX(0.0f).translationY(0.0f).scaleX(1.0f).scaleY(1.0f).rotation(0.0f).setInterpolator(AnimationUtils.SLOW_FAST_SLOW_INTERPOLATOR).setDuration(300L).setListener(new SimpleAnimatorListener() {

                    @Override
                    public void onAnimationEnd(Animator animation) {
                        mInAnimation = false;
                    }
                }).start();
            }
        });
        animator.start();
    }

    private void hideEditPanel(boolean animation) {
        if (animation) {
            hideEditPanelWithAnimation();
        } else {
            if (null == mFab || null == mEditPanel) {
                return;
            }
            ((View) mFab).setVisibility(View.VISIBLE);
            mEditPanel.setVisibility(View.INVISIBLE);
        }
    }

    @Nullable
    private String getGalleryDetailUrl() {
        if (mGid != -1 && mToken != null) {
            return EhUrl.getGalleryDetailUrl(mGid, mToken, 0, mShowAllComments);
        } else {
            return null;
        }
    }

    /**
     * 点击发送评论按钮时触发
     * @param v
     */
    @Override
    public void onClick(View v) {
        Context context = getContext2();
        MainActivity activity = getActivity2();
        if (null == context || null == activity || null == mEditText) {
            return;
        }
        if (mFab == v) {
            if (!mInAnimation) {
                prepareNewComment();
                showEditPanel(true);
            }
        } else if (mSendImage == v) {
            if (!mInAnimation) {
                String comment = mEditText.getText().toString();
                if (TextUtils.isEmpty(comment)) {
                    // Comment is empty
                    return;
                }
                String url = getGalleryDetailUrl();
                if (url == null) {
                    return;
                }
                // Request
                EhRequest request = new EhRequest().setMethod(EhClient.METHOD_GET_COMMENT_GALLERY).setArgs(url, comment, mCommentId != 0 ? Long.toString(mCommentId) : null).setCallback(new CommentGalleryListener(context, activity.getStageId(), getTag(), mCommentId));
                EhApplication.getEhClient(context).execute(request);
                hideSoftInput();
                hideEditPanel(true);
            }
        }
    }

    /**
     * 点击评论详情页右上角返回图标时触发
     */
    @Override
    public void onBackPressed() {
        if (mInAnimation) {
            return;
        }
        if (null != mEditPanel && mEditPanel.getVisibility() == View.VISIBLE) {
            hideEditPanel(true);
        } else {
            finish();
        }
    }

    private static final int TYPE_COMMENT = 0;

    private static final int TYPE_MORE = 1;

    private static final int TYPE_PROGRESS = 2;

    private abstract clreplaced CommentHolder extends RecyclerView.ViewHolder {

        public CommentHolder(LayoutInflater inflater, int resId, ViewGroup parent) {
            super(inflater.inflate(resId, parent, false));
        }
    }

    private clreplaced ActualCommentHolder extends CommentHolder {

        private final TextView user;

        private final TextView time;

        private final LinkifyTextView comment;

        public ActualCommentHolder(LayoutInflater inflater, ViewGroup parent) {
            super(inflater, R.layout.item_gallery_comment, parent);
            user = itemView.findViewById(R.id.user);
            time = itemView.findViewById(R.id.time);
            comment = itemView.findViewById(R.id.comment);
        }

        private CharSequence generateComment(Context context, ObservedTextView textView, GalleryComment comment) {
            SpannableStringBuilder ssb = Html.fromHtml(comment.comment, new URLImageGetter(textView, EhApplication.getConaco(context)), null);
            if (0 != comment.id && 0 != comment.score) {
                int score = comment.score;
                String scoreString = score > 0 ? "+" + score : Integer.toString(score);
                SpannableString ss = new SpannableString(scoreString);
                ss.setSpan(new RelativeSizeSpan(0.8f), 0, scoreString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                ss.setSpan(new StyleSpan(Typeface.BOLD), 0, scoreString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                ss.setSpan(new ForegroundColorSpan(AttrResources.getAttrColor(context, android.R.attr.textColorSecondary)), 0, scoreString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                ssb.append("  ").append(ss);
            }
            if (comment.lastEdited != 0) {
                String str = context.getString(R.string.last_edited, ReadableTime.getTimeAgo(comment.lastEdited));
                SpannableString ss = new SpannableString(str);
                ss.setSpan(new RelativeSizeSpan(0.8f), 0, str.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                ss.setSpan(new StyleSpan(Typeface.BOLD), 0, str.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                ss.setSpan(new ForegroundColorSpan(AttrResources.getAttrColor(context, android.R.attr.textColorSecondary)), 0, str.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                ssb.append("\n\n").append(ss);
            }
            return TextUrl.handleTextUrl(ssb);
        }

        public void bind(GalleryComment value) {
            user.setText(value.user);
            time.setText(ReadableTime.getTimeAgo(value.time));
            comment.setText(generateComment(comment.getContext(), comment, value));
        }
    }

    private clreplaced MoreCommentHolder extends CommentHolder {

        public MoreCommentHolder(LayoutInflater inflater, ViewGroup parent) {
            super(inflater, R.layout.item_gallery_comment_more, parent);
        }
    }

    private clreplaced ProgressCommentHolder extends CommentHolder {

        public ProgressCommentHolder(LayoutInflater inflater, ViewGroup parent) {
            super(inflater, R.layout.item_gallery_comment_progress, parent);
        }
    }

    private clreplaced CommentAdapter extends RecyclerView.Adapter<CommentHolder> {

        private final LayoutInflater mInflater;

        public CommentAdapter() {
            mInflater = getLayoutInflater2();
            replacedertUtils.replacedertNotNull(mInflater);
        }

        @Override
        public CommentHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            switch(viewType) {
                case TYPE_COMMENT:
                    return new ActualCommentHolder(mInflater, parent);
                case TYPE_MORE:
                    return new MoreCommentHolder(mInflater, parent);
                case TYPE_PROGRESS:
                    return new ProgressCommentHolder(mInflater, parent);
                default:
                    throw new IllegalStateException("Invalid view type: " + viewType);
            }
        }

        @Override
        public void onBindViewHolder(@NonNull CommentHolder holder, int position) {
            Context context = getContext2();
            if (context == null || mCommentList == null) {
                return;
            }
            if (holder instanceof ActualCommentHolder) {
                ((ActualCommentHolder) holder).bind(mCommentList.comments[position]);
            }
        }

        @Override
        public int gereplacedemCount() {
            if (mCommentList == null || mCommentList.comments == null) {
                return 0;
            } else if (mCommentList.hasMore) {
                return mCommentList.comments.length + 1;
            } else {
                return mCommentList.comments.length;
            }
        }

        @Override
        public int gereplacedemViewType(int position) {
            if (position >= mCommentList.comments.length) {
                return mRefreshingComments ? TYPE_PROGRESS : TYPE_MORE;
            } else {
                return TYPE_COMMENT;
            }
        }
    }

    private void onRefreshGallerySuccess(GalleryCommentList result) {
        if (mAdapter == null) {
            return;
        }
        mRefreshingComments = false;
        mCommentList = result;
        mAdapter.notifyDataSetChanged();
        updateView(true);
        Bundle re = new Bundle();
        re.putParcelable(KEY_COMMENT_LIST, result);
        setResult(SceneFragment.RESULT_OK, re);
    }

    private void onRefreshGalleryFailure() {
        if (mAdapter == null) {
            return;
        }
        mRefreshingComments = false;
        int position = mAdapter.gereplacedemCount() - 1;
        if (position >= 0) {
            mAdapter.notifyItemChanged(position);
        }
    }

    private void onCommentGallerySuccess(GalleryCommentList result) {
        if (mAdapter == null) {
            return;
        }
        mCommentList = result;
        mAdapter.notifyDataSetChanged();
        Bundle re = new Bundle();
        re.putParcelable(KEY_COMMENT_LIST, result);
        setResult(SceneFragment.RESULT_OK, re);
        // Remove text
        if (mEditText != null) {
            mEditText.setText("");
        }
        updateView(true);
    }

    private void onVoteCommentSuccess(VoteCommentParser.Result result) {
        if (mAdapter == null || mCommentList == null || mCommentList.comments == null) {
            return;
        }
        int position = -1;
        for (int i = 0, n = mCommentList.comments.length; i < n; i++) {
            GalleryComment comment = mCommentList.comments[i];
            if (comment.id == result.id) {
                position = i;
                break;
            }
        }
        if (-1 == position) {
            Log.d(TAG, "Can't find comment with id " + result.id);
            return;
        }
        // Update comment
        GalleryComment comment = mCommentList.comments[position];
        comment.score = result.score;
        if (result.expectVote > 0) {
            comment.voteUpEd = 0 != result.vote;
            comment.voteDownEd = false;
        } else {
            comment.voteDownEd = 0 != result.vote;
            comment.voteUpEd = false;
        }
        mAdapter.notifyItemChanged(position);
        Bundle re = new Bundle();
        re.putParcelable(KEY_COMMENT_LIST, mCommentList);
        setResult(SceneFragment.RESULT_OK, re);
    }

    private static clreplaced RefreshCommentListener extends EhCallback<GalleryCommentsScene, GalleryDetail> {

        public RefreshCommentListener(Context context, int stageId, String sceneTag) {
            super(context, stageId, sceneTag);
        }

        @Override
        public void onSuccess(GalleryDetail result) {
            GalleryCommentsScene scene = getScene();
            if (scene != null) {
                scene.onRefreshGallerySuccess(result.comments);
            }
        }

        @Override
        public void onFailure(Exception e) {
            GalleryCommentsScene scene = getScene();
            if (scene != null) {
                scene.onRefreshGalleryFailure();
            }
        }

        @Override
        public void onCancel() {
        }

        @Override
        public boolean isInstance(SceneFragment scene) {
            return scene instanceof GalleryCommentsScene;
        }
    }

    private static clreplaced CommentGalleryListener extends EhCallback<GalleryCommentsScene, GalleryCommentList> {

        private long mCommentId;

        public CommentGalleryListener(Context context, int stageId, String sceneTag, long commentId) {
            super(context, stageId, sceneTag);
            mCommentId = commentId;
        }

        @Override
        public void onSuccess(GalleryCommentList result) {
            showTip(mCommentId != 0 ? R.string.edit_comment_successfully : R.string.comment_successfully, LENGTH_SHORT);
            GalleryCommentsScene scene = getScene();
            if (scene != null) {
                scene.onCommentGallerySuccess(result);
            }
        }

        @Override
        public void onFailure(Exception e) {
            showTip(getContent().getString(mCommentId != 0 ? R.string.edit_comment_failed : R.string.comment_failed) + "\n" + ExceptionUtils.getReadableString(e), LENGTH_LONG);
        }

        @Override
        public void onCancel() {
        }

        @Override
        public boolean isInstance(SceneFragment scene) {
            return scene instanceof GalleryCommentsScene;
        }
    }

    private static clreplaced VoteCommentListener extends EhCallback<GalleryCommentsScene, VoteCommentParser.Result> {

        public VoteCommentListener(Context context, int stageId, String sceneTag) {
            super(context, stageId, sceneTag);
        }

        @Override
        public void onSuccess(VoteCommentParser.Result result) {
            showTip(result.expectVote > 0 ? (0 != result.vote ? R.string.vote_up_successfully : R.string.cancel_vote_up_successfully) : (0 != result.vote ? R.string.vote_down_successfully : R.string.cancel_vote_down_successfully), LENGTH_SHORT);
            GalleryCommentsScene scene = getScene();
            if (scene != null) {
                scene.onVoteCommentSuccess(result);
            }
        }

        @Override
        public void onFailure(Exception e) {
            showTip(R.string.vote_failed, LENGTH_LONG);
        }

        @Override
        public void onCancel() {
        }

        @Override
        public boolean isInstance(SceneFragment scene) {
            return scene instanceof GalleryCommentsScene;
        }
    }
}

17 Source : GalleryCommentsScene.java
with Apache License 2.0
from xiaojieonly

@SuppressLint("InflateParams")
public void showVoteStatusDialog(Context context, String voteStatus) {
    String[] temp = StringUtils.split(voteStatus, ',');
    final int length = temp.length;
    final String[] userArray = new String[length];
    final String[] voteArray = new String[length];
    for (int i = 0; i < length; i++) {
        String str = StringUtils.trim(temp[i]);
        int index = str.lastIndexOf(' ');
        if (index < 0) {
            Log.d(TAG, "Something wrong happened about vote state");
            userArray[i] = str;
            voteArray[i] = "";
        } else {
            userArray[i] = StringUtils.trim(str.substring(0, index));
            voteArray[i] = StringUtils.trim(str.substring(index + 1));
        }
    }
    AlertDialog.Builder builder = new AlertDialog.Builder(context);
    context = builder.getContext();
    final LayoutInflater inflater = LayoutInflater.from(context);
    EasyRecyclerView rv = (EasyRecyclerView) inflater.inflate(R.layout.dialog_recycler_view, null);
    rv.setAdapter(new RecyclerView.Adapter<InfoHolder>() {

        @Override
        public InfoHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            return new InfoHolder(inflater.inflate(R.layout.item_drawer_favorites, parent, false));
        }

        @Override
        public void onBindViewHolder(InfoHolder holder, int position) {
            holder.key.setText(userArray[position]);
            holder.value.setText(voteArray[position]);
        }

        @Override
        public int gereplacedemCount() {
            return length;
        }
    });
    rv.setLayoutManager(new LinearLayoutManager(context));
    LinearDividerItemDecoration decoration = new LinearDividerItemDecoration(LinearDividerItemDecoration.VERTICAL, AttrResources.getAttrColor(context, R.attr.dividerColor), LayoutUtils.dp2pix(context, 1));
    decoration.setPadding(ResourcesUtils.getAttrDimensionPixelOffset(context, R.attr.dialogPreferredPadding));
    rv.addItemDecoration(decoration);
    rv.setSelector(Ripple.generateRippleDrawable(context, !AttrResources.getAttrBoolean(context, R.attr.isLightTheme), new ColorDrawable(Color.TRANSPARENT)));
    rv.setClipToPadding(false);
    builder.setView(rv).show();
}

17 Source : DownloadsScene.java
with Apache License 2.0
from xiaojieonly

@Override
public boolean onItemLongClick(EasyRecyclerView parent, View view, int position, long id) {
    EasyRecyclerView recyclerView = mRecyclerView;
    if (recyclerView == null) {
        return false;
    }
    if (!recyclerView.isInCustomChoice()) {
        recyclerView.intoCustomChoiceMode();
    }
    recyclerView.toggleItemChecked(position);
    return true;
}

17 Source : DownloadLabelsScene.java
with Apache License 2.0
from xiaojieonly

public clreplaced DownloadLabelsScene extends ToolbarScene {

    /*---------------
     Whole life cycle
     ---------------*/
    @Nullable
    public List<DownloadLabel> mList = null;

    /*---------------
     View life cycle
     ---------------*/
    @Nullable
    private EasyRecyclerView mRecyclerView;

    @Nullable
    private ViewTransition mViewTransition;

    @Nullable
    private RecyclerView.Adapter mAdapter;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mList = EhApplication.getDownloadManager(getContext2()).getLabelList();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mList = null;
    }

    @SuppressWarnings("deprecation")
    @Nullable
    @Override
    public View onCreateView3(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.scene_label_list, container, false);
        mRecyclerView = (EasyRecyclerView) ViewUtils.$$(view, R.id.recycler_view);
        TextView tip = (TextView) ViewUtils.$$(view, R.id.tip);
        mViewTransition = new ViewTransition(mRecyclerView, tip);
        Context context = getContext2();
        replacedertUtils.replacedertNotNull(context);
        Drawable drawable = DrawableManager.getVectorDrawable(context, R.drawable.big_label);
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        tip.setCompoundDrawables(null, drawable, null, null);
        tip.setText(R.string.no_download_label);
        // drag & drop manager
        RecyclerViewDragDropManager dragDropManager = new RecyclerViewDragDropManager();
        dragDropManager.setDraggingItemShadowDrawable((NinePatchDrawable) context.getResources().getDrawable(R.drawable.shadow_8dp));
        RecyclerView.Adapter adapter = new LabelAdapter();
        adapter.setHreplacedtableIds(true);
        // wrap for dragging
        adapter = dragDropManager.createWrappedAdapter(adapter);
        mAdapter = adapter;
        final GeneralItemAnimator animator = new SwipeDismissItemAnimator();
        mRecyclerView.setLayoutManager(new LinearLayoutManager(context));
        mRecyclerView.setAdapter(adapter);
        mRecyclerView.sereplacedemAnimator(animator);
        dragDropManager.attachRecyclerView(mRecyclerView);
        updateView();
        return view;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        setreplacedle(R.string.download_labels);
        setNavigationIcon(R.drawable.v_arrow_left_dark_x24);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (null != mRecyclerView) {
            mRecyclerView.stopScroll();
            mRecyclerView = null;
        }
        mViewTransition = null;
        mAdapter = null;
    }

    @Override
    public void onNavigationClick() {
        onBackPressed();
    }

    @Override
    public int getMenuResId() {
        return R.menu.scene_download_label;
    }

    @Override
    public boolean onMenuItemClick(MenuItem item) {
        Context context = getContext2();
        if (null == context) {
            return false;
        }
        int id = item.gereplacedemId();
        switch(id) {
            case R.id.action_add:
                {
                    EditTextDialogBuilder builder = new EditTextDialogBuilder(context, null, getString(R.string.download_labels));
                    builder.setreplacedle(R.string.new_label_replacedle);
                    builder.setPositiveButton(android.R.string.ok, null);
                    AlertDialog dialog = builder.show();
                    new NewLabelDialogHelper(builder, dialog);
                }
        }
        return false;
    }

    private void updateView() {
        if (mViewTransition != null) {
            if (mList != null && mList.size() > 0) {
                mViewTransition.showView(0);
            } else {
                mViewTransition.showView(1);
            }
        }
    }

    private clreplaced NewLabelDialogHelper implements View.OnClickListener {

        private final EditTextDialogBuilder mBuilder;

        private final AlertDialog mDialog;

        public NewLabelDialogHelper(EditTextDialogBuilder builder, AlertDialog dialog) {
            mBuilder = builder;
            mDialog = dialog;
            Button button = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
            if (button != null) {
                button.setOnClickListener(this);
            }
        }

        @Override
        public void onClick(View v) {
            Context context = getContext2();
            if (null == context) {
                return;
            }
            String text = mBuilder.getText();
            if (TextUtils.isEmpty(text)) {
                mBuilder.setError(getString(R.string.label_text_is_empty));
            } else if (getString(R.string.default_download_label_name).equals(text)) {
                mBuilder.setError(getString(R.string.label_text_is_invalid));
            } else if (EhApplication.getDownloadManager(context).containLabel(text)) {
                mBuilder.setError(getString(R.string.label_text_exist));
            } else {
                mBuilder.setError(null);
                mDialog.dismiss();
                EhApplication.getDownloadManager(context).addLabel(text);
                if (mAdapter != null && mList != null) {
                    mAdapter.notifyItemInserted(mList.size() - 1);
                }
                if (mViewTransition != null) {
                    if (mList != null && mList.size() > 0) {
                        mViewTransition.showView(0);
                    } else {
                        mViewTransition.showView(1);
                    }
                }
            }
        }
    }

    private clreplaced RenameLabelDialogHelper implements View.OnClickListener {

        private final EditTextDialogBuilder mBuilder;

        private final AlertDialog mDialog;

        private final String mOriginalLabel;

        private final int mPosition;

        public RenameLabelDialogHelper(EditTextDialogBuilder builder, AlertDialog dialog, String originalLabel, int position) {
            mBuilder = builder;
            mDialog = dialog;
            mOriginalLabel = originalLabel;
            mPosition = position;
            Button button = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
            if (button != null) {
                button.setOnClickListener(this);
            }
        }

        @Override
        public void onClick(View v) {
            Context context = getContext2();
            if (null == context) {
                return;
            }
            String text = mBuilder.getText();
            if (TextUtils.isEmpty(text)) {
                mBuilder.setError(getString(R.string.label_text_is_empty));
            } else if (getString(R.string.default_download_label_name).equals(text)) {
                mBuilder.setError(getString(R.string.label_text_is_invalid));
            } else if (EhApplication.getDownloadManager(context).containLabel(text)) {
                mBuilder.setError(getString(R.string.label_text_exist));
            } else {
                mBuilder.setError(null);
                mDialog.dismiss();
                EhApplication.getDownloadManager(context).renameLabel(mOriginalLabel, text);
                if (mAdapter != null) {
                    mAdapter.notifyItemChanged(mPosition);
                }
            }
        }
    }

    private clreplaced LabelHolder extends AbstractDraggableItemViewHolder implements View.OnClickListener {

        public final TextView label;

        public final View dragHandler;

        public final View delete;

        public LabelHolder(View itemView) {
            super(itemView);
            label = (TextView) ViewUtils.$$(itemView, R.id.label);
            dragHandler = ViewUtils.$$(itemView, R.id.drag_handler);
            delete = ViewUtils.$$(itemView, R.id.delete);
            label.setOnClickListener(this);
            delete.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            int position = getAdapterPosition();
            Context context = getContext2();
            if (null == context || null == mList || null == mRecyclerView) {
                return;
            }
            if (label == v) {
                DownloadLabel raw = mList.get(position);
                EditTextDialogBuilder builder = new EditTextDialogBuilder(context, raw.getLabel(), getString(R.string.download_labels));
                builder.setreplacedle(R.string.rename_label_replacedle);
                builder.setPositiveButton(android.R.string.ok, null);
                AlertDialog dialog = builder.show();
                new RenameLabelDialogHelper(builder, dialog, raw.getLabel(), position);
            } else if (delete == v) {
                final DownloadLabel label = mList.get(position);
                new AlertDialog.Builder(context).setreplacedle(R.string.delete_label_replacedle).setMessage(getString(R.string.delete_label_message, label.getLabel())).setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        EhApplication.getDownloadManager(context).deleteLabel(label.getLabel());
                    }
                }).setOnDismissListener(new DialogInterface.OnDismissListener() {

                    @Override
                    public void onDismiss(DialogInterface dialog) {
                        if (null != mAdapter) {
                            mAdapter.notifyDataSetChanged();
                        }
                        updateView();
                    }
                }).show();
            }
        }
    }

    private clreplaced LabelAdapter extends RecyclerView.Adapter<LabelHolder> implements DraggableItemAdapter<LabelHolder> {

        private final LayoutInflater mInflater;

        public LabelAdapter() {
            mInflater = getLayoutInflater2();
            replacedertUtils.replacedertNotNull(mInflater);
        }

        @Override
        public LabelHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            return new LabelHolder(mInflater.inflate(R.layout.item_download_label, parent, false));
        }

        @Override
        public void onBindViewHolder(LabelHolder holder, int position) {
            if (mList != null) {
                holder.label.setText(mList.get(position).getLabel());
            }
        }

        @Override
        public long gereplacedemId(int position) {
            return mList != null ? mList.get(position).getId() : 0;
        }

        @Override
        public int gereplacedemCount() {
            return mList != null ? mList.size() : 0;
        }

        @Override
        public boolean onCheckCanStartDrag(LabelHolder holder, int position, int x, int y) {
            return ViewUtils.isViewUnder(holder.dragHandler, x, y, 0);
        }

        @Override
        public ItemDraggableRange onGereplacedemDraggableRange(LabelHolder holder, int position) {
            return null;
        }

        @Override
        public void onMoveItem(int fromPosition, int toPosition) {
            Context context = getContext2();
            if (null == context || fromPosition == toPosition) {
                return;
            }
            EhApplication.getDownloadManager(context).moveLabel(fromPosition, toPosition);
        }

        @Override
        public boolean onCheckCanDrop(int draggingPosition, int dropPosition) {
            return true;
        }

        @Override
        public void onItemDragStarted(int position) {
        }

        @Override
        public void onItemDragFinished(int fromPosition, int toPosition, boolean result) {
        }
    }
}

17 Source : HostsActivity.java
with Apache License 2.0
from xiaojieonly

@Override
public boolean onItemClick(EasyRecyclerView easyRecyclerView, View view, int position, long id) {
    Pair<String, String> pair = data.get(position);
    Bundle args = new Bundle();
    args.putString(KEY_HOST, pair.first);
    args.putString(KEY_IP, pair.second);
    DialogFragment fragment = new EditHostDialogFragment();
    fragment.setArguments(args);
    fragment.show(getSupportFragmentManager(), DIALOG_TAG_EDIT_HOST);
    return true;
}

17 Source : GalleryCommentsScene.java
with Apache License 2.0
from NuclearVGA

public final clreplaced GalleryCommentsScene extends ToolbarScene implements View.OnClickListener {

    public static final String TAG = GalleryCommentsScene.clreplaced.getSimpleName();

    public static final String KEY_API_UID = "api_uid";

    public static final String KEY_API_KEY = "api_key";

    public static final String KEY_GID = "gid";

    public static final String KEY_TOKEN = "token";

    public static final String KEY_COMMENT_LIST = "comment_list";

    private static final int TYPE_COMMENT = 0;

    private static final int TYPE_MORE = 1;

    private static final int TYPE_PROGRESS = 2;

    private long mApiUid;

    private String mApiKey;

    private long mGid;

    private String mToken;

    @Nullable
    private GalleryCommentList mCommentList;

    @Nullable
    private EasyRecyclerView mRecyclerView;

    @Nullable
    private FabLayout mFabLayout;

    @Nullable
    private FloatingActionButton mFab;

    @Nullable
    private View mEditPanel;

    @Nullable
    private ImageView mSendImage;

    @Nullable
    private EditText mEditText;

    @Nullable
    private CommentAdapter mAdapter;

    @Nullable
    private ViewTransition mViewTransition;

    private Drawable mSendDrawable;

    private Drawable mPencilDrawable;

    private long mCommentId;

    private boolean mInAnimation = false;

    private boolean mShowAllComments = false;

    private boolean mRefreshingComments = false;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState == null) {
            onInit();
        } else {
            onRestore(savedInstanceState);
        }
    }

    private void handleArgs(Bundle args) {
        if (args == null) {
            return;
        }
        mApiUid = args.getLong(KEY_API_UID, -1L);
        mApiKey = args.getString(KEY_API_KEY);
        mGid = args.getLong(KEY_GID, -1L);
        mToken = args.getString(KEY_TOKEN, null);
        mCommentList = args.getParcelable(KEY_COMMENT_LIST);
        mShowAllComments = mCommentList != null && !mCommentList.hasMore;
    }

    private void onInit() {
        handleArgs(getArguments());
    }

    private void onRestore(@NonNull Bundle savedInstanceState) {
        mApiUid = savedInstanceState.getLong(KEY_API_UID, -1L);
        mApiKey = savedInstanceState.getString(KEY_API_KEY);
        mGid = savedInstanceState.getLong(KEY_GID, -1L);
        mToken = savedInstanceState.getString(KEY_TOKEN, null);
        mCommentList = savedInstanceState.getParcelable(KEY_COMMENT_LIST);
        mShowAllComments = mCommentList != null && !mCommentList.hasMore;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putLong(KEY_API_UID, mApiUid);
        outState.putString(KEY_API_KEY, mApiKey);
        outState.putLong(KEY_GID, mGid);
        outState.putString(KEY_TOKEN, mToken);
        outState.putParcelable(KEY_COMMENT_LIST, mCommentList);
    }

    @Nullable
    @Override
    public View onCreateView3(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.scene_gallery_comments, container, false);
        mRecyclerView = (EasyRecyclerView) ViewUtils.$$(view, R.id.recycler_view);
        TextView tip = (TextView) ViewUtils.$$(view, R.id.tip);
        mEditPanel = ViewUtils.$$(view, R.id.edit_panel);
        mSendImage = (ImageView) ViewUtils.$$(mEditPanel, R.id.send);
        mEditText = (EditText) ViewUtils.$$(mEditPanel, R.id.edit_text);
        mFabLayout = (FabLayout) ViewUtils.$$(view, R.id.fab_layout);
        mFab = (FloatingActionButton) ViewUtils.$$(view, R.id.fab);
        Context context = getContext2();
        replacedertUtils.replacedertNotNull(context);
        Resources resources = context.getResources();
        int paddingBottomFab = resources.getDimensionPixelOffset(R.dimen.gallery_padding_bottom_fab);
        Drawable drawable = DrawableManager.getVectorDrawable(context, R.drawable.big_sad_pandroid);
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        tip.setCompoundDrawables(null, drawable, null, null);
        mSendDrawable = DrawableManager.getVectorDrawable(context, R.drawable.v_send_dark_x24);
        mPencilDrawable = DrawableManager.getVectorDrawable(context, R.drawable.v_pencil_dark_x24);
        mAdapter = new CommentAdapter();
        mRecyclerView.setAdapter(mAdapter);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(context, RecyclerView.VERTICAL, false));
        LinearDividerItemDecoration decoration = new LinearDividerItemDecoration(LinearDividerItemDecoration.VERTICAL, AttrResources.getAttrColor(context, R.attr.dividerColor), LayoutUtils.dp2pix(context, 1));
        decoration.setShowLastDivider(true);
        mRecyclerView.addItemDecoration(decoration);
        // mRecyclerView.setSelector(Ripple.generateRippleDrawable(context, !AttrResources.getAttrBoolean(context, R.attr.isLightTheme), new ColorDrawable(Color.TRANSPARENT)));
        mRecyclerView.setHasFixedSize(true);
        // mRecyclerView.setOnItemClickListener(this);
        mRecyclerView.setPadding(mRecyclerView.getPaddingLeft(), mRecyclerView.getPaddingTop(), mRecyclerView.getPaddingRight(), mRecyclerView.getPaddingBottom() + paddingBottomFab);
        // Cancel change animator
        RecyclerView.ItemAnimator itemAnimator = mRecyclerView.gereplacedemAnimator();
        if (itemAnimator instanceof DefaulreplacedemAnimator) {
            ((DefaulreplacedemAnimator) itemAnimator).setSupportsChangeAnimations(false);
        }
        mSendImage.setOnClickListener(this);
        mFab.setOnClickListener(this);
        addAboveSnackView(mEditPanel);
        addAboveSnackView(mFabLayout);
        mViewTransition = new ViewTransition(mRecyclerView, tip);
        updateView(false);
        return view;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (null != mRecyclerView) {
            mRecyclerView.stopScroll();
            mRecyclerView = null;
        }
        if (null != mEditPanel) {
            removeAboveSnackView(mEditPanel);
            mEditPanel = null;
        }
        if (null != mFabLayout) {
            removeAboveSnackView(mFabLayout);
            mFabLayout = null;
        }
        mFab = null;
        mSendImage = null;
        mEditText = null;
        mAdapter = null;
        mViewTransition = null;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        setreplacedle(R.string.gallery_comments);
        setNavigationIcon(R.drawable.v_arrow_left_dark_x24);
    }

    @Override
    public void onNavigationClick() {
        onBackPressed();
    }

    private void voteComment(long id, int vote) {
        Context context = getContext2();
        MainActivity activity = getActivity2();
        if (null == context || null == activity) {
            return;
        }
        EhRequest request = new EhRequest().setMethod(EhClient.METHOD_VOTE_COMMENT).setArgs(mApiUid, mApiKey, mGid, mToken, id, vote).setCallback(new VoteCommentListener(context, activity.getStageId(), getTag()));
        EhApplication.getEhClient(context).execute(request);
    }

    @SuppressLint("InflateParams")
    public void showVoteStatusDialog(Context context, String voteStatus) {
        String[] temp = StringUtils.split(voteStatus, ',');
        final int length = temp.length;
        final String[] userArray = new String[length];
        final String[] voteArray = new String[length];
        for (int i = 0; i < length; i++) {
            String str = StringUtils.trim(temp[i]);
            int index = str.lastIndexOf(' ');
            if (index < 0) {
                Log.d(TAG, "Something wrong happened about vote state");
                userArray[i] = str;
                voteArray[i] = "";
            } else {
                userArray[i] = StringUtils.trim(str.substring(0, index));
                voteArray[i] = StringUtils.trim(str.substring(index + 1));
            }
        }
        AlertDialog.Builder builder = new MaterialAlertDialogBuilder(context);
        context = builder.getContext();
        final LayoutInflater inflater = LayoutInflater.from(context);
        EasyRecyclerView rv = (EasyRecyclerView) inflater.inflate(R.layout.dialog_recycler_view, null);
        rv.setAdapter(new RecyclerView.Adapter<InfoHolder>() {

            @Override
            public InfoHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                return new InfoHolder(inflater.inflate(R.layout.item_drawer_favorites, parent, false));
            }

            @Override
            public void onBindViewHolder(InfoHolder holder, int position) {
                holder.key.setText(userArray[position]);
                holder.value.setText(voteArray[position]);
            }

            @Override
            public int gereplacedemCount() {
                return length;
            }
        });
        rv.setLayoutManager(new LinearLayoutManager(context));
        LinearDividerItemDecoration decoration = new LinearDividerItemDecoration(LinearDividerItemDecoration.VERTICAL, AttrResources.getAttrColor(context, R.attr.dividerColor), LayoutUtils.dp2pix(context, 1));
        decoration.setPadding(ResourcesUtils.getAttrDimensionPixelOffset(context, R.attr.dialogPreferredPadding));
        rv.addItemDecoration(decoration);
        // rv.setSelector(Ripple.generateRippleDrawable(context, !AttrResources.getAttrBoolean(context, R.attr.isLightTheme), new ColorDrawable(Color.TRANSPARENT)));
        rv.setClipToPadding(false);
        builder.setView(rv).show();
    }

    private void showCommentDialog(int position) {
        final Context context = getContext2();
        if (context == null || mCommentList == null || mCommentList.comments == null || position >= mCommentList.comments.length || position < 0) {
            return;
        }
        final GalleryComment comment = mCommentList.comments[position];
        List<String> menu = new ArrayList<>();
        final IntList menuId = new IntList();
        Resources resources = context.getResources();
        menu.add(resources.getString(R.string.copy_comment_text));
        menuId.add(R.id.copy);
        if (comment.editable) {
            menu.add(resources.getString(R.string.edit_comment));
            menuId.add(R.id.edit_comment);
        }
        if (comment.voteUpAble) {
            menu.add(resources.getString(comment.voteUpEd ? R.string.cancel_vote_up : R.string.vote_up));
            menuId.add(R.id.vote_up);
        }
        if (comment.voteDownAble) {
            menu.add(resources.getString(comment.voteDownEd ? R.string.cancel_vote_down : R.string.vote_down));
            menuId.add(R.id.vote_down);
        }
        if (!TextUtils.isEmpty(comment.voteState)) {
            menu.add(resources.getString(R.string.check_vote_status));
            menuId.add(R.id.check_vote_status);
        }
        new MaterialAlertDialogBuilder(context).sereplacedems(menu.toArray(new String[menu.size()]), (dialog, which) -> {
            if (which < 0 || which >= menuId.size()) {
                return;
            }
            int id = menuId.get(which);
            switch(id) {
                case R.id.copy:
                    ClipboardManager cmb = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
                    cmb.setPrimaryClip(ClipData.newPlainText(null, comment.comment));
                    showTip(R.string.copied_to_clipboard, LENGTH_SHORT);
                    break;
                case R.id.vote_up:
                    voteComment(comment.id, 1);
                    break;
                case R.id.vote_down:
                    voteComment(comment.id, -1);
                    break;
                case R.id.check_vote_status:
                    showVoteStatusDialog(context, comment.voteState);
                    break;
                case R.id.edit_comment:
                    prepareEditComment(comment.id);
                    if (!mInAnimation && mEditPanel != null && mEditPanel.getVisibility() != View.VISIBLE) {
                        showEditPanel(true);
                    }
                    break;
            }
        }).show();
    }

    public boolean onItemClick(EasyRecyclerView parent, View view, int position) {
        MainActivity activity = getActivity2();
        if (null == activity) {
            return false;
        }
        RecyclerView.ViewHolder holder = parent.getChildViewHolder(view);
        if (holder instanceof ActualCommentHolder) {
            ActualCommentHolder commentHolder = (ActualCommentHolder) holder;
            ClickableSpan span = commentHolder.comment.getCurrentSpan();
            commentHolder.comment.clearCurrentSpan();
            if (span instanceof URLSpan) {
                UrlOpener.openUrl(activity, ((URLSpan) span).getURL(), true);
            } else {
                showCommentDialog(position);
            }
        } else if (holder instanceof MoreCommentHolder && !mRefreshingComments && mAdapter != null) {
            mRefreshingComments = true;
            mShowAllComments = true;
            mAdapter.notifyItemChanged(position);
            String url = getGalleryDetailUrl();
            if (url != null) {
                // Request
                EhRequest request = new EhRequest().setMethod(EhClient.METHOD_GET_GALLERY_DETAIL).setArgs(url).setCallback(new RefreshCommentListener(activity, activity.getStageId(), getTag()));
                EhApplication.getEhClient(activity).execute(request);
            }
        }
        return true;
    }

    private void updateView(boolean animation) {
        if (null == mViewTransition) {
            return;
        }
        if (mCommentList == null || mCommentList.comments == null || mCommentList.comments.length <= 0) {
            mViewTransition.showView(1, animation);
        } else {
            mViewTransition.showView(0, animation);
        }
    }

    private void prepareNewComment() {
        mCommentId = 0;
        if (mSendImage != null) {
            mSendImage.setImageDrawable(mSendDrawable);
        }
    }

    private void prepareEditComment(long commentId) {
        mCommentId = commentId;
        if (mSendImage != null) {
            mSendImage.setImageDrawable(mPencilDrawable);
        }
    }

    private void showEditPanelWithAnimation() {
        if (null == mFab || null == mEditPanel) {
            return;
        }
        mInAnimation = true;
        mFab.setTranslationX(0.0f);
        mFab.setTranslationY(0.0f);
        mFab.setScaleX(1.0f);
        mFab.setScaleY(1.0f);
        int fabEndX = mEditPanel.getLeft() + (mEditPanel.getWidth() / 2) - (mFab.getWidth() / 2);
        int fabEndY = mEditPanel.getTop() + (mEditPanel.getHeight() / 2) - (mFab.getHeight() / 2);
        mFab.animate().x(fabEndX).y(fabEndY).scaleX(0.0f).scaleY(0.0f).setInterpolator(AnimationUtils.SLOW_FAST_SLOW_INTERPOLATOR).setDuration(300L).setListener(new SimpleAnimatorListener() {

            @Override
            public void onAnimationEnd(Animator animation) {
                if (null == mFab || null == mEditPanel) {
                    return;
                }
                ((View) mFab).setVisibility(View.INVISIBLE);
                mEditPanel.setVisibility(View.VISIBLE);
                int halfW = mEditPanel.getWidth() / 2;
                int halfH = mEditPanel.getHeight() / 2;
                Animator animator = ViewAnimationUtils.createCircularReveal(mEditPanel, halfW, halfH, 0, (float) Math.hypot(halfW, halfH)).setDuration(300L);
                animator.addListener(new SimpleAnimatorListener() {

                    @Override
                    public void onAnimationEnd(Animator a) {
                        mInAnimation = false;
                    }
                });
                animator.start();
            }
        }).start();
    }

    private void showEditPanel(boolean animation) {
        if (animation) {
            showEditPanelWithAnimation();
        } else {
            if (null == mFab || null == mEditPanel) {
                return;
            }
            ((View) mFab).setVisibility(View.INVISIBLE);
            mEditPanel.setVisibility(View.VISIBLE);
        }
    }

    private void hideEditPanelWithAnimation() {
        if (null == mFab || null == mEditPanel) {
            return;
        }
        mInAnimation = true;
        int halfW = mEditPanel.getWidth() / 2;
        int halfH = mEditPanel.getHeight() / 2;
        Animator animator = ViewAnimationUtils.createCircularReveal(mEditPanel, halfW, halfH, (float) Math.hypot(halfW, halfH), 0.0f).setDuration(300L);
        animator.addListener(new SimpleAnimatorListener() {

            @Override
            public void onAnimationEnd(Animator a) {
                if (null == mFab || null == mEditPanel) {
                    return;
                }
                if (Looper.myLooper() != Looper.getMainLooper()) {
                    // Some devices may run this block in non-UI thread.
                    // It might be a bug of Android OS.
                    // Check it here to avoid crash.
                    return;
                }
                mEditPanel.setVisibility(View.GONE);
                ((View) mFab).setVisibility(View.VISIBLE);
                int fabStartX = mEditPanel.getLeft() + (mEditPanel.getWidth() / 2) - (mFab.getWidth() / 2);
                int fabStartY = mEditPanel.getTop() + (mEditPanel.getHeight() / 2) - (mFab.getHeight() / 2);
                mFab.setX(fabStartX);
                mFab.setY(fabStartY);
                mFab.setScaleX(0.0f);
                mFab.setScaleY(0.0f);
                mFab.setRotation(-45.0f);
                mFab.animate().translationX(0.0f).translationY(0.0f).scaleX(1.0f).scaleY(1.0f).rotation(0.0f).setInterpolator(AnimationUtils.SLOW_FAST_SLOW_INTERPOLATOR).setDuration(300L).setListener(new SimpleAnimatorListener() {

                    @Override
                    public void onAnimationEnd(Animator animation) {
                        mInAnimation = false;
                    }
                }).start();
            }
        });
        animator.start();
    }

    private void hideEditPanel(boolean animation) {
        if (animation) {
            hideEditPanelWithAnimation();
        } else {
            if (null == mFab || null == mEditPanel) {
                return;
            }
            ((View) mFab).setVisibility(View.VISIBLE);
            mEditPanel.setVisibility(View.INVISIBLE);
        }
    }

    @Nullable
    private String getGalleryDetailUrl() {
        if (mGid != -1 && mToken != null) {
            return EhUrl.getGalleryDetailUrl(mGid, mToken, 0, mShowAllComments);
        } else {
            return null;
        }
    }

    @Override
    public void onClick(View v) {
        Context context = getContext2();
        MainActivity activity = getActivity2();
        if (null == context || null == activity || null == mEditText) {
            return;
        }
        if (mFab == v) {
            if (!mInAnimation) {
                prepareNewComment();
                showEditPanel(true);
            }
        } else if (mSendImage == v) {
            if (!mInAnimation) {
                String comment = mEditText.getText().toString();
                if (TextUtils.isEmpty(comment)) {
                    // Comment is empty
                    return;
                }
                String url = getGalleryDetailUrl();
                if (url == null) {
                    return;
                }
                // Request
                EhRequest request = new EhRequest().setMethod(EhClient.METHOD_GET_COMMENT_GALLERY).setArgs(url, comment, mCommentId != 0 ? Long.toString(mCommentId) : null).setCallback(new CommentGalleryListener(context, activity.getStageId(), getTag(), mCommentId));
                EhApplication.getEhClient(context).execute(request);
                hideSoftInput();
                hideEditPanel(true);
            }
        }
    }

    @Override
    public void onBackPressed() {
        if (mInAnimation) {
            return;
        }
        if (null != mEditPanel && mEditPanel.getVisibility() == View.VISIBLE) {
            hideEditPanel(true);
        } else {
            finish();
        }
    }

    private void onRefreshGallerySuccess(GalleryCommentList result) {
        if (mAdapter == null) {
            return;
        }
        mRefreshingComments = false;
        mCommentList = result;
        mAdapter.notifyDataSetChanged();
        updateView(true);
        Bundle re = new Bundle();
        re.putParcelable(KEY_COMMENT_LIST, result);
        setResult(SceneFragment.RESULT_OK, re);
    }

    private void onRefreshGalleryFailure() {
        if (mAdapter == null) {
            return;
        }
        mRefreshingComments = false;
        int position = mAdapter.gereplacedemCount() - 1;
        if (position >= 0) {
            mAdapter.notifyItemChanged(position);
        }
    }

    private void onCommentGallerySuccess(GalleryCommentList result) {
        if (mAdapter == null) {
            return;
        }
        mCommentList = result;
        mAdapter.notifyDataSetChanged();
        Bundle re = new Bundle();
        re.putParcelable(KEY_COMMENT_LIST, result);
        setResult(SceneFragment.RESULT_OK, re);
        // Remove text
        if (mEditText != null) {
            mEditText.setText("");
        }
        updateView(true);
    }

    private void onVoteCommentSuccess(VoteCommentParser.Result result) {
        if (mAdapter == null || mCommentList == null || mCommentList.comments == null) {
            return;
        }
        int position = -1;
        for (int i = 0, n = mCommentList.comments.length; i < n; i++) {
            GalleryComment comment = mCommentList.comments[i];
            if (comment.id == result.id) {
                position = i;
                break;
            }
        }
        if (-1 == position) {
            Log.d(TAG, "Can't find comment with id " + result.id);
            return;
        }
        // Update comment
        GalleryComment comment = mCommentList.comments[position];
        comment.score = result.score;
        if (result.expectVote > 0) {
            comment.voteUpEd = 0 != result.vote;
            comment.voteDownEd = false;
        } else {
            comment.voteDownEd = 0 != result.vote;
            comment.voteUpEd = false;
        }
        mAdapter.notifyItemChanged(position);
        Bundle re = new Bundle();
        re.putParcelable(KEY_COMMENT_LIST, mCommentList);
        setResult(SceneFragment.RESULT_OK, re);
    }

    private static clreplaced RefreshCommentListener extends EhCallback<GalleryCommentsScene, GalleryDetail> {

        public RefreshCommentListener(Context context, int stageId, String sceneTag) {
            super(context, stageId, sceneTag);
        }

        @Override
        public void onSuccess(GalleryDetail result) {
            GalleryCommentsScene scene = getScene();
            if (scene != null) {
                scene.onRefreshGallerySuccess(result.comments);
            }
        }

        @Override
        public void onFailure(Exception e) {
            GalleryCommentsScene scene = getScene();
            if (scene != null) {
                scene.onRefreshGalleryFailure();
            }
        }

        @Override
        public void onCancel() {
        }

        @Override
        public boolean isInstance(SceneFragment scene) {
            return scene instanceof GalleryCommentsScene;
        }
    }

    private static clreplaced CommentGalleryListener extends EhCallback<GalleryCommentsScene, GalleryCommentList> {

        private final long mCommentId;

        public CommentGalleryListener(Context context, int stageId, String sceneTag, long commentId) {
            super(context, stageId, sceneTag);
            mCommentId = commentId;
        }

        @Override
        public void onSuccess(GalleryCommentList result) {
            showTip(mCommentId != 0 ? R.string.edit_comment_successfully : R.string.comment_successfully, LENGTH_SHORT);
            GalleryCommentsScene scene = getScene();
            if (scene != null) {
                scene.onCommentGallerySuccess(result);
            }
        }

        @Override
        public void onFailure(Exception e) {
            showTip(getContent().getString(mCommentId != 0 ? R.string.edit_comment_failed : R.string.comment_failed) + "\n" + ExceptionUtils.getReadableString(e), LENGTH_LONG);
        }

        @Override
        public void onCancel() {
        }

        @Override
        public boolean isInstance(SceneFragment scene) {
            return scene instanceof GalleryCommentsScene;
        }
    }

    private static clreplaced VoteCommentListener extends EhCallback<GalleryCommentsScene, VoteCommentParser.Result> {

        public VoteCommentListener(Context context, int stageId, String sceneTag) {
            super(context, stageId, sceneTag);
        }

        @Override
        public void onSuccess(VoteCommentParser.Result result) {
            showTip(result.expectVote > 0 ? (0 != result.vote ? R.string.vote_up_successfully : R.string.cancel_vote_up_successfully) : (0 != result.vote ? R.string.vote_down_successfully : R.string.cancel_vote_down_successfully), LENGTH_SHORT);
            GalleryCommentsScene scene = getScene();
            if (scene != null) {
                scene.onVoteCommentSuccess(result);
            }
        }

        @Override
        public void onFailure(Exception e) {
            showTip(R.string.vote_failed, LENGTH_LONG);
        }

        @Override
        public void onCancel() {
        }

        @Override
        public boolean isInstance(SceneFragment scene) {
            return scene instanceof GalleryCommentsScene;
        }
    }

    private clreplaced InfoHolder extends RecyclerView.ViewHolder {

        private final TextView key;

        private final TextView value;

        public InfoHolder(View itemView) {
            super(itemView);
            key = (TextView) ViewUtils.$$(itemView, R.id.key);
            value = (TextView) ViewUtils.$$(itemView, R.id.value);
        }
    }

    private abstract clreplaced CommentHolder extends RecyclerView.ViewHolder {

        public CommentHolder(LayoutInflater inflater, int resId, ViewGroup parent) {
            super(inflater.inflate(resId, parent, false));
        }
    }

    private clreplaced ActualCommentHolder extends CommentHolder {

        private final TextView user;

        private final TextView time;

        private final LinkifyTextView comment;

        public ActualCommentHolder(LayoutInflater inflater, ViewGroup parent) {
            super(inflater, R.layout.item_gallery_comment, parent);
            user = itemView.findViewById(R.id.user);
            time = itemView.findViewById(R.id.time);
            comment = itemView.findViewById(R.id.comment);
        }

        private CharSequence generateComment(Context context, ObservedTextView textView, GalleryComment comment) {
            SpannableStringBuilder ssb = Html.fromHtml(comment.comment, new URLImageGetter(textView, EhApplication.getConaco(context)), null);
            if (0 != comment.id && 0 != comment.score) {
                int score = comment.score;
                String scoreString = score > 0 ? "+" + score : Integer.toString(score);
                SpannableString ss = new SpannableString(scoreString);
                ss.setSpan(new RelativeSizeSpan(0.8f), 0, scoreString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                ss.setSpan(new StyleSpan(Typeface.BOLD), 0, scoreString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                ss.setSpan(new ForegroundColorSpan(AttrResources.getAttrColor(context, android.R.attr.textColorSecondary)), 0, scoreString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                ssb.append("  ").append(ss);
            }
            if (comment.lastEdited != 0) {
                String str = context.getString(R.string.last_edited, ReadableTime.getTimeAgo(comment.lastEdited));
                SpannableString ss = new SpannableString(str);
                ss.setSpan(new RelativeSizeSpan(0.8f), 0, str.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                ss.setSpan(new StyleSpan(Typeface.BOLD), 0, str.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                ss.setSpan(new ForegroundColorSpan(AttrResources.getAttrColor(context, android.R.attr.textColorSecondary)), 0, str.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                ssb.append("\n\n").append(ss);
            }
            return TextUrl.handleTextUrl(ssb);
        }

        public void bind(GalleryComment value) {
            user.setText(value.user);
            time.setText(ReadableTime.getTimeAgo(value.time));
            comment.setText(generateComment(comment.getContext(), comment, value));
        }
    }

    private clreplaced MoreCommentHolder extends CommentHolder {

        public MoreCommentHolder(LayoutInflater inflater, ViewGroup parent) {
            super(inflater, R.layout.item_gallery_comment_more, parent);
        }
    }

    private clreplaced ProgressCommentHolder extends CommentHolder {

        public ProgressCommentHolder(LayoutInflater inflater, ViewGroup parent) {
            super(inflater, R.layout.item_gallery_comment_progress, parent);
        }
    }

    private clreplaced CommentAdapter extends RecyclerView.Adapter<CommentHolder> {

        private final LayoutInflater mInflater;

        public CommentAdapter() {
            mInflater = getLayoutInflater2();
            replacedertUtils.replacedertNotNull(mInflater);
        }

        @Override
        public CommentHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            switch(viewType) {
                case TYPE_COMMENT:
                    return new ActualCommentHolder(mInflater, parent);
                case TYPE_MORE:
                    return new MoreCommentHolder(mInflater, parent);
                case TYPE_PROGRESS:
                    return new ProgressCommentHolder(mInflater, parent);
                default:
                    throw new IllegalStateException("Invalid view type: " + viewType);
            }
        }

        @Override
        public void onBindViewHolder(@NonNull CommentHolder holder, int position) {
            Context context = getContext2();
            if (context == null || mCommentList == null) {
                return;
            }
            holder.itemView.setOnClickListener(v -> onItemClick(mRecyclerView, holder.itemView, position));
            holder.itemView.setClickable(true);
            holder.itemView.setFocusable(true);
            if (holder instanceof ActualCommentHolder) {
                ((ActualCommentHolder) holder).bind(mCommentList.comments[position]);
            }
        }

        @Override
        public int gereplacedemCount() {
            if (mCommentList == null || mCommentList.comments == null) {
                return 0;
            } else if (mCommentList.hasMore) {
                return mCommentList.comments.length + 1;
            } else {
                return mCommentList.comments.length;
            }
        }

        @Override
        public int gereplacedemViewType(int position) {
            if (position >= mCommentList.comments.length) {
                return mRefreshingComments ? TYPE_PROGRESS : TYPE_MORE;
            } else {
                return TYPE_COMMENT;
            }
        }
    }
}

17 Source : GalleryCommentsScene.java
with Apache License 2.0
from NuclearVGA

@SuppressLint("InflateParams")
public void showVoteStatusDialog(Context context, String voteStatus) {
    String[] temp = StringUtils.split(voteStatus, ',');
    final int length = temp.length;
    final String[] userArray = new String[length];
    final String[] voteArray = new String[length];
    for (int i = 0; i < length; i++) {
        String str = StringUtils.trim(temp[i]);
        int index = str.lastIndexOf(' ');
        if (index < 0) {
            Log.d(TAG, "Something wrong happened about vote state");
            userArray[i] = str;
            voteArray[i] = "";
        } else {
            userArray[i] = StringUtils.trim(str.substring(0, index));
            voteArray[i] = StringUtils.trim(str.substring(index + 1));
        }
    }
    AlertDialog.Builder builder = new MaterialAlertDialogBuilder(context);
    context = builder.getContext();
    final LayoutInflater inflater = LayoutInflater.from(context);
    EasyRecyclerView rv = (EasyRecyclerView) inflater.inflate(R.layout.dialog_recycler_view, null);
    rv.setAdapter(new RecyclerView.Adapter<InfoHolder>() {

        @Override
        public InfoHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            return new InfoHolder(inflater.inflate(R.layout.item_drawer_favorites, parent, false));
        }

        @Override
        public void onBindViewHolder(InfoHolder holder, int position) {
            holder.key.setText(userArray[position]);
            holder.value.setText(voteArray[position]);
        }

        @Override
        public int gereplacedemCount() {
            return length;
        }
    });
    rv.setLayoutManager(new LinearLayoutManager(context));
    LinearDividerItemDecoration decoration = new LinearDividerItemDecoration(LinearDividerItemDecoration.VERTICAL, AttrResources.getAttrColor(context, R.attr.dividerColor), LayoutUtils.dp2pix(context, 1));
    decoration.setPadding(ResourcesUtils.getAttrDimensionPixelOffset(context, R.attr.dialogPreferredPadding));
    rv.addItemDecoration(decoration);
    // rv.setSelector(Ripple.generateRippleDrawable(context, !AttrResources.getAttrBoolean(context, R.attr.isLightTheme), new ColorDrawable(Color.TRANSPARENT)));
    rv.setClipToPadding(false);
    builder.setView(rv).show();
}

17 Source : GalleryPreviewsScene.java
with Apache License 2.0
from duzhaokun123

public clreplaced GalleryPreviewsScene extends ToolbarScene {

    public static final String KEY_GALLERY_INFO = "gallery_info";

    private final static String KEY_HAS_FIRST_REFRESH = "has_first_refresh";

    /*---------------
     Whole life cycle
     ---------------*/
    @Nullable
    private EhClient mClient;

    @Nullable
    private GalleryInfo mGalleryInfo;

    /*---------------
     View life cycle
     ---------------*/
    @Nullable
    private ContentLayout mContentLayout;

    @Nullable
    private EasyRecyclerView mRecyclerView;

    @Nullable
    private GalleryPreviewAdapter mAdapter;

    @Nullable
    private GalleryPreviewHelper mHelper;

    private boolean mHasFirstRefresh = false;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Context context = getContext();
        replacedertUtils.replacedertNotNull(context);
        mClient = EhApplication.getEhClient(context);
        if (savedInstanceState == null) {
            onInit();
        } else {
            onRestore(savedInstanceState);
        }
    }

    private void onInit() {
        Bundle args = getArguments();
        if (args == null) {
            return;
        }
        mGalleryInfo = args.getParcelable(KEY_GALLERY_INFO);
    }

    private void onRestore(@NonNull Bundle savedInstanceState) {
        mGalleryInfo = savedInstanceState.getParcelable(KEY_GALLERY_INFO);
        mHasFirstRefresh = savedInstanceState.getBoolean(KEY_HAS_FIRST_REFRESH);
    }

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        boolean hasFirstRefresh;
        if (mHelper != null && 1 == mHelper.getShownViewIndex()) {
            hasFirstRefresh = false;
        } else {
            hasFirstRefresh = mHasFirstRefresh;
        }
        outState.putBoolean(KEY_HAS_FIRST_REFRESH, hasFirstRefresh);
        outState.putParcelable(KEY_GALLERY_INFO, mGalleryInfo);
    }

    @Nullable
    @Override
    public View onCreateViewWithToolbar(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mContentLayout = (ContentLayout) inflater.inflate(R.layout.scene_gallery_previews, container, false);
        mContentLayout.hideFastScroll();
        mRecyclerView = mContentLayout.getRecyclerView();
        Context context = getContext();
        replacedertUtils.replacedertNotNull(context);
        Resources resources = context.getResources();
        mAdapter = new GalleryPreviewAdapter();
        mRecyclerView.setAdapter(mAdapter);
        int columnWidth = resources.getDimensionPixelOffset(Settings.getThumbSizeResId());
        AutoGridLayoutManager layoutManager = new AutoGridLayoutManager(context, columnWidth);
        layoutManager.setStrategy(AutoGridLayoutManager.STRATEGY_SUITABLE_SIZE);
        mRecyclerView.setLayoutManager(layoutManager);
        mRecyclerView.setClipToPadding(false);
        int padding = LayoutUtils.dp2pix(context, 4);
        MarginItemDecoration decoration = new MarginItemDecoration(padding, padding, padding, padding, padding);
        mRecyclerView.addItemDecoration(decoration);
        decoration.applyPaddings(mRecyclerView);
        mHelper = new GalleryPreviewHelper();
        mContentLayout.setHelper(mHelper);
        // Only refresh for the first time
        if (!mHasFirstRefresh) {
            mHasFirstRefresh = true;
            mHelper.firstRefresh();
        }
        return mContentLayout;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (null != mHelper) {
            if (1 == mHelper.getShownViewIndex()) {
                mHasFirstRefresh = false;
            }
        }
        if (null != mRecyclerView) {
            mRecyclerView.stopScroll();
            mRecyclerView = null;
        }
        mAdapter = null;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        setreplacedle(R.string.gallery_previews);
        setNavigationIcon(R.drawable.v_arrow_left_dark_x24);
    }

    @Override
    public int getMenuResId() {
        return R.menu.scene_gallery_previews;
    }

    @Override
    public boolean onMenuItemClick(MenuItem item) {
        Context context = getContext();
        if (null == context) {
            return false;
        }
        int id = item.gereplacedemId();
        if (id == R.id.action_go_to) {
            if (mHelper == null) {
                return true;
            }
            int pages = mHelper.getPages();
            if (pages > 0 && mHelper.canGoTo()) {
                GoToDialogHelper helper = new GoToDialogHelper(pages, mHelper.getPageForTop());
                AlertDialog dialog = new MaterialAlertDialogBuilder(context).setreplacedle(R.string.go_to).setView(R.layout.dialog_go_to).setPositiveButton(android.R.string.ok, null).create();
                dialog.show();
                helper.setDialog(dialog);
            }
            return true;
        }
        return false;
    }

    @Override
    public void onNavigationClick() {
        onBackPressed();
    }

    public boolean onItemClick(int position) {
        Context context = getContext();
        if (null != context && null != mHelper && null != mGalleryInfo) {
            GalleryPreview p = mHelper.getDataAtEx(position);
            if (p != null) {
                Intent intent = new Intent(context, GalleryActivity.clreplaced);
                intent.setAction(GalleryActivity.ACTION_EH);
                intent.putExtra(GalleryActivity.KEY_GALLERY_INFO, mGalleryInfo);
                intent.putExtra(GalleryActivity.KEY_PAGE, p.getPosition());
                startActivity(intent);
            }
        }
        return true;
    }

    private void onGetPreviewSetSuccess(Pair<PreviewSet, Integer> result, int taskId) {
        if (null != mHelper && mHelper.isCurrentTask(taskId) && null != mGalleryInfo) {
            PreviewSet previewSet = result.first;
            int size = previewSet.size();
            ArrayList<GalleryPreview> list = new ArrayList<>(size);
            for (int i = 0; i < size; i++) {
                list.add(previewSet.getGalleryPreview(mGalleryInfo.gid, i));
            }
            mHelper.onGetPageData(taskId, result.second, 0, list);
        }
    }

    private void onGetPreviewSetFailure(Exception e, int taskId) {
        if (mHelper != null && mHelper.isCurrentTask(taskId)) {
            mHelper.onGetException(taskId, e);
        }
    }

    private static clreplaced GetPreviewSetListener extends EhCallback<GalleryPreviewsScene, Pair<PreviewSet, Integer>> {

        private final int mTaskId;

        public GetPreviewSetListener(Context context, int stageId, String sceneTag, int taskId) {
            super(context, stageId, sceneTag);
            mTaskId = taskId;
        }

        @Override
        public void onSuccess(Pair<PreviewSet, Integer> result) {
            GalleryPreviewsScene scene = getScene();
            if (scene != null) {
                scene.onGetPreviewSetSuccess(result, mTaskId);
            }
        }

        @Override
        public void onFailure(Exception e) {
            GalleryPreviewsScene scene = getScene();
            if (scene != null) {
                scene.onGetPreviewSetFailure(e, mTaskId);
            }
        }

        @Override
        public void onCancel() {
        }

        @Override
        public boolean isInstance(SceneFragment scene) {
            return scene instanceof GalleryPreviewsScene;
        }
    }

    private static clreplaced GalleryPreviewHolder extends RecyclerView.ViewHolder {

        public LoadImageView image;

        public TextView text;

        public GalleryPreviewHolder(View itemView) {
            super(itemView);
            image = itemView.findViewById(R.id.image);
            text = itemView.findViewById(R.id.text);
        }
    }

    private clreplaced GalleryPreviewAdapter extends RecyclerView.Adapter<GalleryPreviewHolder> {

        private final LayoutInflater mInflater;

        public GalleryPreviewAdapter() {
            mInflater = getLayoutInflater();
            replacedertUtils.replacedertNotNull(mInflater);
        }

        @NonNull
        @Override
        public GalleryPreviewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            return new GalleryPreviewHolder(mInflater.inflate(R.layout.item_gallery_preview, parent, false));
        }

        @Override
        @SuppressLint("SetTextI18n")
        public void onBindViewHolder(@NonNull GalleryPreviewHolder holder, int position) {
            if (null != mHelper) {
                GalleryPreview preview = mHelper.getDataAtEx(position);
                if (preview != null) {
                    preview.load(holder.image);
                    holder.text.setText(Integer.toString(preview.getPosition() + 1));
                }
            }
            holder.itemView.setOnClickListener(v -> onItemClick(position));
        }

        @Override
        public int gereplacedemCount() {
            return mHelper != null ? mHelper.size() : 0;
        }
    }

    private clreplaced GalleryPreviewHelper extends ContentLayout.ContentHelper<GalleryPreview> {

        @Override
        protected void getPageData(final int taskId, int type, int page) {
            MainActivity activity = getMainActivity();
            if (null == activity || null == mClient || null == mGalleryInfo) {
                onGetException(taskId, new EhException(getString(R.string.error_cannot_find_gallery)));
                return;
            }
            String url = EhUrl.getGalleryDetailUrl(mGalleryInfo.gid, mGalleryInfo.token, page, false);
            EhRequest request = new EhRequest();
            request.setMethod(EhClient.METHOD_GET_PREVIEW_SET);
            request.setCallback(new GetPreviewSetListener(getContext(), activity.getStageId(), getTag(), taskId));
            request.setArgs(url);
            mClient.execute(request);
        }

        @Override
        protected Context getContext() {
            return GalleryPreviewsScene.this.getContext();
        }

        @Override
        protected void notifyDataSetChanged() {
            if (mAdapter != null) {
                mAdapter.notifyDataSetChanged();
            }
        }

        @Override
        protected void notifyItemRangeRemoved(int positionStart, int itemCount) {
            if (mAdapter != null) {
                mAdapter.notifyItemRangeRemoved(positionStart, itemCount);
            }
        }

        @Override
        protected void notifyItemRangeInserted(int positionStart, int itemCount) {
            if (mAdapter != null) {
                mAdapter.notifyItemRangeInserted(positionStart, itemCount);
            }
        }

        @Override
        protected boolean isDuplicate(GalleryPreview d1, GalleryPreview d2) {
            return false;
        }
    }

    private clreplaced GoToDialogHelper implements View.OnClickListener, DialogInterface.OnDismissListener {

        private final int mPages;

        private final int mCurrentPage;

        @Nullable
        private Slider mSlider;

        @Nullable
        private Dialog mDialog;

        private GoToDialogHelper(int pages, int currentPage) {
            mPages = pages;
            mCurrentPage = currentPage;
        }

        public void setDialog(@NonNull AlertDialog dialog) {
            mDialog = dialog;
            ((TextView) ViewUtils.$$(dialog, R.id.start)).setText(String.format(Locale.US, "%d", 1));
            ((TextView) ViewUtils.$$(dialog, R.id.end)).setText(String.format(Locale.US, "%d", mPages));
            mSlider = (Slider) ViewUtils.$$(dialog, R.id.slider);
            mSlider.setRange(1, mPages);
            mSlider.setProgress(mCurrentPage + 1);
            dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(this);
            dialog.setOnDismissListener(this);
        }

        @Override
        public void onClick(View v) {
            if (null == mSlider) {
                return;
            }
            int page = mSlider.getProgress() - 1;
            if (page >= 0 && page < mPages && mHelper != null) {
                mHelper.goTo(page);
                if (mDialog != null) {
                    mDialog.dismiss();
                    mDialog = null;
                }
            } else {
                showTip(R.string.error_out_of_range, LENGTH_LONG);
            }
        }

        @Override
        public void onDismiss(DialogInterface dialog) {
            mDialog = null;
            mSlider = null;
        }
    }

    @Override
    public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
        Insets insets1 = insets.getInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.ime());
        v.setPadding(insets1.left, 0, insets1.right, 0);
        View statusBarBackground = v.findViewById(R.id.status_bar_background);
        statusBarBackground.getLayoutParams().height = insets1.top;
        statusBarBackground.setBackgroundColor(AttrResources.getAttrColor(requireContext(), R.attr.colorPrimaryDark));
        if (mContentLayout != null) {
            mContentLayout.setFitPaddingBottom(insets1.bottom);
        }
        return WindowInsetsCompat.CONSUMED;
    }
}

16 Source : HistoryScene.java
with Apache License 2.0
from NuclearVGA

public clreplaced HistoryScene extends ToolbarScene {

    /*---------------
     View life cycle
     ---------------*/
    @Nullable
    private EasyRecyclerView mRecyclerView;

    @Nullable
    private ViewTransition mViewTransition;

    @Nullable
    private RecyclerView.Adapter<?> mAdapter;

    @Nullable
    private LazyList<HistoryInfo> mLazyList;

    private DownloadManager mDownloadManager;

    private DownloadManager.DownloadInfoListener mDownloadInfoListener;

    private FavouriteStatusRouter mFavouriteStatusRouter;

    private FavouriteStatusRouter.Listener mFavouriteStatusRouterListener;

    @Override
    public void onDestroy() {
        super.onDestroy();
        mDownloadManager.removeDownloadInfoListener(mDownloadInfoListener);
        mFavouriteStatusRouter.removeListener(mFavouriteStatusRouterListener);
    }

    @Override
    public int getNavCheckedItem() {
        return R.id.nav_history;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Context context = getContext2();
        replacedert context != null;
        mDownloadManager = EhApplication.getDownloadManager(context);
        mDownloadManager = EhApplication.getDownloadManager(context);
        mFavouriteStatusRouter = EhApplication.getFavouriteStatusRouter(context);
        mDownloadInfoListener = new DownloadManager.DownloadInfoListener() {

            @Override
            public void onAdd(@NonNull DownloadInfo info, @NonNull List<DownloadInfo> list, int position) {
                if (mAdapter != null) {
                    mAdapter.notifyDataSetChanged();
                }
            }

            @Override
            public void onUpdate(@NonNull DownloadInfo info, @NonNull List<DownloadInfo> list) {
            }

            @Override
            public void onUpdateAll() {
            }

            @Override
            public void onReload() {
                if (mAdapter != null) {
                    mAdapter.notifyDataSetChanged();
                }
            }

            @Override
            public void onChange() {
                if (mAdapter != null) {
                    mAdapter.notifyDataSetChanged();
                }
            }

            @Override
            public void onRenameLabel(String from, String to) {
            }

            @Override
            public void onRemove(@NonNull DownloadInfo info, @NonNull List<DownloadInfo> list, int position) {
                if (mAdapter != null) {
                    mAdapter.notifyDataSetChanged();
                }
            }

            @Override
            public void onUpdateLabels() {
            }
        };
        mDownloadManager.addDownloadInfoListener(mDownloadInfoListener);
        mFavouriteStatusRouterListener = (gid, slot) -> {
            if (mAdapter != null) {
                mAdapter.notifyDataSetChanged();
            }
        };
        mFavouriteStatusRouter.addListener(mFavouriteStatusRouterListener);
    }

    @Nullable
    @Override
    public View onCreateView3(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.scene_history, container, false);
        View content = ViewUtils.$$(view, R.id.content);
        mRecyclerView = (EasyRecyclerView) ViewUtils.$$(content, R.id.recycler_view);
        FastScroller fastScroller = (FastScroller) ViewUtils.$$(content, R.id.fast_scroller);
        TextView tip = (TextView) ViewUtils.$$(view, R.id.tip);
        mViewTransition = new ViewTransition(content, tip);
        Context context = getContext2();
        replacedertUtils.replacedertNotNull(context);
        Resources resources = context.getResources();
        Drawable drawable = DrawableManager.getVectorDrawable(context, R.drawable.big_history);
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        tip.setCompoundDrawables(null, drawable, null, null);
        RecyclerViewTouchActionGuardManager guardManager = new RecyclerViewTouchActionGuardManager();
        guardManager.setInterceptVerticalScrollingWhileAnimationRunning(true);
        guardManager.setEnabled(true);
        RecyclerViewSwipeManager swipeManager = new RecyclerViewSwipeManager();
        mAdapter = new HistoryAdapter();
        mAdapter.setHreplacedtableIds(true);
        mAdapter = swipeManager.createWrappedAdapter(mAdapter);
        mRecyclerView.setAdapter(mAdapter);
        final GeneralItemAnimator animator = new SwipeDismissItemAnimator();
        animator.setSupportsChangeAnimations(false);
        mRecyclerView.sereplacedemAnimator(animator);
        AutoStaggeredGridLayoutManager layoutManager = new AutoStaggeredGridLayoutManager(0, StaggeredGridLayoutManager.VERTICAL);
        layoutManager.setColumnSize(resources.getDimensionPixelOffset(Settings.getDetailSizeResId()));
        layoutManager.setStrategy(AutoStaggeredGridLayoutManager.STRATEGY_MIN_SIZE);
        mRecyclerView.setLayoutManager(layoutManager);
        // mRecyclerView.setSelector(Ripple.generateRippleDrawable(context, !AttrResources.getAttrBoolean(context, R.attr.isLightTheme), new ColorDrawable(Color.TRANSPARENT)));
        // mRecyclerView.setDrawSelectorOnTop(true);
        mRecyclerView.setClipToPadding(false);
        mRecyclerView.setClipChildren(false);
        // mRecyclerView.setOnItemClickListener(this);
        // mRecyclerView.setOnItemLongClickListener(this);
        int interval = resources.getDimensionPixelOffset(R.dimen.gallery_list_interval);
        int paddingH = resources.getDimensionPixelOffset(R.dimen.gallery_list_margin_h);
        int paddingV = resources.getDimensionPixelOffset(R.dimen.gallery_list_margin_v);
        MarginItemDecoration decoration = new MarginItemDecoration(interval, paddingH, paddingV, paddingH, paddingV);
        mRecyclerView.addItemDecoration(decoration);
        decoration.applyPaddings(mRecyclerView);
        guardManager.attachRecyclerView(mRecyclerView);
        swipeManager.attachRecyclerView(mRecyclerView);
        fastScroller.attachToRecyclerView(mRecyclerView);
        HandlerDrawable handlerDrawable = new HandlerDrawable();
        handlerDrawable.setColor(AttrResources.getAttrColor(context, R.attr.widgetColorThemeAccent));
        fastScroller.setHandlerDrawable(handlerDrawable);
        updateLazyList();
        updateView(false);
        return view;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        setreplacedle(R.string.history);
        setNavigationIcon(new DrawerArrowDrawable(getContext2(), Color.WHITE));
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (null != mLazyList) {
            mLazyList.close();
            mLazyList = null;
            if (mAdapter != null) {
                mAdapter.notifyDataSetChanged();
            }
        }
        if (null != mRecyclerView) {
            mRecyclerView.stopScroll();
            mRecyclerView = null;
        }
        mViewTransition = null;
        mAdapter = null;
    }

    // Remember to notify
    private void updateLazyList() {
        LazyList<HistoryInfo> lazyList = EhDB.getHistoryLazyList();
        if (mLazyList != null) {
            mLazyList.close();
        }
        mLazyList = lazyList;
    }

    private void updateView(boolean animation) {
        if (null == mAdapter || null == mViewTransition) {
            return;
        }
        if (mAdapter.gereplacedemCount() == 0) {
            mViewTransition.showView(1, animation);
        } else {
            mViewTransition.showView(0, animation);
        }
    }

    @Override
    public void onNavigationClick() {
        toggleDrawer(Gravity.LEFT);
    }

    @Override
    public int getMenuResId() {
        return R.menu.scene_history;
    }

    private void showClearAllDialog() {
        new MaterialAlertDialogBuilder(getContext2()).setMessage(R.string.clear_all_history).setPositiveButton(R.string.clear_all, (dialog, which) -> {
            if (DialogInterface.BUTTON_POSITIVE != which || null == mAdapter) {
                return;
            }
            EhDB.clearHistoryInfo();
            updateLazyList();
            mAdapter.notifyDataSetChanged();
            updateView(true);
        }).show();
    }

    @Override
    public boolean onMenuItemClick(MenuItem item) {
        // Skip when in choice mode
        Context context = getContext2();
        if (null == context) {
            return false;
        }
        int id = item.gereplacedemId();
        switch(id) {
            case R.id.action_clear_all:
                {
                    showClearAllDialog();
                    return true;
                }
        }
        return false;
    }

    public boolean onItemClick(View view, int position) {
        if (null == mLazyList) {
            return false;
        }
        Bundle args = new Bundle();
        args.putString(GalleryDetailScene.KEY_ACTION, GalleryDetailScene.ACTION_GALLERY_INFO);
        args.putParcelable(GalleryDetailScene.KEY_GALLERY_INFO, mLazyList.get(position));
        Announcer announcer = new Announcer(GalleryDetailScene.clreplaced).setArgs(args);
        View thumb;
        if (null != (thumb = view.findViewById(R.id.thumb))) {
            announcer.setTranHelper(new EnterGalleryDetailTransaction(thumb));
        }
        startScene(announcer);
        return true;
    }

    public boolean onItemLongClick(int position) {
        final Context context = getContext2();
        final MainActivity activity = getActivity2();
        if (null == context || null == activity || null == mLazyList) {
            return false;
        }
        final GalleryInfo gi = mLazyList.get(position);
        if (gi == null) {
            return true;
        }
        boolean downloaded = mDownloadManager.getDownloadState(gi.gid) != DownloadInfo.STATE_INVALID;
        boolean favourited = gi.favoriteSlot != -2;
        CharSequence[] items = downloaded ? new CharSequence[] { context.getString(R.string.read), context.getString(R.string.delete_downloads), context.getString(favourited ? R.string.remove_from_favourites : R.string.add_to_favourites), context.getString(R.string.delete), context.getString(R.string.download_move_dialog_replacedle) } : new CharSequence[] { context.getString(R.string.read), context.getString(R.string.download), context.getString(favourited ? R.string.remove_from_favourites : R.string.add_to_favourites), context.getString(R.string.delete) };
        int[] icons = downloaded ? new int[] { R.drawable.v_book_open_x24, R.drawable.v_delete_x24, favourited ? R.drawable.v_heart_broken_x24 : R.drawable.v_heart_x24, R.drawable.v_delete_x24, R.drawable.v_folder_move_x24 } : new int[] { R.drawable.v_book_open_x24, R.drawable.v_download_x24, favourited ? R.drawable.v_heart_broken_x24 : R.drawable.v_heart_x24, R.drawable.v_delete_x24 };
        new MaterialAlertDialogBuilder(context).setreplacedle(EhUtils.getSuitablereplacedle(gi)).setAdapter(new SelecreplacedemWithIconAdapter(context, items, icons), (dialog, which) -> {
            switch(which) {
                case // Read
                0:
                    Intent intent = new Intent(activity, GalleryActivity.clreplaced);
                    intent.setAction(GalleryActivity.ACTION_EH);
                    intent.putExtra(GalleryActivity.KEY_GALLERY_INFO, gi);
                    startActivity(intent);
                    break;
                case // Download
                1:
                    if (downloaded) {
                        new MaterialAlertDialogBuilder(context).setreplacedle(R.string.download_remove_dialog_replacedle).setMessage(getString(R.string.download_remove_dialog_message, gi.replacedle)).setPositiveButton(android.R.string.ok, (dialog1, which1) -> mDownloadManager.deleteDownload(gi.gid)).show();
                    } else {
                        CommonOperations.startDownload(activity, gi, false);
                    }
                    break;
                case // Favorites
                2:
                    if (favourited) {
                        CommonOperations.removeFromFavorites(activity, gi, new RemoveFromFavoriteListener(context, activity.getStageId(), getTag()));
                    } else {
                        CommonOperations.addToFavorites(activity, gi, new AddToFavoriteListener(context, activity.getStageId(), getTag()));
                    }
                    break;
                case // Delete
                3:
                    if (null == mLazyList || null == mAdapter) {
                        return;
                    }
                    HistoryInfo info = mLazyList.get(position);
                    EhDB.deleteHistoryInfo(info);
                    updateLazyList();
                    mAdapter.notifyDataSetChanged();
                    updateView(true);
                    break;
                case // Move
                4:
                    List<DownloadLabel> labelRawList = EhApplication.getDownloadManager(context).getLabelList();
                    List<String> labelList = new ArrayList<>(labelRawList.size() + 1);
                    labelList.add(getString(R.string.default_download_label_name));
                    for (int i = 0, n = labelRawList.size(); i < n; i++) {
                        labelList.add(labelRawList.get(i).getLabel());
                    }
                    String[] labels = labelList.toArray(new String[0]);
                    MoveDialogHelper helper = new MoveDialogHelper(labels, gi);
                    new MaterialAlertDialogBuilder(context).setreplacedle(R.string.download_move_dialog_replacedle).sereplacedems(labels, helper).show();
                    break;
            }
        }).show();
        return true;
    }

    private clreplaced MoveDialogHelper implements DialogInterface.OnClickListener {

        private final String[] mLabels;

        private final GalleryInfo mGi;

        public MoveDialogHelper(String[] labels, GalleryInfo gi) {
            mLabels = labels;
            mGi = gi;
        }

        @Override
        public void onClick(DialogInterface dialog, int which) {
            // Cancel check mode
            Context context = getContext2();
            if (null == context) {
                return;
            }
            if (null != mRecyclerView) {
                mRecyclerView.outOfCustomChoiceMode();
            }
            DownloadManager downloadManager = EhApplication.getDownloadManager(context);
            DownloadInfo downloadInfo = downloadManager.getDownloadInfo(mGi.gid);
            if (downloadInfo == null) {
                return;
            }
            String label = which == 0 ? null : mLabels[which];
            downloadManager.changeLabel(Collections.singletonList(downloadInfo), label);
        }
    }

    private static clreplaced AddToFavoriteListener extends EhCallback<GalleryListScene, Void> {

        public AddToFavoriteListener(Context context, int stageId, String sceneTag) {
            super(context, stageId, sceneTag);
        }

        @Override
        public void onSuccess(Void result) {
            showTip(R.string.add_to_favorite_success, LENGTH_SHORT);
        }

        @Override
        public void onFailure(Exception e) {
            showTip(R.string.add_to_favorite_failure, LENGTH_LONG);
        }

        @Override
        public void onCancel() {
        }

        @Override
        public boolean isInstance(SceneFragment scene) {
            return scene instanceof GalleryListScene;
        }
    }

    private static clreplaced RemoveFromFavoriteListener extends EhCallback<GalleryListScene, Void> {

        public RemoveFromFavoriteListener(Context context, int stageId, String sceneTag) {
            super(context, stageId, sceneTag);
        }

        @Override
        public void onSuccess(Void result) {
            showTip(R.string.remove_from_favorite_success, LENGTH_SHORT);
        }

        @Override
        public void onFailure(Exception e) {
            showTip(R.string.remove_from_favorite_failure, LENGTH_LONG);
        }

        @Override
        public void onCancel() {
        }

        @Override
        public boolean isInstance(SceneFragment scene) {
            return scene instanceof GalleryListScene;
        }
    }

    private static clreplaced HistoryHolder extends AbstractSwipeableItemViewHolder {

        public final View card;

        public final LoadImageView thumb;

        public final TextView replacedle;

        public final TextView uploader;

        public final SimpleRatingView rating;

        public final TextView category;

        public final TextView posted;

        public final TextView simpleLanguage;

        public HistoryHolder(View itemView) {
            super(itemView);
            card = itemView.findViewById(R.id.card);
            thumb = itemView.findViewById(R.id.thumb);
            replacedle = itemView.findViewById(R.id.replacedle);
            uploader = itemView.findViewById(R.id.uploader);
            rating = itemView.findViewById(R.id.rating);
            category = itemView.findViewById(R.id.category);
            posted = itemView.findViewById(R.id.posted);
            simpleLanguage = itemView.findViewById(R.id.simple_language);
        }

        @Override
        public View getSwipeableContainerView() {
            return card;
        }
    }

    private clreplaced HistoryAdapter extends RecyclerView.Adapter<HistoryHolder> implements SwipeableItemAdapter<HistoryHolder> {

        private final LayoutInflater mInflater;

        private final int mListThumbWidth;

        private final int mListThumbHeight;

        public HistoryAdapter() {
            mInflater = getLayoutInflater2();
            View calculator = mInflater.inflate(R.layout.item_gallery_list_thumb_height, null);
            ViewUtils.measureView(calculator, 1024, ViewGroup.LayoutParams.WRAP_CONTENT);
            mListThumbHeight = calculator.getMeasuredHeight();
            mListThumbWidth = mListThumbHeight * 2 / 3;
        }

        @Override
        public long gereplacedemId(int position) {
            if (null == mLazyList) {
                return super.gereplacedemId(position);
            } else {
                return mLazyList.get(position).gid;
            }
        }

        @Override
        public HistoryHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            HistoryHolder holder = new HistoryHolder(mInflater.inflate(R.layout.item_history, parent, false));
            ViewGroup.LayoutParams lp = holder.thumb.getLayoutParams();
            lp.width = mListThumbWidth;
            lp.height = mListThumbHeight;
            holder.thumb.setLayoutParams(lp);
            return holder;
        }

        @Override
        public void onBindViewHolder(HistoryHolder holder, int position) {
            if (null == mLazyList) {
                return;
            }
            GalleryInfo gi = mLazyList.get(position);
            holder.thumb.load(EhCacheKeyFactory.getThumbKey(gi.gid), gi.thumb);
            holder.replacedle.setText(EhUtils.getSuitablereplacedle(gi));
            holder.uploader.setText(gi.uploader);
            holder.rating.setRating(gi.rating);
            TextView category = holder.category;
            String newCategoryText = EhUtils.getCategory(gi.category);
            if (!newCategoryText.equals(category.getText())) {
                category.setText(newCategoryText);
                category.setBackgroundColor(EhUtils.getCategoryColor(gi.category));
            }
            holder.posted.setText(gi.posted);
            holder.simpleLanguage.setText(gi.simpleLanguage);
            // Update transition name
            long gid = gi.gid;
            ViewCompat.setTransitionName(holder.thumb, TransitionNameFactory.getThumbTransitionName(gid));
            holder.card.setOnClickListener(v -> onItemClick(holder.itemView, position));
            holder.card.setOnLongClickListener(v -> onItemLongClick(position));
        }

        @Override
        public int gereplacedemCount() {
            return null != mLazyList ? mLazyList.size() : 0;
        }

        @Override
        public int onGetSwipeReactionType(HistoryHolder holder, int position, int x, int y) {
            return SwipeableItemConstants.REACTION_CAN_SWIPE_LEFT;
        }

        @Override
        public void onSwipeItemStarted(HistoryHolder holder, int position) {
        }

        @Override
        public void onSetSwipeBackground(HistoryHolder holder, int position, int type) {
        }

        @Override
        public SwipeResultAction onSwipeItem(HistoryHolder holder, int position, int result) {
            switch(result) {
                case SwipeableItemConstants.RESULT_SWIPED_LEFT:
                    return new SwipeResultActionClear(position);
                case SwipeableItemConstants.RESULT_SWIPED_RIGHT:
                case SwipeableItemConstants.RESULT_CANCELED:
                default:
                    return new SwipeResultActionDefault();
            }
        }
    }

    private clreplaced SwipeResultActionClear extends SwipeResultActionRemoveItem {

        private final int mPosition;

        protected SwipeResultActionClear(int position) {
            mPosition = position;
        }

        @Override
        protected void onPerformAction() {
            super.onPerformAction();
            if (null == mLazyList || null == mAdapter) {
                return;
            }
            HistoryInfo info = mLazyList.get(mPosition);
            EhDB.deleteHistoryInfo(info);
            updateLazyList();
            mAdapter.notifyDataSetChanged();
            updateView(true);
        }
    }
}

16 Source : FavoritesScene.java
with Apache License 2.0
from NuclearVGA

// TODO Get favorite, modify favorite, add favorite, what a mess!
public clreplaced FavoritesScene extends BaseScene implements FastScroller.OnDragHandlerListener, SearchBarMover.Helper, SearchBar.Helper, FabLayout.OnClickFabListener, FabLayout.OnExpandListener, EasyRecyclerView.CustomChoiceListener {

    private static final long ANIMATE_TIME = 300L;

    private static final String KEY_URL_BUILDER = "url_builder";

    private static final String KEY_SEARCH_MODE = "search_mode";

    private static final String KEY_HAS_FIRST_REFRESH = "has_first_refresh";

    private static final String KEY_FAV_COUNT_ARRAY = "fav_count_array";

    // For modify action
    private final List<GalleryInfo> mModifyGiList = new ArrayList<>();

    // -1 for error
    public int current;

    // -1 for error
    public int limit;

    @Nullable
    @ViewLifeCircle
    private EasyRecyclerView mRecyclerView;

    @Nullable
    @ViewLifeCircle
    private SearchBar mSearchBar;

    @Nullable
    @ViewLifeCircle
    private FabLayout mFabLayout;

    @Nullable
    @ViewLifeCircle
    private FavoritesAdapter mAdapter;

    @Nullable
    @ViewLifeCircle
    private FavoritesHelper mHelper;

    @Nullable
    @ViewLifeCircle
    private SearchBarMover mSearchBarMover;

    @Nullable
    @ViewLifeCircle
    private DrawerArrowDrawable mLeftDrawable;

    private AddDeleteDrawable mActionFabDrawable;

    @Nullable
    private EhDrawerLayout mDrawerLayout;

    @Nullable
    @DrawerLifeCircle
    private FavDrawerAdapter mDrawerAdapter;

    @Nullable
    @WholeLifeCircle
    private EhClient mClient;

    @Nullable
    @WholeLifeCircle
    private String[] mFavCatArray;

    @Nullable
    @WholeLifeCircle
    private int[] mFavCountArray;

    @Nullable
    @WholeLifeCircle
    private FavListUrlBuilder mUrlBuilder;

    private int mFavLocalCount = 0;

    private int mFavCountSum = 0;

    private boolean mHasFirstRefresh;

    private boolean mSearchMode;

    // Avoid unnecessary search bar update
    private String mOldFavCat;

    // Avoid unnecessary search bar update
    private String mOldKeyword;

    // For modify action
    private boolean mEnableModify;

    // For modify action
    private int mModifyFavCat;

    // For modify action
    private boolean mModifyAdd;

    private final Runnable showNormalFabsRunnable = new Runnable() {

        @Override
        public void run() {
            if (mFabLayout != null) {
                mFabLayout.setSecondaryFabVisibilityAt(0, true);
                mFabLayout.setSecondaryFabVisibilityAt(1, true);
                mFabLayout.setSecondaryFabVisibilityAt(2, false);
                mFabLayout.setSecondaryFabVisibilityAt(3, false);
                mFabLayout.setSecondaryFabVisibilityAt(4, false);
            }
        }
    };

    @Override
    public int getNavCheckedItem() {
        return R.id.nav_favourite;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Context context = getContext2();
        replacedertUtils.replacedertNotNull(context);
        mClient = EhApplication.getEhClient(context);
        mFavCatArray = Settings.getFavCat();
        mFavCountArray = Settings.getFavCount();
        mFavLocalCount = Settings.getFavLocalCount();
        mFavCountSum = Settings.getFavCloudCount();
        if (savedInstanceState == null) {
            onInit();
        } else {
            onRestore(savedInstanceState);
        }
    }

    private void onInit() {
        mUrlBuilder = new FavListUrlBuilder();
        mUrlBuilder.setFavCat(Settings.getRecentFavCat());
        mSearchMode = false;
    }

    private void onRestore(Bundle savedInstanceState) {
        mUrlBuilder = savedInstanceState.getParcelable(KEY_URL_BUILDER);
        if (mUrlBuilder == null) {
            mUrlBuilder = new FavListUrlBuilder();
        }
        mSearchMode = savedInstanceState.getBoolean(KEY_SEARCH_MODE);
        mHasFirstRefresh = savedInstanceState.getBoolean(KEY_HAS_FIRST_REFRESH);
        mFavCountArray = savedInstanceState.getIntArray(KEY_FAV_COUNT_ARRAY);
    }

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        boolean hasFirstRefresh;
        if (mHelper != null && 1 == mHelper.getShownViewIndex()) {
            hasFirstRefresh = false;
        } else {
            hasFirstRefresh = mHasFirstRefresh;
        }
        outState.putBoolean(KEY_HAS_FIRST_REFRESH, hasFirstRefresh);
        outState.putParcelable(KEY_URL_BUILDER, mUrlBuilder);
        outState.putBoolean(KEY_SEARCH_MODE, mSearchMode);
        outState.putIntArray(KEY_FAV_COUNT_ARRAY, mFavCountArray);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mClient = null;
        mFavCatArray = null;
        mFavCountArray = null;
        mFavCountSum = 0;
        mUrlBuilder = null;
    }

    @Nullable
    @Override
    public View onCreateView2(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.scene_favorites, container, false);
        ContentLayout contentLayout = view.findViewById(R.id.content_layout);
        MainActivity activity = getActivity2();
        replacedertUtils.replacedertNotNull(activity);
        mDrawerLayout = (EhDrawerLayout) ViewUtils.$$(activity, R.id.draw_view);
        mRecyclerView = contentLayout.getRecyclerView();
        FastScroller fastScroller = contentLayout.getFastScroller();
        RefreshLayout refreshLayout = contentLayout.getRefreshLayout();
        mSearchBar = (SearchBar) ViewUtils.$$(view, R.id.search_bar);
        mFabLayout = (FabLayout) ViewUtils.$$(view, R.id.fab_layout);
        Context context = getContext2();
        replacedertUtils.replacedertNotNull(context);
        Resources resources = context.getResources();
        int paddingTopSB = resources.getDimensionPixelOffset(R.dimen.gallery_padding_top_search_bar);
        mHelper = new FavoritesHelper();
        mHelper.setEmptyString(resources.getString(R.string.gallery_list_empty_hit));
        contentLayout.setHelper(mHelper);
        contentLayout.getFastScroller().setOnDragHandlerListener(this);
        contentLayout.setFitPaddingTop(paddingTopSB);
        mAdapter = new FavoritesAdapter(inflater, resources, mRecyclerView, Settings.getListMode());
        // mRecyclerView.setSelector(Ripple.generateRippleDrawable(context, !AttrResources.getAttrBoolean(context, R.attr.isLightTheme), new ColorDrawable(Color.TRANSPARENT)));
        // mRecyclerView.setDrawSelectorOnTop(true);
        mRecyclerView.setClipToPadding(false);
        mRecyclerView.setClipChildren(false);
        // mRecyclerView.setOnItemClickListener(this);
        // mRecyclerView.setOnItemLongClickListener(this);
        mRecyclerView.setChoiceMode(EasyRecyclerView.CHOICE_MODE_MULTIPLE_CUSTOM);
        mRecyclerView.setCustomCheckedListener(this);
        fastScroller.setPadding(fastScroller.getPaddingLeft(), fastScroller.getPaddingTop() + paddingTopSB, fastScroller.getPaddingRight(), fastScroller.getPaddingBottom());
        mLeftDrawable = new DrawerArrowDrawable(context, AttrResources.getAttrColor(context, R.attr.drawableColorPrimary));
        mSearchBar.setLeftDrawable(mLeftDrawable);
        mSearchBar.setRightDrawable(DrawableManager.getVectorDrawable(context, R.drawable.v_magnify_x24));
        mSearchBar.setHelper(this);
        mSearchBar.setAllowEmptySearch(false);
        updateSearchBar();
        mSearchBarMover = new SearchBarMover(this, mSearchBar, mRecyclerView);
        mActionFabDrawable = new AddDeleteDrawable(context, resources.getColor(R.color.primary_drawable_dark));
        mFabLayout.getPrimaryFab().setImageDrawable(mActionFabDrawable);
        mFabLayout.setExpanded(false, false);
        mFabLayout.setAutoCancel(true);
        mFabLayout.setHidePrimaryFab(false);
        mFabLayout.setOnClickFabListener(this);
        mFabLayout.setOnExpandListener(this);
        addAboveSnackView(mFabLayout);
        // Restore search mode
        if (mSearchMode) {
            mSearchMode = false;
            enterSearchMode(false);
        }
        // Only refresh for the first time
        if (!mHasFirstRefresh) {
            mHasFirstRefresh = true;
            mHelper.firstRefresh();
        }
        guideCollections();
        return view;
    }

    private void guideCollections() {
        Activity activity = getActivity2();
        if (null == activity || !Settings.getGuideCollections()) {
            return;
        }
        Display display = activity.getWindowManager().getDefaultDisplay();
        Point point = new Point();
        display.getSize(point);
        Rect bounds = new Rect(point.x + LayoutUtils.dp2pix(requireContext(), 20), point.y / 3 + LayoutUtils.dp2pix(requireContext(), 20), point.x - LayoutUtils.dp2pix(requireContext(), 20), point.y / 3 - LayoutUtils.dp2pix(requireContext(), 20));
        TapTargetView.showFor(requireActivity(), TapTarget.forBounds(bounds, getString(R.string.guide_collections_replacedle), getString(R.string.guide_collections_text)).transparentTarget(true), new TapTargetView.Listener() {

            @Override
            public void onTargetDismissed(TapTargetView view, boolean userInitiated) {
                super.onTargetClick(view);
                Settings.putGuideCollections(false);
                openDrawer(Gravity.RIGHT);
            }
        });
    }

    // keyword of mUrlBuilder, fav cat of mUrlBuilder, mFavCatArray.
    // They changed, call it
    private void updateSearchBar() {
        Context context = getContext2();
        if (null == context || null == mUrlBuilder || null == mSearchBar || null == mFavCatArray) {
            return;
        }
        // Update replacedle
        int favCat = mUrlBuilder.getFavCat();
        String favCatName;
        if (favCat >= 0 && favCat < 10) {
            favCatName = mFavCatArray[favCat];
        } else if (favCat == FavListUrlBuilder.FAV_CAT_LOCAL) {
            favCatName = getString(R.string.local_favorites);
        } else {
            favCatName = getString(R.string.cloud_favorites);
        }
        String keyword = mUrlBuilder.getKeyword();
        if (TextUtils.isEmpty(keyword)) {
            if (!ObjectUtils.equal(favCatName, mOldFavCat)) {
                mSearchBar.setreplacedle(getString(R.string.favorites_replacedle, favCatName));
            }
        } else {
            if (!ObjectUtils.equal(favCatName, mOldFavCat) || !ObjectUtils.equal(keyword, mOldKeyword)) {
                mSearchBar.setreplacedle(getString(R.string.favorites_replacedle_2, favCatName, keyword));
            }
        }
        // Update hint
        if (!ObjectUtils.equal(favCatName, mOldFavCat)) {
            mSearchBar.setEditTextHint(getString(R.string.favorites_search_bar_hint, favCatName));
        }
        mOldFavCat = favCatName;
        mOldKeyword = keyword;
        // Save recent fav cat
        Settings.putRecentFavCat(mUrlBuilder.getFavCat());
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (null != mHelper) {
            mHelper.destroy();
            if (1 == mHelper.getShownViewIndex()) {
                mHasFirstRefresh = false;
            }
        }
        if (null != mRecyclerView) {
            mRecyclerView.stopScroll();
            mRecyclerView = null;
        }
        if (null != mFabLayout) {
            removeAboveSnackView(mFabLayout);
            mFabLayout = null;
        }
        mAdapter = null;
        mSearchBar = null;
        mSearchBarMover = null;
        mLeftDrawable = null;
        mOldFavCat = null;
        mOldKeyword = null;
    }

    @Override
    public View onCreateDrawerView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.drawer_list_rv, container, false);
        final Context context = getContext2();
        Toolbar toolbar = (Toolbar) ViewUtils.$$(view, R.id.toolbar);
        replacedertUtils.replacedertNotNull(context);
        toolbar.setreplacedle(R.string.collections);
        toolbar.inflateMenu(R.menu.drawer_favorites);
        toolbar.setOnMenuItemClickListener(item -> {
            int id = item.gereplacedemId();
            if (id == R.id.action_default_favorites_slot) {
                String[] items = new String[12];
                items[0] = getString(R.string.let_me_select);
                items[1] = getString(R.string.local_favorites);
                String[] favCat = Settings.getFavCat();
                System.arraycopy(favCat, 0, items, 2, 10);
                new MaterialAlertDialogBuilder(context).setreplacedle(R.string.default_favorites_collection).sereplacedems(items, (dialog, which) -> Settings.putDefaultFavSlot(which - 2)).show();
                return true;
            }
            return false;
        });
        EasyRecyclerView recyclerView = view.findViewById(R.id.recycler_view_drawer);
        recyclerView.setLayoutManager(new LinearLayoutManager(context));
        LinearDividerItemDecoration decoration = new LinearDividerItemDecoration(LinearDividerItemDecoration.VERTICAL, AttrResources.getAttrColor(context, R.attr.dividerColor), LayoutUtils.dp2pix(context, 1));
        decoration.setShowLastDivider(true);
        recyclerView.addItemDecoration(decoration);
        mDrawerAdapter = new FavDrawerAdapter(inflater);
        recyclerView.setAdapter(mDrawerAdapter);
        return view;
    }

    @Override
    public void onDestroyDrawerView() {
        super.onDestroyDrawerView();
        mDrawerAdapter = null;
    }

    @Override
    public void onBackPressed() {
        if (mRecyclerView != null && mRecyclerView.isInCustomChoice()) {
            mRecyclerView.outOfCustomChoiceMode();
        } else if (mFabLayout != null && mFabLayout.isExpanded()) {
            mFabLayout.toggle();
        } else if (mSearchMode) {
            exitSearchMode(true);
        } else {
            finish();
        }
    }

    @Override
    @Implemented(FastScroller.OnDragHandlerListener.clreplaced)
    public void onStartDragHandler() {
        // Lock right drawer
        setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, Gravity.RIGHT);
    }

    @Override
    @Implemented(FastScroller.OnDragHandlerListener.clreplaced)
    public void onEndDragHandler() {
        // Restore right drawer
        if (null != mRecyclerView && !mRecyclerView.isInCustomChoice()) {
            setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, Gravity.RIGHT);
        }
        if (mSearchBarMover != null) {
            mSearchBarMover.returnSearchBarPosition();
        }
    }

    public boolean onItemClick(View view, int position) {
        if (mDrawerLayout != null && mDrawerLayout.isDrawerOpen(Gravity.RIGHT)) {
            // Skip if in search mode
            if (mRecyclerView != null && mRecyclerView.isInCustomChoice()) {
                return true;
            }
            if (mUrlBuilder == null || mHelper == null) {
                return true;
            }
            // Local favorite position is 0, All favorite position is 1, so position - 2 is OK
            int newFavCat = position - 2;
            // Check is the same
            if (mUrlBuilder.getFavCat() == newFavCat) {
                return true;
            }
            // Ensure outOfCustomChoiceMode to avoid error
            if (mRecyclerView != null) {
                mRecyclerView.isInCustomChoice();
            }
            exitSearchMode(true);
            mUrlBuilder.setKeyword(null);
            mUrlBuilder.setFavCat(newFavCat);
            updateSearchBar();
            mHelper.refresh();
            closeDrawer(Gravity.RIGHT);
        } else {
            if (mRecyclerView != null && mRecyclerView.isInCustomChoice()) {
                mRecyclerView.toggleItemChecked(position);
            } else if (mHelper != null) {
                GalleryInfo gi = mHelper.getDataAtEx(position);
                if (gi == null) {
                    return true;
                }
                Bundle args = new Bundle();
                args.putString(GalleryDetailScene.KEY_ACTION, GalleryDetailScene.ACTION_GALLERY_INFO);
                args.putParcelable(GalleryDetailScene.KEY_GALLERY_INFO, gi);
                Announcer announcer = new Announcer(GalleryDetailScene.clreplaced).setArgs(args);
                View thumb;
                if (null != (thumb = view.findViewById(R.id.thumb))) {
                    announcer.setTranHelper(new EnterGalleryDetailTransaction(thumb));
                }
                startScene(announcer);
            }
        }
        return true;
    }

    public boolean onItemLongClick(View view, int position) {
        // Can not into
        if (mRecyclerView != null && !mSearchMode) {
            if (!mRecyclerView.isInCustomChoice()) {
                mRecyclerView.intoCustomChoiceMode();
            }
            mRecyclerView.toggleItemChecked(position);
        }
        return true;
    }

    @Override
    @Implemented(SearchBarMover.Helper.clreplaced)
    public boolean isValidView(RecyclerView recyclerView) {
        return recyclerView == mRecyclerView;
    }

    @Override
    @Implemented(SearchBarMover.Helper.clreplaced)
    public RecyclerView getValidRecyclerView() {
        return mRecyclerView;
    }

    @Override
    @Implemented(SearchBarMover.Helper.clreplaced)
    public boolean forceShowSearchBar() {
        return false;
    }

    @Override
    @Implemented(SearchBar.Helper.clreplaced)
    public void onClickreplacedle() {
        // Skip if in search mode
        if (mRecyclerView != null && mRecyclerView.isInCustomChoice()) {
            return;
        }
        if (!mSearchMode) {
            enterSearchMode(true);
        }
    }

    @Override
    @Implemented(SearchBar.Helper.clreplaced)
    public void onClickLeftIcon() {
        // Skip if in search mode
        if (mRecyclerView != null && mRecyclerView.isInCustomChoice()) {
            return;
        }
        if (mSearchMode) {
            exitSearchMode(true);
        } else {
            toggleDrawer(Gravity.LEFT);
        }
    }

    @Override
    @Implemented(SearchBar.Helper.clreplaced)
    public void onClickRightIcon() {
        // Skip if in search mode
        if (mRecyclerView != null && mRecyclerView.isInCustomChoice()) {
            return;
        }
        if (!mSearchMode) {
            enterSearchMode(true);
        } else if (mSearchBar != null) {
            if (mSearchBar.getEditText().length() == 0) {
                exitSearchMode(true);
            } else {
                mSearchBar.applySearch();
            }
        }
    }

    @Override
    @Implemented(SearchBar.Helper.clreplaced)
    public void onSearchEditTextClick() {
    }

    @Override
    @Implemented(SearchBar.Helper.clreplaced)
    public void onApplySearch(String query) {
        // Skip if in search mode
        if (mRecyclerView != null && mRecyclerView.isInCustomChoice()) {
            return;
        }
        if (mUrlBuilder == null || mHelper == null) {
            return;
        }
        // Ensure outOfCustomChoiceMode to avoid error
        if (mRecyclerView != null) {
            mRecyclerView.isInCustomChoice();
        }
        exitSearchMode(true);
        mUrlBuilder.setKeyword(query);
        updateSearchBar();
        mHelper.refresh();
    }

    @Override
    @Implemented(SearchBar.Helper.clreplaced)
    public void onSearchEditTextBackPressed() {
        onBackPressed();
    }

    @Override
    public void onExpand(boolean expanded) {
        if (expanded) {
            mActionFabDrawable.setDelete(ANIMATE_TIME);
        } else {
            mActionFabDrawable.setAdd(ANIMATE_TIME);
        }
    }

    @Override
    @Implemented(FabLayout.OnClickFabListener.clreplaced)
    public void onClickPrimaryFab(FabLayout view, FloatingActionButton fab) {
        if (mRecyclerView != null && mFabLayout != null) {
            if (mRecyclerView.isInCustomChoice()) {
                mRecyclerView.outOfCustomChoiceMode();
            } else {
                mFabLayout.toggle();
            }
        }
    }

    private void showGoToDialog() {
        Context context = getContext2();
        if (null == context || null == mHelper) {
            return;
        }
        final int page = mHelper.getPageForTop();
        final int pages = mHelper.getPages();
        String hint = getString(R.string.go_to_hint, page + 1, pages);
        final EditTextDialogBuilder builder = new EditTextDialogBuilder(context, null, hint);
        builder.getEditText().setInputType(InputType.TYPE_CLreplaced_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
        final AlertDialog dialog = builder.setreplacedle(R.string.go_to).setPositiveButton(android.R.string.ok, null).show();
        dialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> {
            if (null == mHelper) {
                dialog.dismiss();
                return;
            }
            String text = builder.getText().trim();
            int goTo;
            try {
                goTo = Integer.parseInt(text) - 1;
            } catch (NumberFormatException e) {
                builder.setError(getString(R.string.error_invalid_number));
                return;
            }
            if (goTo < 0 || goTo >= pages) {
                builder.setError(getString(R.string.error_out_of_range));
                return;
            }
            builder.setError(null);
            mHelper.goTo(goTo);
            AppHelper.hideSoftInput(dialog);
            dialog.dismiss();
        });
    }

    @Override
    @Implemented(FabLayout.OnClickFabListener.clreplaced)
    public void onClickSecondaryFab(FabLayout view, FloatingActionButton fab, int position) {
        Context context = getContext2();
        if (null == context || null == mRecyclerView || null == mHelper) {
            return;
        }
        if (!mRecyclerView.isInCustomChoice()) {
            switch(position) {
                case // Open right
                0:
                    openDrawer(Gravity.RIGHT);
                    break;
                case // Go to
                1:
                    if (mHelper.canGoTo()) {
                        showGoToDialog();
                    }
                    break;
                case // Refresh
                2:
                    mHelper.refresh();
                    break;
            }
            view.setExpanded(false);
            return;
        }
        mModifyGiList.clear();
        SparseBooleanArray stateArray = mRecyclerView.getCheckedItemPositions();
        for (int i = 0, n = stateArray.size(); i < n; i++) {
            if (stateArray.valueAt(i)) {
                GalleryInfo gi = mHelper.getDataAtEx(stateArray.keyAt(i));
                if (gi != null) {
                    mModifyGiList.add(gi);
                }
            }
        }
        switch(position) {
            case 3:
                {
                    // Download
                    Activity activity = getActivity2();
                    if (activity != null) {
                        CommonOperations.startDownload(getActivity2(), mModifyGiList, false);
                    }
                    mModifyGiList.clear();
                    if (mRecyclerView != null && mRecyclerView.isInCustomChoice()) {
                        mRecyclerView.outOfCustomChoiceMode();
                    }
                    break;
                }
            case 4:
                {
                    // Delete
                    DeleteDialogHelper helper = new DeleteDialogHelper();
                    new MaterialAlertDialogBuilder(context).setreplacedle(R.string.delete_favorites_dialog_replacedle).setMessage(getString(R.string.delete_favorites_dialog_message, mModifyGiList.size())).setPositiveButton(android.R.string.ok, helper).setOnCancelListener(helper).show();
                    break;
                }
            case 5:
                {
                    // Move
                    MoveDialogHelper helper = new MoveDialogHelper();
                    // First is local favorite, the other 10 is cloud favorite
                    String[] array = new String[11];
                    array[0] = getString(R.string.local_favorites);
                    System.arraycopy(Settings.getFavCat(), 0, array, 1, 10);
                    new MaterialAlertDialogBuilder(context).setreplacedle(R.string.move_favorites_dialog_replacedle).sereplacedems(array, helper).setOnCancelListener(helper).show();
                    break;
                }
        }
    }

    private void showNormalFabs() {
        // Delay showing normal fabs to avoid mutation
        SimpleHandler.getInstance().removeCallbacks(showNormalFabsRunnable);
        SimpleHandler.getInstance().postDelayed(showNormalFabsRunnable, 300);
    }

    private void showSelectionFabs() {
        SimpleHandler.getInstance().removeCallbacks(showNormalFabsRunnable);
        if (mFabLayout != null) {
            mFabLayout.setSecondaryFabVisibilityAt(0, false);
            mFabLayout.setSecondaryFabVisibilityAt(1, false);
            mFabLayout.setSecondaryFabVisibilityAt(2, true);
            mFabLayout.setSecondaryFabVisibilityAt(3, true);
            mFabLayout.setSecondaryFabVisibilityAt(4, true);
        }
    }

    @Override
    @Implemented(EasyRecyclerView.CustomChoiceListener.clreplaced)
    public void onIntoCustomChoice(EasyRecyclerView view) {
        if (mFabLayout != null) {
            showSelectionFabs();
            mFabLayout.setAutoCancel(false);
            // Delay expanding action to make layout work fine
            SimpleHandler.getInstance().post(() -> mFabLayout.setExpanded(true));
        }
        if (mHelper != null) {
            mHelper.setRefreshLayoutEnable(false);
        }
        // Lock drawer
        setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, Gravity.LEFT);
        setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, Gravity.RIGHT);
    }

    @Override
    @Implemented(EasyRecyclerView.CustomChoiceListener.clreplaced)
    public void onOutOfCustomChoice(EasyRecyclerView view) {
        if (mFabLayout != null) {
            showNormalFabs();
            mFabLayout.setAutoCancel(true);
            mFabLayout.setExpanded(false);
        }
        if (mHelper != null) {
            mHelper.setRefreshLayoutEnable(true);
        }
        // Unlock drawer
        setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, Gravity.LEFT);
        setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, Gravity.RIGHT);
    }

    @Override
    @Implemented(EasyRecyclerView.CustomChoiceListener.clreplaced)
    public void onItemCheckedStateChanged(EasyRecyclerView view, int position, long id, boolean checked) {
        if (view.getCheckedItemCount() == 0) {
            view.outOfCustomChoiceMode();
        }
    }

    private void enterSearchMode(boolean animation) {
        if (mSearchMode || mSearchBar == null || mSearchBarMover == null || mLeftDrawable == null) {
            return;
        }
        mSearchMode = true;
        mSearchBar.setState(SearchBar.STATE_SEARCH_LIST, animation);
        mSearchBarMover.returnSearchBarPosition(animation);
        mLeftDrawable.setArrow(ANIMATE_TIME);
    }

    private void exitSearchMode(boolean animation) {
        if (!mSearchMode || mSearchBar == null || mSearchBarMover == null || mLeftDrawable == null) {
            return;
        }
        mSearchMode = false;
        mSearchBar.setState(SearchBar.STATE_NORMAL, animation);
        mSearchBarMover.returnSearchBarPosition();
        mLeftDrawable.setMenu(ANIMATE_TIME);
    }

    private void onGetFavoritesSuccess(FavoritesParser.Result result, int taskId) {
        if (mHelper != null && mSearchBarMover != null && mHelper.isCurrentTask(taskId)) {
            if (mFavCatArray != null) {
                System.arraycopy(result.catArray, 0, mFavCatArray, 0, 10);
            }
            mFavCountArray = result.countArray;
            if (mFavCountArray != null) {
                mFavCountSum = 0;
                for (int i = 0; i < 10; i++) {
                    mFavCountSum = mFavCountSum + mFavCountArray[i];
                }
                Settings.putFavCloudCount(mFavCountSum);
            }
            updateSearchBar();
            mHelper.onGetPageData(taskId, result.pages, result.nextPage, result.galleryInfoList);
            if (mDrawerAdapter != null) {
                mDrawerAdapter.notifyDataSetChanged();
            }
        }
    }

    private void onGetFavoritesFailure(Exception e, int taskId) {
        if (mHelper != null && mSearchBarMover != null && mHelper.isCurrentTask(taskId)) {
            mHelper.onGetException(taskId, e);
        }
    }

    @SuppressWarnings("unchecked")
    private void onGetFavoritesLocal(String keyword, int taskId) {
        if (mHelper != null && mHelper.isCurrentTask(taskId)) {
            List<GalleryInfo> list;
            if (TextUtils.isEmpty(keyword)) {
                list = EhDB.getAllLocalFavorites();
            } else {
                list = EhDB.searchLocalFavorites(keyword);
            }
            if (list.size() == 0) {
                mHelper.onGetPageData(taskId, 0, 0, Collections.EMPTY_LIST);
            } else {
                mHelper.onGetPageData(taskId, 1, 0, list);
            }
            if (TextUtils.isEmpty(keyword)) {
                mFavLocalCount = list.size();
                Settings.putFavLocalCount(mFavLocalCount);
                if (mDrawerAdapter != null) {
                    mDrawerAdapter.notifyDataSetChanged();
                }
            }
        }
    }

    private static clreplaced AddFavoritesListener extends EhCallback<FavoritesScene, Void> {

        private final int mTaskId;

        private final String mKeyword;

        private final List<GalleryInfo> mBackup;

        private AddFavoritesListener(Context context, int stageId, String sceneTag, int taskId, String keyword, List<GalleryInfo> backup) {
            super(context, stageId, sceneTag);
            mTaskId = taskId;
            mKeyword = keyword;
            mBackup = backup;
        }

        @Override
        public void onSuccess(Void result) {
            FavoritesScene scene = getScene();
            if (scene != null) {
                scene.onGetFavoritesLocal(mKeyword, mTaskId);
            }
        }

        @Override
        public void onFailure(Exception e) {
            // TODO It's a failure, add all of backup back to db.
            // But how to known which one is failed?
            EhDB.putLocalFavorites(mBackup);
            FavoritesScene scene = getScene();
            if (scene != null) {
                scene.onGetFavoritesLocal(mKeyword, mTaskId);
            }
        }

        @Override
        public void onCancel() {
        }

        @Override
        public boolean isInstance(SceneFragment scene) {
            return scene instanceof FavoritesScene;
        }
    }

    private static clreplaced GetFavoritesListener extends EhCallback<FavoritesScene, FavoritesParser.Result> {

        private final int mTaskId;

        // Local fav is shown now, but operation need be done for cloud fav
        private final boolean mLocal;

        private final String mKeyword;

        private GetFavoritesListener(Context context, int stageId, String sceneTag, int taskId, boolean local, String keyword) {
            super(context, stageId, sceneTag);
            mTaskId = taskId;
            mLocal = local;
            mKeyword = keyword;
        }

        @Override
        public void onSuccess(FavoritesParser.Result result) {
            // Put fav cat
            Settings.putFavCat(result.catArray);
            Settings.putFavCount(result.countArray);
            FavoritesScene scene = getScene();
            if (scene != null) {
                if (mLocal) {
                    scene.onGetFavoritesLocal(mKeyword, mTaskId);
                } else {
                    scene.onGetFavoritesSuccess(result, mTaskId);
                }
            }
        }

        @Override
        public void onFailure(Exception e) {
            FavoritesScene scene = getScene();
            if (scene != null) {
                if (mLocal) {
                    e.printStackTrace();
                    scene.onGetFavoritesLocal(mKeyword, mTaskId);
                } else {
                    scene.onGetFavoritesFailure(e, mTaskId);
                }
            }
        }

        @Override
        public void onCancel() {
        }

        @Override
        public boolean isInstance(SceneFragment scene) {
            return scene instanceof FavoritesScene;
        }
    }

    private clreplaced FavDrawerHolder extends RecyclerView.ViewHolder {

        private final TextView key;

        private final TextView value;

        private FavDrawerHolder(View itemView) {
            super(itemView);
            key = (TextView) ViewUtils.$$(itemView, R.id.key);
            value = (TextView) ViewUtils.$$(itemView, R.id.value);
        }
    }

    private clreplaced FavDrawerAdapter extends RecyclerView.Adapter<FavDrawerHolder> {

        private final LayoutInflater mInflater;

        private FavDrawerAdapter(LayoutInflater inflater) {
            mInflater = inflater;
        }

        @Override
        public int gereplacedemViewType(int position) {
            return position;
        }

        @NonNull
        @Override
        public FavDrawerHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            return new FavDrawerHolder(mInflater.inflate(R.layout.item_drawer_favorites, parent, false));
        }

        @Override
        @SuppressLint("SetTextI18n")
        public void onBindViewHolder(@NonNull FavDrawerHolder holder, int position) {
            if (0 == position) {
                holder.key.setText(R.string.local_favorites);
                holder.value.setText(Integer.toString(mFavLocalCount));
                holder.itemView.setEnabled(true);
            } else if (1 == position) {
                holder.key.setText(R.string.cloud_favorites);
                holder.value.setText(Integer.toString(mFavCountSum));
                holder.itemView.setEnabled(true);
            } else {
                if (null == mFavCatArray || null == mFavCountArray || mFavCatArray.length < (position - 1) || mFavCountArray.length < (position - 1)) {
                    return;
                }
                holder.key.setText(mFavCatArray[position - 2]);
                holder.value.setText(Integer.toString(mFavCountArray[position - 2]));
                holder.itemView.setEnabled(true);
            }
            holder.itemView.setOnClickListener(v -> onItemClick(holder.itemView, position));
        }

        @Override
        public int gereplacedemCount() {
            if (null == mFavCatArray) {
                return 2;
            }
            return 12;
        }
    }

    private clreplaced DeleteDialogHelper implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener {

        @Override
        public void onClick(DialogInterface dialog, int which) {
            if (which != DialogInterface.BUTTON_POSITIVE) {
                return;
            }
            if (mRecyclerView == null || mHelper == null || mUrlBuilder == null) {
                return;
            }
            mRecyclerView.outOfCustomChoiceMode();
            if (mUrlBuilder.getFavCat() == FavListUrlBuilder.FAV_CAT_LOCAL) {
                // Delete local fav
                long[] gidArray = new long[mModifyGiList.size()];
                for (int i = 0, n = mModifyGiList.size(); i < n; i++) {
                    gidArray[i] = mModifyGiList.get(i).gid;
                }
                EhDB.removeLocalFavorites(gidArray);
                mModifyGiList.clear();
                mHelper.refresh();
            } else {
                // Delete cloud fav
                mEnableModify = true;
                mModifyFavCat = -1;
                mModifyAdd = false;
                mHelper.refresh();
            }
        }

        @Override
        public void onCancel(DialogInterface dialog) {
            mModifyGiList.clear();
        }
    }

    private clreplaced MoveDialogHelper implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener {

        @Override
        public void onClick(DialogInterface dialog, int which) {
            if (mRecyclerView == null || mHelper == null || mUrlBuilder == null) {
                return;
            }
            int srcCat = mUrlBuilder.getFavCat();
            int dstCat;
            if (which == 0) {
                dstCat = FavListUrlBuilder.FAV_CAT_LOCAL;
            } else {
                dstCat = which - 1;
            }
            if (srcCat == dstCat) {
                return;
            }
            mRecyclerView.outOfCustomChoiceMode();
            if (srcCat == FavListUrlBuilder.FAV_CAT_LOCAL) {
                // Move from local to cloud
                long[] gidArray = new long[mModifyGiList.size()];
                for (int i = 0, n = mModifyGiList.size(); i < n; i++) {
                    gidArray[i] = mModifyGiList.get(i).gid;
                }
                EhDB.removeLocalFavorites(gidArray);
                mEnableModify = true;
                mModifyFavCat = dstCat;
                mModifyAdd = true;
                mHelper.refresh();
            } else if (dstCat == FavListUrlBuilder.FAV_CAT_LOCAL) {
                // Move from cloud to local
                EhDB.putLocalFavorites(mModifyGiList);
                mEnableModify = true;
                mModifyFavCat = -1;
                mModifyAdd = false;
                mHelper.refresh();
            } else {
                mEnableModify = true;
                mModifyFavCat = dstCat;
                mModifyAdd = false;
                mHelper.refresh();
            }
        }

        @Override
        public void onCancel(DialogInterface dialog) {
            mModifyGiList.clear();
        }
    }

    private clreplaced FavoritesAdapter extends GalleryAdapter {

        public FavoritesAdapter(@NonNull LayoutInflater inflater, @NonNull Resources resources, @NonNull RecyclerView recyclerView, int type) {
            super(inflater, resources, recyclerView, type, false);
        }

        @Override
        public int gereplacedemCount() {
            return null != mHelper ? mHelper.size() : 0;
        }

        @Override
        void onItemClick(View view, int position) {
            FavoritesScene.this.onItemClick(view, position);
        }

        @Override
        boolean onItemLongClick(View view, int position) {
            return FavoritesScene.this.onItemLongClick(view, position);
        }

        @Nullable
        @Override
        public GalleryInfo getDataAt(int position) {
            return null != mHelper ? mHelper.getDataAtEx(position) : null;
        }
    }

    private clreplaced FavoritesHelper extends GalleryInfoContentHelper {

        @Override
        protected void getPageData(final int taskId, int type, int page) {
            MainActivity activity = getActivity2();
            if (null == activity || null == mUrlBuilder || null == mClient) {
                return;
            }
            if (mEnableModify) {
                mEnableModify = false;
                boolean local = mUrlBuilder.getFavCat() == FavListUrlBuilder.FAV_CAT_LOCAL;
                if (mModifyAdd) {
                    long[] gidArray = new long[mModifyGiList.size()];
                    String[] tokenArray = new String[mModifyGiList.size()];
                    for (int i = 0, n = mModifyGiList.size(); i < n; i++) {
                        GalleryInfo gi = mModifyGiList.get(i);
                        gidArray[i] = gi.gid;
                        tokenArray[i] = gi.token;
                    }
                    List<GalleryInfo> modifyGiListBackup = new ArrayList<>(mModifyGiList);
                    mModifyGiList.clear();
                    EhRequest request = new EhRequest();
                    request.setMethod(EhClient.METHOD_ADD_FAVORITES_RANGE);
                    request.setCallback(new AddFavoritesListener(getContext(), activity.getStageId(), getTag(), taskId, mUrlBuilder.getKeyword(), modifyGiListBackup));
                    request.setArgs(gidArray, tokenArray, mModifyFavCat);
                    mClient.execute(request);
                } else {
                    long[] gidArray = new long[mModifyGiList.size()];
                    for (int i = 0, n = mModifyGiList.size(); i < n; i++) {
                        gidArray[i] = mModifyGiList.get(i).gid;
                    }
                    mModifyGiList.clear();
                    String url;
                    if (local) {
                        // Local fav is shown now, but operation need be done for cloud fav
                        url = EhUrl.getFavoritesUrl();
                    } else {
                        url = mUrlBuilder.build();
                    }
                    mUrlBuilder.setIndex(page);
                    EhRequest request = new EhRequest();
                    request.setMethod(EhClient.METHOD_MODIFY_FAVORITES);
                    request.setCallback(new GetFavoritesListener(getContext(), activity.getStageId(), getTag(), taskId, local, mUrlBuilder.getKeyword()));
                    request.setArgs(url, gidArray, mModifyFavCat, Settings.getShowJpnreplacedle());
                    mClient.execute(request);
                }
            } else if (mUrlBuilder.getFavCat() == FavListUrlBuilder.FAV_CAT_LOCAL) {
                final String keyword = mUrlBuilder.getKeyword();
                SimpleHandler.getInstance().post(new Runnable() {

                    @Override
                    public void run() {
                        onGetFavoritesLocal(keyword, taskId);
                    }
                });
            } else {
                mUrlBuilder.setIndex(page);
                String url = mUrlBuilder.build();
                EhRequest request = new EhRequest();
                request.setMethod(EhClient.METHOD_GET_FAVORITES);
                request.setCallback(new GetFavoritesListener(getContext(), activity.getStageId(), getTag(), taskId, false, mUrlBuilder.getKeyword()));
                request.setArgs(url, Settings.getShowJpnreplacedle());
                mClient.execute(request);
            }
        }

        @Override
        protected Context getContext() {
            return FavoritesScene.this.getContext2();
        }

        @Override
        protected void notifyDataSetChanged() {
            // Ensure outOfCustomChoiceMode to avoid error
            if (mRecyclerView != null) {
                mRecyclerView.outOfCustomChoiceMode();
            }
            if (mAdapter != null) {
                mAdapter.notifyDataSetChanged();
            }
        }

        @Override
        protected void notifyItemRangeRemoved(int positionStart, int itemCount) {
            if (mAdapter != null) {
                mAdapter.notifyItemRangeRemoved(positionStart, itemCount);
            }
        }

        @Override
        protected void notifyItemRangeInserted(int positionStart, int itemCount) {
            if (mAdapter != null) {
                mAdapter.notifyItemRangeInserted(positionStart, itemCount);
            }
        }

        @Override
        public void onShowView(View hiddenView, View shownView) {
            if (null != mSearchBarMover) {
                mSearchBarMover.showSearchBar();
            }
        }

        @Override
        protected boolean isDuplicate(GalleryInfo d1, GalleryInfo d2) {
            return d1.gid == d2.gid;
        }

        @Override
        protected void onScrollToPosition(int postion) {
            if (0 == postion) {
                if (null != mSearchBarMover) {
                    mSearchBarMover.showSearchBar();
                }
            }
        }
    }
}

16 Source : FavoritesScene.java
with Apache License 2.0
from NuclearVGA

@Override
@Implemented(EasyRecyclerView.CustomChoiceListener.clreplaced)
public void onItemCheckedStateChanged(EasyRecyclerView view, int position, long id, boolean checked) {
    if (view.getCheckedItemCount() == 0) {
        view.outOfCustomChoiceMode();
    }
}

16 Source : FavoritesScene.java
with Apache License 2.0
from NuclearVGA

@Override
@Implemented(EasyRecyclerView.CustomChoiceListener.clreplaced)
public void onOutOfCustomChoice(EasyRecyclerView view) {
    if (mFabLayout != null) {
        showNormalFabs();
        mFabLayout.setAutoCancel(true);
        mFabLayout.setExpanded(false);
    }
    if (mHelper != null) {
        mHelper.setRefreshLayoutEnable(true);
    }
    // Unlock drawer
    setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, Gravity.LEFT);
    setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, Gravity.RIGHT);
}

16 Source : ContentLayout.java
with Apache License 2.0
from duzhaokun123

public clreplaced ContentLayout extends FrameLayout {

    private CircularProgressIndicator mProgressView;

    private TextView mTipView;

    private ViewGroup mContentView;

    private SwipeRefreshLayout mRefreshLayout;

    private LinearProgressIndicator mBottomProgress;

    private EasyRecyclerView mRecyclerView;

    private FastScroller mFastScroller;

    private ContentHelper<?> mContentHelper;

    private int mRecyclerViewOriginTop;

    private int mRecyclerViewOriginBottom;

    public ContentLayout(Context context) {
        super(context);
        init(context);
    }

    public ContentLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public ContentLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        LayoutInflater.from(context).inflate(R.layout.widget_content_layout, this);
        setClipChildren(false);
        setClipToPadding(false);
        mProgressView = findViewById(R.id.progress);
        mTipView = findViewById(R.id.tip);
        mContentView = findViewById(R.id.content_view);
        mRefreshLayout = mContentView.findViewById(R.id.refresh_layout);
        mBottomProgress = mContentView.findViewById(R.id.bottom_progress);
        mFastScroller = mContentView.findViewById(R.id.fast_scroller);
        mRecyclerView = mRefreshLayout.findViewById(R.id.recycler_view);
        mFastScroller.attachToRecyclerView(mRecyclerView);
        HandlerDrawable drawable = new HandlerDrawable();
        drawable.setColor(AttrResources.getAttrColor(context, R.attr.widgetColorThemeAccent));
        mFastScroller.setHandlerDrawable(drawable);
        mRefreshLayout.setColorSchemeResources(R.color.loading_indicator_red, R.color.loading_indicator_purple, R.color.loading_indicator_blue, R.color.loading_indicator_cyan, R.color.loading_indicator_green, R.color.loading_indicator_yellow);
        Resources resources = getResources();
        mBottomProgress.setIndicatorColor(resources.getColor(R.color.loading_indicator_red), resources.getColor(R.color.loading_indicator_blue), resources.getColor(R.color.loading_indicator_green), resources.getColor(R.color.loading_indicator_orange));
        mBottomProgress.setIndeterminateAnimationType(LinearProgressIndicator.INDETERMINATE_ANIMATION_TYPE_CONTIGUOUS);
        mRecyclerViewOriginTop = mRecyclerView.getPaddingTop();
        mRecyclerViewOriginBottom = mRecyclerView.getPaddingBottom();
    }

    @NonNull
    public EasyRecyclerView getRecyclerView() {
        return mRecyclerView;
    }

    public FastScroller getFastScroller() {
        return mFastScroller;
    }

    public SwipeRefreshLayout getRefreshLayout() {
        return mRefreshLayout;
    }

    public void setHelper(ContentHelper<?> helper) {
        mContentHelper = helper;
        helper.init(this);
    }

    public void showFastScroll() {
        if (!mFastScroller.isAttached()) {
            mFastScroller.attachToRecyclerView(mRecyclerView);
        }
    }

    public void hideFastScroll() {
        mFastScroller.detachedFromRecyclerView();
    }

    public void setFitPaddingTop(int fitPaddingTop) {
        // RecyclerView
        mRecyclerView.setPadding(mRecyclerView.getPaddingLeft(), mRecyclerViewOriginTop + fitPaddingTop, mRecyclerView.getPaddingRight(), mRecyclerView.getPaddingBottom());
        // RefreshLayout
        // TODO
        mRefreshLayout.setProgressViewOffset(true, 0, fitPaddingTop + LayoutUtils.dp2pix(getContext(), 32));
    }

    public void setTopInsets(int topInsets) {
        setPadding(0, topInsets, 0, 0);
    }

    public void setFitPaddingBottom(int fitPaddingBottom) {
        // RecyclerView
        mRecyclerView.setPadding(mRecyclerView.getPaddingLeft(), mRecyclerView.getPaddingTop(), mRecyclerView.getPaddingRight(), mRecyclerViewOriginBottom + fitPaddingBottom);
        mTipView.setPadding(mTipView.getPaddingLeft(), mTipView.getPaddingTop(), mTipView.getPaddingRight(), fitPaddingBottom);
        mProgressView.setPadding(mProgressView.getPaddingLeft(), mProgressView.getPaddingTop(), mProgressView.getPaddingRight(), fitPaddingBottom);
        mFastScroller.setPadding(mFastScroller.getPaddingLeft(), mFastScroller.getPaddingTop(), mFastScroller.getPaddingRight(), fitPaddingBottom);
        if (fitPaddingBottom > LayoutUtils.dp2pix(getContext(), 16)) {
            mBottomProgress.setPadding(0, 0, 0, fitPaddingBottom);
        } else {
            mBottomProgress.setPadding(0, 0, 0, 0);
        }
    }

    @Override
    protected Parcelable onSaveInstanceState() {
        return mContentHelper.saveInstanceState(super.onSaveInstanceState());
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        super.onRestoreInstanceState(mContentHelper.restoreInstanceState(state));
    }

    public abstract static clreplaced ContentHelper<E extends Parcelable> implements ViewTransition.OnShowViewListener {

        public static final int TYPE_REFRESH = 0;

        public static final int TYPE_PRE_PAGE = 1;

        public static final int TYPE_PRE_PAGE_KEEP_POS = 2;

        public static final int TYPE_NEXT_PAGE = 3;

        public static final int TYPE_NEXT_PAGE_KEEP_POS = 4;

        public static final int TYPE_SOMEWHERE = 5;

        public static final int TYPE_REFRESH_PAGE = 6;

        public static final int REFRESH_TYPE_HEADER = 0;

        public static final int REFRESH_TYPE_FOOTER = 1;

        public static final int REFRESH_TYPE_PROGRESS_VIEW = 2;

        private static final String TAG = ContentHelper.clreplaced.getSimpleName();

        private static final int CHECK_DUPLICATE_RANGE = 50;

        private static final String KEY_SUPER = "super";

        private static final String KEY_SHOWN_VIEW = "shown_view";

        private static final String KEY_TIP = "tip";

        private static final String KEY_DATA = "data";

        private static final String KEY_NEXT_ID = "next_id";

        private static final String KEY_PAGE_DIVIDER = "page_divider";

        private static final String KEY_START_PAGE = "start_page";

        private static final String KEY_END_PAGE = "end_page";

        private static final String KEY_PAGES = "pages";

        /**
         * Generate task id
         */
        private final IntIdGenerator mIdGenerator = new IntIdGenerator();

        private final LayoutManagerUtils.OnScrollToPositionListener mOnScrollToPositionListener = ContentHelper.this::onScrollToPosition;

        private CircularProgressIndicator mProgressView;

        private TextView mTipView;

        private ViewGroup mContentView;

        private SwipeRefreshLayout mRefreshLayout;

        private LinearProgressIndicator mBottomProgress;

        private EasyRecyclerView mRecyclerView;

        private ViewTransition mViewTransition;

        /**
         * Store data
         */
        private ArrayList<E> mData = new ArrayList<>();

        /**
         * Store the page divider index
         * <p>
         * For example, the data contain page 3, page 4, page 5,
         * page 3 size is 7, page 4 size is 8, page 5 size is 9,
         * so <code>mPageDivider</code> contain 7, 15, 24.
         */
        private IntList mPageDivider = new IntList();

        /**
         * The first page in <code>mData</code>
         */
        private int mStartPage;

        /**
         * The last page + 1 in <code>mData</code>
         */
        private int mEndPage;

        /**
         * The available page count.
         */
        private int mPages;

        private int mNextPage;

        private int mCurrentTaskId;

        private int mCurrentTaskType;

        private int mCurrentTaskPage;

        private int mNextPageScrollSize;

        private String mEmptyString = "No hint";

        private final SwipeRefreshLayout.OnRefreshListener mOnRefreshListener = new SwipeRefreshLayout.OnRefreshListener() {

            @Override
            public void onRefresh() {
                if (mStartPage > 0) {
                    mCurrentTaskId = mIdGenerator.nextId();
                    mCurrentTaskType = TYPE_PRE_PAGE_KEEP_POS;
                    mCurrentTaskPage = mStartPage - 1;
                    getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
                } else {
                    doRefresh();
                }
            }
        };

        private final RecyclerView.OnScrollListener mOnScrollListener = new RecyclerView.OnScrollListener() {

            @Override
            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                if (!mRefreshLayout.isRefreshing() && !recyclerView.canScrollVertically(1) && mEndPage < mPages) {
                    // Get next page
                    mBottomProgress.show();
                    if (mEndPage < mPages) {
                        // Get next page
                        // Fill pages before NextPage with empty list
                        while (mNextPage > mEndPage && mEndPage < mPages) {
                            mCurrentTaskId = mIdGenerator.nextId();
                            mCurrentTaskType = TYPE_NEXT_PAGE_KEEP_POS;
                            mCurrentTaskPage = mEndPage;
                            onGetPageData(mCurrentTaskId, mPages, mNextPage, Collections.emptyList());
                        }
                        mCurrentTaskId = mIdGenerator.nextId();
                        mCurrentTaskType = TYPE_NEXT_PAGE_KEEP_POS;
                        mCurrentTaskPage = mEndPage;
                        getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
                    } else if (mEndPage == mPages) {
                        // Refresh last page
                        mCurrentTaskId = mIdGenerator.nextId();
                        mCurrentTaskType = TYPE_REFRESH_PAGE;
                        mCurrentTaskPage = mEndPage - 1;
                        getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
                    } else {
                        Log.e(TAG, "Try to footer refresh, but mEndPage = " + mEndPage + ", mPages = " + mPages);
                        mBottomProgress.hide();
                    }
                }
            }
        };

        private int mSavedDataId = IntIdGenerator.INVALID_ID;

        private void init(ContentLayout contentLayout) {
            mNextPageScrollSize = LayoutUtils.dp2pix(contentLayout.getContext(), 48);
            mProgressView = contentLayout.mProgressView;
            mTipView = contentLayout.mTipView;
            mContentView = contentLayout.mContentView;
            mRefreshLayout = contentLayout.mRefreshLayout;
            mBottomProgress = contentLayout.mBottomProgress;
            mRecyclerView = contentLayout.mRecyclerView;
            Drawable drawable = ContextCompat.getDrawable(getContext(), R.drawable.big_sad_pandroid);
            drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
            mTipView.setCompoundDrawables(null, drawable, null, null);
            mViewTransition = new ViewTransition(mContentView, mProgressView, mTipView);
            mViewTransition.setOnShowViewListener(this);
            mRecyclerView.addOnScrollListener(mOnScrollListener);
            mRefreshLayout.setOnRefreshListener(mOnRefreshListener);
            mTipView.setOnClickListener(v -> refresh());
        }

        /**
         * Call {@link #onGetPageData(int, int, int, List)} when get data
         *
         * @param taskId task id
         * @param page   the page to get
         */
        protected abstract void getPageData(int taskId, int type, int page);

        protected abstract Context getContext();

        protected abstract void notifyDataSetChanged();

        protected abstract void notifyItemRangeRemoved(int positionStart, int itemCount);

        protected abstract void notifyItemRangeInserted(int positionStart, int itemCount);

        protected void onScrollToPosition(int postion) {
        }

        @Override
        public void onShowView(View hiddenView, View shownView) {
        }

        public int getShownViewIndex() {
            return mViewTransition.getShownViewIndex();
        }

        public void setRefreshLayoutEnable(boolean enable) {
            mRefreshLayout.setEnabled(enable);
        }

        public void setEnable(boolean enable) {
            mRefreshLayout.setEnabled(enable);
        }

        public void setEmptyString(String str) {
            mEmptyString = str;
        }

        public List<E> getData() {
            return mData;
        }

        /**
         * @throws IndexOutOfBoundsException if {@code location < 0 || location >= size()}
         */
        public E getDataAt(int location) {
            return mData.get(location);
        }

        @Nullable
        public E getDataAtEx(int location) {
            if (location >= 0 && location < mData.size()) {
                return mData.get(location);
            } else {
                return null;
            }
        }

        public int size() {
            return mData.size();
        }

        public boolean isCurrentTask(int taskId) {
            return mCurrentTaskId == taskId;
        }

        public int getPages() {
            return mPages;
        }

        public void addAt(int index, E data) {
            mData.add(index, data);
            onAddData(data);
            for (int i = 0, n = mPageDivider.size(); i < n; i++) {
                int divider = mPageDivider.get(i);
                if (index < divider) {
                    mPageDivider.set(i, divider + 1);
                }
            }
            notifyItemRangeInserted(index, 1);
        }

        public void removeAt(int index) {
            E data = mData.remove(index);
            onRemoveData(data);
            for (int i = 0, n = mPageDivider.size(); i < n; i++) {
                int divider = mPageDivider.get(i);
                if (index < divider) {
                    mPageDivider.set(i, divider - 1);
                }
            }
            notifyItemRangeRemoved(index, 1);
        }

        protected abstract boolean isDuplicate(E d1, E d2);

        private void removeDuplicateData(List<E> data, int start, int end) {
            start = Math.max(0, start);
            end = Math.min(mData.size(), end);
            for (Iterator<E> iterator = data.iterator(); iterator.hasNext(); ) {
                E d = iterator.next();
                for (int i = start; i < end; i++) {
                    if (isDuplicate(d, mData.get(i))) {
                        iterator.remove();
                        break;
                    }
                }
            }
        }

        protected void onAddData(E data) {
        }

        protected void onAddData(List<E> data) {
        }

        protected void onRemoveData(E data) {
        }

        protected void onRemoveData(List<E> data) {
        }

        protected void onClearData() {
        }

        public void onGetPageData(int taskId, int pages, int nextPage, List<E> data) {
            if (mCurrentTaskId == taskId) {
                int dataSize;
                switch(mCurrentTaskType) {
                    case TYPE_REFRESH:
                        mStartPage = 0;
                        mEndPage = 1;
                        mPages = pages;
                        mNextPage = nextPage;
                        mPageDivider.clear();
                        mPageDivider.add(data.size());
                        if (data.isEmpty()) {
                            mData.clear();
                            onClearData();
                            notifyDataSetChanged();
                            if (true || mEndPage >= mPages) {
                                // Not found
                                // Ui change, show empty string
                                mRefreshLayout.setRefreshing(false);
                                mBottomProgress.hide();
                                showEmptyString();
                            } else {
                                // Ui change, show progress bar
                                mRefreshLayout.setRefreshing(false);
                                mBottomProgress.hide();
                                showProgressBar();
                                // Get next page
                                mCurrentTaskId = mIdGenerator.nextId();
                                mCurrentTaskType = TYPE_NEXT_PAGE_KEEP_POS;
                                mCurrentTaskPage = mEndPage;
                                getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
                            }
                        } else {
                            mData.clear();
                            onClearData();
                            mData.addAll(data);
                            onAddData(data);
                            notifyDataSetChanged();
                            // Ui change, show content
                            mRefreshLayout.setRefreshing(false);
                            mBottomProgress.hide();
                            showContent();
                            // RecyclerView scroll
                            if (mRecyclerView.isAttachedToWindow()) {
                                mRecyclerView.stopScroll();
                                LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), 0, 0);
                                onScrollToPosition(0);
                            }
                        }
                        break;
                    case TYPE_PRE_PAGE:
                    case TYPE_PRE_PAGE_KEEP_POS:
                        removeDuplicateData(data, 0, CHECK_DUPLICATE_RANGE);
                        dataSize = data.size();
                        for (int i = 0, n = mPageDivider.size(); i < n; i++) {
                            mPageDivider.set(i, mPageDivider.get(i) + dataSize);
                        }
                        mPageDivider.add(0, dataSize);
                        mStartPage--;
                        mPages = Math.max(mEndPage, pages);
                        // replacedert mStartPage >= 0
                        if (data.isEmpty()) {
                            if (true || mStartPage <= 0) {
                                // OK, that's all
                                if (mData.isEmpty()) {
                                    // Ui change, show empty string
                                    mRefreshLayout.setRefreshing(false);
                                    mBottomProgress.hide();
                                    showEmptyString();
                                } else {
                                    // Ui change, show content
                                    mRefreshLayout.setRefreshing(false);
                                    mBottomProgress.hide();
                                    showContent();
                                    if (mCurrentTaskType == TYPE_PRE_PAGE && mRecyclerView.isAttachedToWindow()) {
                                        // RecyclerView scroll, to top
                                        mRecyclerView.stopScroll();
                                        LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), 0, 0);
                                        onScrollToPosition(0);
                                    }
                                }
                            } else {
                                // Keep UI
                                // Get previous
                                mCurrentTaskId = mIdGenerator.nextId();
                                // Keep mCurrentTaskType
                                mCurrentTaskPage = mStartPage - 1;
                                getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
                            }
                        } else {
                            mData.addAll(0, data);
                            onAddData(data);
                            notifyItemRangeInserted(0, data.size());
                            // Ui change, show content
                            mRefreshLayout.setRefreshing(false);
                            mBottomProgress.hide();
                            showContent();
                            if (mRecyclerView.isAttachedToWindow()) {
                                // RecyclerView scroll
                                if (mCurrentTaskType == TYPE_PRE_PAGE_KEEP_POS) {
                                    mRecyclerView.stopScroll();
                                    LayoutManagerUtils.scrollToPositionProperly(mRecyclerView.getLayoutManager(), getContext(), dataSize - 1, mOnScrollToPositionListener);
                                } else {
                                    mRecyclerView.stopScroll();
                                    LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), 0, 0);
                                    onScrollToPosition(0);
                                }
                            }
                        }
                        break;
                    case TYPE_NEXT_PAGE:
                    case TYPE_NEXT_PAGE_KEEP_POS:
                        removeDuplicateData(data, mData.size() - CHECK_DUPLICATE_RANGE, mData.size());
                        dataSize = data.size();
                        int oldDataSize = mData.size();
                        mPageDivider.add(oldDataSize + dataSize);
                        mEndPage++;
                        mNextPage = nextPage;
                        mPages = Math.max(mEndPage, pages);
                        if (data.isEmpty()) {
                            if (true || mEndPage >= mPages) {
                                // OK, that's all
                                if (mData.isEmpty()) {
                                    // Ui change, show empty string
                                    mRefreshLayout.setRefreshing(false);
                                    mBottomProgress.hide();
                                    showEmptyString();
                                } else {
                                    // Ui change, show content
                                    mRefreshLayout.setRefreshing(false);
                                    mBottomProgress.hide();
                                    showContent();
                                    if (mCurrentTaskType == TYPE_NEXT_PAGE && mRecyclerView.isAttachedToWindow()) {
                                        // RecyclerView scroll
                                        mRecyclerView.stopScroll();
                                        LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), oldDataSize, 0);
                                        onScrollToPosition(oldDataSize);
                                    }
                                }
                            } else {
                                // Keep UI
                                // Get next page
                                mCurrentTaskId = mIdGenerator.nextId();
                                // Keep mCurrentTaskType
                                mCurrentTaskPage = mEndPage;
                                getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
                            }
                        } else {
                            mData.addAll(data);
                            onAddData(data);
                            notifyItemRangeInserted(oldDataSize, dataSize);
                            // Ui change, show content
                            mRefreshLayout.setRefreshing(false);
                            mBottomProgress.hide();
                            showContent();
                            if (mRecyclerView.isAttachedToWindow()) {
                                if (mCurrentTaskType == TYPE_NEXT_PAGE_KEEP_POS) {
                                    mRecyclerView.stopScroll();
                                    mRecyclerView.smoothScrollBy(0, mNextPageScrollSize);
                                } else {
                                    mRecyclerView.stopScroll();
                                    LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), oldDataSize, 0);
                                    onScrollToPosition(oldDataSize);
                                }
                            }
                        }
                        break;
                    case TYPE_SOMEWHERE:
                        mStartPage = mCurrentTaskPage;
                        mEndPage = mCurrentTaskPage + 1;
                        mNextPage = nextPage;
                        mPages = pages;
                        mPageDivider.clear();
                        mPageDivider.add(data.size());
                        if (data.isEmpty()) {
                            mData.clear();
                            onClearData();
                            notifyDataSetChanged();
                            if (true || mEndPage >= mPages) {
                                // Not found
                                // Ui change, show empty string
                                mRefreshLayout.setRefreshing(false);
                                mBottomProgress.hide();
                                showEmptyString();
                            } else {
                                // Ui change, show progress bar
                                mRefreshLayout.setRefreshing(false);
                                mBottomProgress.hide();
                                showProgressBar();
                                // Get next page
                                mCurrentTaskId = mIdGenerator.nextId();
                                mCurrentTaskType = TYPE_NEXT_PAGE_KEEP_POS;
                                mCurrentTaskPage = mEndPage;
                                getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
                            }
                        } else {
                            mData.clear();
                            onClearData();
                            mData.addAll(data);
                            onAddData(data);
                            notifyDataSetChanged();
                            // Ui change, show content
                            mRefreshLayout.setRefreshing(false);
                            mBottomProgress.hide();
                            showContent();
                            if (mRecyclerView.isAttachedToWindow()) {
                                // RecyclerView scroll
                                mRecyclerView.stopScroll();
                                LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), 0, 0);
                                onScrollToPosition(0);
                            }
                        }
                        break;
                    case TYPE_REFRESH_PAGE:
                        if (mCurrentTaskPage < mStartPage || mCurrentTaskPage >= mEndPage) {
                            Log.e(TAG, "TYPE_REFRESH_PAGE, but mCurrentTaskPage = " + mCurrentTaskPage + ", mStartPage = " + mStartPage + ", mEndPage = " + mEndPage);
                            break;
                        }
                        if (mCurrentTaskPage == mEndPage - 1) {
                            mNextPage = nextPage;
                        }
                        mPages = Math.max(mEndPage, pages);
                        int oldIndexStart = mCurrentTaskPage == mStartPage ? 0 : mPageDivider.get(mCurrentTaskPage - mStartPage - 1);
                        int oldIndexEnd = mPageDivider.get(mCurrentTaskPage - mStartPage);
                        List<E> toRemove = mData.subList(oldIndexStart, oldIndexEnd);
                        onRemoveData(toRemove);
                        toRemove.clear();
                        removeDuplicateData(data, oldIndexStart - CHECK_DUPLICATE_RANGE, oldIndexStart + CHECK_DUPLICATE_RANGE);
                        int newIndexStart = oldIndexStart;
                        int newIndexEnd = newIndexStart + data.size();
                        mData.addAll(oldIndexStart, data);
                        onAddData(data);
                        notifyDataSetChanged();
                        for (int i = mCurrentTaskPage - mStartPage, n = mPageDivider.size(); i < n; i++) {
                            mPageDivider.set(i, mPageDivider.get(i) - oldIndexEnd + newIndexEnd);
                        }
                        if (mData.isEmpty()) {
                            // Ui change, show empty string
                            mRefreshLayout.setRefreshing(false);
                            mBottomProgress.hide();
                            showEmptyString();
                        } else {
                            // Ui change, show content
                            mRefreshLayout.setRefreshing(false);
                            mBottomProgress.hide();
                            showContent();
                            // RecyclerView scroll
                            if (newIndexEnd > oldIndexEnd && newIndexEnd > 0 && mRecyclerView.isAttachedToWindow()) {
                                mRecyclerView.stopScroll();
                                LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), newIndexEnd - 1, 0);
                                onScrollToPosition(newIndexEnd - 1);
                            }
                        }
                        break;
                }
            }
        }

        public void onGetException(int taskId, Exception e) {
            if (mCurrentTaskId == taskId) {
                mRefreshLayout.setRefreshing(false);
                mBottomProgress.hide();
                String readableError;
                if (e != null) {
                    e.printStackTrace();
                    readableError = ExceptionUtils.getReadableString(e);
                } else {
                    readableError = getContext().getString(R.string.error_unknown);
                }
                if (mViewTransition.getShownViewIndex() == 0) {
                    Toast.makeText(getContext(), readableError, Toast.LENGTH_SHORT).show();
                } else {
                    showText(readableError);
                }
            }
        }

        public void showContent() {
            mViewTransition.showView(0);
        }

        private boolean isContentShowing() {
            return mViewTransition.getShownViewIndex() == 0;
        }

        public void showProgressBar() {
            showProgressBar(true);
        }

        public void showProgressBar(boolean animation) {
            mViewTransition.showView(1, animation);
        }

        public void showText(CharSequence text) {
            mTipView.setText(text);
            mViewTransition.showView(2);
        }

        public void showEmptyString() {
            showText(mEmptyString);
        }

        /**
         * Be carefull
         */
        public void doGetData(int type, int page, int refreshType) {
            switch(refreshType) {
                default:
                case REFRESH_TYPE_HEADER:
                    showContent();
                    mRefreshLayout.setRefreshing(false);
                    mBottomProgress.hide();
                    break;
                case REFRESH_TYPE_FOOTER:
                    showContent();
                    mRefreshLayout.setRefreshing(false);
                    mBottomProgress.hide();
                    break;
                case REFRESH_TYPE_PROGRESS_VIEW:
                    showProgressBar();
                    mRefreshLayout.setRefreshing(false);
                    mBottomProgress.hide();
                    break;
            }
            mCurrentTaskId = mIdGenerator.nextId();
            mCurrentTaskType = type;
            mCurrentTaskPage = page;
            getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
        }

        private void doRefresh() {
            mCurrentTaskId = mIdGenerator.nextId();
            mCurrentTaskType = TYPE_REFRESH;
            mCurrentTaskPage = 0;
            getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
        }

        /**
         * Lisk {@link #refresh()}, but no animation when show progress bar
         */
        public void firstRefresh() {
            showProgressBar(false);
            doRefresh();
        }

        /**
         * Show progress bar first, than do refresh
         */
        public void refresh() {
            showProgressBar();
            doRefresh();
        }

        private void cancelCurrentTask() {
            mCurrentTaskId = mIdGenerator.nextId();
            mRefreshLayout.setRefreshing(false);
            mBottomProgress.hide();
        }

        private int getPageStart(int page) {
            if (mStartPage == page) {
                return 0;
            } else {
                return mPageDivider.get(page - mStartPage - 1);
            }
        }

        private int getPageEnd(int page) {
            return mPageDivider.get(page - mStartPage);
        }

        private int getPageForPosition(int position) {
            if (position < 0) {
                return -1;
            }
            IntList pageDivider = mPageDivider;
            for (int i = 0, n = pageDivider.size(); i < n; i++) {
                if (position < pageDivider.get(i)) {
                    return i + mStartPage;
                }
            }
            return -1;
        }

        public int getPageForTop() {
            return getPageForPosition(LayoutManagerUtils.getFirstVisibleItemPosition(mRecyclerView.getLayoutManager()));
        }

        public int getPageForBottom() {
            return getPageForPosition(LayoutManagerUtils.getLastVisibleItemPosition(mRecyclerView.getLayoutManager()));
        }

        public boolean canGoTo() {
            return isContentShowing();
        }

        /**
         * Check range first!
         *
         * @param page the target page
         * @throws IndexOutOfBoundsException
         */
        public void goTo(int page) throws IndexOutOfBoundsException {
            if (page < 0 || page >= mPages) {
                throw new IndexOutOfBoundsException("Page count is " + mPages + ", page is " + page);
            } else if (page >= mStartPage && page < mEndPage) {
                cancelCurrentTask();
                int position = getPageStart(page);
                mRecyclerView.stopScroll();
                LayoutManagerUtils.scrollToPositionWithOffset(mRecyclerView.getLayoutManager(), position, 0);
                onScrollToPosition(position);
            } else if (page == mStartPage - 1) {
                mRefreshLayout.setRefreshing(false);
                mBottomProgress.hide();
                mCurrentTaskId = mIdGenerator.nextId();
                mCurrentTaskType = TYPE_PRE_PAGE;
                mCurrentTaskPage = page;
                getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
            } else if (page == mEndPage) {
                mRefreshLayout.setRefreshing(false);
                mBottomProgress.hide();
                mCurrentTaskId = mIdGenerator.nextId();
                mCurrentTaskType = TYPE_NEXT_PAGE;
                mCurrentTaskPage = page;
                getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
            } else {
                mRefreshLayout.setRefreshing(false);
                mBottomProgress.hide();
                mCurrentTaskId = mIdGenerator.nextId();
                mCurrentTaskType = TYPE_SOMEWHERE;
                mCurrentTaskPage = page;
                getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage);
            }
        }

        protected Parcelable saveInstanceState(Parcelable superState) {
            Bundle bundle = new Bundle();
            bundle.putParcelable(KEY_SUPER, superState);
            int shownView = mViewTransition.getShownViewIndex();
            bundle.putInt(KEY_SHOWN_VIEW, shownView);
            bundle.putString(KEY_TIP, mTipView.getText().toString());
            // TODO It's a bad design
            EhApplication app = (EhApplication) getContext().getApplicationContext();
            if (mSavedDataId != IntIdGenerator.INVALID_ID) {
                app.removeGlobalStuff(mSavedDataId);
                mSavedDataId = IntIdGenerator.INVALID_ID;
            }
            mSavedDataId = app.putGlobalStuff(mData);
            bundle.putInt(KEY_DATA, mSavedDataId);
            bundle.putInt(KEY_NEXT_ID, mIdGenerator.nextId());
            bundle.putParcelable(KEY_PAGE_DIVIDER, mPageDivider);
            bundle.putInt(KEY_START_PAGE, mStartPage);
            bundle.putInt(KEY_END_PAGE, mEndPage);
            bundle.putInt(KEY_PAGES, mPages);
            return bundle;
        }

        protected Parcelable restoreInstanceState(Parcelable state) {
            if (state instanceof Bundle) {
                Bundle bundle = (Bundle) state;
                mViewTransition.showView(bundle.getInt(KEY_SHOWN_VIEW), false);
                mTipView.setText(bundle.getString(KEY_TIP));
                mSavedDataId = bundle.getInt(KEY_DATA);
                ArrayList<E> newData = null;
                EhApplication app = (EhApplication) getContext().getApplicationContext();
                if (mSavedDataId != IntIdGenerator.INVALID_ID) {
                    newData = (ArrayList<E>) app.removeGlobalStuff(mSavedDataId);
                    mSavedDataId = IntIdGenerator.INVALID_ID;
                    if (newData != null) {
                        mData = newData;
                    }
                }
                mIdGenerator.setNextId(bundle.getInt(KEY_NEXT_ID));
                mPageDivider = bundle.getParcelable(KEY_PAGE_DIVIDER);
                mStartPage = bundle.getInt(KEY_START_PAGE);
                mEndPage = bundle.getInt(KEY_END_PAGE);
                mPages = bundle.getInt(KEY_PAGES);
                notifyDataSetChanged();
                if (newData == null) {
                    mPageDivider.clear();
                    mStartPage = 0;
                    mEndPage = 0;
                    mPages = 0;
                    firstRefresh();
                }
                return bundle.getParcelable(KEY_SUPER);
            } else {
                return state;
            }
        }
    }
}

16 Source : GalleryCommentsScene.java
with Apache License 2.0
from duzhaokun123

public final clreplaced GalleryCommentsScene extends ToolbarScene implements View.OnClickListener, SwipeRefreshLayout.OnRefreshListener {

    public static final String TAG = GalleryCommentsScene.clreplaced.getSimpleName();

    public static final String KEY_API_UID = "api_uid";

    public static final String KEY_API_KEY = "api_key";

    public static final String KEY_GID = "gid";

    public static final String KEY_TOKEN = "token";

    public static final String KEY_COMMENT_LIST = "comment_list";

    private static final int TYPE_COMMENT = 0;

    private static final int TYPE_MORE = 1;

    private static final int TYPE_PROGRESS = 2;

    private long mApiUid;

    private String mApiKey;

    private long mGid;

    private String mToken;

    @Nullable
    private GalleryCommentList mCommentList;

    @Nullable
    private EasyRecyclerView mRecyclerView;

    @Nullable
    private FabLayout mFabLayout;

    @Nullable
    private FloatingActionButton mFab;

    @Nullable
    private View mEditPanel;

    @Nullable
    private ImageView mSendImage;

    @Nullable
    private EditText mEditText;

    @Nullable
    private CommentAdapter mAdapter;

    @Nullable
    private ViewTransition mViewTransition;

    private SwipeRefreshLayout mRefreshLayout;

    private Drawable mSendDrawable;

    private Drawable mPencilDrawable;

    private long mCommentId;

    private boolean mInAnimation = false;

    private boolean mShowAllComments = false;

    private boolean mRefreshingComments = false;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState == null) {
            onInit();
        } else {
            onRestore(savedInstanceState);
        }
    }

    private void handleArgs(Bundle args) {
        if (args == null) {
            return;
        }
        mApiUid = args.getLong(KEY_API_UID, -1L);
        mApiKey = args.getString(KEY_API_KEY);
        mGid = args.getLong(KEY_GID, -1L);
        mToken = args.getString(KEY_TOKEN, null);
        mCommentList = args.getParcelable(KEY_COMMENT_LIST);
        mShowAllComments = mCommentList != null && !mCommentList.hasMore;
    }

    private void onInit() {
        handleArgs(getArguments());
    }

    private void onRestore(@NonNull Bundle savedInstanceState) {
        mApiUid = savedInstanceState.getLong(KEY_API_UID, -1L);
        mApiKey = savedInstanceState.getString(KEY_API_KEY);
        mGid = savedInstanceState.getLong(KEY_GID, -1L);
        mToken = savedInstanceState.getString(KEY_TOKEN, null);
        mCommentList = savedInstanceState.getParcelable(KEY_COMMENT_LIST);
        mShowAllComments = mCommentList != null && !mCommentList.hasMore;
    }

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putLong(KEY_API_UID, mApiUid);
        outState.putString(KEY_API_KEY, mApiKey);
        outState.putLong(KEY_GID, mGid);
        outState.putString(KEY_TOKEN, mToken);
        outState.putParcelable(KEY_COMMENT_LIST, mCommentList);
    }

    @NonNull
    @Override
    public View onCreateViewWithToolbar(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.scene_gallery_comments, container, false);
        mRecyclerView = (EasyRecyclerView) ViewUtils.$$(view, R.id.recycler_view);
        TextView tip = (TextView) ViewUtils.$$(view, R.id.tip);
        mEditPanel = ViewUtils.$$(view, R.id.edit_panel);
        mSendImage = (ImageView) ViewUtils.$$(mEditPanel, R.id.send);
        mEditText = (EditText) ViewUtils.$$(mEditPanel, R.id.edit_text);
        mFabLayout = (FabLayout) ViewUtils.$$(view, R.id.fab_layout);
        mFab = (FloatingActionButton) ViewUtils.$$(view, R.id.fab);
        mRefreshLayout = (SwipeRefreshLayout) ViewUtils.$$(view, R.id.refresh_layout);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            view.setWindowInsetsAnimationCallback(new WindowInsetsAnimation.Callback(WindowInsetsAnimation.Callback.DISPATCH_MODE_STOP) {

                int startBottomEditPanel = 0;

                int startBottomFabLayout = 0;

                int endBottomEditPanel = 0;

                int endBottomFabLayout = 0;

                WindowInsetsAnimation animation;

                @Override
                public void onPrepare(@NonNull WindowInsetsAnimation animation) {
                    this.animation = animation;
                    if (mEditPanel != null) {
                        startBottomEditPanel = mEditPanel.getPaddingBottom();
                    }
                    if (mFabLayout != null) {
                        startBottomFabLayout = mFabLayout.getPaddingBottom();
                    }
                    super.onPrepare(animation);
                }

                @NonNull
                @Override
                public WindowInsetsAnimation.Bounds onStart(@NonNull WindowInsetsAnimation animation, @NonNull WindowInsetsAnimation.Bounds bounds) {
                    this.animation = animation;
                    if (mEditPanel != null) {
                        endBottomEditPanel = mEditPanel.getPaddingBottom();
                        mEditPanel.setTranslationY(-(startBottomEditPanel - endBottomEditPanel));
                    }
                    if (mFabLayout != null) {
                        endBottomFabLayout = mFabLayout.getPaddingBottom();
                        mFabLayout.setTranslationY(-(startBottomFabLayout - endBottomFabLayout));
                    }
                    return bounds;
                }

                @NonNull
                @Override
                public WindowInsets onProgress(@NonNull WindowInsets insets, @NonNull List<WindowInsetsAnimation> runningAnimations) {
                    if (mEditPanel != null) {
                        int offset = MathUtils.lerp(-(startBottomEditPanel - endBottomEditPanel), 0, animation.getInterpolatedFraction());
                        mEditPanel.setTranslationY(offset);
                    }
                    if (mFabLayout != null) {
                        int offset = MathUtils.lerp(-(startBottomFabLayout - endBottomFabLayout), 0, animation.getInterpolatedFraction());
                        mFabLayout.setTranslationY(offset);
                    }
                    return insets;
                }

                @Override
                public void onEnd(@NonNull WindowInsetsAnimation animation) {
                    startBottomEditPanel = 0;
                    startBottomFabLayout = 0;
                    endBottomEditPanel = 0;
                    endBottomFabLayout = 0;
                    this.animation = null;
                    if (mEditPanel != null) {
                        mEditPanel.setTranslationY(0);
                    }
                    if (mFabLayout != null) {
                        mFabLayout.setTranslationY(0);
                    }
                }
            });
        }
        mRefreshLayout.setColorSchemeResources(R.color.loading_indicator_red, R.color.loading_indicator_purple, R.color.loading_indicator_blue, R.color.loading_indicator_cyan, R.color.loading_indicator_green, R.color.loading_indicator_yellow);
        mRefreshLayout.setOnRefreshListener(this);
        Context context = requireContext();
        Resources resources = getResources();
        int paddingBottomFab = resources.getDimensionPixelOffset(R.dimen.gallery_padding_bottom_fab);
        Drawable drawable = ContextCompat.getDrawable(context, R.drawable.big_sad_pandroid);
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        tip.setCompoundDrawables(null, drawable, null, null);
        mSendDrawable = ContextCompat.getDrawable(context, R.drawable.v_send_dark_x24);
        mPencilDrawable = ContextCompat.getDrawable(context, R.drawable.v_pencil_dark_x24);
        mAdapter = new CommentAdapter();
        mRecyclerView.setAdapter(mAdapter);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(context, RecyclerView.VERTICAL, false));
        LinearDividerItemDecoration decoration = new LinearDividerItemDecoration(LinearDividerItemDecoration.VERTICAL, AttrResources.getAttrColor(context, R.attr.dividerColor), LayoutUtils.dp2pix(context, 1));
        decoration.setShowLastDivider(true);
        mRecyclerView.addItemDecoration(decoration);
        mRecyclerView.setHasFixedSize(true);
        mRecyclerView.setPadding(mRecyclerView.getPaddingLeft(), mRecyclerView.getPaddingTop(), mRecyclerView.getPaddingRight(), mRecyclerView.getPaddingBottom() + paddingBottomFab);
        // Cancel change animator
        RecyclerView.ItemAnimator itemAnimator = mRecyclerView.gereplacedemAnimator();
        if (itemAnimator instanceof DefaulreplacedemAnimator) {
            ((DefaulreplacedemAnimator) itemAnimator).setSupportsChangeAnimations(false);
        }
        mSendImage.setOnClickListener(this);
        mFab.setOnClickListener(this);
        addAboveSnackView(mEditPanel);
        addAboveSnackView(mFabLayout);
        mViewTransition = new ViewTransition(mRecyclerView, tip);
        updateView(false);
        return view;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (null != mRecyclerView) {
            mRecyclerView.stopScroll();
            mRecyclerView = null;
        }
        if (null != mEditPanel) {
            removeAboveSnackView(mEditPanel);
            mEditPanel = null;
        }
        if (null != mFabLayout) {
            removeAboveSnackView(mFabLayout);
            mFabLayout = null;
        }
        mFab = null;
        mSendImage = null;
        mEditText = null;
        mAdapter = null;
        mViewTransition = null;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        setreplacedle(R.string.gallery_comments);
        setNavigationIcon(R.drawable.v_arrow_left_dark_x24);
    }

    @Override
    public void onNavigationClick() {
        onBackPressed();
    }

    private void voteComment(long id, int vote) {
        Context context = getContext();
        MainActivity activity = getMainActivity();
        if (null == context || null == activity) {
            return;
        }
        EhRequest request = new EhRequest().setMethod(EhClient.METHOD_VOTE_COMMENT).setArgs(mApiUid, mApiKey, mGid, mToken, id, vote).setCallback(new VoteCommentListener(context, activity.getStageId(), getTag()));
        EhApplication.getEhClient(context).execute(request);
    }

    @SuppressLint("InflateParams")
    public void showVoteStatusDialog(Context context, String voteStatus) {
        String[] temp = StringUtils.split(voteStatus, ',');
        final int length = temp.length;
        final String[] userArray = new String[length];
        final String[] voteArray = new String[length];
        for (int i = 0; i < length; i++) {
            String str = StringUtils.trim(temp[i]);
            int index = str.lastIndexOf(' ');
            if (index < 0) {
                Log.d(TAG, "Something wrong happened about vote state");
                userArray[i] = str;
                voteArray[i] = "";
            } else {
                userArray[i] = StringUtils.trim(str.substring(0, index));
                voteArray[i] = StringUtils.trim(str.substring(index + 1));
            }
        }
        AlertDialog.Builder builder = new MaterialAlertDialogBuilder(context);
        context = builder.getContext();
        final LayoutInflater inflater = LayoutInflater.from(context);
        EasyRecyclerView rv = (EasyRecyclerView) inflater.inflate(R.layout.dialog_recycler_view, null);
        rv.setAdapter(new RecyclerView.Adapter<InfoHolder>() {

            @NonNull
            @Override
            public InfoHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
                return new InfoHolder(inflater.inflate(R.layout.item_drawer_favorites, parent, false));
            }

            @Override
            public void onBindViewHolder(@NonNull InfoHolder holder, int position) {
                holder.key.setText(userArray[position]);
                holder.value.setText(voteArray[position]);
            }

            @Override
            public int gereplacedemCount() {
                return length;
            }
        });
        rv.setLayoutManager(new LinearLayoutManager(context));
        LinearDividerItemDecoration decoration = new LinearDividerItemDecoration(LinearDividerItemDecoration.VERTICAL, AttrResources.getAttrColor(context, R.attr.dividerColor), LayoutUtils.dp2pix(context, 1));
        decoration.setPadding(ResourcesUtils.getAttrDimensionPixelOffset(context, R.attr.dialogPreferredPadding));
        rv.addItemDecoration(decoration);
        rv.setClipToPadding(false);
        builder.setView(rv).show();
    }

    private void showCommentDialog(int position) {
        final Context context = getContext();
        if (context == null || mCommentList == null || mCommentList.comments == null || position >= mCommentList.comments.length || position < 0) {
            return;
        }
        final GalleryComment comment = mCommentList.comments[position];
        List<String> menu = new ArrayList<>();
        final IntList menuId = new IntList();
        Resources resources = context.getResources();
        menu.add(resources.getString(R.string.copy_comment_text));
        menuId.add(R.id.copy);
        if (comment.editable) {
            menu.add(resources.getString(R.string.edit_comment));
            menuId.add(R.id.edit_comment);
        }
        if (comment.voteUpAble) {
            menu.add(resources.getString(comment.voteUpEd ? R.string.cancel_vote_up : R.string.vote_up));
            menuId.add(R.id.vote_up);
        }
        if (comment.voteDownAble) {
            menu.add(resources.getString(comment.voteDownEd ? R.string.cancel_vote_down : R.string.vote_down));
            menuId.add(R.id.vote_down);
        }
        if (!TextUtils.isEmpty(comment.voteState)) {
            menu.add(resources.getString(R.string.check_vote_status));
            menuId.add(R.id.check_vote_status);
        }
        new MaterialAlertDialogBuilder(context).sereplacedems(menu.toArray(new String[0]), (dialog, which) -> {
            if (which < 0 || which >= menuId.size()) {
                return;
            }
            int id = menuId.get(which);
            if (id == R.id.copy) {
                ClipboardUtil.addTextToClipboard(comment.comment);
                showTip(R.string.copied_to_clipboard, LENGTH_SHORT);
            } else if (id == R.id.vote_up) {
                voteComment(comment.id, 1);
            } else if (id == R.id.vote_down) {
                voteComment(comment.id, -1);
            } else if (id == R.id.check_vote_status) {
                showVoteStatusDialog(context, comment.voteState);
            } else if (id == R.id.edit_comment) {
                prepareEditComment(comment.id);
                if (!mInAnimation && mEditPanel != null && mEditPanel.getVisibility() != View.VISIBLE) {
                    showEditPanel(true);
                }
            }
        }).show();
    }

    public boolean onItemClick(EasyRecyclerView parent, View view, int position) {
        MainActivity activity = getMainActivity();
        if (null == activity) {
            return false;
        }
        RecyclerView.ViewHolder holder = parent.getChildViewHolder(view);
        if (holder instanceof ActualCommentHolder) {
            ActualCommentHolder commentHolder = (ActualCommentHolder) holder;
            ClickableSpan span = commentHolder.comment.getCurrentSpan();
            commentHolder.comment.clearCurrentSpan();
            if (span instanceof URLSpan) {
                UrlOpener.openUrl(activity, ((URLSpan) span).getURL(), true);
            } else {
                showCommentDialog(position);
            }
        } else if (holder instanceof MoreCommentHolder && !mRefreshingComments && mAdapter != null) {
            mRefreshingComments = true;
            mShowAllComments = true;
            mAdapter.notifyItemChanged(position);
            String url = getGalleryDetailUrl();
            if (url != null) {
                // Request
                EhRequest request = new EhRequest().setMethod(EhClient.METHOD_GET_GALLERY_DETAIL).setArgs(url).setCallback(new RefreshCommentListener(activity, activity.getStageId(), getTag()));
                EhApplication.getEhClient(activity).execute(request);
            }
        }
        return true;
    }

    private void updateView(boolean animation) {
        if (null == mViewTransition) {
            return;
        }
        if (mCommentList == null || mCommentList.comments == null || mCommentList.comments.length <= 0) {
            mViewTransition.showView(1, animation);
        } else {
            mViewTransition.showView(0, animation);
        }
    }

    private void prepareNewComment() {
        mCommentId = 0;
        if (mSendImage != null) {
            mSendImage.setImageDrawable(mSendDrawable);
        }
    }

    private void prepareEditComment(long commentId) {
        mCommentId = commentId;
        if (mSendImage != null) {
            mSendImage.setImageDrawable(mPencilDrawable);
        }
    }

    private void showEditPanelWithAnimation() {
        if (null == mFab || null == mEditPanel) {
            return;
        }
        mInAnimation = true;
        mFab.setTranslationX(0.0f);
        mFab.setTranslationY(0.0f);
        mFab.setScaleX(1.0f);
        mFab.setScaleY(1.0f);
        int fabEndX = mEditPanel.getLeft() + (mEditPanel.getWidth() / 2) - (mFab.getWidth() / 2);
        int fabEndY = mEditPanel.getTop() + (mEditPanel.getHeight() / 2) - (mFab.getHeight() / 2);
        mFab.animate().x(fabEndX).y(fabEndY).scaleX(0.0f).scaleY(0.0f).setInterpolator(AnimationUtils.SLOW_FAST_SLOW_INTERPOLATOR).setDuration(300L).setListener(new SimpleAnimatorListener() {

            @Override
            public void onAnimationEnd(Animator animation) {
                if (null == mFab || null == mEditPanel) {
                    return;
                }
                ((View) mFab).setVisibility(View.INVISIBLE);
                mEditPanel.setVisibility(View.VISIBLE);
                int halfW = mEditPanel.getWidth() / 2;
                int halfH = mEditPanel.getHeight() / 2;
                Animator animator = ViewAnimationUtils.createCircularReveal(mEditPanel, halfW, halfH, 0, (float) Math.hypot(halfW, halfH)).setDuration(300L);
                animator.addListener(new SimpleAnimatorListener() {

                    @Override
                    public void onAnimationEnd(Animator a) {
                        mInAnimation = false;
                    }
                });
                animator.start();
            }
        }).start();
    }

    private void showEditPanel(boolean animation) {
        if (animation) {
            showEditPanelWithAnimation();
        } else {
            if (null == mFab || null == mEditPanel) {
                return;
            }
            ((View) mFab).setVisibility(View.INVISIBLE);
            mEditPanel.setVisibility(View.VISIBLE);
        }
    }

    private void hideEditPanelWithAnimation() {
        if (null == mFab || null == mEditPanel) {
            return;
        }
        mInAnimation = true;
        int halfW = mEditPanel.getWidth() / 2;
        int halfH = mEditPanel.getHeight() / 2;
        Animator animator = ViewAnimationUtils.createCircularReveal(mEditPanel, halfW, halfH, (float) Math.hypot(halfW, halfH), 0.0f).setDuration(300L);
        animator.addListener(new SimpleAnimatorListener() {

            @Override
            public void onAnimationEnd(Animator a) {
                if (null == mFab || null == mEditPanel) {
                    return;
                }
                if (Looper.myLooper() != Looper.getMainLooper()) {
                    // Some devices may run this block in non-UI thread.
                    // It might be a bug of Android OS.
                    // Check it here to avoid crash.
                    return;
                }
                mEditPanel.setVisibility(View.GONE);
                ((View) mFab).setVisibility(View.VISIBLE);
                int fabStartX = mEditPanel.getLeft() + (mEditPanel.getWidth() / 2) - (mFab.getWidth() / 2);
                int fabStartY = mEditPanel.getTop() + (mEditPanel.getHeight() / 2) - (mFab.getHeight() / 2);
                mFab.setX(fabStartX);
                mFab.setY(fabStartY);
                mFab.setScaleX(0.0f);
                mFab.setScaleY(0.0f);
                mFab.setRotation(-45.0f);
                mFab.animate().translationX(0.0f).translationY(0.0f).scaleX(1.0f).scaleY(1.0f).rotation(0.0f).setInterpolator(AnimationUtils.SLOW_FAST_SLOW_INTERPOLATOR).setDuration(300L).setListener(new SimpleAnimatorListener() {

                    @Override
                    public void onAnimationEnd(Animator animation) {
                        mInAnimation = false;
                    }
                }).start();
            }
        });
        animator.start();
    }

    private void hideEditPanel(boolean animation) {
        hideSoftInput();
        if (animation) {
            hideEditPanelWithAnimation();
        } else {
            if (null == mFab || null == mEditPanel) {
                return;
            }
            ((View) mFab).setVisibility(View.VISIBLE);
            mEditPanel.setVisibility(View.INVISIBLE);
        }
    }

    @Nullable
    private String getGalleryDetailUrl() {
        if (mGid != -1 && mToken != null) {
            return EhUrl.getGalleryDetailUrl(mGid, mToken, 0, mShowAllComments);
        } else {
            return null;
        }
    }

    @Override
    public void onClick(View v) {
        Context context = getContext();
        MainActivity activity = getMainActivity();
        if (null == context || null == activity || null == mEditText) {
            return;
        }
        if (mFab == v) {
            if (!mInAnimation) {
                prepareNewComment();
                showEditPanel(true);
            }
        } else if (mSendImage == v) {
            if (!mInAnimation) {
                String comment = mEditText.getText().toString();
                if (TextUtils.isEmpty(comment)) {
                    // Comment is empty
                    return;
                }
                String url = getGalleryDetailUrl();
                if (url == null) {
                    return;
                }
                // Request
                EhRequest request = new EhRequest().setMethod(EhClient.METHOD_GET_COMMENT_GALLERY).setArgs(url, comment, mCommentId != 0 ? Long.toString(mCommentId) : null).setCallback(new CommentGalleryListener(context, activity.getStageId(), getTag(), mCommentId));
                EhApplication.getEhClient(context).execute(request);
                hideSoftInput();
                hideEditPanel(true);
            }
        }
    }

    @Override
    public void onBackPressed() {
        if (mInAnimation) {
            return;
        }
        if (null != mEditPanel && mEditPanel.getVisibility() == View.VISIBLE) {
            hideEditPanel(true);
        } else {
            finish();
        }
    }

    private void onRefreshGallerySuccess(GalleryCommentList result) {
        if (mAdapter == null) {
            return;
        }
        mRefreshLayout.setRefreshing(false);
        mRefreshingComments = false;
        mCommentList = result;
        mAdapter.notifyDataSetChanged();
        updateView(true);
        Bundle re = new Bundle();
        re.putParcelable(KEY_COMMENT_LIST, result);
        setResult(SceneFragment.RESULT_OK, re);
    }

    private void onRefreshGalleryFailure() {
        if (mAdapter == null) {
            return;
        }
        mRefreshLayout.setRefreshing(false);
        mRefreshingComments = false;
        int position = mAdapter.gereplacedemCount() - 1;
        if (position >= 0) {
            mAdapter.notifyItemChanged(position);
        }
    }

    private void onCommentGallerySuccess(GalleryCommentList result) {
        if (mAdapter == null) {
            return;
        }
        mCommentList = result;
        mAdapter.notifyDataSetChanged();
        Bundle re = new Bundle();
        re.putParcelable(KEY_COMMENT_LIST, result);
        setResult(SceneFragment.RESULT_OK, re);
        // Remove text
        if (mEditText != null) {
            mEditText.setText("");
        }
        updateView(true);
    }

    private void onVoteCommentSuccess(VoteCommentParser.Result result) {
        if (mAdapter == null || mCommentList == null || mCommentList.comments == null) {
            return;
        }
        int position = -1;
        for (int i = 0, n = mCommentList.comments.length; i < n; i++) {
            GalleryComment comment = mCommentList.comments[i];
            if (comment.id == result.id) {
                position = i;
                break;
            }
        }
        if (-1 == position) {
            Log.d(TAG, "Can't find comment with id " + result.id);
            return;
        }
        // Update comment
        GalleryComment comment = mCommentList.comments[position];
        comment.score = result.score;
        if (result.expectVote > 0) {
            comment.voteUpEd = 0 != result.vote;
            comment.voteDownEd = false;
        } else {
            comment.voteDownEd = 0 != result.vote;
            comment.voteUpEd = false;
        }
        mAdapter.notifyItemChanged(position);
        Bundle re = new Bundle();
        re.putParcelable(KEY_COMMENT_LIST, mCommentList);
        setResult(SceneFragment.RESULT_OK, re);
    }

    @Override
    public void onRefresh() {
        if (!mRefreshingComments && mAdapter != null) {
            MainActivity activity = (MainActivity) requireActivity();
            mRefreshingComments = true;
            String url = getGalleryDetailUrl();
            if (url != null) {
                // Request
                EhRequest request = new EhRequest().setMethod(EhClient.METHOD_GET_GALLERY_DETAIL).setArgs(url).setCallback(new RefreshCommentListener(activity, activity.getStageId(), getTag()));
                EhApplication.getEhClient(activity).execute(request);
            }
        }
    }

    private static clreplaced RefreshCommentListener extends EhCallback<GalleryCommentsScene, GalleryDetail> {

        public RefreshCommentListener(Context context, int stageId, String sceneTag) {
            super(context, stageId, sceneTag);
        }

        @Override
        public void onSuccess(GalleryDetail result) {
            GalleryCommentsScene scene = getScene();
            if (scene != null) {
                scene.onRefreshGallerySuccess(result.comments);
            }
        }

        @Override
        public void onFailure(Exception e) {
            GalleryCommentsScene scene = getScene();
            if (scene != null) {
                scene.onRefreshGalleryFailure();
            }
        }

        @Override
        public void onCancel() {
        }

        @Override
        public boolean isInstance(SceneFragment scene) {
            return scene instanceof GalleryCommentsScene;
        }
    }

    private static clreplaced CommentGalleryListener extends EhCallback<GalleryCommentsScene, GalleryCommentList> {

        private final long mCommentId;

        public CommentGalleryListener(Context context, int stageId, String sceneTag, long commentId) {
            super(context, stageId, sceneTag);
            mCommentId = commentId;
        }

        @Override
        public void onSuccess(GalleryCommentList result) {
            showTip(mCommentId != 0 ? R.string.edit_comment_successfully : R.string.comment_successfully, LENGTH_SHORT);
            GalleryCommentsScene scene = getScene();
            if (scene != null) {
                scene.onCommentGallerySuccess(result);
            }
        }

        @Override
        public void onFailure(Exception e) {
            showTip(getContent().getString(mCommentId != 0 ? R.string.edit_comment_failed : R.string.comment_failed) + "\n" + ExceptionUtils.getReadableString(e), LENGTH_LONG);
        }

        @Override
        public void onCancel() {
        }

        @Override
        public boolean isInstance(SceneFragment scene) {
            return scene instanceof GalleryCommentsScene;
        }
    }

    private static clreplaced VoteCommentListener extends EhCallback<GalleryCommentsScene, VoteCommentParser.Result> {

        public VoteCommentListener(Context context, int stageId, String sceneTag) {
            super(context, stageId, sceneTag);
        }

        @Override
        public void onSuccess(VoteCommentParser.Result result) {
            showTip(result.expectVote > 0 ? (0 != result.vote ? R.string.vote_up_successfully : R.string.cancel_vote_up_successfully) : (0 != result.vote ? R.string.vote_down_successfully : R.string.cancel_vote_down_successfully), LENGTH_SHORT);
            GalleryCommentsScene scene = getScene();
            if (scene != null) {
                scene.onVoteCommentSuccess(result);
            }
        }

        @Override
        public void onFailure(Exception e) {
            showTip(R.string.vote_failed, LENGTH_LONG);
        }

        @Override
        public void onCancel() {
        }

        @Override
        public boolean isInstance(SceneFragment scene) {
            return scene instanceof GalleryCommentsScene;
        }
    }

    private static clreplaced InfoHolder extends RecyclerView.ViewHolder {

        private final TextView key;

        private final TextView value;

        public InfoHolder(View itemView) {
            super(itemView);
            key = (TextView) ViewUtils.$$(itemView, R.id.key);
            value = (TextView) ViewUtils.$$(itemView, R.id.value);
        }
    }

    private abstract static clreplaced CommentHolder extends RecyclerView.ViewHolder {

        public CommentHolder(LayoutInflater inflater, int resId, ViewGroup parent) {
            super(inflater.inflate(resId, parent, false));
        }
    }

    private clreplaced ActualCommentHolder extends CommentHolder {

        private final TextView user;

        private final TextView time;

        private final LinkifyTextView comment;

        public ActualCommentHolder(LayoutInflater inflater, ViewGroup parent) {
            super(inflater, R.layout.item_gallery_comment, parent);
            user = itemView.findViewById(R.id.user);
            time = itemView.findViewById(R.id.time);
            comment = itemView.findViewById(R.id.comment);
        }

        private CharSequence generateComment(Context context, ObservedTextView textView, GalleryComment comment) {
            SpannableStringBuilder ssb = Html.fromHtml(comment.comment, new URLImageGetter(textView, EhApplication.getConaco(context)), null);
            if (0 != comment.id && 0 != comment.score) {
                int score = comment.score;
                String scoreString = score > 0 ? "+" + score : Integer.toString(score);
                SpannableString ss = new SpannableString(scoreString);
                ss.setSpan(new RelativeSizeSpan(0.8f), 0, scoreString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                ss.setSpan(new StyleSpan(Typeface.BOLD), 0, scoreString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                ss.setSpan(new ForegroundColorSpan(AttrResources.getAttrColor(context, android.R.attr.textColorSecondary)), 0, scoreString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                ssb.append("  ").append(ss);
            }
            if (comment.lastEdited != 0) {
                String str = context.getString(R.string.last_edited, ReadableTime.getTimeAgo(comment.lastEdited));
                SpannableString ss = new SpannableString(str);
                ss.setSpan(new RelativeSizeSpan(0.8f), 0, str.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                ss.setSpan(new StyleSpan(Typeface.BOLD), 0, str.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                ss.setSpan(new ForegroundColorSpan(AttrResources.getAttrColor(context, android.R.attr.textColorSecondary)), 0, str.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                ssb.append("\n\n").append(ss);
            }
            LinkifyCompat.addLinks(ssb, Linkify.WEB_URLS);
            return ssb;
        }

        public void bind(GalleryComment value) {
            user.setText(value.uploader ? getString(R.string.comment_user_uploader, value.user) : value.user);
            user.setOnClickListener(v -> {
                ListUrlBuilder lub = new ListUrlBuilder();
                lub.setMode(ListUrlBuilder.MODE_UPLOADER);
                lub.setKeyword(value.user);
                GalleryListScene.startScene(GalleryCommentsScene.this, lub);
            });
            time.setText(ReadableTime.getTimeAgo(value.time));
            comment.setText(generateComment(comment.getContext(), comment, value));
        }
    }

    private static clreplaced MoreCommentHolder extends CommentHolder {

        public MoreCommentHolder(LayoutInflater inflater, ViewGroup parent) {
            super(inflater, R.layout.item_gallery_comment_more, parent);
        }
    }

    private static clreplaced ProgressCommentHolder extends CommentHolder {

        public ProgressCommentHolder(LayoutInflater inflater, ViewGroup parent) {
            super(inflater, R.layout.item_gallery_comment_progress, parent);
        }
    }

    private clreplaced CommentAdapter extends RecyclerView.Adapter<CommentHolder> {

        private final LayoutInflater mInflater;

        public CommentAdapter() {
            mInflater = getLayoutInflater();
            replacedertUtils.replacedertNotNull(mInflater);
        }

        @NonNull
        @Override
        public CommentHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            switch(viewType) {
                case TYPE_COMMENT:
                    return new ActualCommentHolder(mInflater, parent);
                case TYPE_MORE:
                    return new MoreCommentHolder(mInflater, parent);
                case TYPE_PROGRESS:
                    return new ProgressCommentHolder(mInflater, parent);
                default:
                    throw new IllegalStateException("Invalid view type: " + viewType);
            }
        }

        @Override
        public void onBindViewHolder(@NonNull CommentHolder holder, int position) {
            Context context = getContext();
            if (context == null || mCommentList == null) {
                return;
            }
            holder.itemView.setOnClickListener(v -> onItemClick(mRecyclerView, holder.itemView, position));
            holder.itemView.setClickable(true);
            holder.itemView.setFocusable(true);
            if (holder instanceof ActualCommentHolder) {
                ((ActualCommentHolder) holder).bind(mCommentList.comments[position]);
            }
        }

        @Override
        public int gereplacedemCount() {
            if (mCommentList == null || mCommentList.comments == null) {
                return 0;
            } else if (mCommentList.hasMore) {
                return mCommentList.comments.length + 1;
            } else {
                return mCommentList.comments.length;
            }
        }

        @Override
        public int gereplacedemViewType(int position) {
            if (position >= mCommentList.comments.length) {
                return mRefreshingComments ? TYPE_PROGRESS : TYPE_MORE;
            } else {
                return TYPE_COMMENT;
            }
        }
    }

    @Override
    public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
        Insets insets1 = insets.getInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.ime());
        v.setPadding(insets1.left, 0, insets1.right, 0);
        View statusBarBackground = v.findViewById(R.id.status_bar_background);
        statusBarBackground.getLayoutParams().height = insets1.top;
        statusBarBackground.setBackgroundColor(AttrResources.getAttrColor(requireContext(), R.attr.colorPrimaryDark));
        if (mFabLayout != null) {
            int corner_fab_margin = getResources().getDimensionPixelOffset(R.dimen.corner_fab_margin);
            mFabLayout.setPadding(mFabLayout.getPaddingLeft(), mFabLayout.getPaddingTop(), mFabLayout.getPaddingRight(), corner_fab_margin + insets1.bottom);
        }
        if (mEditPanel != null) {
            mEditPanel.setPadding(mEditPanel.getPaddingLeft(), mEditPanel.getPaddingTop(), mEditPanel.getPaddingRight(), insets1.bottom);
        }
        if (mRecyclerView != null) {
            int paddingBottomFab = getResources().getDimensionPixelOffset(R.dimen.gallery_padding_bottom_fab);
            mRecyclerView.setPadding(mRecyclerView.getPaddingLeft(), mRecyclerView.getPaddingTop(), mRecyclerView.getPaddingRight(), paddingBottomFab + insets1.bottom);
        }
        return WindowInsetsCompat.CONSUMED;
    }
}

16 Source : GalleryCommentsScene.java
with Apache License 2.0
from duzhaokun123

public boolean onItemClick(EasyRecyclerView parent, View view, int position) {
    MainActivity activity = getMainActivity();
    if (null == activity) {
        return false;
    }
    RecyclerView.ViewHolder holder = parent.getChildViewHolder(view);
    if (holder instanceof ActualCommentHolder) {
        ActualCommentHolder commentHolder = (ActualCommentHolder) holder;
        ClickableSpan span = commentHolder.comment.getCurrentSpan();
        commentHolder.comment.clearCurrentSpan();
        if (span instanceof URLSpan) {
            UrlOpener.openUrl(activity, ((URLSpan) span).getURL(), true);
        } else {
            showCommentDialog(position);
        }
    } else if (holder instanceof MoreCommentHolder && !mRefreshingComments && mAdapter != null) {
        mRefreshingComments = true;
        mShowAllComments = true;
        mAdapter.notifyItemChanged(position);
        String url = getGalleryDetailUrl();
        if (url != null) {
            // Request
            EhRequest request = new EhRequest().setMethod(EhClient.METHOD_GET_GALLERY_DETAIL).setArgs(url).setCallback(new RefreshCommentListener(activity, activity.getStageId(), getTag()));
            EhApplication.getEhClient(activity).execute(request);
        }
    }
    return true;
}

16 Source : GalleryCommentsScene.java
with Apache License 2.0
from axlecho

public final clreplaced GalleryCommentsScene extends ToolbarScene implements EasyRecyclerView.OnItemClickListener, View.OnClickListener {

    public static final String TAG = GalleryCommentsScene.clreplaced.getSimpleName();

    public static final String KEY_API_UID = "api_uid";

    public static final String KEY_API_KEY = "api_key";

    public static final String KEY_GID = "gid";

    public static final String KEY_TOKEN = "token";

    public static final String KEY_COMMENTS = "comments";

    private long mApiUid;

    private String mApiKey;

    private String mGid;

    private String mToken;

    @Nullable
    private GalleryComment[] mComments;

    @Nullable
    private EasyRecyclerView mRecyclerView;

    @Nullable
    private FabLayout mFabLayout;

    @Nullable
    private FloatingActionButton mFab;

    @Nullable
    private View mEditPanel;

    @Nullable
    private ImageView mSendImage;

    @Nullable
    private EditText mEditText;

    @Nullable
    private CommentAdapter mAdapter;

    @Nullable
    private ViewTransition mViewTransition;

    private boolean mInAnimation = false;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState == null) {
            onInit();
        } else {
            onRestore(savedInstanceState);
        }
    }

    private void handleArgs(Bundle args) {
        if (args == null) {
            return;
        }
        mApiUid = args.getLong(KEY_API_UID, -1L);
        mApiKey = args.getString(KEY_API_KEY);
        mGid = args.getString(KEY_GID);
        mToken = args.getString(KEY_TOKEN, null);
        Parcelable[] parcelables = args.getParcelableArray(KEY_COMMENTS);
        if (parcelables instanceof GalleryComment[]) {
            mComments = (GalleryComment[]) parcelables;
        }
    }

    private void onInit() {
        handleArgs(getArguments());
    }

    private void onRestore(@NonNull Bundle savedInstanceState) {
        mApiUid = savedInstanceState.getLong(KEY_API_UID, -1L);
        mApiKey = savedInstanceState.getString(KEY_API_KEY);
        mGid = savedInstanceState.getString(KEY_GID);
        mToken = savedInstanceState.getString(KEY_TOKEN, null);
        Parcelable[] parcelables = savedInstanceState.getParcelableArray(KEY_COMMENTS);
        if (parcelables instanceof GalleryComment[]) {
            mComments = (GalleryComment[]) parcelables;
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putLong(KEY_API_UID, mApiUid);
        outState.putString(KEY_API_KEY, mApiKey);
        outState.putString(KEY_GID, mGid);
        outState.putString(KEY_TOKEN, mToken);
        outState.putParcelableArray(KEY_COMMENTS, mComments);
    }

    @Nullable
    @Override
    public View onCreateView3(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.scene_gallery_comments, container, false);
        mRecyclerView = (EasyRecyclerView) ViewUtils.$$(view, R.id.recycler_view);
        TextView tip = (TextView) ViewUtils.$$(view, R.id.tip);
        mEditPanel = ViewUtils.$$(view, R.id.edit_panel);
        mSendImage = (ImageView) ViewUtils.$$(mEditPanel, R.id.send);
        mEditText = (EditText) ViewUtils.$$(mEditPanel, R.id.edit_text);
        mFabLayout = (FabLayout) ViewUtils.$$(view, R.id.fab_layout);
        mFab = (FloatingActionButton) ViewUtils.$$(view, R.id.fab);
        Context context = getContext2();
        replacedertUtils.replacedertNotNull(context);
        Resources resources = context.getResources();
        int paddingBottomFab = resources.getDimensionPixelOffset(R.dimen.gallery_padding_bottom_fab);
        Drawable drawable = DrawableManager.getVectorDrawable(context, R.drawable.big_sad_pandroid);
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        tip.setCompoundDrawables(null, drawable, null, null);
        mAdapter = new CommentAdapter();
        mRecyclerView.setAdapter(mAdapter);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(context, RecyclerView.VERTICAL, false));
        LinearDividerItemDecoration decoration = new LinearDividerItemDecoration(LinearDividerItemDecoration.VERTICAL, AttrResources.getAttrColor(context, R.attr.dividerColor), LayoutUtils.dp2pix(context, 1));
        decoration.setShowLastDivider(true);
        mRecyclerView.addItemDecoration(decoration);
        mRecyclerView.setSelector(Ripple.generateRippleDrawable(context, !AttrResources.getAttrBoolean(context, R.attr.isLightTheme), new ColorDrawable(Color.TRANSPARENT)));
        mRecyclerView.setHasFixedSize(true);
        mRecyclerView.setOnItemClickListener(this);
        mRecyclerView.setPadding(mRecyclerView.getPaddingLeft(), mRecyclerView.getPaddingTop(), mRecyclerView.getPaddingRight(), mRecyclerView.getPaddingBottom() + paddingBottomFab);
        // Cancel change animator
        RecyclerView.ItemAnimator itemAnimator = mRecyclerView.gereplacedemAnimator();
        if (itemAnimator instanceof DefaulreplacedemAnimator) {
            ((DefaulreplacedemAnimator) itemAnimator).setSupportsChangeAnimations(false);
        }
        mSendImage.setOnClickListener(this);
        mFab.setOnClickListener(this);
        addAboveSnackView(mEditPanel);
        addAboveSnackView(mFabLayout);
        mViewTransition = new ViewTransition(mRecyclerView, tip);
        updateView(false);
        return view;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (null != mRecyclerView) {
            mRecyclerView.stopScroll();
            mRecyclerView = null;
        }
        if (null != mEditPanel) {
            removeAboveSnackView(mEditPanel);
            mEditPanel = null;
        }
        if (null != mFabLayout) {
            removeAboveSnackView(mFabLayout);
            mFabLayout = null;
        }
        mFab = null;
        mSendImage = null;
        mEditText = null;
        mAdapter = null;
        mViewTransition = null;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        setreplacedle(R.string.gallery_comments);
        setNavigationIcon(R.drawable.v_arrow_left_dark_x24);
    }

    @Override
    public void onNavigationClick() {
        onBackPressed();
    }

    private void voteComment(long id, int vote) {
        Context context = getContext2();
        MainActivity activity = getActivity2();
        if (null == context || null == activity) {
            return;
        }
        EhRequest request = new EhRequest().setMethod(EhClient.METHOD_VOTE_COMMENT).setArgs(mApiUid, mApiKey, mGid, mToken, id, vote).setCallback(new VoteCommentListener(context, activity.getStageId(), getTag()));
        EhApplication.getEhClient(context).execute(request);
    }

    private clreplaced InfoHolder extends RecyclerView.ViewHolder {

        private final TextView key;

        private final TextView value;

        public InfoHolder(View itemView) {
            super(itemView);
            key = (TextView) ViewUtils.$$(itemView, R.id.key);
            value = (TextView) ViewUtils.$$(itemView, R.id.value);
        }
    }

    @SuppressLint("InflateParams")
    public void showVoteStatusDialog(Context context, String voteStatus) {
        String[] temp = StringUtils.split(voteStatus, ',');
        final int length = temp.length;
        final String[] userArray = new String[length];
        final String[] voteArray = new String[length];
        for (int i = 0; i < length; i++) {
            String str = StringUtils.trim(temp[i]);
            int index = str.lastIndexOf(' ');
            if (index < 0) {
                Log.d(TAG, "Something wrong happened about vote state");
                userArray[i] = str;
                voteArray[i] = "";
            } else {
                userArray[i] = StringUtils.trim(str.substring(0, index));
                voteArray[i] = StringUtils.trim(str.substring(index + 1));
            }
        }
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        context = builder.getContext();
        final LayoutInflater inflater = LayoutInflater.from(context);
        EasyRecyclerView rv = (EasyRecyclerView) inflater.inflate(R.layout.dialog_recycler_view, null);
        rv.setAdapter(new RecyclerView.Adapter<InfoHolder>() {

            @Override
            public InfoHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                return new InfoHolder(inflater.inflate(R.layout.item_drawer_favorites, parent, false));
            }

            @Override
            public void onBindViewHolder(InfoHolder holder, int position) {
                holder.key.setText(userArray[position]);
                holder.value.setText(voteArray[position]);
            }

            @Override
            public int gereplacedemCount() {
                return length;
            }
        });
        rv.setLayoutManager(new LinearLayoutManager(context));
        LinearDividerItemDecoration decoration = new LinearDividerItemDecoration(LinearDividerItemDecoration.VERTICAL, AttrResources.getAttrColor(context, R.attr.dividerColor), LayoutUtils.dp2pix(context, 1));
        decoration.setPadding(ResourcesUtils.getAttrDimensionPixelOffset(context, R.attr.dialogPreferredPadding));
        rv.addItemDecoration(decoration);
        rv.setSelector(Ripple.generateRippleDrawable(context, !AttrResources.getAttrBoolean(context, R.attr.isLightTheme), new ColorDrawable(Color.TRANSPARENT)));
        rv.setClipToPadding(false);
        builder.setView(rv).show();
    }

    private void showCommentDialog(int position) {
        final Context context = getContext2();
        if (null == context || null == mComments || position >= mComments.length || position < 0) {
            return;
        }
        final GalleryComment comment = mComments[position];
        List<String> menu = new ArrayList<>();
        final IntList menuId = new IntList();
        Resources resources = context.getResources();
        if (0 == comment.id || mApiUid < 0) {
            // 0 id is uploader comment, can't vote
            // Not sign in, can't vote
            menu.add(resources.getString(R.string.copy_comment_text));
            menuId.add(R.id.copy);
        } else {
            menu.add(resources.getString(R.string.copy_comment_text));
            menuId.add(R.id.copy);
            menu.add(resources.getString(comment.voteUp ? R.string.cancel_vote_up : R.string.vote_up));
            menuId.add(R.id.vote_up);
            menu.add(resources.getString(comment.voteDown ? R.string.cancel_vote_down : R.string.vote_down));
            menuId.add(R.id.vote_down);
        }
        if (!TextUtils.isEmpty(comment.voteState)) {
            menu.add(resources.getString(R.string.check_vote_status));
            menuId.add(R.id.check_vote_status);
        }
        new AlertDialog.Builder(context).sereplacedems(menu.toArray(new String[menu.size()]), new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (which < 0 || which >= menuId.size()) {
                    return;
                }
                int id = menuId.get(which);
                switch(id) {
                    case R.id.copy:
                        ClipboardManager cmb = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
                        cmb.setPrimaryClip(ClipData.newPlainText(null, comment.comment));
                        showTip(R.string.copied_to_clipboard, LENGTH_SHORT);
                        break;
                    case R.id.vote_up:
                        voteComment(comment.id, 1);
                        break;
                    case R.id.vote_down:
                        voteComment(comment.id, -1);
                        break;
                    case R.id.check_vote_status:
                        showVoteStatusDialog(context, comment.voteState);
                        break;
                }
            }
        }).show();
    }

    @Override
    public boolean onItemClick(EasyRecyclerView parent, View view, int position, long id) {
        Activity activity = getActivity2();
        if (null == activity) {
            return false;
        }
        RecyclerView.ViewHolder holder = parent.getChildViewHolder(view);
        if (holder instanceof CommentHolder) {
            CommentHolder commentHolder = (CommentHolder) holder;
            ClickableSpan span = commentHolder.comment.getCurrentSpan();
            commentHolder.comment.clearCurrentSpan();
            if (span instanceof URLSpan) {
                UrlOpener.openUrl(activity, ((URLSpan) span).getURL(), true);
                return true;
            }
        }
        showCommentDialog(position);
        return true;
    }

    private void updateView(boolean animation) {
        if (null == mViewTransition) {
            return;
        }
        if (mComments == null || mComments.length <= 0) {
            mViewTransition.showView(1, animation);
        } else {
            mViewTransition.showView(0, animation);
        }
    }

    private void showEditPanelWithAnimation() {
        if (null == mFab || null == mEditPanel) {
            return;
        }
        mInAnimation = true;
        mFab.setTranslationX(0.0f);
        mFab.setTranslationY(0.0f);
        mFab.setScaleX(1.0f);
        mFab.setScaleY(1.0f);
        int fabEndX = mEditPanel.getLeft() + (mEditPanel.getWidth() / 2) - (mFab.getWidth() / 2);
        int fabEndY = mEditPanel.getTop() + (mEditPanel.getHeight() / 2) - (mFab.getHeight() / 2);
        mFab.animate().x(fabEndX).y(fabEndY).scaleX(0.0f).scaleY(0.0f).setInterpolator(AnimationUtils.SLOW_FAST_SLOW_INTERPOLATOR).setDuration(300L).setListener(new SimpleAnimatorListener() {

            @Override
            public void onAnimationEnd(Animator animation) {
                if (null == mFab || null == mEditPanel) {
                    return;
                }
                ((View) mFab).setVisibility(View.INVISIBLE);
                mEditPanel.setVisibility(View.VISIBLE);
                int halfW = mEditPanel.getWidth() / 2;
                int halfH = mEditPanel.getHeight() / 2;
                Animator animator = ViewAnimationUtils.createCircularReveal(mEditPanel, halfW, halfH, 0, (float) Math.hypot(halfW, halfH)).setDuration(300L);
                animator.addListener(new SimpleAnimatorListener() {

                    @Override
                    public void onAnimationEnd(Animator a) {
                        mInAnimation = false;
                    }
                });
                animator.start();
            }
        }).start();
    }

    private void showEditPanel(boolean animation) {
        if (animation) {
            showEditPanelWithAnimation();
        } else {
            if (null == mFab || null == mEditPanel) {
                return;
            }
            ((View) mFab).setVisibility(View.INVISIBLE);
            mEditPanel.setVisibility(View.VISIBLE);
        }
    }

    private void hideEditPanelWithAnimation() {
        if (null == mFab || null == mEditPanel) {
            return;
        }
        mInAnimation = true;
        int halfW = mEditPanel.getWidth() / 2;
        int halfH = mEditPanel.getHeight() / 2;
        Animator animator = ViewAnimationUtils.createCircularReveal(mEditPanel, halfW, halfH, (float) Math.hypot(halfW, halfH), 0.0f).setDuration(300L);
        animator.addListener(new SimpleAnimatorListener() {

            @Override
            public void onAnimationEnd(Animator a) {
                if (null == mFab || null == mEditPanel) {
                    return;
                }
                if (Looper.myLooper() != Looper.getMainLooper()) {
                    // Some devices may run this block in non-UI thread.
                    // It might be a bug of Android OS.
                    // Check it here to avoid crash.
                    return;
                }
                mEditPanel.setVisibility(View.GONE);
                ((View) mFab).setVisibility(View.VISIBLE);
                int fabStartX = mEditPanel.getLeft() + (mEditPanel.getWidth() / 2) - (mFab.getWidth() / 2);
                int fabStartY = mEditPanel.getTop() + (mEditPanel.getHeight() / 2) - (mFab.getHeight() / 2);
                mFab.setX(fabStartX);
                mFab.setY(fabStartY);
                mFab.setScaleX(0.0f);
                mFab.setScaleY(0.0f);
                mFab.setRotation(-45.0f);
                mFab.animate().translationX(0.0f).translationY(0.0f).scaleX(1.0f).scaleY(1.0f).rotation(0.0f).setInterpolator(AnimationUtils.SLOW_FAST_SLOW_INTERPOLATOR).setDuration(300L).setListener(new SimpleAnimatorListener() {

                    @Override
                    public void onAnimationEnd(Animator animation) {
                        mInAnimation = false;
                    }
                }).start();
            }
        });
        animator.start();
    }

    private void hideEditPanel(boolean animation) {
        if (animation) {
            hideEditPanelWithAnimation();
        } else {
            if (null == mFab || null == mEditPanel) {
                return;
            }
            ((View) mFab).setVisibility(View.VISIBLE);
            mEditPanel.setVisibility(View.INVISIBLE);
        }
    }

    @Nullable
    private String getGalleryDetailUrl() {
        return MHApi.Companion.getINSTANCE().get(currentSource).pageUrl(mGid);
    }

    @Override
    public void onClick(View v) {
        Context context = getContext2();
        MainActivity activity = getActivity2();
        if (null == context || null == activity || null == mEditText) {
            return;
        }
        if (mFab == v) {
            if (!mInAnimation) {
                showEditPanel(true);
            }
        } else if (mSendImage == v) {
            if (!mInAnimation) {
                String comment = mEditText.getText().toString();
                if (TextUtils.isEmpty(comment)) {
                    // Comment is empty
                    return;
                }
                String url = getGalleryDetailUrl();
                if (url == null) {
                    return;
                }
                // Request
                EhRequest request = new EhRequest().setMethod(EhClient.METHOD_GET_COMMENT_GALLERY).setArgs(url, comment).setCallback(new CommentGalleryListener(context, activity.getStageId(), getTag()));
                EhApplication.getEhClient(context).execute(request);
                hideSoftInput();
                hideEditPanel(true);
            }
        }
    }

    @Override
    public void onBackPressed() {
        if (mInAnimation) {
            return;
        }
        if (null != mEditPanel && mEditPanel.getVisibility() == View.VISIBLE) {
            hideEditPanel(true);
        } else {
            finish();
        }
    }

    private clreplaced CommentHolder extends RecyclerView.ViewHolder {

        public final TextView user;

        public final TextView time;

        public final LinkifyTextView comment;

        public CommentHolder(View itemView) {
            super(itemView);
            user = (TextView) itemView.findViewById(R.id.user);
            time = (TextView) itemView.findViewById(R.id.time);
            comment = (LinkifyTextView) itemView.findViewById(R.id.comment);
        }
    }

    private clreplaced CommentAdapter extends RecyclerView.Adapter<CommentHolder> {

        private final LayoutInflater mInflater;

        public CommentAdapter() {
            mInflater = getLayoutInflater2();
            replacedertUtils.replacedertNotNull(mInflater);
        }

        @Override
        public CommentHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            return new CommentHolder(mInflater.inflate(R.layout.item_gallery_comment, parent, false));
        }

        public CharSequence generateComment(Context context, ObservedTextView textView, GalleryComment comment) {
            SpannableStringBuilder ssb = Html.fromHtml(comment.comment, new URLImageGetter(textView, EhApplication.getConaco(context)), null);
            if (0 != comment.id && 0 != comment.score) {
                int score = comment.score;
                String scoreString = score > 0 ? "+" + score : Integer.toString(score);
                SpannableString ss = new SpannableString(scoreString);
                ss.setSpan(new RelativeSizeSpan(0.8f), 0, scoreString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                ss.setSpan(new StyleSpan(Typeface.BOLD), 0, scoreString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                ss.setSpan(new ForegroundColorSpan(AttrResources.getAttrColor(context, android.R.attr.textColorSecondary)), 0, scoreString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                ssb.append("  ").append(ss);
            }
            return TextUrl.handleTextUrl(ssb);
        }

        @Override
        public void onBindViewHolder(CommentHolder holder, int position) {
            Context context = getContext2();
            if (null == context || null == mComments) {
                return;
            }
            GalleryComment comment = mComments[position];
            holder.user.setText(comment.user);
            holder.time.setText(comment.time);
            holder.comment.setText(generateComment(context, holder.comment, comment));
        }

        @Override
        public int gereplacedemCount() {
            return mComments == null ? 0 : mComments.length;
        }
    }

    private void onCommentGallerySuccess(GalleryComment[] result) {
        if (null == mAdapter) {
            return;
        }
        mComments = result;
        mAdapter.notifyDataSetChanged();
        Bundle re = new Bundle();
        re.putParcelableArray(KEY_COMMENTS, result);
        setResult(SceneFragment.RESULT_OK, re);
        // Remove text
        if (mEditText != null) {
            mEditText.setText("");
        }
        updateView(true);
    }

    private void onVoteCommentSuccess(VoteCommentParser.Result result) {
        if (null == mAdapter || null == mComments) {
            return;
        }
        int position = -1;
        for (int i = 0, n = mComments.length; i < n; i++) {
            GalleryComment comment = mComments[i];
            if (comment.id == result.id) {
                position = i;
                break;
            }
        }
        if (-1 == position) {
            Log.d(TAG, "Can't find comment with id " + result.id);
            return;
        }
        // Update comment
        GalleryComment comment = mComments[position];
        comment.score = result.score;
        if (result.expectVote > 0) {
            comment.voteUp = 0 != result.vote;
            comment.voteDown = false;
        } else {
            comment.voteDown = 0 != result.vote;
            comment.voteUp = false;
        }
        mAdapter.notifyItemChanged(position);
        Bundle re = new Bundle();
        re.putParcelableArray(KEY_COMMENTS, mComments);
        setResult(SceneFragment.RESULT_OK, re);
    }

    private static clreplaced CommentGalleryListener extends EhCallback<GalleryCommentsScene, GalleryComment[]> {

        public CommentGalleryListener(Context context, int stageId, String sceneTag) {
            super(context, stageId, sceneTag);
        }

        @Override
        public void onSuccess(GalleryComment[] result) {
            showTip(R.string.comment_successfully, LENGTH_SHORT);
            GalleryCommentsScene scene = getScene();
            if (scene != null) {
                scene.onCommentGallerySuccess(result);
            }
        }

        @Override
        public void onFailure(Exception e) {
            showTip(getContent().getString(R.string.comment_failed) + "\n" + ExceptionUtils.getReadableString(e), LENGTH_LONG);
        }

        @Override
        public void onCancel() {
        }

        @Override
        public boolean isInstance(SceneFragment scene) {
            return scene instanceof GalleryCommentsScene;
        }
    }

    private static clreplaced VoteCommentListener extends EhCallback<GalleryCommentsScene, VoteCommentParser.Result> {

        public VoteCommentListener(Context context, int stageId, String sceneTag) {
            super(context, stageId, sceneTag);
        }

        @Override
        public void onSuccess(VoteCommentParser.Result result) {
            showTip(result.expectVote > 0 ? (0 != result.vote ? R.string.vote_up_successfully : R.string.cancel_vote_up_successfully) : (0 != result.vote ? R.string.vote_down_successfully : R.string.cancel_vote_down_successfully), LENGTH_SHORT);
            GalleryCommentsScene scene = getScene();
            if (scene != null) {
                scene.onVoteCommentSuccess(result);
            }
        }

        @Override
        public void onFailure(Exception e) {
            showTip(R.string.vote_failed, LENGTH_LONG);
        }

        @Override
        public void onCancel() {
        }

        @Override
        public boolean isInstance(SceneFragment scene) {
            return scene instanceof GalleryCommentsScene;
        }
    }

    @Override
    public void loadSource() {
    }
}

15 Source : FavoritesScene.java
with Apache License 2.0
from NuclearVGA

@Override
@Implemented(EasyRecyclerView.CustomChoiceListener.clreplaced)
public void onIntoCustomChoice(EasyRecyclerView view) {
    if (mFabLayout != null) {
        showSelectionFabs();
        mFabLayout.setAutoCancel(false);
        // Delay expanding action to make layout work fine
        SimpleHandler.getInstance().post(() -> mFabLayout.setExpanded(true));
    }
    if (mHelper != null) {
        mHelper.setRefreshLayoutEnable(false);
    }
    // Lock drawer
    setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, Gravity.LEFT);
    setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, Gravity.RIGHT);
}

14 Source : DownloadsScene.java
with Apache License 2.0
from xiaojieonly

public clreplaced DownloadsScene extends ToolbarScene implements DownloadManager.DownloadInfoListener, EasyRecyclerView.OnItemClickListener, EasyRecyclerView.OnItemLongClickListener, FabLayout.OnClickFabListener, FastScroller.OnDragHandlerListener {

    private static final String TAG = DownloadsScene.clreplaced.getSimpleName();

    public static final String KEY_GID = "gid";

    public static final String KEY_ACTION = "action";

    private static final String KEY_LABEL = "label";

    public static final String ACTION_CLEAR_DOWNLOAD_SERVICE = "clear_download_service";

    /*---------------
     Whole life cycle
     ---------------*/
    @Nullable
    private DownloadManager mDownloadManager;

    @Nullable
    private String mLabel;

    @Nullable
    private List<DownloadInfo> mList;

    /*---------------
     View life cycle
     ---------------*/
    @Nullable
    private EasyRecyclerView mRecyclerView;

    @Nullable
    private ViewTransition mViewTransition;

    @Nullable
    private FabLayout mFabLayout;

    @Nullable
    private DownloadAdapter mAdapter;

    @Nullable
    private AutoStaggeredGridLayoutManager mLayoutManager;

    private ShowcaseView mShowcaseView;

    private int mInitPosition = -1;

    @Override
    public int getNavCheckedItem() {
        return R.id.nav_downloads;
    }

    private boolean handleArguments(Bundle args) {
        if (null == args) {
            return false;
        }
        if (ACTION_CLEAR_DOWNLOAD_SERVICE.equals(args.getString(KEY_ACTION))) {
            DownloadService.clear();
        }
        long gid;
        if (null != mDownloadManager && -1L != (gid = args.getLong(KEY_GID, -1L))) {
            DownloadInfo info = mDownloadManager.getDownloadInfo(gid);
            if (null != info) {
                mLabel = info.getLabel();
                updateForLabel();
                updateView();
                // Get position
                if (null != mList) {
                    int position = mList.indexOf(info);
                    if (position >= 0 && null != mRecyclerView) {
                        mRecyclerView.scrollToPosition(position);
                    } else {
                        mInitPosition = position;
                    }
                }
                return true;
            }
        }
        return false;
    }

    @Override
    public void onNewArguments(@NonNull Bundle args) {
        handleArguments(args);
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Context context = getContext2();
        replacedertUtils.replacedertNotNull(context);
        mDownloadManager = EhApplication.getDownloadManager(context);
        mDownloadManager.addDownloadInfoListener(this);
        if (savedInstanceState == null) {
            onInit();
        } else {
            onRestore(savedInstanceState);
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mList = null;
        DownloadManager manager = mDownloadManager;
        if (null == manager) {
            Context context = getContext2();
            if (null != context) {
                manager = EhApplication.getDownloadManager(context);
            }
        } else {
            mDownloadManager = null;
        }
        if (null != manager) {
            manager.removeDownloadInfoListener(this);
        } else {
            Log.e(TAG, "Can't removeDownloadInfoListener");
        }
    }

    private void updateForLabel() {
        if (null == mDownloadManager) {
            return;
        }
        if (mLabel == null) {
            mList = mDownloadManager.getDefaultDownloadInfoList();
        } else {
            mList = mDownloadManager.getLabelDownloadInfoList(mLabel);
            if (mList == null) {
                mLabel = null;
                mList = mDownloadManager.getDefaultDownloadInfoList();
            }
        }
        if (mAdapter != null) {
            mAdapter.notifyDataSetChanged();
        }
        updatereplacedle();
        Settings.putRecentDownloadLabel(mLabel);
    }

    private void updatereplacedle() {
        setreplacedle(getString(R.string.scene_download_replacedle, mLabel != null ? mLabel : getString(R.string.default_download_label_name)));
    }

    private void onInit() {
        if (!handleArguments(getArguments())) {
            mLabel = Settings.getRecentDownloadLabel();
            updateForLabel();
        }
    }

    private void onRestore(@NonNull Bundle savedInstanceState) {
        mLabel = savedInstanceState.getString(KEY_LABEL);
        updateForLabel();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString(KEY_LABEL, mLabel);
    }

    @Nullable
    @Override
    public View onCreateView3(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.scene_download, container, false);
        View content = ViewUtils.$$(view, R.id.content);
        mRecyclerView = (EasyRecyclerView) ViewUtils.$$(content, R.id.recycler_view);
        FastScroller fastScroller = (FastScroller) ViewUtils.$$(content, R.id.fast_scroller);
        mFabLayout = (FabLayout) ViewUtils.$$(view, R.id.fab_layout);
        TextView tip = (TextView) ViewUtils.$$(view, R.id.tip);
        mViewTransition = new ViewTransition(content, tip);
        Context context = getContext2();
        replacedertUtils.replacedertNotNull(content);
        Resources resources = context.getResources();
        Drawable drawable = DrawableManager.getVectorDrawable(context, R.drawable.big_download);
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        tip.setCompoundDrawables(null, drawable, null, null);
        mAdapter = new DownloadAdapter();
        mAdapter.setHreplacedtableIds(true);
        mRecyclerView.setAdapter(mAdapter);
        mLayoutManager = new AutoStaggeredGridLayoutManager(0, StaggeredGridLayoutManager.VERTICAL);
        mLayoutManager.setColumnSize(resources.getDimensionPixelOffset(Settings.getDetailSizeResId()));
        mLayoutManager.setStrategy(AutoStaggeredGridLayoutManager.STRATEGY_MIN_SIZE);
        mRecyclerView.setLayoutManager(mLayoutManager);
        mRecyclerView.setSelector(Ripple.generateRippleDrawable(context, !AttrResources.getAttrBoolean(context, R.attr.isLightTheme), new ColorDrawable(Color.TRANSPARENT)));
        mRecyclerView.setDrawSelectorOnTop(true);
        mRecyclerView.setClipToPadding(false);
        mRecyclerView.setOnItemClickListener(this);
        mRecyclerView.setOnItemLongClickListener(this);
        mRecyclerView.setChoiceMode(EasyRecyclerView.CHOICE_MODE_MULTIPLE_CUSTOM);
        mRecyclerView.setCustomCheckedListener(new DownloadChoiceListener());
        // Cancel change animation
        RecyclerView.ItemAnimator itemAnimator = mRecyclerView.gereplacedemAnimator();
        if (itemAnimator instanceof SimpleItemAnimator) {
            ((SimpleItemAnimator) itemAnimator).setSupportsChangeAnimations(false);
        }
        int interval = resources.getDimensionPixelOffset(R.dimen.gallery_list_interval);
        int paddingH = resources.getDimensionPixelOffset(R.dimen.gallery_list_margin_h);
        int paddingV = resources.getDimensionPixelOffset(R.dimen.gallery_list_margin_v);
        MarginItemDecoration decoration = new MarginItemDecoration(interval, paddingH, paddingV, paddingH, paddingV);
        mRecyclerView.addItemDecoration(decoration);
        decoration.applyPaddings(mRecyclerView);
        if (mInitPosition >= 0) {
            mRecyclerView.scrollToPosition(mInitPosition);
            mInitPosition = -1;
        }
        fastScroller.attachToRecyclerView(mRecyclerView);
        HandlerDrawable handlerDrawable = new HandlerDrawable();
        handlerDrawable.setColor(AttrResources.getAttrColor(context, R.attr.widgetColorThemeAccent));
        fastScroller.setHandlerDrawable(handlerDrawable);
        fastScroller.setOnDragHandlerListener(this);
        mFabLayout.setExpanded(false, false);
        mFabLayout.setHidePrimaryFab(true);
        mFabLayout.setAutoCancel(false);
        mFabLayout.setOnClickFabListener(this);
        addAboveSnackView(mFabLayout);
        updateView();
        guide();
        return view;
    }

    private void guide() {
        if (Settings.getGuideDownloadThumb() && null != mRecyclerView) {
            mRecyclerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

                @Override
                public void onGlobalLayout() {
                    if (Settings.getGuideDownloadThumb()) {
                        guideDownloadThumb();
                    }
                    if (null != mRecyclerView) {
                        ViewUtils.removeOnGlobalLayoutListener(mRecyclerView.getViewTreeObserver(), this);
                    }
                }
            });
        } else {
            guideDownloadLabels();
        }
    }

    private void guideDownloadThumb() {
        MainActivity activity = getActivity2();
        if (null == activity || !Settings.getGuideDownloadThumb() || null == mLayoutManager || null == mRecyclerView) {
            guideDownloadLabels();
            return;
        }
        int position = mLayoutManager.findFirstCompletelyVisibleItemPositions(null)[0];
        if (position < 0) {
            guideDownloadLabels();
            return;
        }
        RecyclerView.ViewHolder holder = mRecyclerView.findViewHolderForAdapterPosition(position);
        if (null == holder) {
            guideDownloadLabels();
            return;
        }
        mShowcaseView = new ShowcaseView.Builder(activity).withMaterialShowcase().setStyle(R.style.Guide).setTarget(new ViewTarget(((DownloadHolder) holder).thumb)).blockAllTouches().setContentreplacedle(R.string.guide_download_thumb_replacedle).setContentText(R.string.guide_download_thumb_text).replaceEndButton(R.layout.button_guide).setShowcaseEventListener(new SimpleShowcaseEventListener() {

            @Override
            public void onShowcaseViewDidHide(ShowcaseView showcaseView) {
                mShowcaseView = null;
                ViewUtils.removeFromParent(showcaseView);
                Settings.putGuideDownloadThumb(false);
                guideDownloadLabels();
            }
        }).build();
    }

    private void guideDownloadLabels() {
        MainActivity activity = getActivity2();
        if (null == activity || !Settings.getGuideDownloadLabels()) {
            return;
        }
        Display display = activity.getWindowManager().getDefaultDisplay();
        Point point = new Point();
        display.getSize(point);
        mShowcaseView = new ShowcaseView.Builder(activity).withMaterialShowcase().setStyle(R.style.Guide).setTarget(new PointTarget(point.x, point.y / 3)).blockAllTouches().setContentreplacedle(R.string.guide_download_labels_replacedle).setContentText(R.string.guide_download_labels_text).replaceEndButton(R.layout.button_guide).setShowcaseEventListener(new SimpleShowcaseEventListener() {

            @Override
            public void onShowcaseViewDidHide(ShowcaseView showcaseView) {
                mShowcaseView = null;
                ViewUtils.removeFromParent(showcaseView);
                Settings.puttGuideDownloadLabels(false);
                openDrawer(Gravity.RIGHT);
            }
        }).build();
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        updatereplacedle();
        setNavigationIcon(R.drawable.v_arrow_left_dark_x24);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (null != mShowcaseView) {
            ViewUtils.removeFromParent(mShowcaseView);
            mShowcaseView = null;
        }
        if (null != mRecyclerView) {
            mRecyclerView.stopScroll();
            mRecyclerView = null;
        }
        if (null != mFabLayout) {
            removeAboveSnackView(mFabLayout);
            mFabLayout = null;
        }
        mRecyclerView = null;
        mViewTransition = null;
        mAdapter = null;
        mLayoutManager = null;
    }

    @Override
    public void onNavigationClick() {
        onBackPressed();
    }

    @Override
    public int getMenuResId() {
        return R.menu.scene_download;
    }

    @Override
    public boolean onMenuItemClick(MenuItem item) {
        // Skip when in choice mode
        Activity activity = getActivity2();
        if (null == activity || null == mRecyclerView || mRecyclerView.isInCustomChoice()) {
            return false;
        }
        int id = item.gereplacedemId();
        switch(id) {
            case R.id.action_start_all:
                {
                    Intent intent = new Intent(activity, DownloadService.clreplaced);
                    intent.setAction(DownloadService.ACTION_START_ALL);
                    activity.startService(intent);
                    return true;
                }
            case R.id.action_stop_all:
                {
                    if (null != mDownloadManager) {
                        mDownloadManager.stopAllDownload();
                    }
                    return true;
                }
            case R.id.action_reset_reading_progress:
                {
                    new AlertDialog.Builder(getContext()).setMessage(R.string.reset_reading_progress_message).setNegativeButton(android.R.string.cancel, null).setPositiveButton(android.R.string.ok, (dialog, which) -> {
                        if (mDownloadManager != null) {
                            mDownloadManager.resetAllReadingProgress();
                        }
                    }).show();
                    return true;
                }
        }
        return false;
    }

    public void updateView() {
        if (mViewTransition != null) {
            if (mList == null || mList.size() == 0) {
                mViewTransition.showView(1);
            } else {
                mViewTransition.showView(0);
            }
        }
    }

    @Override
    public View onCreateDrawerView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.drawer_list, container, false);
        final Context context = getContext2();
        replacedertUtils.replacedertNotNull(context);
        Toolbar toolbar = (Toolbar) view.findViewById(R.id.toolbar);
        toolbar.setreplacedle(R.string.download_labels);
        toolbar.inflateMenu(R.menu.drawer_download);
        toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {

            @Override
            public boolean onMenuItemClick(MenuItem item) {
                int id = item.gereplacedemId();
                switch(id) {
                    case R.id.action_settings:
                        startScene(new Announcer(DownloadLabelsScene.clreplaced));
                        return true;
                    case R.id.action_default_download_label:
                        DownloadManager dm = mDownloadManager;
                        if (null == dm) {
                            return true;
                        }
                        List<DownloadLabel> list = dm.getLabelList();
                        final String[] items = new String[list.size() + 2];
                        items[0] = getString(R.string.let_me_select);
                        items[1] = getString(R.string.default_download_label_name);
                        for (int i = 0, n = list.size(); i < n; i++) {
                            items[i + 2] = list.get(i).getLabel();
                        }
                        new AlertDialog.Builder(context).setreplacedle(R.string.default_download_label).sereplacedems(items, new DialogInterface.OnClickListener() {

                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                if (which == 0) {
                                    Settings.putHasDefaultDownloadLabel(false);
                                } else {
                                    Settings.putHasDefaultDownloadLabel(true);
                                    String label;
                                    if (which == 1) {
                                        label = null;
                                    } else {
                                        label = items[which];
                                    }
                                    Settings.putDefaultDownloadLabel(label);
                                }
                            }
                        }).show();
                        return true;
                }
                return false;
            }
        });
        List<DownloadLabel> list = EhApplication.getDownloadManager(context).getLabelList();
        final List<String> labels = new ArrayList<>(list.size() + 1);
        // Add default label name
        labels.add(getString(R.string.default_download_label_name));
        for (DownloadLabel raw : list) {
            labels.add(raw.getLabel());
        }
        // TODO handle download label items update
        ListView listView = (ListView) view.findViewById(R.id.list_view);
        listView.setAdapter(new ArrayAdapter<>(context, R.layout.item_simple_list, labels));
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                String label;
                if (position == 0) {
                    label = null;
                } else {
                    label = labels.get(position);
                }
                if (!ObjectUtils.equal(label, mLabel)) {
                    mLabel = label;
                    updateForLabel();
                    updateView();
                    closeDrawer(Gravity.RIGHT);
                }
            }
        });
        return view;
    }

    @Override
    public void onBackPressed() {
        if (null != mShowcaseView) {
            return;
        }
        if (mRecyclerView != null && mRecyclerView.isInCustomChoice()) {
            mRecyclerView.outOfCustomChoiceMode();
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public void onStartDragHandler() {
        // Lock right drawer
        setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, Gravity.RIGHT);
    }

    @Override
    public void onEndDragHandler() {
        // Restore right drawer
        if (null != mRecyclerView && !mRecyclerView.isInCustomChoice()) {
            setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, Gravity.RIGHT);
        }
    }

    @Override
    public boolean onItemClick(EasyRecyclerView parent, View view, int position, long id) {
        Activity activity = getActivity2();
        EasyRecyclerView recyclerView = mRecyclerView;
        if (null == activity || null == recyclerView) {
            return false;
        }
        if (recyclerView.isInCustomChoice()) {
            recyclerView.toggleItemChecked(position);
            return true;
        } else {
            List<DownloadInfo> list = mList;
            if (list == null) {
                return false;
            }
            if (position < 0 || position >= list.size()) {
                return false;
            }
            Intent intent = new Intent(activity, GalleryActivity.clreplaced);
            intent.setAction(GalleryActivity.ACTION_EH);
            intent.putExtra(GalleryActivity.KEY_GALLERY_INFO, list.get(position));
            startActivity(intent);
            return true;
        }
    }

    @Override
    public boolean onItemLongClick(EasyRecyclerView parent, View view, int position, long id) {
        EasyRecyclerView recyclerView = mRecyclerView;
        if (recyclerView == null) {
            return false;
        }
        if (!recyclerView.isInCustomChoice()) {
            recyclerView.intoCustomChoiceMode();
        }
        recyclerView.toggleItemChecked(position);
        return true;
    }

    @Override
    public void onClickPrimaryFab(FabLayout view, FloatingActionButton fab) {
        if (mRecyclerView != null && mRecyclerView.isInCustomChoice()) {
            mRecyclerView.outOfCustomChoiceMode();
        }
    }

    @Override
    public void onClickSecondaryFab(FabLayout view, FloatingActionButton fab, int position) {
        Context context = getContext2();
        Activity activity = getActivity2();
        EasyRecyclerView recyclerView = mRecyclerView;
        if (null == context || null == activity || null == recyclerView) {
            return;
        }
        if (0 == position) {
            recyclerView.checkAll();
        } else {
            List<DownloadInfo> list = mList;
            if (list == null) {
                return;
            }
            LongList gidList = null;
            List<DownloadInfo> downloadInfoList = null;
            // Start, Stop, Delete
            boolean collectGid = position == 1 || position == 2 || position == 3;
            // Delete or Move
            boolean collectDownloadInfo = position == 3 || position == 4;
            if (collectGid) {
                gidList = new LongList();
            }
            if (collectDownloadInfo) {
                downloadInfoList = new LinkedList<>();
            }
            SparseBooleanArray stateArray = recyclerView.getCheckedItemPositions();
            for (int i = 0, n = stateArray.size(); i < n; i++) {
                if (stateArray.valueAt(i)) {
                    DownloadInfo info = list.get(stateArray.keyAt(i));
                    if (collectDownloadInfo) {
                        downloadInfoList.add(info);
                    }
                    if (collectGid) {
                        gidList.add(info.gid);
                    }
                }
            }
            switch(position) {
                case 1:
                    {
                        // Start
                        Intent intent = new Intent(activity, DownloadService.clreplaced);
                        intent.setAction(DownloadService.ACTION_START_RANGE);
                        intent.putExtra(DownloadService.KEY_GID_LIST, gidList);
                        activity.startService(intent);
                        // Cancel check mode
                        recyclerView.outOfCustomChoiceMode();
                        break;
                    }
                case 2:
                    {
                        // Stop
                        if (null != mDownloadManager) {
                            mDownloadManager.stopRangeDownload(gidList);
                        }
                        // Cancel check mode
                        recyclerView.outOfCustomChoiceMode();
                        break;
                    }
                case 3:
                    {
                        // Delete
                        CheckBoxDialogBuilder builder = new CheckBoxDialogBuilder(context, getString(R.string.download_remove_dialog_message_2, gidList.size()), getString(R.string.download_remove_dialog_check_text), Settings.getRemoveImageFiles());
                        DeleteRangeDialogHelper helper = new DeleteRangeDialogHelper(downloadInfoList, gidList, builder);
                        builder.setreplacedle(R.string.download_remove_dialog_replacedle).setPositiveButton(android.R.string.ok, helper).show();
                        break;
                    }
                case 4:
                    {
                        // Move
                        List<DownloadLabel> labelRawList = EhApplication.getDownloadManager(context).getLabelList();
                        List<String> labelList = new ArrayList<>(labelRawList.size() + 1);
                        labelList.add(getString(R.string.default_download_label_name));
                        for (int i = 0, n = labelRawList.size(); i < n; i++) {
                            labelList.add(labelRawList.get(i).getLabel());
                        }
                        String[] labels = labelList.toArray(new String[labelList.size()]);
                        MoveDialogHelper helper = new MoveDialogHelper(labels, downloadInfoList);
                        new AlertDialog.Builder(context).setreplacedle(R.string.download_move_dialog_replacedle).sereplacedems(labels, helper).show();
                        break;
                    }
            }
        }
    }

    @Override
    public void onAdd(@NonNull DownloadInfo info, @NonNull List<DownloadInfo> list, int position) {
        if (mList != list) {
            return;
        }
        if (mAdapter != null) {
            mAdapter.notifyItemInserted(position);
        }
        updateView();
    }

    @Override
    public void onUpdate(@NonNull DownloadInfo info, @NonNull List<DownloadInfo> list) {
        if (mList != list) {
            return;
        }
        int index = list.indexOf(info);
        if (index >= 0 && mAdapter != null) {
            mAdapter.notifyItemChanged(index);
        }
    }

    @Override
    public void onUpdateAll() {
        if (mAdapter != null) {
            mAdapter.notifyDataSetChanged();
        }
    }

    @Override
    public void onReload() {
        if (mAdapter != null) {
            mAdapter.notifyDataSetChanged();
        }
        updateView();
    }

    @Override
    public void onChange() {
        mLabel = null;
        updateForLabel();
        updateView();
    }

    @Override
    public void onRenameLabel(String from, String to) {
        if (!ObjectUtils.equal(mLabel, from)) {
            return;
        }
        mLabel = to;
        updateForLabel();
        updateView();
    }

    @Override
    public void onRemove(@NonNull DownloadInfo info, @NonNull List<DownloadInfo> list, int position) {
        if (mList != list) {
            return;
        }
        if (mAdapter != null) {
            mAdapter.notifyItemRemoved(position);
        }
        updateView();
    }

    @Override
    public void onUpdateLabels() {
    // TODO
    }

    private void bindForState(DownloadHolder holder, DownloadInfo info) {
        Resources resources = getResources2();
        if (null == resources) {
            return;
        }
        switch(info.state) {
            case DownloadInfo.STATE_NONE:
                bindState(holder, info, resources.getString(R.string.download_state_none));
                break;
            case DownloadInfo.STATE_WAIT:
                bindState(holder, info, resources.getString(R.string.download_state_wait));
                break;
            case DownloadInfo.STATE_DOWNLOAD:
                bindProgress(holder, info);
                break;
            case DownloadInfo.STATE_FAILED:
                String text;
                if (info.legacy <= 0) {
                    text = resources.getString(R.string.download_state_failed);
                } else {
                    text = resources.getString(R.string.download_state_failed_2, info.legacy);
                }
                bindState(holder, info, text);
                break;
            case DownloadInfo.STATE_FINISH:
                bindState(holder, info, resources.getString(R.string.download_state_finish));
                break;
        }
    }

    private void bindState(DownloadHolder holder, DownloadInfo info, String state) {
        holder.uploader.setVisibility(View.VISIBLE);
        holder.rating.setVisibility(View.VISIBLE);
        holder.category.setVisibility(View.VISIBLE);
        holder.state.setVisibility(View.VISIBLE);
        holder.progressBar.setVisibility(View.GONE);
        holder.percent.setVisibility(View.GONE);
        holder.speed.setVisibility(View.GONE);
        if (info.state == DownloadInfo.STATE_WAIT || info.state == DownloadInfo.STATE_DOWNLOAD) {
            holder.start.setVisibility(View.GONE);
            holder.stop.setVisibility(View.VISIBLE);
        } else {
            holder.start.setVisibility(View.VISIBLE);
            holder.stop.setVisibility(View.GONE);
        }
        holder.state.setText(state);
    }

    @SuppressLint("SetTextI18n")
    private void bindProgress(DownloadHolder holder, DownloadInfo info) {
        holder.uploader.setVisibility(View.GONE);
        holder.rating.setVisibility(View.GONE);
        holder.category.setVisibility(View.GONE);
        holder.state.setVisibility(View.GONE);
        holder.progressBar.setVisibility(View.VISIBLE);
        holder.percent.setVisibility(View.VISIBLE);
        holder.speed.setVisibility(View.VISIBLE);
        if (info.state == DownloadInfo.STATE_WAIT || info.state == DownloadInfo.STATE_DOWNLOAD) {
            holder.start.setVisibility(View.GONE);
            holder.stop.setVisibility(View.VISIBLE);
        } else {
            holder.start.setVisibility(View.VISIBLE);
            holder.stop.setVisibility(View.GONE);
        }
        if (info.total <= 0 || info.finished < 0) {
            holder.percent.setText(null);
            holder.progressBar.setIndeterminate(true);
        } else {
            holder.percent.setText(info.finished + "/" + info.total);
            holder.progressBar.setIndeterminate(false);
            holder.progressBar.setMax(info.total);
            holder.progressBar.setProgress(info.finished);
        }
        long speed = info.speed;
        if (speed < 0) {
            speed = 0;
        }
        holder.speed.setText(FileUtils.humanReadableByteCount(speed, false) + "/S");
    }

    private static void deleteFileAsync(UniFile... files) {
        new AsyncTask<UniFile, Void, Void>() {

            @Override
            protected Void doInBackground(UniFile... params) {
                for (UniFile file : params) {
                    if (file != null) {
                        file.delete();
                    }
                }
                return null;
            }
        }.executeOnExecutor(IoThreadPoolExecutor.getInstance(), files);
    }

    private clreplaced DeleteDialogHelper implements DialogInterface.OnClickListener {

        private final GalleryInfo mGalleryInfo;

        private final CheckBoxDialogBuilder mBuilder;

        public DeleteDialogHelper(GalleryInfo galleryInfo, CheckBoxDialogBuilder builder) {
            mGalleryInfo = galleryInfo;
            mBuilder = builder;
        }

        @Override
        public void onClick(DialogInterface dialog, int which) {
            if (which != DialogInterface.BUTTON_POSITIVE) {
                return;
            }
            // Delete
            if (null != mDownloadManager) {
                mDownloadManager.deleteDownload(mGalleryInfo.gid);
            }
            // Delete image files
            boolean checked = mBuilder.isChecked();
            Settings.putRemoveImageFiles(checked);
            if (checked) {
                // Remove download path
                EhDB.removeDownloadDirname(mGalleryInfo.gid);
                // Delete file
                UniFile file = SpiderDen.getGalleryDownloadDir(mGalleryInfo);
                deleteFileAsync(file);
            }
        }
    }

    private clreplaced DeleteRangeDialogHelper implements DialogInterface.OnClickListener {

        private final List<DownloadInfo> mDownloadInfoList;

        private final LongList mGidList;

        private final CheckBoxDialogBuilder mBuilder;

        public DeleteRangeDialogHelper(List<DownloadInfo> downloadInfoList, LongList gidList, CheckBoxDialogBuilder builder) {
            mDownloadInfoList = downloadInfoList;
            mGidList = gidList;
            mBuilder = builder;
        }

        @Override
        public void onClick(DialogInterface dialog, int which) {
            if (which != DialogInterface.BUTTON_POSITIVE) {
                return;
            }
            // Cancel check mode
            if (mRecyclerView != null) {
                mRecyclerView.outOfCustomChoiceMode();
            }
            // Delete
            if (null != mDownloadManager) {
                mDownloadManager.deleteRangeDownload(mGidList);
            }
            // Delete image files
            boolean checked = mBuilder.isChecked();
            Settings.putRemoveImageFiles(checked);
            if (checked) {
                UniFile[] files = new UniFile[mDownloadInfoList.size()];
                int i = 0;
                for (DownloadInfo info : mDownloadInfoList) {
                    // Remove download path
                    EhDB.removeDownloadDirname(info.gid);
                    // Put file
                    files[i] = SpiderDen.getGalleryDownloadDir(info);
                    i++;
                }
                // Delete file
                deleteFileAsync(files);
            }
        }
    }

    private clreplaced MoveDialogHelper implements DialogInterface.OnClickListener {

        private final String[] mLabels;

        private final List<DownloadInfo> mDownloadInfoList;

        public MoveDialogHelper(String[] labels, List<DownloadInfo> downloadInfoList) {
            mLabels = labels;
            mDownloadInfoList = downloadInfoList;
        }

        @Override
        public void onClick(DialogInterface dialog, int which) {
            // Cancel check mode
            Context context = getContext2();
            if (null == context) {
                return;
            }
            if (null != mRecyclerView) {
                mRecyclerView.outOfCustomChoiceMode();
            }
            String label;
            if (which == 0) {
                label = null;
            } else {
                label = mLabels[which];
            }
            EhApplication.getDownloadManager(context).changeLabel(mDownloadInfoList, label);
        }
    }

    private clreplaced DownloadHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        public final LoadImageView thumb;

        public final TextView replacedle;

        public final TextView uploader;

        public final SimpleRatingView rating;

        public final TextView category;

        public final View start;

        public final View stop;

        public final TextView state;

        public final ProgressBar progressBar;

        public final TextView percent;

        public final TextView speed;

        public DownloadHolder(View itemView) {
            super(itemView);
            thumb = (LoadImageView) itemView.findViewById(R.id.thumb);
            replacedle = (TextView) itemView.findViewById(R.id.replacedle);
            uploader = (TextView) itemView.findViewById(R.id.uploader);
            rating = (SimpleRatingView) itemView.findViewById(R.id.rating);
            category = (TextView) itemView.findViewById(R.id.category);
            start = itemView.findViewById(R.id.start);
            stop = itemView.findViewById(R.id.stop);
            state = (TextView) itemView.findViewById(R.id.state);
            progressBar = (ProgressBar) itemView.findViewById(R.id.progress_bar);
            percent = (TextView) itemView.findViewById(R.id.percent);
            speed = (TextView) itemView.findViewById(R.id.speed);
            // TODO cancel on click listener when select items
            thumb.setOnClickListener(this);
            start.setOnClickListener(this);
            stop.setOnClickListener(this);
            boolean isDarkTheme = !AttrResources.getAttrBoolean(getContext2(), R.attr.isLightTheme);
            Ripple.addRipple(start, isDarkTheme);
            Ripple.addRipple(stop, isDarkTheme);
        }

        @Override
        public void onClick(View v) {
            Context context = getContext2();
            Activity activity = getActivity2();
            EasyRecyclerView recyclerView = mRecyclerView;
            if (null == context || null == activity || null == recyclerView || recyclerView.isInCustomChoice()) {
                return;
            }
            List<DownloadInfo> list = mList;
            if (list == null) {
                return;
            }
            int size = list.size();
            int index = recyclerView.getChildAdapterPosition(itemView);
            if (index < 0 || index >= size) {
                return;
            }
            if (thumb == v) {
                Bundle args = new Bundle();
                args.putString(GalleryDetailScene.KEY_ACTION, GalleryDetailScene.ACTION_GALLERY_INFO);
                args.putParcelable(GalleryDetailScene.KEY_GALLERY_INFO, list.get(index));
                Announcer announcer = new Announcer(GalleryDetailScene.clreplaced).setArgs(args);
                announcer.setTranHelper(new EnterGalleryDetailTransaction(thumb));
                startScene(announcer);
            } else if (start == v) {
                Intent intent = new Intent(activity, DownloadService.clreplaced);
                intent.setAction(DownloadService.ACTION_START);
                intent.putExtra(DownloadService.KEY_GALLERY_INFO, list.get(index));
                activity.startService(intent);
            } else if (stop == v) {
                if (null != mDownloadManager) {
                    mDownloadManager.stopDownload(list.get(index).gid);
                }
            }
        }
    }

    private clreplaced DownloadAdapter extends RecyclerView.Adapter<DownloadHolder> {

        private final LayoutInflater mInflater;

        private final int mListThumbWidth;

        private final int mListThumbHeight;

        public DownloadAdapter() {
            mInflater = getLayoutInflater2();
            replacedertUtils.replacedertNotNull(mInflater);
            View calculator = mInflater.inflate(R.layout.item_gallery_list_thumb_height, null);
            ViewUtils.measureView(calculator, 1024, ViewGroup.LayoutParams.WRAP_CONTENT);
            mListThumbHeight = calculator.getMeasuredHeight();
            mListThumbWidth = mListThumbHeight * 2 / 3;
        }

        @Override
        public long gereplacedemId(int position) {
            if (mList == null || position < 0 || position >= mList.size()) {
                return 0;
            }
            return mList.get(position).gid;
        }

        @Override
        public DownloadHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            DownloadHolder holder = new DownloadHolder(mInflater.inflate(R.layout.item_download, parent, false));
            ViewGroup.LayoutParams lp = holder.thumb.getLayoutParams();
            lp.width = mListThumbWidth;
            lp.height = mListThumbHeight;
            holder.thumb.setLayoutParams(lp);
            return holder;
        }

        @Override
        public void onBindViewHolder(DownloadHolder holder, int position) {
            if (mList == null) {
                return;
            }
            DownloadInfo info = mList.get(position);
            holder.thumb.load(EhCacheKeyFactory.getThumbKey(info.gid), info.thumb, new ThumbDataContainer(info), true);
            holder.replacedle.setText(EhUtils.getSuitablereplacedle(info));
            holder.uploader.setText(info.uploader);
            holder.rating.setRating(info.rating);
            TextView category = holder.category;
            String newCategoryText = EhUtils.getCategory(info.category);
            if (!newCategoryText.equals(category.getText())) {
                category.setText(newCategoryText);
                category.setBackgroundColor(EhUtils.getCategoryColor(info.category));
            }
            bindForState(holder, info);
            // Update transition name
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                ViewCompat.setTransitionName(holder.thumb, TransitionNameFactory.getThumbTransitionName(info.gid));
            }
        }

        @Override
        public int gereplacedemCount() {
            return mList == null ? 0 : mList.size();
        }
    }

    private clreplaced DownloadChoiceListener implements EasyRecyclerView.CustomChoiceListener {

        @Override
        public void onIntoCustomChoice(EasyRecyclerView view) {
            if (mRecyclerView != null) {
                mRecyclerView.setOnItemLongClickListener(null);
                mRecyclerView.setLongClickable(false);
            }
            if (mFabLayout != null) {
                mFabLayout.setExpanded(true);
            }
            // Lock drawer
            setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, Gravity.LEFT);
            setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, Gravity.RIGHT);
        }

        @Override
        public void onOutOfCustomChoice(EasyRecyclerView view) {
            if (mRecyclerView != null) {
                mRecyclerView.setOnItemLongClickListener(DownloadsScene.this);
            }
            if (mFabLayout != null) {
                mFabLayout.setExpanded(false);
            }
            // Unlock drawer
            setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, Gravity.LEFT);
            setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, Gravity.RIGHT);
        }

        @Override
        public void onItemCheckedStateChanged(EasyRecyclerView view, int position, long id, boolean checked) {
            if (view.getCheckedItemCount() == 0) {
                view.outOfCustomChoiceMode();
            }
        }
    }

    private clreplaced ThumbDataContainer implements DataContainer {

        private final DownloadInfo mInfo;

        @Nullable
        private UniFile mFile;

        public ThumbDataContainer(@NonNull DownloadInfo info) {
            mInfo = info;
        }

        private void ensureFile() {
            if (mFile == null) {
                UniFile dir = SpiderDen.getGalleryDownloadDir(mInfo);
                if (dir != null && dir.isDirectory()) {
                    mFile = dir.createFile(".thumb");
                }
            }
        }

        @Override
        public boolean isEnabled() {
            ensureFile();
            return mFile != null;
        }

        @Override
        public void onUrlMoved(String requestUrl, String responseUrl) {
        }

        @Override
        public boolean save(InputStream is, long length, String mediaType, ProgressNotifier notify) {
            ensureFile();
            if (mFile == null) {
                return false;
            }
            OutputStream os = null;
            try {
                os = mFile.openOutputStream();
                IOUtils.copy(is, os);
                return true;
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            } finally {
                IOUtils.closeQuietly(os);
            }
        }

        @Override
        public InputStreamPipe get() {
            ensureFile();
            if (mFile != null) {
                return new UniFileInputStreamPipe(mFile);
            } else {
                return null;
            }
        }

        @Override
        public void remove() {
            if (mFile != null) {
                mFile.delete();
            }
        }
    }
}

14 Source : SearchBar.java
with Apache License 2.0
from NuclearVGA

public clreplaced SearchBar extends MaterialCardView implements View.OnClickListener, TextView.OnEditorActionListener, Texreplacedcher, SearchEditText.SearchEditTextListener {

    public static final int STATE_NORMAL = 0;

    public static final int STATE_SEARCH = 1;

    public static final int STATE_SEARCH_LIST = 2;

    private static final String STATE_KEY_SUPER = "super";

    private static final String STATE_KEY_STATE = "state";

    private static final long ANIMATE_TIME = 300L;

    private final Rect mRect = new Rect();

    private int mState = STATE_NORMAL;

    private int mWidth;

    private int mHeight;

    private int mBaseHeight;

    private float mProgress;

    private ImageView mMenuButton;

    private TextView mreplacedleTextView;

    private ImageView mActionButton;

    private SearchEditText mEditText;

    private EasyRecyclerView mListView;

    private View mListContainer;

    private ViewTransition mViewTransition;

    private SearchDatabase mSearchDatabase;

    private List<Suggestion> mSuggestionList;

    private SuggestionAdapter mSuggestionAdapter;

    private Helper mHelper;

    private OnStateChangeListener mOnStateChangeListener;

    private SuggestionProvider mSuggestionProvider;

    private boolean mAllowEmptySearch = true;

    private boolean mInAnimation;

    public SearchBar(Context context) {
        super(context);
        init(context);
    }

    public SearchBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public SearchBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        mSearchDatabase = SearchDatabase.getInstance(getContext());
        LayoutInflater inflater = LayoutInflater.from(context);
        inflater.inflate(R.layout.widget_search_bar, this);
        mMenuButton = (ImageView) ViewUtils.$$(this, R.id.search_menu);
        mreplacedleTextView = (TextView) ViewUtils.$$(this, R.id.search_replacedle);
        mActionButton = (ImageView) ViewUtils.$$(this, R.id.search_action);
        mEditText = (SearchEditText) ViewUtils.$$(this, R.id.search_edit_text);
        mListContainer = ViewUtils.$$(this, R.id.list_container);
        mListView = (EasyRecyclerView) ViewUtils.$$(mListContainer, R.id.search_bar_list);
        mViewTransition = new ViewTransition(mreplacedleTextView, mEditText);
        mreplacedleTextView.setOnClickListener(this);
        mMenuButton.setOnClickListener(this);
        mActionButton.setOnClickListener(this);
        mEditText.setSearchEditTextListener(this);
        mEditText.setOnEditorActionListener(this);
        mEditText.addTextChangedListener(this);
        // Get base height
        ViewUtils.measureView(this, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        mBaseHeight = getMeasuredHeight();
        mSuggestionList = new ArrayList<>();
        mSuggestionAdapter = new SuggestionAdapter(LayoutInflater.from(getContext()));
        mListView.setAdapter(mSuggestionAdapter);
        LinearLayoutManager layoutManager = new LinearLayoutManager(context);
        LinearDividerItemDecoration decoration = new LinearDividerItemDecoration(LinearDividerItemDecoration.VERTICAL, AttrResources.getAttrColor(context, R.attr.dividerColor), LayoutUtils.dp2pix(context, 1));
        decoration.setShowFirstDivider(true);
        decoration.setShowLastDivider(false);
        mListView.addItemDecoration(decoration);
        mListView.setLayoutManager(layoutManager);
    }

    private void updateSuggestions() {
        updateSuggestions(true);
    }

    private void updateSuggestions(boolean scrollToTop) {
        mSuggestionList.clear();
        String text = mEditText.getText().toString();
        if (mSuggestionProvider != null) {
            List<Suggestion> suggestions = mSuggestionProvider.providerSuggestions(text);
            if (suggestions != null && !suggestions.isEmpty()) {
                mSuggestionList.addAll(suggestions);
            }
        }
        String[] keywords = mSearchDatabase.getSuggestions(text, 128);
        for (String keyword : keywords) {
            mSuggestionList.add(new KeywordSuggestion(keyword));
        }
        EhTagDatabase ehTagDatabase = EhTagDatabase.getInstance(getContext());
        if (!TextUtils.isEmpty(text) && ehTagDatabase != null && !text.endsWith(" ")) {
            String[] s = text.split(" ");
            if (s.length > 0) {
                String keyword = s[s.length - 1];
                ArrayList<Pair<String, String>> searchHints = ehTagDatabase.suggest(keyword);
                for (Pair<String, String> searchHint : searchHints) {
                    mSuggestionList.add(new TagSuggestion(searchHint.first, searchHint.second));
                }
            }
        }
        mSuggestionAdapter.notifyDataSetChanged();
        if (scrollToTop) {
            mListView.scrollToPosition(0);
        }
    }

    public void setAllowEmptySearch(boolean allowEmptySearch) {
        mAllowEmptySearch = allowEmptySearch;
    }

    public void setEditTextHint(CharSequence hint) {
        mEditText.setHint(hint);
    }

    public void setHelper(Helper helper) {
        mHelper = helper;
    }

    public void setOnStateChangeListener(OnStateChangeListener listener) {
        mOnStateChangeListener = listener;
    }

    public void setSuggestionProvider(SuggestionProvider suggestionProvider) {
        mSuggestionProvider = suggestionProvider;
    }

    public String getText() {
        return mEditText.getText().toString();
    }

    public void setText(String text) {
        mEditText.setText(text);
    }

    public void cursorToEnd() {
        mEditText.setSelection(mEditText.getText().length());
    }

    public void setreplacedle(String replacedle) {
        mreplacedleTextView.setText(replacedle);
    }

    public void setSearch(String search) {
        mreplacedleTextView.setText(search);
        mEditText.setText(search);
    }

    public void setLeftDrawable(Drawable drawable) {
        mMenuButton.setImageDrawable(drawable);
    }

    public void setRightDrawable(Drawable drawable) {
        mActionButton.setImageDrawable(drawable);
    }

    public void applySearch() {
        String query = mEditText.getText().toString().trim();
        if (!mAllowEmptySearch && TextUtils.isEmpty(query)) {
            return;
        }
        // Put it into db
        mSearchDatabase.addQuery(query);
        // Callback
        mHelper.onApplySearch(query);
    }

    @Override
    public void onClick(View v) {
        if (v == mreplacedleTextView) {
            mHelper.onClickreplacedle();
        } else if (v == mMenuButton) {
            mHelper.onClickLeftIcon();
        } else if (v == mActionButton) {
            mHelper.onClickRightIcon();
        }
    }

    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        if (v == mEditText) {
            if (actionId == EditorInfo.IME_ACTION_SEARCH || actionId == EditorInfo.IME_NULL) {
                applySearch();
                return true;
            }
        }
        return false;
    }

    public int getState() {
        return mState;
    }

    public void setState(int state) {
        setState(state, true);
    }

    public void setState(int state, boolean animation) {
        if (mState != state) {
            int oldState = mState;
            mState = state;
            switch(oldState) {
                default:
                case STATE_NORMAL:
                    mViewTransition.showView(1, animation);
                    mEditText.requestFocus();
                    if (state == STATE_SEARCH_LIST) {
                        showImeAndSuggestionsList(animation);
                    }
                    if (mOnStateChangeListener != null) {
                        mOnStateChangeListener.onStateChange(this, state, oldState, animation);
                    }
                    break;
                case STATE_SEARCH:
                    if (state == STATE_NORMAL) {
                        mViewTransition.showView(0, animation);
                    } else if (state == STATE_SEARCH_LIST) {
                        showImeAndSuggestionsList(animation);
                    }
                    if (mOnStateChangeListener != null) {
                        mOnStateChangeListener.onStateChange(this, state, oldState, animation);
                    }
                    break;
                case STATE_SEARCH_LIST:
                    hideImeAndSuggestionsList(animation);
                    if (state == STATE_NORMAL) {
                        mViewTransition.showView(0, animation);
                    }
                    if (mOnStateChangeListener != null) {
                        mOnStateChangeListener.onStateChange(this, state, oldState, animation);
                    }
                    break;
            }
        }
    }

    public void showImeAndSuggestionsList(boolean animation) {
        // Show ime
        InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.showSoftInput(mEditText, 0);
        // update suggestion for show suggestions list
        updateSuggestions();
        // Show suggestions list
        if (animation) {
            ObjectAnimator oa = ObjectAnimator.ofFloat(this, "progress", 1f);
            oa.setDuration(ANIMATE_TIME);
            oa.setInterpolator(AnimationUtils.FAST_SLOW_INTERPOLATOR);
            oa.addListener(new SimpleAnimatorListener() {

                @Override
                public void onAnimationStart(Animator animation) {
                    mListContainer.setVisibility(View.VISIBLE);
                    mInAnimation = true;
                }

                @Override
                public void onAnimationEnd(Animator animation) {
                    mInAnimation = false;
                }
            });
            oa.setAutoCancel(true);
            oa.start();
        } else {
            mListContainer.setVisibility(View.VISIBLE);
            setProgress(1f);
        }
    }

    private void hideImeAndSuggestionsList(boolean animation) {
        // Hide ime
        InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(this.getWindowToken(), 0);
        // Hide suggestions list
        if (animation) {
            ObjectAnimator oa = ObjectAnimator.ofFloat(this, "progress", 0f);
            oa.setDuration(ANIMATE_TIME);
            oa.setInterpolator(AnimationUtils.SLOW_FAST_INTERPOLATOR);
            oa.addListener(new SimpleAnimatorListener() {

                @Override
                public void onAnimationStart(Animator animation) {
                    mInAnimation = true;
                }

                @Override
                public void onAnimationEnd(Animator animation) {
                    mListContainer.setVisibility(View.GONE);
                    mInAnimation = false;
                }
            });
            oa.setAutoCancel(true);
            oa.start();
        } else {
            setProgress(0f);
            mListContainer.setVisibility(View.GONE);
        }
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        if (mListContainer.getVisibility() == View.VISIBLE && (!mInAnimation || mHeight == 0)) {
            mWidth = right - left;
            mHeight = bottom - top;
        }
    }

    public float getProgress() {
        return mProgress;
    }

    @Keep
    public void setProgress(float progress) {
        mProgress = progress;
        invalidate();
    }

    public SearchEditText getEditText() {
        return mEditText;
    }

    @Override
    public void draw(@NonNull Canvas canvas) {
        if (mInAnimation && mHeight != 0) {
            final int state = canvas.save();
            int bottom = MathUtils.lerp(mBaseHeight, mHeight, mProgress);
            mRect.set(0, 0, mWidth, bottom);
            setClipBounds(mRect);
            canvas.clipRect(mRect);
            super.draw(canvas);
            canvas.restoreToCount(state);
        } else {
            setClipBounds(null);
            super.draw(canvas);
        }
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    // Empty
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
    // Empty
    }

    @Override
    public void afterTextChanged(Editable s) {
        updateSuggestions();
    }

    @Override
    public void onClick() {
        mHelper.onSearchEditTextClick();
    }

    @Override
    public void onBackPressed() {
        mHelper.onSearchEditTextBackPressed();
    }

    @Override
    public Parcelable onSaveInstanceState() {
        final Bundle state = new Bundle();
        state.putParcelable(STATE_KEY_SUPER, super.onSaveInstanceState());
        state.putInt(STATE_KEY_STATE, mState);
        return state;
    }

    @Override
    public void onRestoreInstanceState(Parcelable state) {
        if (state instanceof Bundle) {
            final Bundle savedState = (Bundle) state;
            super.onRestoreInstanceState(savedState.getParcelable(STATE_KEY_SUPER));
            setState(savedState.getInt(STATE_KEY_STATE), false);
        }
    }

    public interface Helper {

        void onClickreplacedle();

        void onClickLeftIcon();

        void onClickRightIcon();

        void onSearchEditTextClick();

        void onApplySearch(String query);

        void onSearchEditTextBackPressed();
    }

    public interface OnStateChangeListener {

        void onStateChange(SearchBar searchBar, int newState, int oldState, boolean animation);
    }

    public interface SuggestionProvider {

        List<Suggestion> providerSuggestions(String text);
    }

    public abstract static clreplaced Suggestion {

        public abstract CharSequence getText(TextView textView);

        public abstract void onClick();

        public boolean onLongClick() {
            return false;
        }
    }

    private static clreplaced SuggestionHolder extends RecyclerView.ViewHolder {

        TextView text1;

        TextView text2;

        public SuggestionHolder(@NonNull View itemView) {
            super(itemView);
            text1 = itemView.findViewById(android.R.id.text1);
            text2 = itemView.findViewById(android.R.id.text2);
        }
    }

    private clreplaced SuggestionAdapter extends RecyclerView.Adapter<SuggestionHolder> {

        private final LayoutInflater mInflater;

        private SuggestionAdapter(LayoutInflater inflater) {
            mInflater = inflater;
        }

        @NonNull
        @Override
        public SuggestionHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            return new SuggestionHolder(mInflater.inflate(R.layout.item_simple_list_2, parent, false));
        }

        @Override
        public void onBindViewHolder(@NonNull SuggestionHolder holder, int position) {
            Suggestion suggestion = mSuggestionList.get(position);
            CharSequence text1 = suggestion.getText(holder.text1);
            CharSequence text2 = suggestion.getText(holder.text2);
            holder.text1.setText(text1);
            if (text2 == null) {
                holder.text2.setVisibility(View.GONE);
                holder.text2.setText("");
            } else {
                holder.text2.setVisibility(View.VISIBLE);
                holder.text2.setText(text2);
            }
            holder.itemView.setOnClickListener(v -> {
                if (position < mSuggestionList.size()) {
                    mSuggestionList.get(position).onClick();
                }
            });
            holder.itemView.setOnLongClickListener(v -> {
                if (position < mSuggestionList.size()) {
                    return mSuggestionList.get(position).onLongClick();
                } else {
                    return false;
                }
            });
        }

        @Override
        public long gereplacedemId(int position) {
            return position;
        }

        @Override
        public int gereplacedemCount() {
            return mSuggestionList.size();
        }
    }

    public clreplaced TagSuggestion extends SearchBar.Suggestion {

        public String mHint;

        public String mKeyword;

        private TagSuggestion(String hint, String keyword) {
            mHint = hint;
            mKeyword = keyword;
        }

        @Override
        public CharSequence getText(TextView textView) {
            if (textView.getId() == android.R.id.text1) {
                return mKeyword;
            } else {
                return mHint;
            }
        }

        @Override
        public void onClick() {
            Editable editable = mEditText.getText();
            if (editable != null) {
                String text = editable.toString();
                String temp = wrapTagKeyword(mKeyword) + " ";
                if (text.contains(" ")) {
                    temp = text.substring(0, text.lastIndexOf(" ")) + " " + temp;
                }
                mEditText.setText(temp);
                mEditText.setSelection(editable.length());
            }
        }
    }

    public clreplaced KeywordSuggestion extends Suggestion {

        private final String mKeyword;

        private KeywordSuggestion(String keyword) {
            mKeyword = keyword;
        }

        @Override
        public CharSequence getText(TextView textView) {
            if (textView.getId() == android.R.id.text1) {
                return mKeyword;
            } else {
                return null;
            }
        }

        @Override
        public void onClick() {
            mEditText.setText(mKeyword);
            mEditText.setSelection(mEditText.length());
        }

        @Override
        public boolean onLongClick() {
            new MaterialAlertDialogBuilder(getContext()).setMessage(getContext().getString(R.string.delete_search_history, mKeyword)).setNegativeButton(android.R.string.cancel, null).setPositiveButton(R.string.delete, (dialog, which) -> {
                mSearchDatabase.deleteQuery(mKeyword);
                updateSuggestions(false);
            }).show();
            return true;
        }
    }

    private String wrapTagKeyword(String keyword) {
        keyword = keyword.trim();
        int index1 = keyword.indexOf(':');
        if (index1 == -1 || index1 >= keyword.length() - 1) {
            // Can't find :, or : is the last char
            return keyword;
        }
        if (keyword.charAt(index1 + 1) == '"') {
            // The char after : is ", the word must be quoted
            return keyword;
        }
        int index2 = keyword.indexOf(' ');
        if (index2 <= index1) {
            // Can't find space, or space is before :
            return keyword;
        }
        return keyword.substring(0, index1 + 1) + "\"" + keyword.substring(index1 + 1) + "$\"";
    }
}

See More Examples