我编写了一个自定义适配器来加载ListView的列表。有用。目前,我有兴趣让它回复点击,以便发送电子邮件。我添加了代码以向我的点击监听器发送电子邮件(如this)。
这是来自我的自定义适配器;传递给构造函数MessagesAdapter()
的上下文是getApplicationContext()
。 (我按照建议here尝试使用this
;但是,它没有用。)
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;
}
我的问题似乎是startActivity()
造成的。如果不使用ctx.startActivity()
,我会得到一个空指针异常。如果我这样做,我会得到Android运行时异常。即使使用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?
所以,在这里。
MessageAdapter
设置为ListView
。 View.OnClickListener()
。单击显示的消息时,应用程序崩溃。
您能帮我解决一下如何实施点击吗?
各个项目的布局
<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>
列表视图的布局:
<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>
邮件适配器代码
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;
}
}
使用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,"");
}
}) ;
}
答案 0 :(得分:4)
您还可以使用android.text.SpannableString
和android.text.style.URLSpan
创建可点击的文字。您还可以使用不同的操作在同一TextView中单击或单击文本的一部分。我为你做了这个例子:
MainActivity:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getFragmentManager().beginTransaction().add(R.id.container, new MainFragment()).commit();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
MainFragment:
public class MainFragment extends Fragment{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View view = inflater.inflate(R.layout.fragment_main, null);
ListView list = (ListView)view.findViewById(R.id.listView1);
ArrayList<String> items = new ArrayList<String>();
for(int i = 0; i < 10; i++){
items.add("These both words are clickable: word1 word2");
}
ListAdapter adapter = new ListAdapter(getActivity(), items);
list.setAdapter(adapter);
return view;
}
private class ListAdapter extends BaseAdapter {
private LayoutInflater mInflater;
private ArrayList<String> mListItems;
public ListAdapter(Context context, ArrayList<String> items){
mInflater = LayoutInflater.from(context);
mListItems = items;
}
@Override
public int getCount() {
return mListItems.size();
}
@Override
public Object getItem(int position) {
return mListItems.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
public Spannable setSpan(String text){
Spannable span = new SpannableString(text);
//Span the word that you want to be clickable, in this case we span two words
//These both words are clickable: word1 word2
//Span word1, this will also underline the word
span.setSpan(new SpanListener(text.substring(32, 37)), 32, 37, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
span.setSpan(new SpanListener(text.substring(38, 43)), 38, 43, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return span;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView == null){
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.list_item, null);
holder.text = (TextView)convertView.findViewById(R.id.textView1);
convertView.setTag(holder);
} else{
holder = (ViewHolder)convertView.getTag();
}
holder.text.setText(setSpan(mListItems.get(position)));
holder.text.setMovementMethod(LinkMovementMethod.getInstance());
((ViewGroup)convertView).setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
return convertView;
}
}
static class ViewHolder {
TextView text;
}
public class SpanListener extends URLSpan {
String spanned_text;
public SpanListener(String text) {
super(text);
spanned_text = text;
}
public void onClick(View v){
DialogFragment dialog = new TextDialog();
Bundle bundle = new Bundle();
bundle.putString("text", spanned_text);
dialog.setArguments(bundle);
dialog.show(getFragmentManager(), "");
}
@Override
public void updateDrawState(TextPaint paint) {
super.updateDrawState(paint);
//Remove underline
paint.setUnderlineText(false);
}
}
public static class TextDialog extends DialogFragment implements OnClickListener {
@Override
public Dialog onCreateDialog(Bundle savedinstanceState){
final Context context = this.getActivity();
String text = "";
Bundle bundle = this.getArguments();
if(bundle != null){
text = bundle.getString("text");
}
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage("You clicked: " + text);
builder.setPositiveButton("OK", this);
return builder.create();
}
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
}
}
list_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="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp" />
fragment_main.xml
<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"
tools:context="com.example.clickabletextviewinsidelistview.MainActivity$PlaceholderFragment" >
<ListView
android:id="@+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
结果:
答案 1 :(得分:0)
此问题的罪魁祸首可能是android:autoLink="email"
和android:layout_width="match_parent"
。这会使用一个可点击的TextView填充ListView的项目。
此外,您似乎将其设置为无法点击,因此最终挖掘自己一个洞: - )
如果ListView的整个项目都是可点击的,则无需使用autoLink标记。所以只需删除它。其他一切似乎都很好。希望这适用于你。快乐的编码! : - )