diff --git a/common/build.gradle b/common/build.gradle index fd0dd39a6..9a7759865 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -66,6 +66,7 @@ repositories { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar']) + api files('libs/jcc-bate-0.7.3.jar') compileOnly fileTree(dir: '../libs', include: ['*.aar']) api rootProject.ext.dependencies["appcompat-androidx"] api rootProject.ext.dependencies["recyclerview-androidx"] diff --git a/main/libs/jcc-bate-0.7.3.jar b/common/libs/jcc-bate-0.7.3.jar similarity index 100% rename from main/libs/jcc-bate-0.7.3.jar rename to common/libs/jcc-bate-0.7.3.jar diff --git a/common/src/main/java/com/yunbao/common/event/LiveInputEvent.java b/common/src/main/java/com/yunbao/common/event/LiveInputEvent.java new file mode 100644 index 000000000..80a31ff32 --- /dev/null +++ b/common/src/main/java/com/yunbao/common/event/LiveInputEvent.java @@ -0,0 +1,17 @@ +package com.yunbao.common.event; + +import com.yunbao.common.bean.BaseModel; +import com.yunbao.common.bean.OlineUserlistModel; + +public class LiveInputEvent extends BaseModel { + private OlineUserlistModel model; + + public OlineUserlistModel getModel() { + return model; + } + + public LiveInputEvent setModel(OlineUserlistModel model) { + this.model = model; + return this; + } +} diff --git a/common/src/main/java/com/yunbao/common/event/OlineEvent.java b/common/src/main/java/com/yunbao/common/event/OlineEvent.java new file mode 100644 index 000000000..1eb3aa3c9 --- /dev/null +++ b/common/src/main/java/com/yunbao/common/event/OlineEvent.java @@ -0,0 +1,17 @@ +package com.yunbao.common.event; + +import com.yunbao.common.bean.BaseModel; +import com.yunbao.common.bean.OlineUserlistModel; + +public class OlineEvent extends BaseModel { + private OlineUserlistModel model; + + public OlineUserlistModel getModel() { + return model; + } + + public OlineEvent setModel(OlineUserlistModel model) { + this.model = model; + return this; + } +} diff --git a/main/src/main/java/com/yunbao/main/utils/WordsTypeUtil.java b/common/src/main/java/com/yunbao/common/utils/WordsTypeUtil.java similarity index 96% rename from main/src/main/java/com/yunbao/main/utils/WordsTypeUtil.java rename to common/src/main/java/com/yunbao/common/utils/WordsTypeUtil.java index 2ca7de34d..84d7e87e2 100644 --- a/main/src/main/java/com/yunbao/main/utils/WordsTypeUtil.java +++ b/common/src/main/java/com/yunbao/common/utils/WordsTypeUtil.java @@ -1,4 +1,4 @@ -package com.yunbao.main.utils; +package com.yunbao.common.utils; import java.io.IOException; diff --git a/common/src/main/java/com/yunbao/common/views/weight/AtTextWatcher.java b/common/src/main/java/com/yunbao/common/views/weight/AtTextWatcher.java new file mode 100644 index 000000000..b09afcd98 --- /dev/null +++ b/common/src/main/java/com/yunbao/common/views/weight/AtTextWatcher.java @@ -0,0 +1,115 @@ +package com.yunbao.common.views.weight; + +import android.graphics.Color; +import android.text.Editable; +import android.text.Spannable; +import android.text.SpannableStringBuilder; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.KeyEvent; +import android.widget.EditText; + +import com.yunbao.common.bean.OlineUserlistModel; + +import java.util.HashMap; +import java.util.Map; + +//输入监听 +public class AtTextWatcher implements TextWatcher { + private Map spanMap = new HashMap<>(); + private EditText input; + private SpannableStringBuilder spannableStringBuilder; + private SpannableStringBuilder beforeStr, afterText; + private boolean removeListener = true; + + public AtTextWatcher() { + spannableStringBuilder = new SpannableStringBuilder(); + } + + public void insertTextForAt(OlineUserlistModel model, EditText input) { + this.input = input; + if (!spanMap.containsKey(model.getId())) { + if (!TextUtils.isEmpty(input.getText())) { + spannableStringBuilder = new SpannableStringBuilder(input.getText()); + } + String nameStr = model.getUserNicename(); + int startIndex = input.getSelectionStart();//光标的位置 + int endIndex = startIndex + nameStr.length();//字符结束的位置 + spanMap.put(model.getId(), model); + //插入要添加的字符,此处是为了给span占位 + input.getText().insert(startIndex, "@" + nameStr); + //1、使用mEditText构造一个SpannableString + StringBuffer atName = new StringBuffer(); + atName.append("@").append(nameStr); + if (spannableStringBuilder.length() > 0) { + spannableStringBuilder.insert(startIndex, atName.toString()); + } else { + spannableStringBuilder.append(atName.toString()); + } + + AtUserForegroundColorSpan span = new AtUserForegroundColorSpan(Color.parseColor("#2a92f7")); + span.setAtContent(atName.toString()); + span.setUid(model.getId()); + span.setName(nameStr); + spannableStringBuilder.setSpan(span, + startIndex, endIndex + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + input.setTextKeepState(spannableStringBuilder); + input.setOnKeyListener((v, keyCode, event) -> { + if (keyCode == KeyEvent.KEYCODE_DEL && event.getAction() == KeyEvent.ACTION_DOWN) { + if (removeListener) { + input.addTextChangedListener(AtTextWatcher.this); + removeListener = false; + } + } + + return false; + }); + + + } + + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + beforeStr = new SpannableStringBuilder(s); + } + + + @Override + public void onTextChanged(CharSequence afterStr, int start, int before, int count) { + afterText = new SpannableStringBuilder(afterStr); + } + + @Override + public void afterTextChanged(Editable s) { + boolean change = false; + if (!TextUtils.isEmpty(beforeStr)) { + if (afterText.length() < beforeStr.length()) {//删除内容的操作 + SpannableStringBuilder beforeSp = beforeStr; + AtUserForegroundColorSpan[] beforeSpans = beforeSp.getSpans(0, beforeSp.length(), AtUserForegroundColorSpan.class); + for (AtUserForegroundColorSpan span : beforeSpans) { + if (!s.toString().contains(span.getAtContent())) { + beforeSp.replace(beforeSp.getSpanStart(span), beforeSp.getSpanEnd(span), ""); + beforeSp.removeSpan(span); + spanMap.remove(span.getUid()); + input.removeTextChangedListener(this); + removeListener = true; + change = true; + } + } + beforeStr = null; + if (change) { + input.setTextKeepState(beforeSp); + spannableStringBuilder = beforeSp; + } else { + input.setTextKeepState(afterText); + spannableStringBuilder = afterText; + } + + } + + } + } + +} diff --git a/common/src/main/java/com/yunbao/common/views/weight/AtUserForegroundColorSpan.java b/common/src/main/java/com/yunbao/common/views/weight/AtUserForegroundColorSpan.java new file mode 100644 index 000000000..137a6c014 --- /dev/null +++ b/common/src/main/java/com/yunbao/common/views/weight/AtUserForegroundColorSpan.java @@ -0,0 +1,40 @@ +package com.yunbao.common.views.weight; + +import android.text.style.ForegroundColorSpan; + +public class AtUserForegroundColorSpan extends ForegroundColorSpan { + public String name; + public String uid; + public String atContent; + + public AtUserForegroundColorSpan(int color) { + super(color); + } + + public String getUid() { + return uid; + } + + public AtUserForegroundColorSpan setUid(String uid) { + this.uid = uid; + return this; + } + + public String getName() { + return name; + } + + public AtUserForegroundColorSpan setName(String name) { + this.name = name; + return this; + } + + public String getAtContent() { + return atContent; + } + + public AtUserForegroundColorSpan setAtContent(String atContent) { + this.atContent = atContent; + return this; + } +} diff --git a/config.gradle b/config.gradle index 0fbdf38fb..8bea8ea66 100644 --- a/config.gradle +++ b/config.gradle @@ -10,9 +10,9 @@ ext { manifestPlaceholders = [ //正式 - serverHost : "https://napi.yaoulive.com", +// serverHost : "https://napi.yaoulive.com", //測試 -// serverHost : "https://ceshi.yaoulive.com", + serverHost : "https://ceshi.yaoulive.com", //腾讯地图 txMapAppKey : "EOZBZ-ASLCU-4XPV3-BDCHZ-4E3Q7-H4BWB", diff --git a/live/src/main/java/com/yunbao/live/adapter/OlineListAdapter.java b/live/src/main/java/com/yunbao/live/adapter/OlineListAdapter.java index d67df15b1..b3194415a 100644 --- a/live/src/main/java/com/yunbao/live/adapter/OlineListAdapter.java +++ b/live/src/main/java/com/yunbao/live/adapter/OlineListAdapter.java @@ -31,6 +31,7 @@ public class OlineListAdapter extends RecyclerView.Adapter { } public void addAll(List>> models) { + mapList.clear(); mapList.addAll(models); notifyDataSetChanged(); } diff --git a/live/src/main/java/com/yunbao/live/adapter/OlineListItemAdapter.java b/live/src/main/java/com/yunbao/live/adapter/OlineListItemAdapter.java index 46d58b235..a7d4aacc8 100644 --- a/live/src/main/java/com/yunbao/live/adapter/OlineListItemAdapter.java +++ b/live/src/main/java/com/yunbao/live/adapter/OlineListItemAdapter.java @@ -19,6 +19,7 @@ public class OlineListItemAdapter extends RecyclerView.Adapter { private List models = new ArrayList<>(); public void addAll(List userlistModels) { + models.clear(); models.addAll(userlistModels); notifyDataSetChanged(); } diff --git a/live/src/main/java/com/yunbao/live/dialog/LiveInputDialogFragment.java b/live/src/main/java/com/yunbao/live/dialog/LiveInputDialogFragment.java index bb1e17c22..6a9fca469 100644 --- a/live/src/main/java/com/yunbao/live/dialog/LiveInputDialogFragment.java +++ b/live/src/main/java/com/yunbao/live/dialog/LiveInputDialogFragment.java @@ -31,17 +31,23 @@ import com.yunbao.common.bean.BaseModel; import com.yunbao.common.bean.NobleTrumpetModel; import com.yunbao.common.custom.MyRadioButton; import com.yunbao.common.dialog.AbsDialogFragment; +import com.yunbao.common.event.LiveInputEvent; import com.yunbao.common.http.base.HttpCallback; import com.yunbao.common.http.live.LiveNetManager; +import com.yunbao.common.utils.Bus; import com.yunbao.common.utils.DpUtil; import com.yunbao.common.utils.ToastUtil; import com.yunbao.common.utils.WordUtil; +import com.yunbao.common.views.weight.AtTextWatcher; import com.yunbao.common.views.weight.ViewClicksAntiShake; import com.yunbao.live.R; import com.yunbao.live.activity.LiveActivity; import com.yunbao.live.activity.LiveRyAnchorActivity; import com.yunbao.live.views.OlineListActivity; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + import java.util.ArrayList; import java.util.List; @@ -69,7 +75,7 @@ public class LiveInputDialogFragment extends AbsDialogFragment implements View.O private long nobleId;//贵族等级 private long trumpetNum;//喇叭数量 private String mLiveUid;//主播ID - + private AtTextWatcher atTextWatcher; @Override protected int getLayoutId() { @@ -100,7 +106,7 @@ public class LiveInputDialogFragment extends AbsDialogFragment implements View.O @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - + Bus.getOn(this); imm = (InputMethodManager) mContext.getSystemService(INPUT_METHOD_SERVICE); mInput = (EditText) mRootView.findViewById(R.id.input); radioHornType = mRootView.findViewById(R.id.radio_horn_type); @@ -185,7 +191,8 @@ public class LiveInputDialogFragment extends AbsDialogFragment implements View.O getActivity().startActivity(intent); } }); - ; + atTextWatcher = new AtTextWatcher(); + } @Override @@ -247,6 +254,7 @@ public class LiveInputDialogFragment extends AbsDialogFragment implements View.O @Override public void onDestroy() { super.onDestroy(); + Bus.getOff(this); mContext = null; } @@ -356,4 +364,10 @@ public class LiveInputDialogFragment extends AbsDialogFragment implements View.O } }; + @Subscribe(threadMode = ThreadMode.MAIN) + public void onLiveInputEvent(LiveInputEvent event) { + atTextWatcher.insertTextForAt(event.getModel(), mInput); + } + + } diff --git a/live/src/main/java/com/yunbao/live/views/OlineListActivity.java b/live/src/main/java/com/yunbao/live/views/OlineListActivity.java index ce3db8da7..4c41d22d7 100644 --- a/live/src/main/java/com/yunbao/live/views/OlineListActivity.java +++ b/live/src/main/java/com/yunbao/live/views/OlineListActivity.java @@ -1,5 +1,9 @@ package com.yunbao.live.views; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.widget.EditText; import android.widget.TextView; import androidx.recyclerview.widget.LinearLayoutManager; @@ -9,11 +13,18 @@ import com.blankj.utilcode.util.GsonUtils; import com.yunbao.common.activity.AbsActivity; import com.yunbao.common.bean.OlineModel; import com.yunbao.common.bean.OlineUserlistModel; +import com.yunbao.common.event.LiveInputEvent; +import com.yunbao.common.event.OlineEvent; import com.yunbao.common.http.HttpCallback; +import com.yunbao.common.utils.Bus; +import com.yunbao.common.utils.WordsTypeUtil; import com.yunbao.live.R; import com.yunbao.live.adapter.OlineListAdapter; import com.yunbao.live.http.LiveHttpUtil; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -22,6 +33,8 @@ import java.util.Map; public class OlineListActivity extends AbsActivity { private RecyclerView audienceList; private OlineListAdapter itemAdapter; + private EditText edit; + private List userlistModels = null; @Override @@ -32,6 +45,7 @@ public class OlineListActivity extends AbsActivity { @Override protected void main() { super.main(); + Bus.getOn(this); initView(); initData(); } @@ -47,40 +61,140 @@ public class OlineListActivity extends AbsActivity { @Override public void onSuccess(int code, String msg, String[] info) { OlineModel responseData = GsonUtils.fromJson(info[0], OlineModel.class); - List userlistModels = responseData.getUserlist(); - List noblelistModels = new ArrayList<>(); - List audiencelistModels = new ArrayList<>(); - List>> mapList = new ArrayList<>(); - //讲贵族前置顺序 - for (OlineUserlistModel model : userlistModels) { - int nobleId = Integer.parseInt(model.getNobleId()); - if (nobleId > 0) { - noblelistModels.add(model); - } else { - audiencelistModels.add(model); - } - } - Map> noblerMap = new HashMap<>(); - noblerMap.put(0, noblelistModels); - Map> audienceMap = new HashMap<>(); - audienceMap.put(1,audiencelistModels); - mapList.add(0,noblerMap); - mapList.add(1, audienceMap); - itemAdapter.addAll(mapList); + userlistModels = responseData.getUserlist(); + + starData(); } }); } + /** + * 原始数据 + */ + private void starData() { + List noblelistModels = new ArrayList<>(); + List audiencelistModels = new ArrayList<>(); + List>> mapList = new ArrayList<>(); + //讲贵族前置顺序 + for (OlineUserlistModel model : userlistModels) { + int nobleId = Integer.parseInt(model.getNobleId()); + if (nobleId > 0) { + noblelistModels.add(model); + } else { + audiencelistModels.add(model); + } + } + Map> noblerMap = new HashMap<>(); + noblerMap.put(0, noblelistModels); + Map> audienceMap = new HashMap<>(); + audienceMap.put(1, audiencelistModels); + mapList.add(0, noblerMap); + mapList.add(1, audienceMap); + itemAdapter.addAll(mapList); + } + /** * 初始化控件 */ private void initView() { itemAdapter = new OlineListAdapter(mContext); audienceList = findViewById(R.id.audience_list); - TextView titleView = findViewById(R.id.titleView); + TextView titleView = findViewById(R.id.titleView); titleView.setText(R.string.online_audience); audienceList.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, false)); audienceList.setAdapter(itemAdapter); + edit = findViewById(R.id.edit); + + edit.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + if (!TextUtils.isEmpty(s.toString().trim())) { + //繁体转成简体 + String simplified = WordsTypeUtil.changeSimplified(s.toString()); + //简体转繁体 + String traditional = WordsTypeUtil.changeTraditional(s.toString()); + if (TextUtils.equals(simplified, traditional)) { + searchList(simplified, null); + } else { + searchList(simplified, traditional); + } + } else { + starData(); + } + + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); } + + private void searchList(String keyWorld, String keyWorld2) { + if (userlistModels == null) return; + if (TextUtils.isEmpty(keyWorld2)) { + List noblelistModels = new ArrayList<>(); + List audiencelistModels = new ArrayList<>(); + List>> mapList = new ArrayList<>(); + //讲贵族前置顺序 + for (OlineUserlistModel model : userlistModels) { + int nobleId = Integer.parseInt(model.getNobleId()); + if (nobleId > 0 && model.getUserNicename().contains(keyWorld)) { + noblelistModels.add(model); + } else if (nobleId == 0 && model.getUserNicename().contains(keyWorld)) { + audiencelistModels.add(model); + } + } + Map> noblerMap = new HashMap<>(); + noblerMap.put(0, noblelistModels); + Map> audienceMap = new HashMap<>(); + audienceMap.put(1, audiencelistModels); + mapList.add(0, noblerMap); + mapList.add(1, audienceMap); + itemAdapter.addAll(mapList); + } else { + List noblelistModels = new ArrayList<>(); + List audiencelistModels = new ArrayList<>(); + List>> mapList = new ArrayList<>(); + //讲贵族前置顺序 + for (OlineUserlistModel model : userlistModels) { + int nobleId = Integer.parseInt(model.getNobleId()); + if (nobleId > 0 && model.getUserNicename().contains(keyWorld)) { + noblelistModels.add(model); + } else if (nobleId == 0 && model.getUserNicename().contains(keyWorld)) { + audiencelistModels.add(model); + } else if (nobleId > 0 && model.getUserNicename().contains(keyWorld2)) { + noblelistModels.add(model); + } else if (nobleId == 0 && model.getUserNicename().contains(keyWorld2)) { + audiencelistModels.add(model); + } + } + Map> noblerMap = new HashMap<>(); + noblerMap.put(0, noblelistModels); + Map> audienceMap = new HashMap<>(); + audienceMap.put(1, audiencelistModels); + mapList.add(0, noblerMap); + mapList.add(1, audienceMap); + itemAdapter.addAll(mapList); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + Bus.getOff(this); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onOlineEvent(OlineEvent event) { + Bus.get().post(new LiveInputEvent().setModel(event.getModel())); + finish(); + } } diff --git a/live/src/main/java/com/yunbao/live/views/OlineListItemViewHolder.java b/live/src/main/java/com/yunbao/live/views/OlineListItemViewHolder.java index 66e2ddab7..fdbd6001a 100644 --- a/live/src/main/java/com/yunbao/live/views/OlineListItemViewHolder.java +++ b/live/src/main/java/com/yunbao/live/views/OlineListItemViewHolder.java @@ -7,8 +7,11 @@ import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import com.yunbao.common.bean.OlineUserlistModel; +import com.yunbao.common.event.OlineEvent; import com.yunbao.common.glide.ImgLoader; +import com.yunbao.common.utils.Bus; import com.yunbao.common.views.weight.ClipPathCircleImage; +import com.yunbao.common.views.weight.ViewClicksAntiShake; import com.yunbao.live.R; public class OlineListItemViewHolder extends RecyclerView.ViewHolder { @@ -29,5 +32,11 @@ public class OlineListItemViewHolder extends RecyclerView.ViewHolder { public void setData(OlineUserlistModel model) { ImgLoader.displayAvatar(itemView.getContext(), model.getAvatar(), avatar); userName.setText(model.getUserNicename()); + ViewClicksAntiShake.clicksAntiShake(itemView, new ViewClicksAntiShake.ViewClicksCallBack() { + @Override + public void onViewClicks() { + Bus.get().post(new OlineEvent().setModel(model)); + } + }); } } diff --git a/main/build.gradle b/main/build.gradle index 169c23fc6..d4f93446f 100644 --- a/main/build.gradle +++ b/main/build.gradle @@ -82,8 +82,6 @@ dependencies { implementation 'com.justkiddingbaby:slidemenu:1.3.0' implementation 'com.xj.marqueeView:marqueeView:0.1.20' implementation 'com.google.android.gms:play-services-auth:15.0.0' - //Google 繁體簡體轉換庫 - implementation files('libs/jcc-bate-0.7.3.jar') //引导层 implementation 'com.binioter:guideview:1.0.0' } diff --git a/main/src/main/java/com/yunbao/main/activity/SearchActivity.java b/main/src/main/java/com/yunbao/main/activity/SearchActivity.java index 7467ceb56..061575449 100644 --- a/main/src/main/java/com/yunbao/main/activity/SearchActivity.java +++ b/main/src/main/java/com/yunbao/main/activity/SearchActivity.java @@ -26,12 +26,11 @@ import com.yunbao.common.utils.RouteUtil; import com.yunbao.live.activity.LiveAudienceActivity; import com.yunbao.live.bean.LiveBean; import com.yunbao.live.http.LiveHttpUtil; -import com.yunbao.live.presenter.LiveRoomCheckLivePresenter; import com.yunbao.main.R; import com.yunbao.main.event.JumpUserHomeEvent; import com.yunbao.main.fragment.SearchRecommendFragment; import com.yunbao.main.fragment.SearchResultsFragment; -import com.yunbao.main.utils.WordsTypeUtil; +import com.yunbao.common.utils.WordsTypeUtil; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; diff --git a/main/src/main/java/com/yunbao/main/fragment/SearchResultsItemFragment.java b/main/src/main/java/com/yunbao/main/fragment/SearchResultsItemFragment.java index cec504137..01d50d108 100644 --- a/main/src/main/java/com/yunbao/main/fragment/SearchResultsItemFragment.java +++ b/main/src/main/java/com/yunbao/main/fragment/SearchResultsItemFragment.java @@ -20,7 +20,7 @@ import com.yunbao.common.views.weight.OnRecyclerViewScrollListener; import com.yunbao.main.R; import com.yunbao.main.adapter.SearchRecommendBodyAdapter; import com.yunbao.main.adapter.SearchResultsItemAdapter; -import com.yunbao.main.utils.WordsTypeUtil; +import com.yunbao.common.utils.WordsTypeUtil; import java.util.ArrayList; import java.util.List; diff --git a/main/src/main/java/com/yunbao/main/views/SearchResultsViewHolder.java b/main/src/main/java/com/yunbao/main/views/SearchResultsViewHolder.java index 326bc2adb..fe269ffa3 100644 --- a/main/src/main/java/com/yunbao/main/views/SearchResultsViewHolder.java +++ b/main/src/main/java/com/yunbao/main/views/SearchResultsViewHolder.java @@ -21,7 +21,7 @@ import com.yunbao.common.utils.Bus; import com.yunbao.common.views.weight.ViewClicksAntiShake; import com.yunbao.main.R; import com.yunbao.main.event.JumpUserHomeEvent; -import com.yunbao.main.utils.WordsTypeUtil; +import com.yunbao.common.utils.WordsTypeUtil; public class SearchResultsViewHolder extends RecyclerView.ViewHolder { private ImageView avatar, isLive, sex, focusOn, contribute;