我有一个ListView
,其中有几行包含两个按钮,每行一个ProgressBar (Visibility:GONE)
。
我的目的是在点击按钮后显示ProgressBar
,完成一组后台操作后,完全删除该行。
这里的问题是,从创建ArrayList
并ListView
调用notifyDataSetChanged
的{{1}}中移除项目后,该行已成功删除,但ProgressBar
仍然可见。
是否应该将其与其父视图一起删除?
签出以下记录以查看问题的实际效果。
以下是我整个片段的来源:
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;
}
}
}
答案 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,此问题不会出现