# MessageList
[中文文档](./message_list_usage_zh.md)
MessageList is a message list in chatting interface, use to display all kinds of messages, and it can be fully customize.
If you don't define your style, MessageList will use default style.
## Install
We have support several ways to add dependency. You can choose one of them.
- Gradle:
```groovy
compile 'cn.jiguang.imui:messagelist:0.8.0'
```
- Maven:
```groovy
cn.jiguang.imui
messagelist
0.8.0
pom
```
- JitPack
```groovy
// Add in project's build.gradle
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
// Add in module's build.gradle
dependencies {
compile 'com.github.jpush:imui:0.7.7'
}
```
## Usage
To use MessageList only need three simple steps, or you can check out our [sample project](./../../sample) to
try it yourself.
### 1. Add MessageList in your xml layout:
```xml
```
#### Support Pull To Refresh Layout
If you prefer add pull to refresh feature to `MessageList`, then you should use `PullToRefreshLayout` to wrap `MessageList`, for example:
```
```
then you should add a header to `PullToRefreshLayout` and implements pull to refresh interface:
```
final PullToRefreshLayout ptrLayout = (PullToRefreshLayout) findViewById(R.id.pull_to_refresh_layout);
PtrDefaultHeader header = new PtrDefaultHeader(getContext());
int[] colors = getResources().getIntArray(R.array.google_colors);
header.setColorSchemeColors(colors);
header.setLayoutParams(new LayoutParams(-1, -2));
header.setPadding(0, DisplayUtil.dp2px(getContext(),15), 0,DisplayUtil.dp2px(getContext(),10));
header.setPtrFrameLayout(ptrLayout);
ptrLayout.setLoadingMinTime(1000);
ptrLayout.setDurationToCloseHeader(1500);
ptrLayout.setHeaderView(header);
ptrLayout.addPtrUIHandler(header);
// If set to true,when pull to refresh, the content will be
// fixed, only the header view changes
ptrLayout.setPinContent(true);
ptrLayout.setPtrHandler(new PtrHandler() {
@Override
public void onRefreshBegin(PullToRefreshLayout layout) {
Log.i("MessageListActivity", "Loading next page");
loadNextPage();
// After load history messages, call refreshComplete.
ptrLayout.refreshComplete();
}
});
```
The `PtrDefaultHeader` is Material style, you can use any other style you like, just take a look at [android-Ultra-Pull-To-Refresh](https://github.com/liaohuqiu/android-Ultra-Pull-To-Refresh) to implement your header.
We have define many kinds of attributes, to support user to adjust their layout, you can see
[attrs.xml](./../../Android/messagelist/src/main/res/values/attrs.xml) in detail, and we support totally customize style either, please look down.
#### MessageList Custom Config
Almost all attributes not only can be set in XML file but also can be set in code. Here is a example showing how to set show display name or not.
```Java
MessageList messageList = (MessageList) findViewById(R.id.msg_list);
```
- To show receiver or sender 's display name,you can set `showReceiverDisplayName` and `showSenderDisplayName` to true or false in XML file above, or you can also set in code like:
```Java
messageList.setShowSenderDisplayName(true);
messageList.setShowReceiverDisplayName(true);
```
- Forbid pull to refresh(Added since 0.4.8),call `messageList.forbidScrollToRefresh(true)`, then `onLoadMore` would not trigger.
```Java
messageList.forbidScrollToRefresh(true);
```
### 2. Construct adapter
Adapter's constructor has three parameters. The first one is `sender id`, the id of sender, the second one is `HoldersConfig object`,
you can use this object to [construct your custom ViewHolder and layout](./custom_layout.md), the third one is implement of `ImageLoader`,
use to display user's avatar, if this value is null, will not display avatar.([Click here to know more about ImageLoader](./image_loader.md))
```java
MsgListAdapter adapter = new MsgListAdapter("0", holdersConfig, imageLoader);
messageList.setAdapter(adapter);
```
### 3. Construct model
To be add messages, you need to implement IMessage, IUser interface into your existing model and override it's methods:
```java
public class MyMessage implements IMessage {
private long id;
private String text;
private String timeString;
private int type;
private IUser user;
private String contentFile;
private long duration;
public MyMessage(String text, int type) {
this.text = text;
this.type = type;
this.id = UUID.randomUUID().getLeastSignificantBits();
}
@Override
public String getMsgId() {
return String.valueOf(id);
}
@Override
public IUser getFromUser() {
if (user == null) {
return new DefaultUser("0", "user1", null);
}
return user;
}
public void setUserInfo(IUser user) {
this.user = user;
}
public void setMediaFilePath(String path) {
this.contentFile = path;
}
public void setDuration(long duration) {
this.duration = duration;
}
@Override
public long getDuration() {
return duration;
}
public void setTimeString(String timeString) {
this.timeString = timeString;
}
@Override
public String getTimeString() {
return timeString;
}
@Override
public int getType() {
return type;
}
@Override
public String getText() {
return text;
}
@Override
public String getMediaFilePath() {
return contentFile;
}
}
```
MessageType above is an enum class in IMessage class, you need implement IUser interface, too:
```java
public class DefaultUser implements IUser {
private String id;
private String displayName;
private String avatar;
public DefaultUser(String id, String displayName, String avatar) {
this.id = id;
this.displayName = displayName;
this.avatar = avatar;
}
@Override
public String getId() {
return id;
}
@Override
public String getDisplayName() {
return displayName;
}
@Override
public String getAvatarFilePath() {
return avatar;
}
}
```
That's all! Now you can use your own message model to fill into adapter without type converting of any kind!
## Data management
### Add new messages
To add new message in message list is pretty easy, we support two ways to add new messages:
- Add new message in the bottom of message list: `addToStart(IMESSAGE message, boolean scroll)`
```java
// add a new message in the bottom of message list, the second parameter implys whether to scroll to bottom.
adapter.addToStart(message, true);
```
- Add messages to the top of message list, the parameter list is sorted chronologically: `addToEndChronologically`(**Add since 0.7.2**)
```java
// Messages to be add are sorted chronologically(The last message is the latest)
adapter.addToEndChronologically(messages);
```
- Add messages to the top of message list(Usually use this method to load last page of history messages): `addToEnd(List messages)`
```java
// Add messages to the top of message list, messages are in descending order(The first message is the latest)
adapter.addToEnd(messages);
```
- Scroll to load history messages(**Attention: If you add `PullToRefreshLayout`, pass this part.**)
After adding this listener: `OnLoadMoreListener`,when scroll to top will fire `onLoadMore` event,for example:
```java
mAdapter.setOnLoadMoreListener(new MsgListAdapter.OnLoadMoreListener() {
@Override
public void onLoadMore(int page, int totalCount) {
if (totalCount < mData.size()) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mAdapter.addToEnd(mData);
}
}, 1000);
}
}
});
```
### Delete message
Here are methods to delete message:
- *adapter.deleteById(String id)*: according message id to delete
- *adapter.deleteByIds(String[] ids)*: according message ids' array to delete
- *adapter.delete(IMessage message)*: according message object to delete
- *adapter.delete(List messages)*: according message objects' list to delete
- *adapter.clear()*: delete all messages
### Update message
If message updated, you can invoke these methods to notify adapter to update message:
- *adapter.update(IMessage message)*: message to be updated
- *adapter.update(String oldId, IMessage newMessage)*
## Event handling
- `OnMsgClickListener` fires when click message.
```java
mAdapter.setOnMsgClickListener(new MsgListAdapter.OnMsgClickListener() {
@Override
public void onMessageClick(MyMessage message) {
// do something
}
});
```
- `OnAvatarClickListener` fires when click avatar.
```java
mAdapter.setOnAvatarClickListener(new MsgListAdapter.OnAvatarClickListener() {
@Override
public void onAvatarClick(MyMessage message) {
DefaultUser userInfo = (DefaultUser) message.getUserInfo();
// Do something
}
});
```
- `OnMsgLongClickListener` fires when long click message.(Add View parameter since 0.6.4)
```java
mAdapter.setMsgLongClickListener(new MsgListAdapter.OnMsgLongClickListener() {
/**
*@param view The view been long clicked.
*/
@Override
public void onMessageLongClick(View view, MyMessage message){
// do something
}
});
```
- `OnMsgStatusViewClickListener` fires when click message status view button.(previous name was OnMsgResendListener, modified after 0.4.7)
```java
mAdapter.setMsgStatusViewClickListener(new MsgListAdapter.OnMsgStatusViewClickListener() {
@Override
public void onMessageResend(MyMessage message) {
//message status view click, resend or download here
}
});
```
### Progurad
Add the proguard-rule below if you need to obfuscate your code:
```
-keep class cn.jiguang.imui.** { *; }
```