代码之家  ›  专栏  ›  技术社区  ›  Alexander Farber

单击项目时,在RecyclerView+FastAdapter中显示更多详细信息

  •  0
  • Alexander Farber  · 技术社区  · 6 年前

    在使用FastAdapter和ConstraintLayout的应用程序中,我会显示已完成游戏的列表(请原谅屏幕截图中的非英语字符):

    screenshot 1

    当应用程序用户单击列表中的某个项目(该项目中的任何位置)时,我希望显示一个带有方形游戏板的图像视图,并将加号图像视图更改为减号:

    screenshot 2

    为此,我已经准备了一种方法:

    private void toggleDetails() {
        if (mBoard.getVisibility() == View.GONE) {
            mBoard.setVisibility(View.VISIBLE);
            mDetails.setImageResource(R.drawable.minus_circle_gray);
        } else {
            mBoard.setVisibility(View.GONE);
            mDetails.setImageResource(R.drawable.plus_circle_gray);
        }
    }
    

    但是我的问题是我不确定在哪里调用该方法。

    我应该向fast adapter对象添加一个click监听器还是将其添加到我的视图保持器?

    还有,当你看着 ExpandableSampleActivity 例如,我注意到有一些动画,并想知道如何动画我披露的mBoard图像视图。。。

    下面是我当前的源代码:

    public class FinishedGameItem extends AbstractItem<FinishedGameItem, FinishedGameItem.ViewHolder> {
        private final static String WON = "won";
        private final static String LOST = "lost";
    
        public long stamp;
        public int gid;
        public int score1;
        public int score2;
        public int elo1;
        public int elo2;
        public String state1;
        public String finished;
        public String given1;
        public String given2;
        public String photo1;
        public String photo2;
    
        @Override
        public int getType() {
            return R.id.finished_game_item_id;
        }
    
        @Override
        public int getLayoutRes() {
            return R.layout.item_finished_game;
        }
    
        @NonNull
        @Override
        public ViewHolder getViewHolder(@NonNull View v) {
            return new ViewHolder(v);
        }
    
        protected static class ViewHolder extends FastAdapter.ViewHolder<FinishedGameItem> {
            private ImageView mDetails;
            private TextView mGid;
            private TextView mFinished;
            private TextView mScore1;
            private TextView mScore2;
            private TextView mGiven1;
            private TextView mGiven2;
            private TextView mElo1;
            private TextView mElo2;
            private ImageView mPhoto1;
            private ImageView mPhoto2;
            private ImageView mBoard;
    
            public ViewHolder(View view) {
                super(view);
                mDetails = view.findViewById(R.id.details);
                mGid = view.findViewById(R.id.gid);
                mFinished = view.findViewById(R.id.finished);
                mScore1 = view.findViewById(R.id.score1);
                mScore2 = view.findViewById(R.id.score2);
                mGiven1 = view.findViewById(R.id.given1);
                mGiven2 = view.findViewById(R.id.given2);
                mElo1 = view.findViewById(R.id.elo1);
                mElo2 = view.findViewById(R.id.elo2);
                mPhoto1 = view.findViewById(R.id.photo1);
                mPhoto2 = view.findViewById(R.id.photo2);
                mBoard = view.findViewById(R.id.board);
            }
    
            @Override
            public void bindView(@NonNull FinishedGameItem item, @NonNull List<Object> payloads) {
                Context ctx = mDetails.getContext();
                Resources res = mDetails.getResources();
    
                String result = (WON.equals(item.state1) ? "Victory" : (LOST.equals(item.state1) ? "Loss" : "Draw"));
    
                mDetails.setImageResource(R.drawable.plus_circle_gray);
                mBoard.setVisibility(View.GONE);
    
                mGid.setText(r.getString(R.string.str_game, item.gid));
                mFinished.setText(result + " / " + item.finished);
                mScore1.setText(res.getString(R.string.str_score, item.score1));
                mScore2.setText(res.getString(R.string.str_score, item.score2));
                mGiven1.setText(item.given1);
                mGiven2.setText(item.given2);
                mElo1.setText(String.valueOf(item.elo1));
                mElo2.setText(String.valueOf(item.elo2));
    
                if (URLUtil.isHttpsUrl(item.photo1)) {
                    Picasso.with(ctx))
                            .load(item.photo1)
                            .placeholder(R.drawable.account_gray)
                            .into(mPhoto1);
                }
    
                if (URLUtil.isHttpsUrl(item.photo2)) {
                    Picasso.with(ctx)
                            .load(item.photo2)
                            .placeholder(R.drawable.account_gray)
                            .into(mPhoto2);
                }
    
                Picasso.with(ctx)
                        .load("http://slova.de/words/board2.php?gid=" + item.gid)
                        .placeholder(R.drawable.checkerboard_gray)
                        .into(mBoard);
            }
    
            @Override
            public void unbindView(@NonNull FinishedGameItem item) {
                Context ctx = mDetails.getContext();
    
                Picasso.with(ctx).cancelRequest(mPhoto1);
                Picasso.with(ctx).cancelRequest(mPhoto2);
                Picasso.with(ctx).cancelRequest(mBoard);
    
                mDetails.setImageDrawable(null);
                mGid.setText(null);
                mFinished.setText(null);
                mScore1.setText(null);
                mScore2.setText(null);
                mGiven1.setText(null);
                mGiven2.setText(null);
                mElo1.setText(null);
                mElo2.setText(null);
                mPhoto1.setImageDrawable(null);
                mPhoto2.setImageDrawable(null);
                mBoard.setImageDrawable(null);
            }
    
            // WHERE TO CALL THIS METHOD AND HOW TO ANIMATE?
    
            private void toggleDetails() {
                if (mBoard.getVisibility() == View.GONE) {
                    mBoard.setVisibility(View.VISIBLE);
                    mDetails.setImageResource(R.drawable.minus_circle_gray);
                } else {
                    mBoard.setVisibility(View.GONE);
                    mDetails.setImageResource(R.drawable.plus_circle_gray);
                }
            }
        }
    }
    

    我也问过我的问题 Github issue 713

    更新:

    我试过添加布尔值 details 把它用在我的模型上 bindView 方法(true表示显示 mBoard ),但应用程序现在的行为不稳定,显示了错误的详细信息,并且在单击后不会立即显示-

    这里是新的片段源代码:

    mFastAdapter.withSelectable(true);
    mFastAdapter.withOnClickListener(new OnClickListener<FinishedGameItem>() {
        @Override
        public boolean onClick(View v, @NonNull IAdapter<FinishedGameItem> adapter, @NonNull FinishedGameItem item, int position) {
            item.details = !item.details;
    
            // THIS METHOD IS CALLED IN DEBUGGER, BUT VIEWS ARE NOT UPDATED
    
            return true;
        }
    });
    

    这里是修改后的FinishedGameItem模型:

    public class FinishedGameItem extends AbstractItem<FinishedGameItem, FinishedGameItem.ViewHolder> {
        private final static String WON = "won";
        private final static String LOST = "lost";
    
        public boolean details; // TRIED TO ADD THIS BOOLEAN
        public long stamp;
        public int gid;
        public int score1;
        public int score2;
        public int elo1;
        public int elo2;
        public String state1;
        public String finished;
        public String given1;
        public String given2;
        public String photo1;
        public String photo2;
    
        @Override
        public int getType() {
            return R.id.finished_game_item_id;
        }
    
        @Override
        public int getLayoutRes() {
            return R.layout.item_finished_game;
        }
    
        @NonNull
        @Override
        public ViewHolder getViewHolder(@NonNull View v) {
            return new ViewHolder(v);
        }
    
        protected static class ViewHolder extends FastAdapter.ViewHolder<FinishedGameItem> {
            private ImageView mDetails;
            private TextView mGid;
            private TextView mFinished;
            private TextView mScore1;
            private TextView mScore2;
            private TextView mGiven1;
            private TextView mGiven2;
            private TextView mElo1;
            private TextView mElo2;
            private ImageView mPhoto1;
            private ImageView mPhoto2;
            private ImageView mBoard;
    
            public ViewHolder(View view) {
                super(view);
                mDetails = view.findViewById(R.id.details);
                mGid = view.findViewById(R.id.gid);
                mFinished = view.findViewById(R.id.finished);
                mScore1 = view.findViewById(R.id.score1);
                mScore2 = view.findViewById(R.id.score2);
                mGiven1 = view.findViewById(R.id.given1);
                mGiven2 = view.findViewById(R.id.given2);
                mElo1 = view.findViewById(R.id.elo1);
                mElo2 = view.findViewById(R.id.elo2);
                mPhoto1 = view.findViewById(R.id.photo1);
                mPhoto2 = view.findViewById(R.id.photo2);
                mBoard = view.findViewById(R.id.board);
            }
    
            @Override
            public void bindView(@NonNull FinishedGameItem item, @NonNull List<Object> payloads) {
                Context ctx = mDetails.getContext();
                Resources res = mDetails.getResources();
    
                String result = (WON.equals(item.state1) ? "Victory" : (LOST.equals(item.state1) ? "Loss" : "Draw"));
    
                mDetails.setImageResource(item.details ? R.drawable.minus_circle_gray : R.drawable.plus_circle_gray);
                mBoard.setVisibility(item.details ? View.VISIBLE : View.GONE);
    
                mGid.setText(res.getString(R.string.str_game, item.gid));
                mFinished.setText(result + " / " + item.finished);
                mScore1.setText(res.getString(R.string.str_score, item.score1));
                mScore2.setText(res.getString(R.string.str_score, item.score2));
                mGiven1.setText(item.given1);
                mGiven2.setText(item.given2);
                mElo1.setText(String.valueOf(item.elo1));
                mElo2.setText(String.valueOf(item.elo2));
    
                if (URLUtil.isHttpsUrl(item.photo1)) {
                    Picasso.with(ctx)
                            .load(item.photo1)
                            .placeholder(R.drawable.account_gray)
                            .into(mPhoto1);
                }
    
                if (URLUtil.isHttpsUrl(item.photo2)) {
                    Picasso.with(ctx)
                            .load(item.photo2)
                            .placeholder(R.drawable.account_gray)
                            .into(mPhoto2);
                }
    
                if (item.details) {
                    Picasso.with(ctx)
                            .load("http://slova.de/words/board2.php?gid=" + item.gid)
                            .placeholder(R.drawable.checkerboard_gray)
                            .into(mBoard);
                }
            }
    
            @Override
            public void unbindView(@NonNull FinishedGameItem item) {
                Context ctx = mDetails.getContext();
    
                Picasso.with(ctx).cancelRequest(mPhoto1);
                Picasso.with(ctx).cancelRequest(mPhoto2);
                Picasso.with(ctx).cancelRequest(mBoard);
    
                mDetails.setImageDrawable(null);
                mGid.setText(null);
                mFinished.setText(null);
                mScore1.setText(null);
                mScore2.setText(null);
                mGiven1.setText(null);
                mGiven2.setText(null);
                mElo1.setText(null);
                mElo2.setText(null);
                mPhoto1.setImageDrawable(null);
                mPhoto2.setImageDrawable(null);
                mBoard.setImageDrawable(null);
            }
        }
    }
    

    这个应用程序工作正常,但不稳定:

    screenshot 3

    1 回复  |  直到 6 年前
        1
  •  2
  •   crymson    6 年前

    从您的代码来看,您可能忘记告诉适配器您的支持模型( FinishedGameItem )已经改变了。打电话 notifyItemChanged(position) 可能会有帮助。

    mFastAdapter.withSelectable(true);
    mFastAdapter.withOnClickListener(new OnClickListener<FinishedGameItem>() {
        @Override
        public boolean onClick(View v, @NonNull IAdapter<FinishedGameItem> adapter, @NonNull FinishedGameItem item, int position) {
            item.details = !item.details;
    
            mFastAdapter.notifyItemChanged(position);
    
            return true;
        }
    });