如何操作ListView项目中的视图?

时间:2015-05-11 11:47:27

标签: android listview android-listview android-view

我有一个ListView,其中有几行包含两个按钮,每行一个ProgressBar (Visibility:GONE)

我的目的是在点击按钮后显示ProgressBar,完成一组后台操作后,完全删除该行。
这里的问题是,从创建ArrayListListView调用notifyDataSetChanged的{​​{1}}中移除项目后,该行已成功删除,但ProgressBar仍然可见。

是否应该将其与其父视图一起删除?

签出以下记录以查看问题的实际效果。

enter image description here

以下是我整个片段的来源:

public class FriendRequestFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {


    private static final String TAG = "FriendRequestFragment";
    ArrayList<FriendRequest> friendRequests;

    @InjectView(R.id.friendRequestList)
    ListView mListView;
    @InjectView(R.id.noRequestsText)
    TextView noRequestsText;
    @InjectView(R.id.swipe)
    SwipeRefreshLayout swipeRefreshLayout;

//    NotificationHandler nh;
    /**
     * The Adapter which will be used to populate the ListView/GridView with
     * Views.
     */
    private FriendRequestAdapter mAdapter;
    private Context c;
    private boolean isProcessing = false;

    /**
     * Mandatory empty constructor for the fragment manager to instantiate the
     * fragment (e.g. upon screen orientation changes).
     */
    public FriendRequestFragment() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Util.trackFragment(this);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_friendrequest_list, container, false);
        ButterKnife.inject(this, view);
        c = getActivity();
        friendRequests = new ArrayList<>();
        swipeRefreshLayout.setOnRefreshListener(this);
        mAdapter = new FriendRequestAdapter(getActivity(), friendRequests);

        mListView.setAdapter(mAdapter);

        mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {

            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                int topRowVerticalPosition =
                        (view == null || view.getChildCount() == 0) ?
                        0 : view.getChildAt(0).getTop();
                swipeRefreshLayout.setEnabled(firstVisibleItem == 0 && topRowVerticalPosition >= 0);
                Log.d(TAG, "SwipeRefresh: " + String.valueOf(firstVisibleItem == 0 && topRowVerticalPosition >= 0));
            }
        });


        loadRequests();
        return view;
    }

    private void loadRequests() {
//        nh = new NotificationHandler(getActivity());
        swipeRefreshLayout.setRefreshing(true);
        Log.d(TAG, "loading requests init");
        HashMap<String, Integer> params = new HashMap<>();
        params.put("profile_id", Util.getCurrentProfileID(c));
        final String uniqueID = Util.getCurrentProfileID(c) + String.valueOf(System.currentTimeMillis() / 1000 / 1200);
        new ApiRequest(Util.URL_GET_FRIEND_REQUESTS, params, new AjaxCallback<String>() {
            @Override
            public void callback(String url, String result, AjaxStatus status) {
                super.callback(url, result, status);
                ApiResponse apiResponse = new ApiResponse(url, result, uniqueID);
                Log.d(TAG, "Friend Requests Response: " + result);
                if (apiResponse.isSuccessful()) {
                    JSONArray jsonArray = apiResponse.getDataJSONArray();
                    try {
                        for (int i = 0; i < jsonArray.length(); i++) {
                            friendRequests.add(new FriendRequest(jsonArray.getJSONObject(i)));
                        }
                        mAdapter.notifyDataSetChanged();
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                    mListView.setVisibility(View.VISIBLE);
                } else if (apiResponse.getErrorMessage().equals("request_not_found")) {
                    noRequestsText.setVisibility(View.VISIBLE);
                }
                swipeRefreshLayout.setRefreshing(true);
            }

        }).setUniqueID(uniqueID).execute();
    }

    @Override
    public void onRefresh() {
        loadRequests();
    }

    private void acceptRequest(final int position, final View rootView) {
        if (isProcessing) {
            CustomToast.makeToast(getActivity(), CustomToast.TYPE_ALERT, getString(R.string.please_wait), CustomToast.LENGTH_SHORT);
            return;
        }
        rootView.findViewById(R.id.loading).setVisibility(View.VISIBLE);
        rootView.findViewById(R.id.acceptBtn).setVisibility(View.GONE);
        rootView.findViewById(R.id.denyBtn).setVisibility(View.GONE);
        isProcessing = true;
        Log.d("FriendRequest", "accepting:" + position);
        FriendRequest request = friendRequests.get(position);
        HashMap<String, Integer> params = new HashMap<>();
        params.put("request_id", request.getRequestID());
        params.put("profile_id", ProfilesSingleton.getInstance().getCurrentProfile().getProfileID());
        new ApiRequest(Util.URL_ACCEPT_REQUEST, params, new AjaxCallback<String>() {
            @Override
            public void callback(String url, String object, AjaxStatus status) {
                super.callback(url, object, status);
                ApiResponse apiResponse = new ApiResponse(object);
                if (apiResponse.isSuccessful()) {
                    friendRequests.remove(position);
                    CustomToast.makeToast(getActivity(), CustomToast.TYPE_DEFAULT,
                            getString(R.string.you_are_now_friends_with) + " " + friendRequests.get(position).getFullName(),
                            CustomToast.LENGTH_SHORT);
                    mAdapter.notifyDataSetChanged();
                }else {
                    rootView.findViewById(R.id.loading).setVisibility(View.GONE);
                    rootView.findViewById(R.id.acceptBtn).setVisibility(View.VISIBLE);
                    rootView.findViewById(R.id.denyBtn).setVisibility(View.VISIBLE);
                }
                isProcessing = false;
            }
        }).execute();
    }

    private void denyRequest(final int position, final View rootView) {
        if (isProcessing) {
            CustomToast.makeToast(getActivity(), CustomToast.TYPE_ALERT, getString(R.string.please_wait), CustomToast.LENGTH_SHORT);
            return;
        }
        rootView.findViewById(R.id.loading).setVisibility(View.VISIBLE);
        rootView.findViewById(R.id.acceptBtn).setVisibility(View.GONE);
        rootView.findViewById(R.id.denyBtn).setVisibility(View.GONE);
        Log.d("FriendRequest", "denying:" + position);
        FriendRequest request = friendRequests.get(position);
        HashMap<String, Integer> params = new HashMap<>();
        params.put("request_id", request.getRequestID());
        params.put("profile_id", ProfilesSingleton.getInstance().getCurrentProfile().getProfileID());
        new ApiRequest(Util.URL_DENY_REQUEST, params, new AjaxCallback<String>() {
            @Override
            public void callback(String url, String object, AjaxStatus status) {
                super.callback(url, object, status);
                ApiResponse apiResponse = new ApiResponse(object);
                if (apiResponse.isSuccessful()) {
                    friendRequests.remove(position);
                    mAdapter.notifyDataSetChanged();
                }else {
                    rootView.findViewById(R.id.loading).setVisibility(View.GONE);
                    rootView.findViewById(R.id.acceptBtn).setVisibility(View.VISIBLE);
                    rootView.findViewById(R.id.denyBtn).setVisibility(View.VISIBLE);
                }
            }
        }).execute();
    }

    public class FriendRequestAdapter extends ArrayAdapter<FriendRequest> {

        public FriendRequestAdapter(Context context, ArrayList<FriendRequest> objects) {
            super(context, 0, objects);
        }

        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
            View rootView = convertView;
            final ViewHolder holder;
            final FriendRequest friendRequest = getItem(position);
            if (rootView == null) {
                LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                rootView = inflater.inflate(R.layout.friend_request_item, parent, false);
                holder = new ViewHolder();
                holder.profilePhoto = (RoundedImageView) rootView.findViewById(R.id.profilePhoto);
                holder.fullName = (TextView) rootView.findViewById(R.id.fullName);
                holder.acceptBtn = (ImageView) rootView.findViewById(R.id.acceptBtn);
                holder.denyBtn = (ImageView) rootView.findViewById(R.id.denyBtn);
                holder.loading = (ProgressBar) rootView.findViewById(R.id.loading);
                rootView.setTag(holder);
            } else {
                holder = (ViewHolder) rootView.getTag();
            }

            holder.fullName.setText(friendRequest.getFullName());
            if (friendRequest.getFullPhotoPath().equals("")) {
                ImageUtil.replaceWithInitialsView(getContext(), holder.profilePhoto, friendRequest.getInitials());
            } else {
                Util.aQuery.id(holder.profilePhoto).image(friendRequest.getFullPhotoPath(), false, true, 50, R.drawable.avatar_profile, null, AQuery.FADE_IN);
            }

            final View finalRootView = rootView;
            holder.acceptBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    acceptRequest(position, finalRootView);
                }
            });
            holder.denyBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    denyRequest(position, finalRootView);
                }
            });
            return rootView;
        }

        public class ViewHolder {
            RoundedImageView profilePhoto;
            TextView fullName;
            ImageView acceptBtn, denyBtn;
            ProgressBar loading;
        }
    }
}

3 个答案:

答案 0 :(得分:1)

FriendRequest课程中添加一个字段,用于保存进度条的当前状态。基于它设置进度条的可见性。

相同的视图行已发送到另一行。在getView方法中,您必须始终根据其状态设置进度条可见性。

代码示例:

        final View finalRootView = rootView;

        if (friendRequest.acceptingRequestInProgress())
             holder.loading.setVisibility(View.Visibile);
        else
             holder.loading.setVisibility(View.Gone);

        holder.acceptBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                friendRequest.setAcceptingInProgress(true);
                acceptRequest(position, finalRootView);
            }
        });
        holder.denyBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                denyRequest(position, finalRootView);
            }
        });

另一个要修改的地方:

if (apiResponse.isSuccessful()) {
    friendRequest.setAcceptingInProgress(false);
    friendRequests.remove(position);
    mAdapter.notifyDataSetChanged();
}
  

注意:这也处理用户滚动列表时的情况   视图和正在进行的行视图不再可见。这将   将视图交给另一行。但是既然我们检查了行状态了   进度条将被停止。当用户滚动回行时   正在查看进度条并将其设置为可重复使用的进度条视图   如果接受仍在进行中,则再次可见。

答案 1 :(得分:1)

ListView重新使用视图,而getView()方法则不会清理重用的视图,这就是为什么进度条对于不应该显示它的项目可见的原因。

同样,如果某个项目被删除,某些带有进度条的项目会松开进度条,将它们交给一个不需要它的项目。

在getView()中,在初始化持有者之后,您应该检查是否需要进度条。

首先在开头存储进度条值:

private ArrayList<Integer> progresses = new ArrayList<Integer>();

每次列表更改时更新这些值(当loadRequests中的列表更改时以及值更改时不确定的位置)。

在getView()

if (progresses.get(position) == 100) {
  holder.loading.setVisibility(View.GONE);
} else {
  holder.loading.setVisibility(View.VISIBLE);
  holder.loading.setProgress(progresses.get(position));
}

答案 2 :(得分:-1)

问题是由于progressbar的可见性为VISIBLE默认,因此在getView()调用notifyDataSetChanged()后,进度条对行位置(i - 1)可见

holder.loading = (ProgressBar) rootView.findViewById(R.id.loading);
holder.loading.setVisibility(View.GONE);

在getView()中将进度条可见性设置为GONE,此问题不会出现