【发布时间】:2015-11-23 22:30:01
【问题描述】:
我从服务器下载数据并用它们填充列表视图。列表视图中的每个项目都有 3 个按钮,在每个按钮上我都想创建一个 onclicklistener。当用户单击其中一个按钮时,它应该例如打开新活动。每行(对象)都有一些 id,当我点击其中一些按钮时,id 总是例如 15(它总是 listview 中最后一行的 id)。 我试过用很多不同的方式声明 OnClickListeners,结果都是一样的。
法律适配器
public class LawsAdapter extends ArrayAdapter<Law> implements View.OnClickListener {
private LayoutInflater inflater;
private Context context;
private UserLocalStore userLocalStore;
private IsVotedStorage isVotedStorage;
private View convertView;
private ViewHolder viewHolder;
/**
* Constructor, declares storages, context and inflater
* @param context
* @param textViewResourceId
*/
public LawsAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
this.context = context;
inflater = ((Activity) context).getLayoutInflater();
userLocalStore = new UserLocalStore(context);
isVotedStorage = new IsVotedStorage(context);
}
/**
* Second constructor, here you can set the resource (againstr the previous one)
* @param context
* @param resource
* @param items
*/
public LawsAdapter(Context context, int resource, List<Law> items) {
super(context, resource, items);
this.context = context;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
userLocalStore = new UserLocalStore(context);
isVotedStorage = new IsVotedStorage(context);
}
/**
* Overriden method getView, declares graphic objects (btns... ) and set listeners
* @param position
* @param convertView
* @param parent
* @return view
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.law_item, parent, false);
this.convertView = convertView;
viewHolder = new ViewHolder();
viewHolder.tvName = (TextView) convertView.findViewById(R.id.lawItemName);
viewHolder.tvDescription = (TextView) convertView.findViewById(R.id.lawItemDescription);
viewHolder.tvStatus = (TextView) convertView.findViewById(R.id.lawItemStatus);
viewHolder.btnDownvote = (Button) convertView.findViewById(R.id.lawItemDownvote);
viewHolder.btnUpvote = (Button) convertView.findViewById(R.id.lawItemUpvote);
viewHolder.btnMakeComment = (Button) convertView.findViewById(R.id.lawItemMakeComment);
viewHolder.currentLaw = getItem(position);
Log.d("View holder", "new one");
Log.d("LAW ID, ADAPTER", String.valueOf(viewHolder.currentLaw.getId()));
viewHolder.tvName.setText(viewHolder.currentLaw.getName());
viewHolder.tvDescription.setText(viewHolder.currentLaw.getDescription());
viewHolder.tvStatus.setText(viewHolder.currentLaw.getStateValue());
setSurfacesColors();
viewHolder.btnMakeComment.setOnClickListener(this);
viewHolder.btnDownvote.setOnClickListener(this);
viewHolder.btnUpvote.setOnClickListener(this);
disableIfVoted();
convertView.setTag(viewHolder);
}
else {
viewHolder = (ViewHolder) convertView.getTag();
Log.d("View holder", "get tag");
}
return convertView;
}
/**
* Set the colors of surfaces
*/
private void setSurfacesColors() {
viewHolder.sfLeft = (SurfaceView) convertView.findViewById(R.id.lawItemSurfaceLeft);
viewHolder.sfBackground = (SurfaceView) convertView.findViewById(R.id.lawItemSurfaceBackground);
Log.d("VOTES", "Positive: " + viewHolder.currentLaw.getPositiveVotes() + " Negative: " + viewHolder.currentLaw.getNegativeVotes());
if ((viewHolder.currentLaw.getNegativePercent() + viewHolder.currentLaw.getNegativeVotes()) > 1) {
viewHolder.sfBackground.setBackgroundColor(context.getResources().getColor(R.color.redSurfaceBckg));
viewHolder.sfLeft.setBackgroundColor(context.getResources().getColor(R.color.btnSubmitColor));
int screenWidth = getScreenWidth();
int upvote = viewHolder.currentLaw.getNegativePercent();
int downvote = viewHolder.currentLaw.getPositivePercent();
int positivePixels = (screenWidth / 100) * upvote;
int negativePixels = (screenWidth / 100) * downvote;
viewHolder.sfBackground.getHolder().setFixedSize(negativePixels, 5);
viewHolder.sfLeft.getHolder().setFixedSize(positivePixels, 5);
Log.d("UPDATE", "NOTIFY");
}
else {
viewHolder.sfBackground.setBackgroundColor(context.getResources().getColor(R.color.greySurface));
viewHolder.sfLeft.setBackgroundColor(context.getResources().getColor(R.color.greySurface));
}
}
/**
* Upvote
* @param law
*/
private void upvote(Law law) {
ServerRequest serverRequest = new ServerRequest(context);
serverRequest.upvoteLawInBackground(law.getId(), new UpDownCallback() {
@Override
public void done(Law law) {
viewHolder.currentLaw = law;
setSurfacesColors();
Log.e("VOTES in UPVOTE", "Positive: " + viewHolder.currentLaw.getPositiveVotes() + " Negative: " + viewHolder.currentLaw.getNegativeVotes());
}
});
}
/**
* Downvote
* @param law
*/
private void downvote(Law law) {
ServerRequest serverRequest = new ServerRequest(context);
serverRequest.downvoteLawInBackground(law.getId(), new UpDownCallback() {
@Override
public void done(Law law) {
viewHolder.currentLaw = law;
setSurfacesColors();
}
});
}
/**
* Get screen width in pixels
* @return int screen width
*/
private int getScreenWidth() {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
return width;
}
/**
* Disable voting button if I have already voted
*/
private void disableIfVoted() {
if (isVotedStorage.isVoted(viewHolder.currentLaw.getId())) {
viewHolder.btnUpvote.setEnabled(false);
viewHolder.btnDownvote.setEnabled(false);
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.lawItemMakeComment:
if (userLocalStore.isUserLoggedIn()) {
Log.d("ON CLICK LAW ID", String.valueOf(viewHolder.currentLaw.getId()));
Intent commentsIntent = new Intent(context, DialogCommentsActivity.class);
commentsIntent.putExtra("law_id", viewHolder.currentLaw.getId());
commentsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Log.d("CURRENT LAW", viewHolder.currentLaw.getId() + " " + viewHolder.currentLaw.getName());
context.startActivity(commentsIntent);
} else {
context.startActivity(new Intent(context, DialogSignInActivity.class));
}
break;
case R.id.lawItemDownvote:
if (userLocalStore.isUserLoggedIn()) {
isVotedStorage.setVoted(true, viewHolder.currentLaw.getId());
downvote(viewHolder.currentLaw);
disableIfVoted();
notifyDataSetChanged();
} else {
context.startActivity(new Intent(context, DialogSignInActivity.class));
}
break;
case R.id.lawItemUpvote:
if (userLocalStore.isUserLoggedIn()) {
isVotedStorage.setVoted(true, viewHolder.currentLaw.getId());
upvote(viewHolder.currentLaw);
disableIfVoted();
notifyDataSetChanged();
} else {
context.startActivity(new Intent(context, DialogSignInActivity.class));
}
break;
}
}
/**
* Holds items per row
*/
private static class ViewHolder {
private TextView tvName;
private TextView tvDescription;
private TextView tvStatus;
private Button btnUpvote;
private Button btnDownvote;
private Button btnMakeComment;
private SurfaceView sfBackground;
private SurfaceView sfLeft;
private Law currentLaw;
}
}
law_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="170dp"
android:gravity="bottom"
android:padding="6pt"
android:background="@color/button_material_light">
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="140dp"
android:gravity="bottom"
android:background="@color/background_floating_material_light"
android:theme="@style/AppTheme"
android:id="@+id/rel">
<SurfaceView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/lawItemSurfaceBackground"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<SurfaceView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/lawItemSurfaceLeft"
android:layout_alignBaseline="@+id/lawItemSurfaceBackground"
android:layout_alignBottom="@+id/lawItemSurfaceBackground"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/lawItemName"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_below="@+id/lawItemSurfaceBackground"
android:layout_marginTop="2pt"
android:layout_marginBottom="3pt"
android:layout_marginLeft="3pt"
android:layout_marginRight="3pt"
android:padding="1pt"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/lawItemName"
android:textAppearance="?android:attr/textAppearanceMedium"
android:padding="1pt"
android:layout_marginLeft="3pt"
android:layout_marginRight="3pt"
android:layout_marginBottom="3pt"
android:id="@+id/lawItemDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="1pt"
android:layout_marginBottom="3pt"
android:id="@+id/lawItemStatus"
android:layout_marginRight="30pt"
android:layout_below="@+id/lawItemDescription"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="38dp"
android:layout_below="@id/lawItemStatus"
android:orientation="horizontal">
<Button android:layout_weight="1"
android:layout_height="wrap_content"
android:background="@color/btnSubmitColor"
android:textColor="@color/btnSubmitTextColor"
android:layout_width="match_parent"
android:focusable="false"
android:text="@string/button_upvote"
android:id="@+id/lawItemUpvote" />
<Button android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:background="@color/btnSubmitColor"
android:textColor="@color/btnSubmitTextColor"
android:text="@string/button_downvote"
android:focusable="false"
android:id="@+id/lawItemDownvote" />
<Button android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:background="@color/btnSubmitColor"
android:textColor="@color/btnSubmitTextColor"
android:focusable="false"
android:text="@string/button_comment"
android:id="@+id/lawItemMakeComment" />
</LinearLayout>
</RelativeLayout>
</LinearLayout>
示例:我点击第一行的 btnMakeComment,新的 Activity 打开并从 id 为 15 的对象的 db cmets 下载。然后我点击第三行的 btnMakeComment,新的 Activity 打开并从 db cmets 下载具有相同 id 的对象,就像上次一样(再次 15)。 但是在 ListView 中不是相同的行/对象,它们在单击时是不同的,看起来它们是相同的。
DialogCommentsActivity
/**
* Activity for adding and reading comments
*/
public class DialogCommentsActivity extends AppCompatActivity implements AbsListView.OnItemClickListener, AbsListView.OnScrollListener, View.OnClickListener {
private int lawId;
private int limit;
private int offset;
private int preLast;
private int page;
private ListView listView;
private EditText etAddComment;
private List<Comment> activityCommentList;
private UserLocalStore userLocalStore;
private User user;
private Button btnSubmit;
private CommentsAdapter commentsAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_comments_dialog);
setTitle("");
setFinishOnTouchOutside(true);
listView = (ListView) findViewById(R.id.commentDialogListView);
limit = 5;
offset = 0;
page = 1;
userLocalStore = new UserLocalStore(this);
user = userLocalStore.getLoggedUser();
etAddComment = (EditText) findViewById(R.id.commentDialogEditAdd);
btnSubmit = (Button) findViewById(R.id.commentsDialogSubmit);
btnSubmit.setEnabled(false);
listView.setOnItemClickListener(this);
listView.setOnScrollListener(this);
btnSubmit.setOnClickListener(this);
Bundle extras = getIntent().getExtras();
String userName;
dumpIntent(getIntent());
if (extras != null) {
lawId = extras.getInt("law_id");
}
Log.e("LAW ID HOHOHO", String.valueOf(lawId));
fillAdapter(limit, offset);
etAddComment.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (s.toString().trim().length() == 0) {
btnSubmit.setEnabled(false);
} else {
btnSubmit.setEnabled(true);
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_detail_law, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
switch(listView.getId()) {
case R.id.commentDialogListView:
Log.d("SCROLL", "scroll");
boolean loadMore = firstVisibleItem + visibleItemCount >= totalItemCount-1;
if (loadMore) {
page += 1;
// offset = (page * limit) - limit + 1;
// fillAdapter(limit, offset);
// commentsAdapter.notifyDataSetChanged(); TODO
}
}
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
}
public void fillAdapter(int limit, int offset) {
ServerRequest serverRequest = new ServerRequest(this);
Log.e("LAWID BEFORE REQUEST", String.valueOf(lawId));
serverRequest.fetchCommentsInBackground(lawId, limit, offset, new GetCommentsCallback() {
@Override
public void done(List<Comment> comments) {
commentsAdapter = new CommentsAdapter(getApplicationContext(), R.layout.comment_item, comments);
listView.setAdapter(commentsAdapter);
activityCommentList = commentsAdapter.getList();
}
});
}
public void loadData(int limit, int offset) {
ServerRequest serverRequest = new ServerRequest(this);
Log.e("LAWID BEFORE REQUEST", String.valueOf(lawId));
serverRequest.fetchCommentsInBackground(lawId, limit, offset, new GetCommentsCallback() {
@Override
public void done(List<Comment> comments) {
// Updating parsed JSON data into ListView
for (Comment comment : comments) {
Log.d("COMMENT OBJECT", comment.getText());
activityCommentList.add(comment);
}
}
});
}
/**
* Handle click events, comments adding
* @param v
*/
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.commentsDialogSubmit:
String text = String.valueOf(etAddComment.getText());
Date dt = new Date();
Log.d("Click", "Click");
if (userLocalStore.isUserLoggedIn()) {
Log.e("LAW ID NEW COMM", String.valueOf(lawId));
Comment comment = new Comment(text, dt, user, lawId);
addComment(comment);
etAddComment.setText("");
//notifyData(limit, offset);
limit = 15;
offset = 0;
fillAdapter(limit, offset);
commentsAdapter.notifyDataSetChanged();
Log.e("NUMBER OF COMMENTS", String.valueOf(activityCommentList.size()));
}
break;
}
}
/**
* Insert comment
* @param comment
*/
public void addComment(Comment comment) {
ServerRequest serverRequest = new ServerRequest(this);
serverRequest.storeCommentInBackground(comment, new GetCommentsCallback() {
@Override
public void done(List<Comment> list) {
Log.d("Comment", "Comment was added.");
}
});
}
private void dumpIntent(Intent i) {
Bundle bundle = i.getExtras();
if (bundle != null) {
Set<String> keys = bundle.keySet();
Iterator<String> it = keys.iterator();
Log.e("EXTRAS", "Dumping Intent start");
while (it.hasNext()) {
String key = it.next();
Log.e("EXTRAS", "[" + key + "=" + bundle.get(key) + "]");
}
Log.e("EXTRAS", "Dumping Intent end");
}
}
}
解决方案:
我添加了 ViewHolder viewHolder = v.getTag();在每个侦听器中(以及在每个按钮上的 getView 中的 setTag(viewHolder) 之前
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.law_item, parent, false);
this.convertView = convertView;
viewHolder = new ViewHolder();
viewHolder.position = position;
viewHolder.tvName = (TextView) convertView.findViewById(R.id.lawItemName);
viewHolder.tvDescription = (TextView) convertView.findViewById(R.id.lawItemDescription);
viewHolder.tvStatus = (TextView) convertView.findViewById(R.id.lawItemStatus);
viewHolder.btnDownvote = (Button) convertView.findViewById(R.id.lawItemDownvote);
viewHolder.btnUpvote = (Button) convertView.findViewById(R.id.lawItemUpvote);
viewHolder.btnMakeComment = (Button) convertView.findViewById(R.id.lawItemMakeComment);
viewHolder.btnMakeComment.setTag(viewHolder);
viewHolder.btnDownvote.setTag(viewHolder);
viewHolder.btnUpvote.setTag(viewHolder);
convertView.setTag(viewHolder);
}
else {
viewHolder = (ViewHolder) convertView.getTag();
Log.d("View holder", "get tag");
}
viewHolder.currentLaw = getItem(position);
Log.d("View holder", "new one");
Log.d("LAW ID, ADAPTER", String.valueOf(viewHolder.currentLaw.getId()));
viewHolder.tvName.setText(viewHolder.currentLaw.getName());
viewHolder.tvDescription.setText(viewHolder.currentLaw.getDescription());
viewHolder.tvStatus.setText(viewHolder.currentLaw.getStateValue());
setSurfacesColors();
disableIfVoted();
viewHolder.btnMakeComment.setOnClickListener(onCommentClickListener);
viewHolder.btnDownvote.setOnClickListener(onDowvnvoteClickListener);
viewHolder.btnUpvote.setOnClickListener(onUpvoteClickListener);
// viewHolder.btnMakeComment.setOnClickListener(onCommentClickListener);
return convertView;
}
@Override
public long getItemId(int position) {
return laws.get(position).getId();
}
@Override
public Law getItem(int position) {
return laws.get(position);
}
/**
* On upvote listener
*/
private View.OnClickListener onUpvoteClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
ViewHolder viewHolder = (ViewHolder) v.getTag();
if (userLocalStore.isUserLoggedIn()) {
isVotedStorage.setVoted(true, viewHolder.currentLaw.getId());
upvote(viewHolder.currentLaw);
disableIfVoted();
notifyDataSetChanged();
} else {
context.startActivity(new Intent(context, DialogSignInActivity.class));
}
}
};
/**
* On downvote listener
*/
private View.OnClickListener onDowvnvoteClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
ViewHolder viewHolder = (ViewHolder) v.getTag();
if (userLocalStore.isUserLoggedIn()) {
isVotedStorage.setVoted(true, viewHolder.currentLaw.getId());
downvote(viewHolder.currentLaw);
disableIfVoted();
notifyDataSetChanged();
} else {
context.startActivity(new Intent(context, DialogSignInActivity.class));
}
}
};
/**
* On comment listener, open comment dialog
*/
private View.OnClickListener onCommentClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
ViewHolder viewHolder = (ViewHolder) v.getTag();
if (userLocalStore.isUserLoggedIn()) {
Log.d("ON CLICK LAW ID", String.valueOf(viewHolder.currentLaw.getId()));
Intent commentsIntent = new Intent(context, DialogCommentsActivity.class);
commentsIntent.putExtra("law_id", viewHolder.currentLaw.getId());
commentsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Log.d("CURRENT LAW", viewHolder.currentLaw.getId() + " " + viewHolder.currentLaw.getName());
context.startActivity(commentsIntent);
} else {
context.startActivity(new Intent(context, DialogSignInActivity.class));
}
}
};
【问题讨论】:
-
onItemClick() 中没有处理ListView 上的点击事件的函数。同样在您的适配器类中,我看不到您覆盖 getItemId(int position) 的位置
标签: android