Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
X
xabber-android
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
xabber-android
Commits
aab530bf
Commit
aab530bf
authored
Apr 20, 2015
by
Grigory Fedorov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Chat: ListView replaced by RecyclerView. Clicks do not work so far.
parent
4224e9a5
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
145 additions
and
125 deletions
+145
-125
ChatViewerFragment.java
...c/main/java/com/xabber/android/ui/ChatViewerFragment.java
+14
-10
ChatMessageAdapter.java
...ava/com/xabber/android/ui/adapter/ChatMessageAdapter.java
+128
-112
chat_viewer_item.xml
app/src/main/res/layout/chat_viewer_item.xml
+3
-3
No files found.
app/src/main/java/com/xabber/android/ui/ChatViewerFragment.java
View file @
aab530bf
...
...
@@ -8,6 +8,8 @@ import android.content.Context;
import
android.os.Bundle
;
import
android.support.v4.app.NavUtils
;
import
android.support.v7.app.ActionBarActivity
;
import
android.support.v7.widget.LinearLayoutManager
;
import
android.support.v7.widget.RecyclerView
;
import
android.support.v7.widget.Toolbar
;
import
android.text.Editable
;
import
android.text.TextWatcher
;
...
...
@@ -24,7 +26,6 @@ import android.view.animation.AnimationUtils;
import
android.widget.AdapterView
;
import
android.widget.EditText
;
import
android.widget.ImageButton
;
import
android.widget.ListView
;
import
android.widget.PopupMenu
;
import
com.xabber.android.data.Application
;
...
...
@@ -63,7 +64,8 @@ public class ChatViewerFragment extends Fragment implements AdapterView.OnItemCl
private
static
final
int
MINIMUM_MESSAGES_TO_LOAD
=
10
;
private
EditText
inputView
;
private
ListView
listView
;
private
RecyclerView
recyclerView
;
private
ChatMessageAdapter
chatMessageAdapter
;
private
boolean
skipOnTextChanges
;
...
...
@@ -156,10 +158,12 @@ public class ChatViewerFragment extends Fragment implements AdapterView.OnItemCl
chatMessageAdapter
=
new
ChatMessageAdapter
(
getActivity
(),
account
,
user
);
listView
=
(
ListView
)
view
.
findViewById
(
android
.
R
.
id
.
list
);
listView
.
setAdapter
(
chatMessageAdapter
);
listView
.
setOnItemClickListener
(
this
);
recyclerView
=
(
RecyclerView
)
view
.
findViewById
(
R
.
id
.
chat_messages_recycler_view
);
recyclerView
.
setAdapter
(
chatMessageAdapter
);
LinearLayoutManager
layoutManager
=
new
LinearLayoutManager
(
getActivity
());
layoutManager
.
setStackFromEnd
(
true
);
recyclerView
.
setLayoutManager
(
layoutManager
);
inputView
=
(
EditText
)
view
.
findViewById
(
R
.
id
.
chat_input
);
...
...
@@ -369,7 +373,7 @@ public class ChatViewerFragment extends Fragment implements AdapterView.OnItemCl
super
.
onCreateContextMenu
(
menu
,
view
,
menuInfo
);
AdapterView
.
AdapterContextMenuInfo
info
=
(
AdapterView
.
AdapterContextMenuInfo
)
menuInfo
;
ChatMessageAdapter
chatMessageAdapter
=
(
ChatMessageAdapter
)
list
View
.
getAdapter
();
ChatMessageAdapter
chatMessageAdapter
=
(
ChatMessageAdapter
)
recycler
View
.
getAdapter
();
int
itemViewType
=
chatMessageAdapter
.
getItemViewType
(
info
.
position
);
...
...
@@ -388,7 +392,7 @@ public class ChatViewerFragment extends Fragment implements AdapterView.OnItemCl
@Override
public
boolean
onContextItemSelected
(
MenuItem
item
)
{
AdapterView
.
AdapterContextMenuInfo
info
=
(
AdapterView
.
AdapterContextMenuInfo
)
item
.
getMenuInfo
();
final
MessageItem
message
=
(
MessageItem
)
listView
.
getAdapter
()
.
getItem
(
info
.
position
);
final
MessageItem
message
=
(
MessageItem
)
chatMessageAdapter
.
getItem
(
info
.
position
);
switch
(
item
.
getItemId
())
{
case
R
.
id
.
action_message_repeat
:
...
...
@@ -453,9 +457,9 @@ public class ChatViewerFragment extends Fragment implements AdapterView.OnItemCl
@Override
public
void
onItemClick
(
AdapterView
<?>
parent
,
View
view
,
int
position
,
long
id
)
{
registerForContextMenu
(
list
View
);
list
View
.
showContextMenuForChild
(
view
);
unregisterForContextMenu
(
list
View
);
registerForContextMenu
(
recycler
View
);
recycler
View
.
showContextMenuForChild
(
view
);
unregisterForContextMenu
(
recycler
View
);
}
@Override
...
...
app/src/main/java/com/xabber/android/ui/adapter/ChatMessageAdapter.java
View file @
aab530bf
...
...
@@ -15,13 +15,14 @@
package
com
.
xabber
.
android
.
ui
.
adapter
;
import
android.app.Activity
;
import
android.support.v7.widget.RecyclerView
;
import
android.text.Spannable
;
import
android.text.SpannableStringBuilder
;
import
android.text.style.CharacterStyle
;
import
android.text.style.TextAppearanceSpan
;
import
android.view.LayoutInflater
;
import
android.view.View
;
import
android.view.ViewGroup
;
import
android.widget.BaseAdapter
;
import
android.widget.ImageView
;
import
android.widget.TextView
;
...
...
@@ -45,16 +46,8 @@ import java.util.Collections;
import
java.util.Date
;
import
java.util.List
;
/**
* Adapter for the list of messages in the chat.
*
* @author alexander.ivanov
*/
public
class
ChatMessageAdapter
extends
BaseAdapter
implements
UpdatableAdapter
{
public
class
ChatMessageAdapter
extends
RecyclerView
.
Adapter
<
RecyclerView
.
ViewHolder
>
implements
UpdatableAdapter
{
private
static
final
int
VIEW_TYPE_COUNT
=
5
;
private
static
final
int
VIEW_TYPE_EMPTY
=
0
;
private
static
final
int
VIEW_TYPE_HINT
=
1
;
public
static
final
int
VIEW_TYPE_INCOMING_MESSAGE
=
2
;
public
static
final
int
VIEW_TYPE_OUTGOING_MESSAGE
=
3
;
...
...
@@ -81,6 +74,58 @@ public class ChatMessageAdapter extends BaseAdapter implements UpdatableAdapter
*/
private
String
hint
;
public
static
class
HintMessage
extends
RecyclerView
.
ViewHolder
{
public
TextView
info
;
public
HintMessage
(
View
itemView
)
{
super
(
itemView
);
info
=
(
TextView
)
itemView
.
findViewById
(
R
.
id
.
info
);
}
}
public
static
class
ActionMessage
extends
RecyclerView
.
ViewHolder
{
public
TextView
actionMessage
;
public
ActionMessage
(
View
itemView
)
{
super
(
itemView
);
actionMessage
=
(
TextView
)
itemView
.
findViewById
(
R
.
id
.
action_message_text
);
}
}
public
static
abstract
class
Message
extends
RecyclerView
.
ViewHolder
{
public
TextView
messageText
;
public
TextView
messageTime
;
public
Message
(
View
itemView
)
{
super
(
itemView
);
messageText
=
(
TextView
)
itemView
.
findViewById
(
R
.
id
.
message_text
);
messageTime
=
(
TextView
)
itemView
.
findViewById
(
R
.
id
.
message_time
);
}
}
public
static
class
IncomingMessage
extends
Message
{
public
ImageView
avatar
;
public
IncomingMessage
(
View
itemView
)
{
super
(
itemView
);
avatar
=
(
ImageView
)
itemView
.
findViewById
(
R
.
id
.
avatar
);
}
}
public
static
class
OutgoingMessage
extends
Message
{
public
ImageView
statusIcon
;
public
OutgoingMessage
(
View
itemView
)
{
super
(
itemView
);
statusIcon
=
(
ImageView
)
itemView
.
findViewById
(
R
.
id
.
message_status_icon
);
}
}
public
ChatMessageAdapter
(
Activity
activity
,
String
account
,
String
user
)
{
this
.
activity
=
activity
;
messages
=
Collections
.
emptyList
();
...
...
@@ -99,11 +144,64 @@ public class ChatMessageAdapter extends BaseAdapter implements UpdatableAdapter
}
@Override
public
int
getCount
()
{
return
messages
.
size
()
+
1
;
public
RecyclerView
.
ViewHolder
onCreateViewHolder
(
ViewGroup
parent
,
int
viewType
)
{
switch
(
viewType
)
{
case
VIEW_TYPE_HINT:
return
new
HintMessage
(
LayoutInflater
.
from
(
parent
.
getContext
())
.
inflate
(
R
.
layout
.
chat_viewer_info
,
parent
,
false
));
case
VIEW_TYPE_ACTION_MESSAGE:
return
new
ActionMessage
(
LayoutInflater
.
from
(
parent
.
getContext
())
.
inflate
(
R
.
layout
.
chat_viewer_action_message
,
parent
,
false
));
case
VIEW_TYPE_INCOMING_MESSAGE:
return
new
IncomingMessage
(
LayoutInflater
.
from
(
parent
.
getContext
())
.
inflate
(
R
.
layout
.
chat_viewer_incoming_message
,
parent
,
false
));
case
VIEW_TYPE_OUTGOING_MESSAGE:
return
new
OutgoingMessage
(
LayoutInflater
.
from
(
parent
.
getContext
())
.
inflate
(
R
.
layout
.
chat_viewer_outgoing_message
,
parent
,
false
));
default
:
return
null
;
}
}
@Override
public
void
onBindViewHolder
(
RecyclerView
.
ViewHolder
holder
,
int
position
)
{
final
int
viewType
=
getItemViewType
(
position
);
MessageItem
messageItem
=
(
MessageItem
)
getItem
(
position
);
switch
(
viewType
)
{
case
VIEW_TYPE_HINT:
((
HintMessage
)
holder
).
info
.
setText
(
hint
);
break
;
case
VIEW_TYPE_ACTION_MESSAGE:
ChatAction
action
=
messageItem
.
getAction
();
String
time
=
StringUtils
.
getSmartTimeText
(
activity
,
messageItem
.
getTimestamp
());
((
ActionMessage
)
holder
).
actionMessage
.
setText
(
time
+
": "
+
action
.
getText
(
activity
,
messageItem
.
getResource
(),
messageItem
.
getSpannable
().
toString
()));
break
;
case
VIEW_TYPE_INCOMING_MESSAGE:
setUpMessage
(
messageItem
,
(
Message
)
holder
);
setUpAvatar
(
messageItem
,
(
IncomingMessage
)
holder
);
break
;
case
VIEW_TYPE_OUTGOING_MESSAGE:
setUpMessage
(
messageItem
,
(
Message
)
holder
);
setStatusIcon
(
messageItem
,
(
OutgoingMessage
)
holder
);
break
;
}
}
@Override
public
int
getItemCount
()
{
return
messages
.
size
()
+
1
;
}
public
Object
getItem
(
int
position
)
{
if
(
position
<
messages
.
size
())
{
return
messages
.
get
(
position
);
...
...
@@ -117,15 +215,10 @@ public class ChatMessageAdapter extends BaseAdapter implements UpdatableAdapter
return
position
;
}
@Override
public
int
getViewTypeCount
()
{
return
VIEW_TYPE_COUNT
;
}
@Override
public
int
getItemViewType
(
int
position
)
{
if
(
position
>=
messages
.
size
())
{
return
hint
==
null
?
VIEW_TYPE_EMPTY
:
VIEW_TYPE_HINT
;
return
VIEW_TYPE_HINT
;
}
MessageItem
messageItem
=
(
MessageItem
)
getItem
(
position
);
...
...
@@ -136,79 +229,10 @@ public class ChatMessageAdapter extends BaseAdapter implements UpdatableAdapter
return
messageItem
.
isIncoming
()
?
VIEW_TYPE_INCOMING_MESSAGE
:
VIEW_TYPE_OUTGOING_MESSAGE
;
}
@Override
public
View
getView
(
int
position
,
View
convertView
,
ViewGroup
parent
)
{
final
int
type
=
getItemViewType
(
position
);
if
(
type
==
VIEW_TYPE_EMPTY
)
{
if
(
convertView
==
null
)
{
return
activity
.
getLayoutInflater
().
inflate
(
R
.
layout
.
chat_viewer_empty
,
parent
,
false
);
}
else
{
return
convertView
;
}
}
if
(
type
==
VIEW_TYPE_HINT
)
{
View
view
=
convertView
;
if
(
convertView
==
null
)
{
view
=
activity
.
getLayoutInflater
().
inflate
(
R
.
layout
.
chat_viewer_info
,
parent
,
false
);
}
TextView
textView
=
((
TextView
)
view
.
findViewById
(
R
.
id
.
info
));
textView
.
setText
(
hint
);
textView
.
setTextAppearance
(
activity
,
R
.
style
.
ChatInfo_Warning
);
return
view
;
}
MessageItem
messageItem
=
(
MessageItem
)
getItem
(
position
);
if
(
type
==
VIEW_TYPE_ACTION_MESSAGE
)
{
View
view
=
convertView
;
if
(
convertView
==
null
)
{
view
=
activity
.
getLayoutInflater
().
inflate
(
R
.
layout
.
chat_viewer_action_message
,
parent
,
false
);
}
ChatAction
action
=
messageItem
.
getAction
();
String
time
=
StringUtils
.
getSmartTimeText
(
activity
,
messageItem
.
getTimestamp
());
((
TextView
)
view
.
findViewById
(
R
.
id
.
action_message_text
)).
setText
(
time
+
": "
+
action
.
getText
(
activity
,
messageItem
.
getResource
(),
messageItem
.
getSpannable
().
toString
()));
return
view
;
}
View
view
=
convertView
;
if
(
convertView
==
null
)
{
final
int
layoutId
;
if
(
type
==
VIEW_TYPE_INCOMING_MESSAGE
)
{
layoutId
=
R
.
layout
.
chat_viewer_incoming_message
;
}
else
if
(
type
==
VIEW_TYPE_OUTGOING_MESSAGE
)
{
layoutId
=
R
.
layout
.
chat_viewer_outgoing_message
;
}
else
{
throw
new
IllegalStateException
();
}
view
=
activity
.
getLayoutInflater
().
inflate
(
layoutId
,
parent
,
false
);
}
setUpMessageView
(
messageItem
,
view
);
return
view
;
}
private
void
setUpMessageView
(
MessageItem
messageItem
,
View
view
)
{
final
boolean
incoming
=
messageItem
.
isIncoming
();
private
void
setUpMessage
(
MessageItem
messageItem
,
Message
message
)
{
SpannableStringBuilder
builder
=
new
SpannableStringBuilder
();
final
String
resource
=
messageItem
.
getResource
();
if
(!
incoming
)
{
setStatusIcon
(
messageItem
,
view
);
}
if
(
isMUC
)
{
append
(
builder
,
resource
,
new
TextAppearanceSpan
(
activity
,
R
.
style
.
ChatHeader_Time
));
append
(
builder
,
divider
,
new
TextAppearanceSpan
(
activity
,
R
.
style
.
ChatHeader
));
...
...
@@ -230,29 +254,23 @@ public class ChatMessageAdapter extends BaseAdapter implements UpdatableAdapter
append
(
builder
,
text
,
new
TextAppearanceSpan
(
activity
,
R
.
style
.
ChatRead
));
}
TextView
textView
=
(
TextView
)
view
.
findViewById
(
R
.
id
.
message_text
);
textView
.
setTextAppearance
(
activity
,
appearanceStyle
);
textView
.
setText
(
builder
);
textView
.
getBackground
().
setLevel
(
AccountManager
.
getInstance
().
getColorLevel
(
account
));
message
.
messageText
.
setTextAppearance
(
activity
,
appearanceStyle
);
message
.
messageText
.
setText
(
builder
);
message
.
messageText
.
getBackground
().
setLevel
(
AccountManager
.
getInstance
().
getColorLevel
(
account
));
String
time
=
StringUtils
.
getSmartTimeText
(
activity
,
messageItem
.
getTimestamp
());
if
(
delayTimestamp
!=
null
)
{
String
delay
=
activity
.
getString
(
incoming
?
R
.
string
.
chat_delay
:
R
.
string
.
chat_typed
,
String
delay
=
activity
.
getString
(
messageItem
.
isIncoming
()
?
R
.
string
.
chat_delay
:
R
.
string
.
chat_typed
,
StringUtils
.
getSmartTimeText
(
activity
,
delayTimestamp
));
time
+=
" ("
+
delay
+
")"
;
}
((
TextView
)
view
.
findViewById
(
R
.
id
.
message_time
)).
setText
(
time
);
if
(
incoming
)
{
setUpAvatar
(
messageItem
,
view
);
}
message
.
messageTime
.
setText
(
time
);
}
private
void
setStatusIcon
(
MessageItem
messageItem
,
View
view
)
{
ImageView
messageStatusIcon
=
(
ImageView
)
view
.
findViewById
(
R
.
id
.
message_status_icon
);
messageStatusIcon
.
setVisibility
(
View
.
VISIBLE
);
private
void
setStatusIcon
(
MessageItem
messageItem
,
OutgoingMessage
message
)
{
message
.
statusIcon
.
setVisibility
(
View
.
VISIBLE
);
int
messageIcon
=
R
.
drawable
.
ic_message_delivered_18dp
;
if
(
messageItem
.
isError
())
{
...
...
@@ -260,10 +278,10 @@ public class ChatMessageAdapter extends BaseAdapter implements UpdatableAdapter
}
else
if
(!
messageItem
.
isSent
())
{
messageIcon
=
R
.
drawable
.
ic_message_not_sent_18dp
;
}
else
if
(!
messageItem
.
isDelivered
())
{
message
S
tatusIcon
.
setVisibility
(
View
.
INVISIBLE
);
message
.
s
tatusIcon
.
setVisibility
(
View
.
INVISIBLE
);
}
message
S
tatusIcon
.
setImageResource
(
messageIcon
);
message
.
s
tatusIcon
.
setImageResource
(
messageIcon
);
}
private
void
append
(
SpannableStringBuilder
builder
,
CharSequence
text
,
CharacterStyle
span
)
{
...
...
@@ -272,30 +290,28 @@ public class ChatMessageAdapter extends BaseAdapter implements UpdatableAdapter
builder
.
setSpan
(
span
,
start
,
start
+
text
.
length
(),
Spannable
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
}
private
void
setUpAvatar
(
MessageItem
messageItem
,
View
view
)
{
ImageView
avatarView
=
(
ImageView
)
view
.
findViewById
(
R
.
id
.
avatar
);
private
void
setUpAvatar
(
MessageItem
messageItem
,
IncomingMessage
message
)
{
if
(
SettingsManager
.
chatsShowAvatars
())
{
final
String
account
=
messageItem
.
getChat
().
getAccount
();
final
String
user
=
messageItem
.
getChat
().
getUser
();
final
String
resource
=
messageItem
.
getResource
();
avatarView
.
setVisibility
(
View
.
VISIBLE
);
message
.
avatar
.
setVisibility
(
View
.
VISIBLE
);
if
((
isMUC
&&
MUCManager
.
getInstance
().
getNickname
(
account
,
user
).
equalsIgnoreCase
(
resource
)))
{
avatarView
.
setImageDrawable
(
AvatarManager
.
getInstance
().
getAccountAvatar
(
account
));
message
.
avatar
.
setImageDrawable
(
AvatarManager
.
getInstance
().
getAccountAvatar
(
account
));
}
else
{
if
(
isMUC
)
{
if
(
""
.
equals
(
resource
))
{
avatarView
.
setImageDrawable
(
AvatarManager
.
getInstance
().
getRoomAvatar
(
user
));
message
.
avatar
.
setImageDrawable
(
AvatarManager
.
getInstance
().
getRoomAvatar
(
user
));
}
else
{
avatarView
.
setImageDrawable
(
AvatarManager
.
getInstance
().
getOccupantAvatar
(
user
+
"/"
+
resource
));
message
.
avatar
.
setImageDrawable
(
AvatarManager
.
getInstance
().
getOccupantAvatar
(
user
+
"/"
+
resource
));
}
}
else
{
avatarView
.
setImageDrawable
(
AvatarManager
.
getInstance
().
getUserAvatar
(
user
));
message
.
avatar
.
setImageDrawable
(
AvatarManager
.
getInstance
().
getUserAvatar
(
user
));
}
}
}
else
{
avatarView
.
setVisibility
(
View
.
GONE
);
message
.
avatar
.
setVisibility
(
View
.
GONE
);
}
}
...
...
app/src/main/res/layout/chat_viewer_item.xml
View file @
aab530bf
...
...
@@ -38,12 +38,12 @@
</android.support.v7.widget.Toolbar>
<
List
View
android:id=
"@
android:id/list
"
<
android.support.v7.widget.Recycler
View
android:id=
"@
+id/chat_messages_recycler_view
"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:scrollbars=
"vertical"
android:stackFromBottom=
"true"
android:transcriptMode=
"normal"
android:smoothScrollbar=
"false"
android:divider=
"@null"
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment