package com.netease.nim.uikit.contact_selector.activity;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.widget.SearchView;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.GridView;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.netease.nim.uikit.R;
import com.netease.nim.uikit.common.activity.UI;
import com.netease.nim.uikit.common.ui.liv.LetterIndexView;
import com.netease.nim.uikit.common.ui.liv.LivIndex;
import com.netease.nim.uikit.contact.core.item.AbsContactItem;
import com.netease.nim.uikit.contact.core.item.ContactItem;
import com.netease.nim.uikit.contact.core.item.ContactItemFilter;
import com.netease.nim.uikit.contact.core.item.ItemTypes;
import com.netease.nim.uikit.contact.core.model.ContactGroupStrategy;
import com.netease.nim.uikit.contact.core.model.IContact;
import com.netease.nim.uikit.contact.core.provider.ContactDataProvider;
import com.netease.nim.uikit.contact.core.provider.TeamMemberDataProvider;
import com.netease.nim.uikit.contact.core.query.IContactDataProvider;
import com.netease.nim.uikit.contact.core.query.TextQuery;
import com.netease.nim.uikit.contact.core.viewholder.LabelHolder;
import com.netease.nim.uikit.contact_selector.adapter.ContactSelectAdapter;
import com.netease.nim.uikit.contact_selector.adapter.ContactSelectAvatarAdapter;
import com.netease.nim.uikit.contact_selector.viewholder.ContactsMultiSelectHolder;
import com.netease.nim.uikit.contact_selector.viewholder.ContactsSelectHolder;
import com.netease.nim.uikit.model.ToolBarOptions;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* 联系人选择器
* <p/>
* Created by huangjun on 2015/3/3.
*/
public class ContactSelectActivity extends UI implements View.OnClickListener, android.support.v7.widget.SearchView.OnQueryTextListener {
public static final String EXTRA_DATA = "EXTRA_DATA"; // 请求数据:Option
public static final String RESULT_DATA = "RESULT_DATA"; // 返回结果
// adapter
private ContactSelectAdapter contactAdapter;
private ContactSelectAvatarAdapter contactSelectedAdapter;
// view
private ListView listView;
private LivIndex livIndex;
private RelativeLayout bottomPanel;
private HorizontalScrollView scrollViewSelected;
private GridView imageSelectedGridView;
private Button btnSelect;
private SearchView searchView;
// other
private String queryText;
private Option option;
// class
private static class ContactsSelectGroupStrategy extends ContactGroupStrategy {
public ContactsSelectGroupStrategy() {
add(ContactGroupStrategy.GROUP_NULL, -1, "");
addABC(0);
}
}
/**
* 联系人选择器配置可选项
*/
public enum ContactSelectType {
BUDDY,
TEAM_MEMBER,
TEAM
}
public static class Option implements Serializable {
/**
* 联系人选择器中数据源类型:好友(默认)、群、群成员(需要设置teamId)
*/
public ContactSelectType type = ContactSelectType.BUDDY;
/**
* 联系人选择器数据源类型为群成员时,需要设置群号
*/
public String teamId = null;
/**
* 联系人选择器标题
*/
public String title = "联系人选择器";
/**
* 联系人单选/多选(默认)
*/
public boolean multi = true;
/**
* 至少选择人数
*/
public int minSelectNum = 1;
/**
* 低于最少选择人数的提示
*/
public String minSelectedTip = null;
/**
* 最大可选人数
*/
public int maxSelectNum = 2000;
/**
* 超过最大可选人数的提示
*/
public String maxSelectedTip = null;
/**
* 是否显示已选头像区域
*/
public boolean showContactSelectArea = true;
/**
* 默认勾选(且可操作)的联系人项
*/
public ArrayList<String> alreadySelectedAccounts = null;
/**
* 需要过滤(不显示)的联系人项
*/
public ContactItemFilter itemFilter = null;
/**
* 需要disable(可见但不可操作)的联系人项
*/
public ContactItemFilter itemDisableFilter = null;
/**
* 是否支持搜索
*/
public boolean searchVisible = true;
/**
* 允许不选任何人点击确定
*/
public boolean allowSelectEmpty = false;
}
public static void startActivityForResult(Context context, Option option, int requestCode) {
Intent intent = new Intent();
intent.putExtra(EXTRA_DATA, option);
intent.setClass(context, ContactSelectActivity.class);
((Activity) context).startActivityForResult(intent, requestCode);
}
@Override
public void onBackPressed() {
searchView.setQuery("", true);
searchView.setIconified(true);
showKeyboard(false);
finish();
}
@Override
public boolean onCreateOptionsMenu(android.view.Menu menu) {
// search view
getMenuInflater().inflate(R.menu.contacts_search_menu, menu);
MenuItem item = menu.findItem(R.id.action_search);
MenuItemCompat.setOnActionExpandListener(item, new MenuItemCompat.OnActionExpandListener() {
@Override
public boolean onMenuItemActionExpand(MenuItem menuItem) {
return true;
}
@Override
public boolean onMenuItemActionCollapse(MenuItem menuItem) {
finish();
return false;
}
});
SearchView searchView = (SearchView) MenuItemCompat.getActionView(item);
this.searchView = searchView;
this.searchView.setVisibility(option.searchVisible ? View.VISIBLE : View.GONE);
searchView.setOnQueryTextListener(this);
return true;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.nim_contacts_select);
ToolBarOptions options = new ToolBarOptions();
setToolBar(R.id.toolbar, options);
parseIntentData();
initAdapter();
initListView();
initContactSelectArea();
loadData();
}
private void parseIntentData() {
this.option = (Option) getIntent().getSerializableExtra(EXTRA_DATA);
if (TextUtils.isEmpty(option.maxSelectedTip)) {
option.maxSelectedTip = "最多选择" + option.maxSelectNum + "人";
}
if (TextUtils.isEmpty(option.minSelectedTip)) {
option.minSelectedTip = "至少选择" + option.minSelectNum + "人";
}
setTitle(option.title);
}
private class ContactDataProviderEx extends ContactDataProvider {
private String teamId;
public ContactDataProviderEx(String teamId, int... itemTypes) {
super(itemTypes);
this.teamId = teamId;
}
@Override
public List<AbsContactItem> provide(TextQuery query) {
return TeamMemberDataProvider.provide(query, teamId);
}
}
private void initAdapter() {
IContactDataProvider dataProvider;
if (option.type == ContactSelectType.TEAM_MEMBER && !TextUtils.isEmpty(this.option.teamId)) {
dataProvider = new ContactDataProviderEx(this.option.teamId, ItemTypes.TEAM_MEMBER);
} else if (option.type == ContactSelectType.TEAM) {
option.showContactSelectArea = false;
dataProvider = new ContactDataProvider(ItemTypes.TEAM);
} else {
dataProvider = new ContactDataProvider(ItemTypes.FRIEND);
}
// contact adapter
contactAdapter = new ContactSelectAdapter(ContactSelectActivity.this, new ContactsSelectGroupStrategy(),
dataProvider) {
boolean isEmptyContacts = false;
@Override
protected List<AbsContactItem> onNonDataItems() {
return null;
}
@Override
protected void onPostLoad(boolean empty, String queryText, boolean all) {
if (empty) {
if (TextUtils.isEmpty(queryText)) {
isEmptyContacts = true;
}
updateEmptyView(queryText);
} else {
setSearchViewVisible(true);
}
}
private void updateEmptyView(String queryText) {
if (!isEmptyContacts && !TextUtils.isEmpty(queryText)) {
setSearchViewVisible(true);
} else {
setSearchViewVisible(false);
}
}
private void setSearchViewVisible(boolean visible) {
option.searchVisible = visible;
if (searchView != null) {
searchView.setVisibility(option.searchVisible ? View.VISIBLE : View.GONE);
}
}
};
Class c = option.multi ? ContactsMultiSelectHolder.class : ContactsSelectHolder.class;
contactAdapter.addViewHolder(ItemTypes.LABEL, LabelHolder.class);
contactAdapter.addViewHolder(ItemTypes.FRIEND, c);
contactAdapter.addViewHolder(ItemTypes.TEAM_MEMBER, c);
contactAdapter.addViewHolder(ItemTypes.TEAM, c);
contactAdapter.setFilter(option.itemFilter);
contactAdapter.setDisableFilter(option.itemDisableFilter);
// contact select adapter
contactSelectedAdapter = new ContactSelectAvatarAdapter(this);
}
private void initListView() {
listView = findView(R.id.contact_list_view);
listView.setAdapter(contactAdapter);
listView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
showKeyboard(false);
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
});
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
position = position - listView.getHeaderViewsCount();
AbsContactItem item = (AbsContactItem) contactAdapter.getItem(position);
if (item == null) {
return;
}
if (option.multi) {
if (!contactAdapter.isEnabled(position)) {
return;
}
IContact contact = null;
if (item instanceof ContactItem) {
contact = ((ContactItem) item).getContact();
}
if (contactAdapter.isSelected(position)) {
contactAdapter.cancelItem(position);
if (contact != null) {
contactSelectedAdapter.removeContact(contact);
}
} else {
if (contactSelectedAdapter.getCount() <= option.maxSelectNum) {
contactAdapter.selectItem(position);
if (contact != null) {
contactSelectedAdapter.addContact(contact);
}
} else {
Toast.makeText(ContactSelectActivity.this, option.maxSelectedTip, Toast.LENGTH_SHORT).show();
}
if (!TextUtils.isEmpty(queryText) && searchView != null) {
searchView.setQuery("", true);
searchView.setIconified(true);
showKeyboard(false);
}
}
arrangeSelected();
} else {
if (item instanceof ContactItem) {
final IContact contact = ((ContactItem) item).getContact();
ArrayList<String> selectedIds = new ArrayList<>();
selectedIds.add(contact.getContactId());
onSelected(selectedIds);
}
arrangeSelected();
}
}
});
// 字母导航
TextView letterHit = (TextView) findViewById(R.id.tv_hit_letter);
LetterIndexView idxView = (LetterIndexView) findViewById(R.id.liv_index);
idxView.setLetters(getResources().getStringArray(R.array.letter_list2));
ImageView imgBackLetter = (ImageView) findViewById(R.id.img_hit_letter);
if (option.type != ContactSelectType.TEAM) {
livIndex = contactAdapter.createLivIndex(listView, idxView, letterHit, imgBackLetter);
livIndex.show();
} else {
idxView.setVisibility(View.GONE);
}
}
private void initContactSelectArea() {
btnSelect = (Button) findViewById(R.id.btnSelect);
if (!option.allowSelectEmpty) {
btnSelect.setEnabled(false);
} else {
btnSelect.setEnabled(true);
}
btnSelect.setOnClickListener(this);
bottomPanel = (RelativeLayout) findViewById(R.id.rlCtrl);
scrollViewSelected = (HorizontalScrollView) findViewById(R.id.contact_select_area);
if (option.multi) {
bottomPanel.setVisibility(View.VISIBLE);
if (option.showContactSelectArea) {
scrollViewSelected.setVisibility(View.VISIBLE);
btnSelect.setVisibility(View.VISIBLE);
} else {
scrollViewSelected.setVisibility(View.GONE);
btnSelect.setVisibility(View.GONE);
}
btnSelect.setText(getOKBtnText(0));
} else {
bottomPanel.setVisibility(View.GONE);
}
// selected contact image banner
imageSelectedGridView = (GridView) findViewById(R.id.contact_select_area_grid);
imageSelectedGridView.setAdapter(contactSelectedAdapter);
notifySelectAreaDataSetChanged();
imageSelectedGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
try {
if (contactSelectedAdapter.getItem(position) == null) {
return;
}
IContact iContact = contactSelectedAdapter.remove(position);
if (iContact != null) {
contactAdapter.cancelItem(iContact);
}
arrangeSelected();
} catch (Exception e) {
e.printStackTrace();
}
}
});
// init already selected items
List<String> selectedUids = option.alreadySelectedAccounts;
if (selectedUids != null && !selectedUids.isEmpty()) {
contactAdapter.setAlreadySelectedAccounts(selectedUids);
List<ContactItem> selectedItems = contactAdapter.getSelectedItem();
for (ContactItem item : selectedItems) {
contactSelectedAdapter.addContact(item.getContact());
}
arrangeSelected();
}
}
private void loadData() {
contactAdapter.load(true);
}
private void arrangeSelected() {
this.contactAdapter.notifyDataSetChanged();
if (option.multi) {
int count = contactSelectedAdapter.getCount();
if (!option.allowSelectEmpty) {
btnSelect.setEnabled(count > 1);
} else {
btnSelect.setEnabled(true);
}
btnSelect.setText(getOKBtnText(count));
notifySelectAreaDataSetChanged();
}
}
private void notifySelectAreaDataSetChanged() {
int converViewWidth = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 46, this.getResources()
.getDisplayMetrics()));
ViewGroup.LayoutParams layoutParams = imageSelectedGridView.getLayoutParams();
layoutParams.width = converViewWidth * contactSelectedAdapter.getCount();
layoutParams.height = converViewWidth;
imageSelectedGridView.setLayoutParams(layoutParams);
imageSelectedGridView.setNumColumns(contactSelectedAdapter.getCount());
try {
final int x = layoutParams.width;
final int y = layoutParams.height;
new Handler().post(new Runnable() {
@Override
public void run() {
scrollViewSelected.scrollTo(x, y);
}
});
} catch (Exception e) {
e.printStackTrace();
}
contactSelectedAdapter.notifyDataSetChanged();
}
private String getOKBtnText(int count) {
String caption = getString(R.string.ok);
return caption + " (" + (count < 1 ? 0 : (count - 1)) + ")";
}
/**
* ************************** select ************************
*/
@Override
public void onClick(View v) {
if (v.getId() == R.id.btnSelect) {
List<IContact> contacts = contactSelectedAdapter
.getSelectedContacts();
if (option.allowSelectEmpty || checkMinMaxSelection(contacts.size())) {
ArrayList<String> selectedAccounts = new ArrayList<>();
for (IContact c : contacts) {
selectedAccounts.add(c.getContactId());
}
onSelected(selectedAccounts);
}
}
}
private boolean checkMinMaxSelection(int selected) {
if (option.minSelectNum > selected) {
return showMaxMinSelectTip(true);
} else if (option.maxSelectNum < selected) {
return showMaxMinSelectTip(false);
}
return true;
}
private boolean showMaxMinSelectTip(boolean min) {
if (min) {
Toast.makeText(this, option.minSelectedTip, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, option.maxSelectedTip, Toast.LENGTH_SHORT).show();
}
return false;
}
public void onSelected(ArrayList<String> selects) {
Intent intent = new Intent();
intent.putStringArrayListExtra(RESULT_DATA, selects);
setResult(Activity.RESULT_OK, intent);
this.finish();
}
/**
* ************************* search ******************************
*/
@Override
public boolean onQueryTextChange(String query) {
queryText = query;
if (TextUtils.isEmpty(query)) {
this.contactAdapter.load(true);
} else {
this.contactAdapter.query(query);
}
return true;
}
@Override
public boolean onQueryTextSubmit(String arg0) {
return false;
}
@Override
public void finish() {
showKeyboard(false);
super.finish();
}
}