I have written a custom adapter to load the list for my ListView. It works. Currently, I am interested in making it respond to click so that an email could be sent. I added the code to send email (like this) to my click listener.
This is from my custom adapter; the context passed to the constructor MessagesAdapter()
is getApplicationContext()
. (I did try with this
as suggested here; but, it didn't work.)
public MessagesAdapter(Context context, int textViewResourceId, ArrayList<String> fileRecords) {
super(context, textViewResourceId, fileRecords);
this.ctx = context;
this.l = fileRecords;
}
@SuppressLint("ViewHolder")
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) ctx
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.activity_messages_item, parent, false);
TextView hView = (TextView) rowView.findViewById(R.id.messageHeader);
TextView dView = (TextView) rowView.findViewById(R.id.messageDetail);
TextView fView = (TextView) rowView.findViewById(R.id.messageFooter);
String s = l.get(position);
String[] parts = s.split(";");
hView.setText(parts[0]);
rm.setmHeader(parts[0]);
hView.setTextSize(TypedValue.COMPLEX_UNIT_SP, ctx.getResources().getDimension(R.dimen.header_text));
dView.setText(parts[1]);
rm.setmDetail(parts[1]);
hView.setTextSize(TypedValue.COMPLEX_UNIT_SP, ctx.getResources().getDimension(R.dimen.detail_text));
fView.setText(parts[2]);
rm.setmFooter(parts[2]);
hView.setTextSize(TypedValue.COMPLEX_UNIT_SP, ctx.getResources().getDimension(R.dimen.footer_text));
dView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(Intent.EXTRA_EMAIL, rm.getmDetail().split(" ")[1]);
intent.putExtra(Intent.EXTRA_SUBJECT, ctx.getResources().getString(R.string.email_subject) + " " + rm.getmHeader());
ctx.startActivity(Intent.createChooser(intent, ""));
}
});
return rowView;
}
My problem seems to be due to startActivity()
. If don't use ctx.startActivity()
, I get a null pointer exception. If I do, I get a Android Runtime Exception. This is even with Intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.
07-27 02:50:15.747: E/AndroidRuntime(2092): android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
So, here it is.
- The Activity sets up the
MessageAdapter
to theListView
. - The adapter sets up the text views with list data correctly.
- The adapter also sets up a
View.OnClickListener()
.
When the displayed message is clicked, the application crashes.
Could you please help me how to implement the click ?
Layout for individual items
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="match_parent"
tools:context="com.foo.bar.MessageActivity" >
<TextView
android:id="@+id/messageHeader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:textStyle="bold"/>
<TextView
android:id="@+id/messageDetail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/messageHeader"
android:autoLink="email"/>
<TextView
android:id="@+id/messageFooter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/messageDetail" />
</RelativeLayout>
Layout for list view:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context="com.foo.bar.MessagesActivity" >
<ListView
android:id="@android:id/list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true" >
</ListView>
</RelativeLayout>
Message adapter code
import java.util.ArrayList;
import android.annotation.SuppressLint;
import android.content.Context;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
public class MessagesAdapter extends ArrayAdapter<String> {
private Context ctx;
private ArrayList<String> l;
ReceivedMessages rm = new ReceivedMessages();
public MessagesAdapter(Context context, int textViewResourceId, ArrayList<String> fileRecords) {
super(context, textViewResourceId, fileRecords);
this.ctx = context;
this.l = fileRecords;
}
@SuppressLint("ViewHolder")
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) ctx
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.activity_messages_item, parent, false);
TextView hView = (TextView) rowView.findViewById(R.id.messageHeader);
TextView dView = (TextView) rowView.findViewById(R.id.messageDetail);
TextView fView = (TextView) rowView.findViewById(R.id.messageFooter);
String s = l.get(position);
String[] parts = s.split(";");
hView.setText(parts[0]);
hView.setTextSize(TypedValue.COMPLEX_UNIT_SP, ctx.getResources().getDimension(R.dimen.header_text));
hView.setClickable(false);
hView.setLongClickable(false);
hView.setOnClickListener(null);
dView.setText(parts[1]);
dView.setTextSize(TypedValue.COMPLEX_UNIT_SP, ctx.getResources().getDimension(R.dimen.detail_text));
dView.setClickable(false);
dView.setLongClickable(false);
fView.setText(parts[2]);
fView.setTextSize(TypedValue.COMPLEX_UNIT_SP, ctx.getResources().getDimension(R.dimen.footer_text));
fView.setClickable(false);
dView.setOnClickListener(null);
return rowView;
}
}
Using the MessageAdapter
// Handler for received Intents
private BroadcastReceiver fileReadReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
populateList();
}
};
private void populateList() {
String[] values = fc.getMessageArray();
final ArrayList<String> list = new ArrayList<String>();
for (int i = 0; i < values.length; i++) {
list.add(values[values.length-1-i]); // Reversing the list to show recent messages first
++i;
}
MessagesAdapter ma = new MessagesAdapter(getApplicationContext(),
R.layout.activity_messages_item, list);
final ListView listView = (ListView) findViewById(android.R.id.list);
listView.setClickable(true);
listView.setAdapter(ma);
listView.setOnItemClickListener(new ListView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
String s = list.get(Long.valueOf(id).intValue());
Log.d("MessagesActivity", s);
Intent emailintent = new Intent(android.content.Intent.ACTION_SEND);
emailintent.setType("plain/text");
emailintent.putExtra(android.content.Intent.EXTRA_EMAIL,new String[] {"random@gmail.com" });
emailintent.putExtra(android.content.Intent.EXTRA_SUBJECT, "");
emailintent.putExtra(android.content.Intent.EXTRA_TEXT,"");
}
}) ;
}