Android 的简单游标适配器和多行布局
Android's simple cursor adapter and multiple row layouts
在过去的几个月里,我一直在研究 android(主要是教程)。我一直在空闲时间开发一个短信应用程序(为我自己)学习,我已经成功地为每一行获得了不同的布局,但它并没有像我预期的那样工作。
每一行要么在左边,要么在右边(默认为左边),这取决于光标位置的数字是否是我的 phone 数字。
问题是我的测试数据看起来像这样(绿色是我的文本):
这是我的自定义适配器的代码:
public class ConversationMessageListAdapter extends SimpleCursorAdapter {
private LayoutInflater inflater;
private String myPhoneNumber;
public ConversationMessageListAdapter(Context context, int layout, Cursor cursor, String[] from, int[] to, int flags) {
super(context, layout, cursor, from, to, flags);
myPhoneNumber = getMyPhoneNumber(context);
inflater = LayoutInflater.from(context);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
String number = cursor.getString(2);
System.out.println("phone#: "+number);
System.out.println("my#: "+myPhoneNumber);
if(number.equals(myPhoneNumber)){
View view = inflater.inflate(R.layout.single_message_layout_right, null);
return view;
}
return super.newView(context, cursor, parent);
}
public String getMyPhoneNumber(Context context){
TelephonyManager tMgr = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
return tMgr.getLine1Number();
}
}
您可以看到我尝试通过打印出 myPhoneNumber 和 number 的值来调试问题。看起来它们并不总是与行正确匹配。它会在应该是我的那一行显示朋友的号码,但如果我保留默认布局(将它们全部放在左边),它会在文本视图的同一行显示我的号码。喜欢:
555-555-FRND
Have you played Dynasty Warriors?
555-555-MINE
Not yet. Maybe soon.
但此时,打印出来的是:
phone#: 555-555-FRND
my# 555-555-MINE
phone#: 555-555-FRND
my# 555-555-MINE
什么时候应该看起来像:
phone#: 555-555-FRND
my# 555-555-MINE
phone#: 555-555-MINE
my# 555-555-MINE
我不知道是什么原因造成的。
如果有帮助,这是我的 setViewBinder:
textsDbAdapter.setViewBinder(new ConversationMessageListAdapter.ViewBinder() {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
if(columnIndex == 2){
String number = cursor.getString(columnIndex);
String sentBy = getContactName(contentResolver, number);
if(number.equals(myPhoneNumber)){
return false;
}
TextView sender = (TextView) view;
sender.setText(sentBy);
return true;
}
//datetime
if(columnIndex == 5){
Long messageDatetime = Long.valueOf(cursor.getString(columnIndex));
String receivedOn;
if(startOfToday > messageDatetime){
receivedOn = getDateFromDatetime(messageDatetime);
} else {
receivedOn = getTimeFromDatetime(messageDatetime);
}
TextView datetime = (TextView) view;
datetime.setText(receivedOn);
return true;
}
return false;
}
});
编辑:我还发现当我向上滚动然后向下滚动时,行会随机对齐。
EDIT2: XML 添加
single_message_layout_right.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"
android:paddingLeft="0dp"
android:paddingRight="5dp"
android:paddingTop="0dp"
android:paddingBottom="0dp"
android:layout_gravity="right"
tools:context=".ConversationActivity">
<!--Datetime Received-->
<TextView
android:id="@+id/datetime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="bottom"
android:layout_below="@+id/messageContent"
android:layout_toLeftOf="@+id/displayPicContainer"
android:textSize="14sp"
android:textColor="#9110828f" />
<!--Message-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/messageContent"
android:textSize="15sp"
android:layout_marginTop="5dp"
android:layout_toLeftOf="@+id/displayPicContainer"/>
<!--Display picture layout-->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:padding="3dp"
android:layout_marginLeft="5dp"
android:id="@+id/displayPicContainer">
<!--Display picture-->
<ImageView
android:layout_width="45dp"
android:layout_height="45dp"
android:src="@drawable/bigboss150x150"
android:id="@+id/displayPic"/>
</LinearLayout>
</RelativeLayout>
single_message_layout_left.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"
android:paddingLeft="0dp"
android:paddingRight="5dp"
android:paddingTop="0dp"
android:paddingBottom="0dp"
tools:context=".ConversationActivity">
<!--Display picture layout-->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="3dp"
android:layout_marginRight="5dp"
android:id="@+id/displayPicContainer">
<!--Display picture-->
<ImageView
android:layout_width="45dp"
android:layout_height="45dp"
android:src="@drawable/bigboss150x150"
android:id="@+id/displayPic"/>
</LinearLayout>
<!-- sender -->
<TextView
android:id="@+id/sender"
android:textSize="14sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:text="NAME"
android:textColor="#ff9b9aa0"
android:layout_toRightOf="@+id/displayPicContainer"/>
<!--Datetime Received-->
<TextView
android:id="@+id/datetime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="bottom"
android:layout_below="@+id/messageContent"
android:layout_toRightOf="@+id/displayPicContainer"
android:textSize="14sp"
android:textColor="#9110828f" />
<!--Message-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/messageContent"
android:textSize="15sp"
android:layout_below="@+id/sender"
android:layout_toRightOf="@+id/displayPicContainer"/>
</RelativeLayout>
conversation_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ListView
android:id="@+id/conversationListView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="43dp"
android:stackFromBottom="true"
android:transcriptMode="normal">
</ListView>
<RelativeLayout
android:id="@+id/form"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:orientation="vertical"
android:background="#ffffff">
<EditText
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:inputType="textCapSentences|textMultiLine"
android:ems="10"
android:lines="5"
android:minLines="1"
android:hint="Enter message"
android:id="@+id/newMessageText"
android:scrollHorizontally="true"
android:scrollbars="vertical"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_toLeftOf="@+id/sendButton"/>
<Button
android:layout_width="60dp"
android:layout_height="wrap_content"
android:text="Send"
android:id="@+id/sendButton"
android:layout_alignBottom="@+id/newMessageText"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
</RelativeLayout>
</RelativeLayout>
我从执行 newView 切换到执行 getView,这对我有用。
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row;
Log.d("RowID", messages.getString(messages.getColumnIndex("_id")));
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
String fromNumber = messages.getString(messages.getColumnIndex("fromNumber"));
if(fromNumber.equals(myPhoneNumber)){
row = inflater.inflate(R.layout.single_message_layout_right, parent, false);
} else {
row = inflater.inflate(R.layout.single_message_layout_left, parent, false);
TextView sender = (TextView) row.findViewById(R.id.sender);
String name = getContactName(fromNumber);
sender.setText(name);
}
TextView datetime = (TextView) row.findViewById(R.id.datetime);
Long messageDatetime = messages.getLong(messages.getColumnIndex("datetime"));
String receivedOn;
if(startOfToday > messageDatetime){
receivedOn = getDateFromDatetime(messageDatetime);
} else {
receivedOn = getTimeFromDatetime(messageDatetime);
}
datetime.setText(receivedOn);
String message = messages.getString(messages.getColumnIndex("message"));
TextView messageContent = (TextView) row.findViewById(R.id.messageContent);
messageContent.setText(message);
return row;
}
在过去的几个月里,我一直在研究 android(主要是教程)。我一直在空闲时间开发一个短信应用程序(为我自己)学习,我已经成功地为每一行获得了不同的布局,但它并没有像我预期的那样工作。
每一行要么在左边,要么在右边(默认为左边),这取决于光标位置的数字是否是我的 phone 数字。
问题是我的测试数据看起来像这样(绿色是我的文本):
这是我的自定义适配器的代码:
public class ConversationMessageListAdapter extends SimpleCursorAdapter {
private LayoutInflater inflater;
private String myPhoneNumber;
public ConversationMessageListAdapter(Context context, int layout, Cursor cursor, String[] from, int[] to, int flags) {
super(context, layout, cursor, from, to, flags);
myPhoneNumber = getMyPhoneNumber(context);
inflater = LayoutInflater.from(context);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
String number = cursor.getString(2);
System.out.println("phone#: "+number);
System.out.println("my#: "+myPhoneNumber);
if(number.equals(myPhoneNumber)){
View view = inflater.inflate(R.layout.single_message_layout_right, null);
return view;
}
return super.newView(context, cursor, parent);
}
public String getMyPhoneNumber(Context context){
TelephonyManager tMgr = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
return tMgr.getLine1Number();
}
}
您可以看到我尝试通过打印出 myPhoneNumber 和 number 的值来调试问题。看起来它们并不总是与行正确匹配。它会在应该是我的那一行显示朋友的号码,但如果我保留默认布局(将它们全部放在左边),它会在文本视图的同一行显示我的号码。喜欢:
555-555-FRND
Have you played Dynasty Warriors?
555-555-MINE
Not yet. Maybe soon.
但此时,打印出来的是:
phone#: 555-555-FRND
my# 555-555-MINE
phone#: 555-555-FRND
my# 555-555-MINE
什么时候应该看起来像:
phone#: 555-555-FRND
my# 555-555-MINE
phone#: 555-555-MINE
my# 555-555-MINE
我不知道是什么原因造成的。
如果有帮助,这是我的 setViewBinder:
textsDbAdapter.setViewBinder(new ConversationMessageListAdapter.ViewBinder() {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
if(columnIndex == 2){
String number = cursor.getString(columnIndex);
String sentBy = getContactName(contentResolver, number);
if(number.equals(myPhoneNumber)){
return false;
}
TextView sender = (TextView) view;
sender.setText(sentBy);
return true;
}
//datetime
if(columnIndex == 5){
Long messageDatetime = Long.valueOf(cursor.getString(columnIndex));
String receivedOn;
if(startOfToday > messageDatetime){
receivedOn = getDateFromDatetime(messageDatetime);
} else {
receivedOn = getTimeFromDatetime(messageDatetime);
}
TextView datetime = (TextView) view;
datetime.setText(receivedOn);
return true;
}
return false;
}
});
编辑:我还发现当我向上滚动然后向下滚动时,行会随机对齐。
EDIT2: XML 添加
single_message_layout_right.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"
android:paddingLeft="0dp"
android:paddingRight="5dp"
android:paddingTop="0dp"
android:paddingBottom="0dp"
android:layout_gravity="right"
tools:context=".ConversationActivity">
<!--Datetime Received-->
<TextView
android:id="@+id/datetime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="bottom"
android:layout_below="@+id/messageContent"
android:layout_toLeftOf="@+id/displayPicContainer"
android:textSize="14sp"
android:textColor="#9110828f" />
<!--Message-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/messageContent"
android:textSize="15sp"
android:layout_marginTop="5dp"
android:layout_toLeftOf="@+id/displayPicContainer"/>
<!--Display picture layout-->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:padding="3dp"
android:layout_marginLeft="5dp"
android:id="@+id/displayPicContainer">
<!--Display picture-->
<ImageView
android:layout_width="45dp"
android:layout_height="45dp"
android:src="@drawable/bigboss150x150"
android:id="@+id/displayPic"/>
</LinearLayout>
</RelativeLayout>
single_message_layout_left.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"
android:paddingLeft="0dp"
android:paddingRight="5dp"
android:paddingTop="0dp"
android:paddingBottom="0dp"
tools:context=".ConversationActivity">
<!--Display picture layout-->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="3dp"
android:layout_marginRight="5dp"
android:id="@+id/displayPicContainer">
<!--Display picture-->
<ImageView
android:layout_width="45dp"
android:layout_height="45dp"
android:src="@drawable/bigboss150x150"
android:id="@+id/displayPic"/>
</LinearLayout>
<!-- sender -->
<TextView
android:id="@+id/sender"
android:textSize="14sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:text="NAME"
android:textColor="#ff9b9aa0"
android:layout_toRightOf="@+id/displayPicContainer"/>
<!--Datetime Received-->
<TextView
android:id="@+id/datetime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="bottom"
android:layout_below="@+id/messageContent"
android:layout_toRightOf="@+id/displayPicContainer"
android:textSize="14sp"
android:textColor="#9110828f" />
<!--Message-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/messageContent"
android:textSize="15sp"
android:layout_below="@+id/sender"
android:layout_toRightOf="@+id/displayPicContainer"/>
</RelativeLayout>
conversation_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ListView
android:id="@+id/conversationListView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="43dp"
android:stackFromBottom="true"
android:transcriptMode="normal">
</ListView>
<RelativeLayout
android:id="@+id/form"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:orientation="vertical"
android:background="#ffffff">
<EditText
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:inputType="textCapSentences|textMultiLine"
android:ems="10"
android:lines="5"
android:minLines="1"
android:hint="Enter message"
android:id="@+id/newMessageText"
android:scrollHorizontally="true"
android:scrollbars="vertical"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_toLeftOf="@+id/sendButton"/>
<Button
android:layout_width="60dp"
android:layout_height="wrap_content"
android:text="Send"
android:id="@+id/sendButton"
android:layout_alignBottom="@+id/newMessageText"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
</RelativeLayout>
</RelativeLayout>
我从执行 newView 切换到执行 getView,这对我有用。
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row;
Log.d("RowID", messages.getString(messages.getColumnIndex("_id")));
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
String fromNumber = messages.getString(messages.getColumnIndex("fromNumber"));
if(fromNumber.equals(myPhoneNumber)){
row = inflater.inflate(R.layout.single_message_layout_right, parent, false);
} else {
row = inflater.inflate(R.layout.single_message_layout_left, parent, false);
TextView sender = (TextView) row.findViewById(R.id.sender);
String name = getContactName(fromNumber);
sender.setText(name);
}
TextView datetime = (TextView) row.findViewById(R.id.datetime);
Long messageDatetime = messages.getLong(messages.getColumnIndex("datetime"));
String receivedOn;
if(startOfToday > messageDatetime){
receivedOn = getDateFromDatetime(messageDatetime);
} else {
receivedOn = getTimeFromDatetime(messageDatetime);
}
datetime.setText(receivedOn);
String message = messages.getString(messages.getColumnIndex("message"));
TextView messageContent = (TextView) row.findViewById(R.id.messageContent);
messageContent.setText(message);
return row;
}