6.6.9版本
This commit is contained in:
@@ -39,6 +39,7 @@ public class CommonAppConfig {
|
||||
public static final boolean IS_UPLOAD_ERROR_LOG = getMetaDataBoolean("IS_UPLOAD_ERROR_LOG");
|
||||
//是否为插件包模式
|
||||
public static final boolean IS_PLUGIN_MODEL = getMetaDataBoolean("IS_PLUGIN_MODEL");
|
||||
public static final String BUILD_TIME = getMetaDataString("BUILD_TIME");
|
||||
|
||||
//外部sd卡
|
||||
public static final String DCMI_PATH = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath();
|
||||
|
||||
@@ -3,6 +3,8 @@ package com.yunbao.common.bean;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import com.yunbao.common.CommonAppConfig;
|
||||
import com.yunbao.common.utils.StringUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -421,7 +423,13 @@ public class IMLoginModel extends BaseModel {
|
||||
}
|
||||
|
||||
public String getAvatar() {
|
||||
return avatar;
|
||||
if ("/default.jpg".equals(avatar)) {
|
||||
avatar = CommonAppConfig.HOST + avatar;
|
||||
}
|
||||
if (StringUtil.isEmpty(avatar)) {
|
||||
return "";
|
||||
}
|
||||
return avatar.trim();
|
||||
}
|
||||
|
||||
public IMLoginModel setAvatar(String avatar) {
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.yunbao.common.bean;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import com.yunbao.common.utils.StringUtil;
|
||||
|
||||
public class MainMessageChatListTimer extends BaseModel {
|
||||
@SerializedName("uid")
|
||||
private String uid;
|
||||
@SerializedName("time")
|
||||
private int time;
|
||||
|
||||
public MainMessageChatListTimer() {
|
||||
}
|
||||
|
||||
public String getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
public void setUid(String uid) {
|
||||
this.uid = uid;
|
||||
}
|
||||
|
||||
public int getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(int time) {
|
||||
this.time = time;
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import android.text.TextUtils;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import com.yunbao.common.CommonAppConfig;
|
||||
import com.yunbao.common.utils.StringUtil;
|
||||
|
||||
/**
|
||||
@@ -417,7 +418,13 @@ public class UserBean implements Parcelable {
|
||||
}
|
||||
|
||||
public String getAvatar() {
|
||||
return avatar;
|
||||
if ("/default.jpg".equals(avatar)) {
|
||||
avatar = CommonAppConfig.HOST + avatar;
|
||||
}
|
||||
if (StringUtil.isEmpty(avatar)) {
|
||||
return "";
|
||||
}
|
||||
return avatar.trim();
|
||||
}
|
||||
|
||||
public void setAvatar(String avatar) {
|
||||
|
||||
@@ -15,6 +15,7 @@ import com.lzf.easyfloat.EasyFloat;
|
||||
import com.lzf.easyfloat.enums.ShowPattern;
|
||||
import com.lzf.easyfloat.interfaces.OnPermissionResult;
|
||||
import com.lzf.easyfloat.permission.PermissionUtils;
|
||||
import com.yunbao.common.CommonAppConfig;
|
||||
import com.yunbao.common.adapter.DebugDialogAdapter;
|
||||
import com.yunbao.common.utils.AppManager;
|
||||
import com.yunbao.common.utils.ToastUtil;
|
||||
@@ -129,6 +130,7 @@ public class DebugDialog {
|
||||
recyclerView.setAdapter(adapter);
|
||||
recyclerView.setBackgroundColor(Color.WHITE);
|
||||
TextView textView = new TextView(mContext);
|
||||
TextView buildTime = new TextView(mContext);
|
||||
textView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
@@ -137,6 +139,7 @@ public class DebugDialog {
|
||||
}
|
||||
});
|
||||
params.put("debug弹窗", textView);
|
||||
params.put("发包时间:" + CommonAppConfig.BUILD_TIME, buildTime);
|
||||
adapter.setParamMap(params);
|
||||
|
||||
EasyFloat.with(mContext)
|
||||
@@ -144,7 +147,6 @@ public class DebugDialog {
|
||||
.setShowPattern(this.showPattern)
|
||||
.setLayout(recyclerView)
|
||||
.show();
|
||||
runnable.run(this);
|
||||
Log.i("debug弹窗", "createView: 创建");
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.RequestBuilder;
|
||||
import com.bumptech.glide.load.DataSource;
|
||||
import com.bumptech.glide.load.engine.GlideException;
|
||||
import com.bumptech.glide.load.resource.bitmap.CircleCrop;
|
||||
import com.bumptech.glide.request.RequestListener;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
import com.bumptech.glide.request.target.CustomTarget;
|
||||
@@ -48,10 +49,10 @@ public class ImgLoader {
|
||||
if (!contextIsExist(context)) {
|
||||
return;
|
||||
}
|
||||
if(StringUtil.isEmpty(url)){
|
||||
if (StringUtil.isEmpty(url)) {
|
||||
return;
|
||||
}
|
||||
if(!url.startsWith("http")){
|
||||
if (!url.startsWith("http")) {
|
||||
return;
|
||||
}
|
||||
RequestBuilder<Drawable> builder = Glide.with(context)
|
||||
@@ -159,11 +160,33 @@ public class ImgLoader {
|
||||
displayAvatar(context, url, imageView, -1, -1);
|
||||
}
|
||||
|
||||
public static void displayAvatarCircleCrop(Context context, String url, ImageView imageView) {
|
||||
if (!contextIsExist(context)) {
|
||||
return;
|
||||
}
|
||||
if (!contextIsExist(context) || imageView == null) {
|
||||
return;
|
||||
}
|
||||
if (StringUtil.isEmpty(url)) {
|
||||
return;
|
||||
}
|
||||
if (!url.startsWith("http")) {
|
||||
imageView.setImageResource(R.mipmap.chat_head_mo);
|
||||
return;
|
||||
}
|
||||
RequestBuilder<Drawable> builder = Glide.with(context)
|
||||
.load(url)
|
||||
.thumbnail(thumbnail)
|
||||
.apply(RequestOptions.bitmapTransform(new CircleCrop()))
|
||||
.error(R.mipmap.icon_avatar_placeholder);
|
||||
builder.into(imageView);
|
||||
}
|
||||
|
||||
public static void displayAvatar(Context context, String url, ImageView imageView, int width, int height) {
|
||||
if (!contextIsExist(context) || imageView == null) {
|
||||
return;
|
||||
}
|
||||
if(StringUtil.isEmpty(url)){
|
||||
if (StringUtil.isEmpty(url)) {
|
||||
return;
|
||||
}
|
||||
if (!url.startsWith("http")) {
|
||||
|
||||
@@ -51,6 +51,7 @@ import com.yunbao.common.bean.LiveRoomVoteModel;
|
||||
import com.yunbao.common.bean.LiveStetUpStatusModel;
|
||||
import com.yunbao.common.bean.LiveTaskModel;
|
||||
import com.yunbao.common.bean.LiveUserMailBoxModel;
|
||||
import com.yunbao.common.bean.MainMessageChatListTimer;
|
||||
import com.yunbao.common.bean.MedalAchievementModel;
|
||||
import com.yunbao.common.bean.MessageChatIsAnchor;
|
||||
import com.yunbao.common.bean.MessageChatUserBean;
|
||||
@@ -1346,6 +1347,14 @@ public interface PDLiveApi {
|
||||
@GET("/api/public/?service=User.userFeedbackRestrict")
|
||||
Observable<ResponseModel<List<BaseModel>>> checkFeedback();
|
||||
|
||||
@GET("/api/public/?service=Pdlinfos.getOtherList")
|
||||
Observable<ResponseModel<List<MessageChatUserBean>>> getOtherList(@Query("ids") String uids);
|
||||
|
||||
@GET("/api/public/?service=Pdlinfos.getRelation")
|
||||
Observable<ResponseModel<List<String>>> getRelation(@Query("type") String type);
|
||||
@GET("/api/public/?service=Pdlinfos.getIsLook")
|
||||
Observable<ResponseModel<List<MainMessageChatListTimer>>> getIsLook(@Query("ids") String uids);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param roomId 房间ID
|
||||
|
||||
@@ -55,6 +55,7 @@ import com.yunbao.common.bean.LiveRoomVoteModel;
|
||||
import com.yunbao.common.bean.LiveStetUpStatusModel;
|
||||
import com.yunbao.common.bean.LiveTaskModel;
|
||||
import com.yunbao.common.bean.LiveUserMailBoxModel;
|
||||
import com.yunbao.common.bean.MainMessageChatListTimer;
|
||||
import com.yunbao.common.bean.MedalAchievementModel;
|
||||
import com.yunbao.common.bean.MessageChatIsAnchor;
|
||||
import com.yunbao.common.bean.MessageChatUserBean;
|
||||
@@ -3887,8 +3888,61 @@ public class LiveNetManager {
|
||||
}).isDisposed();
|
||||
}
|
||||
|
||||
public void getOtherList(String uids, HttpCallback<List<MessageChatUserBean>> callback) {
|
||||
API.get().pdLiveApi(mContext)
|
||||
.getOtherList(uids)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Consumer<ResponseModel<List<MessageChatUserBean>>>() {
|
||||
@Override
|
||||
public void accept(ResponseModel<List<MessageChatUserBean>> messageUserInfoBeanResponseModel) throws Exception {
|
||||
if (callback != null) {
|
||||
callback.onSuccess(messageUserInfoBeanResponseModel.getData().getInfo());
|
||||
}
|
||||
}
|
||||
}, new Consumer<Throwable>() {
|
||||
@Override
|
||||
public void accept(Throwable throwable) throws Exception {
|
||||
throwable.printStackTrace();
|
||||
if (callback != null) {
|
||||
callback.onError(mContext.getString(R.string.net_error));
|
||||
}
|
||||
}
|
||||
}).isDisposed();
|
||||
}
|
||||
|
||||
|
||||
public void getRelation(String type, HttpCallback<List<String>> callback) {
|
||||
API.get().pdLiveApi(mContext)
|
||||
.getRelation(type)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(messageUserInfoBeanResponseModel -> {
|
||||
if (callback != null) {
|
||||
callback.onSuccess(messageUserInfoBeanResponseModel.getData().getInfo());
|
||||
}
|
||||
}, throwable -> {
|
||||
throwable.printStackTrace();
|
||||
if (callback != null) {
|
||||
callback.onError(mContext.getString(R.string.net_error));
|
||||
}
|
||||
}).isDisposed();
|
||||
}
|
||||
public void getIsLook(String uids, HttpCallback<List<MainMessageChatListTimer>> callback) {
|
||||
API.get().pdLiveApi(mContext)
|
||||
.getIsLook(uids)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(messageUserInfoBeanResponseModel -> {
|
||||
if (callback != null) {
|
||||
callback.onSuccess(messageUserInfoBeanResponseModel.getData().getInfo());
|
||||
}
|
||||
}, throwable -> {
|
||||
throwable.printStackTrace();
|
||||
if (callback != null) {
|
||||
callback.onError(mContext.getString(R.string.net_error));
|
||||
}
|
||||
}).isDisposed();
|
||||
}
|
||||
private MultipartBody.Part createUploadFile(File file) {
|
||||
RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
|
||||
return MultipartBody.Part.createFormData("file", file.getName(), requestBody);
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.yunbao.common.interfaces;
|
||||
|
||||
public interface OnRecyclerListRefreshListener<T> {
|
||||
void onFinish(T t);
|
||||
}
|
||||
@@ -427,7 +427,12 @@ public class IMLoginManager extends BaseCacheManager {
|
||||
public boolean isGiftEffect() {
|
||||
return getBoolean(GiftEffect, !(Build.VERSION.SDK_INT < Build.VERSION_CODES.O));
|
||||
}
|
||||
|
||||
public void setAnchorB(int isAnchor) {
|
||||
put("isAnchorB", isAnchor);
|
||||
}
|
||||
public int getAnchorB(){
|
||||
return getInt("isAnchorB", -1);
|
||||
}
|
||||
public void setLiveNotifySettings(boolean isTrue) {
|
||||
put(LIVE_NOTIFY_SETTINGS, isTrue);
|
||||
}
|
||||
@@ -584,4 +589,5 @@ public class IMLoginManager extends BaseCacheManager {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import android.util.Log;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.yunbao.common.bean.IMLoginModel;
|
||||
import com.yunbao.common.utils.ToastUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -28,11 +29,41 @@ public class PDMessageInterceptor implements MessageInterceptor {
|
||||
TextMessage textMessage = (TextMessage) message.getContent();
|
||||
String context = textMessage.getContent();
|
||||
//符合条件的接受消息不做展示
|
||||
if (context.contains("LivePK")||context.contains("LiveDRPK")||context.contains("LiveRandomPK")) {
|
||||
if (context.contains("LivePK") ||
|
||||
context.contains("LivePKDRLM") ||
|
||||
context.contains("LiveDRPK") ||
|
||||
context.contains("LiveRandomPK")) {
|
||||
Message[] messages = new Message[]{message};
|
||||
Log.e("PDMessageInterceptor", textMessage.getContent());
|
||||
Log.e("PDMessageInterceptor", message.getMessageId() + "|" + textMessage.getContent());
|
||||
//删除消息
|
||||
IMCenter.getInstance().deleteRemoteMessages(Conversation.ConversationType.PRIVATE, message.getTargetId(), messages, null);
|
||||
IMCenter.getInstance().deleteMessages(Conversation.ConversationType.PRIVATE, message.getTargetId(), new int[]{
|
||||
message.getMessageId()
|
||||
}, new RongIMClient.ResultCallback<Boolean>() {
|
||||
@Override
|
||||
public void onSuccess(Boolean aBoolean) {
|
||||
Log.i("PDMessageInterceptor", "onSuccess: 删除成功:" + aBoolean+" "+ message.getMessageId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(RongIMClient.ErrorCode errorCode) {
|
||||
Log.i("PDMessageInterceptor", "onSuccess: 删除失败:" + errorCode);
|
||||
ToastUtil.showDebug("删除消息失败:"+errorCode.code+"|"+errorCode.msg);
|
||||
}
|
||||
});
|
||||
|
||||
IMCenter.getInstance().deleteRemoteMessages(Conversation.ConversationType.PRIVATE, message.getTargetId(), messages, new RongIMClient.OperationCallback() {
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
Log.i("PDMessageInterceptor", "onSuccess: 删除成功:" + message.getMessageId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(RongIMClient.ErrorCode errorCode) {
|
||||
Log.i("PDMessageInterceptor", "onSuccess: 删除失败:" + errorCode);
|
||||
ToastUtil.showDebug("删除消息失败:"+errorCode.code+"|"+errorCode.msg);
|
||||
}
|
||||
});
|
||||
|
||||
IMCenter.getInstance().clearMessagesUnreadStatus(Conversation.ConversationType.PRIVATE, message.getTargetId(), null);
|
||||
|
||||
// return true;
|
||||
|
||||
@@ -214,7 +214,7 @@ public class RongcloudIMManager {
|
||||
break;
|
||||
//用户账号在其它设备登录,此设备被踢下线
|
||||
case KICKED_OFFLINE_BY_OTHER_CLIENT:
|
||||
EventBus.getDefault().post(new RongIMConnectionStatusEvent());
|
||||
EventBus.getDefault().post(new RongIMConnectionStatusEvent().setStatus(-1));
|
||||
break;
|
||||
//连接暂时挂起(多是由于网络问题导致),SDK 会在合适时机进行自动重连
|
||||
case SUSPEND:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.yunbao.common.utils;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.util.Log;
|
||||
|
||||
import com.yunbao.common.BuildConfig;
|
||||
|
||||
@@ -11,7 +12,7 @@ public class AppManager {
|
||||
private static Stack<Activity> activityStack;
|
||||
|
||||
public AppManager() {
|
||||
activityStack=new Stack<>();
|
||||
activityStack = new Stack<>();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,6 +49,10 @@ public class AppManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
activityStack.clear();
|
||||
}
|
||||
|
||||
public static class SingleApp {
|
||||
public static AppManager INSTANCE = new AppManager();
|
||||
}
|
||||
@@ -59,6 +64,10 @@ public class AppManager {
|
||||
if (activityStack == null) {
|
||||
activityStack = new Stack<Activity>();
|
||||
}
|
||||
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>class com.yunbao.main.activity.MsgAddressBookActivity
|
||||
if (getActivity(activity.getClass()) != null) {
|
||||
activityStack.remove(getActivity(activity.getClass()));
|
||||
}
|
||||
activityStack.add(activity);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.yunbao.common.utils;
|
||||
|
||||
import androidx.viewpager2.widget.ViewPager2;
|
||||
|
||||
import net.lucode.hackware.magicindicator.MagicIndicator;
|
||||
|
||||
public class ViewPageIndicatorUtils {
|
||||
public static void bind(final MagicIndicator magicIndicator, ViewPager2 viewPager,ViewPager2.OnPageChangeCallback callback) {
|
||||
viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
super.onPageScrolled(position, positionOffset, positionOffsetPixels);
|
||||
magicIndicator.onPageScrolled(position, positionOffset, positionOffsetPixels);
|
||||
if(callback!=null){
|
||||
callback.onPageScrolled(position, positionOffset, positionOffsetPixels);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
super.onPageSelected(position);
|
||||
magicIndicator.onPageSelected(position);
|
||||
if (callback != null) {
|
||||
callback.onPageSelected(position);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
super.onPageScrollStateChanged(state);
|
||||
magicIndicator.onPageScrollStateChanged(state);
|
||||
if (callback != null) {
|
||||
callback.onPageScrollStateChanged(state);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,10 @@ package com.yunbao.common.views;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Paint;
|
||||
import android.text.TextPaint;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.widget.TextView;
|
||||
|
||||
@@ -42,6 +44,49 @@ public class AutoSplitTextView extends androidx.appcompat.widget.AppCompatTextVi
|
||||
}
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
}*/
|
||||
StringBuffer sb = new StringBuffer();
|
||||
StringBuffer tmp = new StringBuffer();
|
||||
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
TextPaint paint = getPaint();
|
||||
String text = getText().toString();
|
||||
Log.i("用户备注卡片", "默认值:" + text);
|
||||
float textWidth = paint.measureText(text);
|
||||
if (textWidth > getWidth()) {
|
||||
sb.setLength(0);
|
||||
tmp.setLength(0);
|
||||
for (int i = 0; i < text.length(); i++) {
|
||||
String str;
|
||||
str = text.substring(i, i + 1);
|
||||
Log.i("用户备注卡片", "添加:" + str + "|" + i);
|
||||
if (str.contains("\n") || str.contains("\r") || str.contains("\t")) {
|
||||
if(tmp.length()>0) {
|
||||
sb.append(tmp);
|
||||
}
|
||||
sb.append(str);
|
||||
tmp.setLength(0);
|
||||
continue;
|
||||
}
|
||||
float measured = paint.measureText(tmp.toString() + str);
|
||||
if (measured > getWidth()) {
|
||||
sb.append(tmp).append("\n");
|
||||
tmp.setLength(0);
|
||||
tmp.append(str);
|
||||
} else {
|
||||
tmp.append(str);
|
||||
}
|
||||
}
|
||||
if (tmp.length() > 0) {
|
||||
sb.append(tmp);
|
||||
}
|
||||
Log.i("用户备注卡片", "最终值:" + sb.toString());
|
||||
setText(sb);
|
||||
}
|
||||
}
|
||||
|
||||
public void setAutoText(CharSequence text) {
|
||||
this.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
|
||||
|
||||
136
common/src/main/java/com/yunbao/common/views/CustomLayout.java
Normal file
136
common/src/main/java/com/yunbao/common/views/CustomLayout.java
Normal file
@@ -0,0 +1,136 @@
|
||||
package com.yunbao.common.views;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.text.Layout;
|
||||
import android.text.StaticLayout;
|
||||
import android.text.TextPaint;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.lzf.easyfloat.enums.ShowPattern;
|
||||
import com.yunbao.common.dialog.DebugDialog;
|
||||
import com.yunbao.common.utils.DpUtil;
|
||||
|
||||
/**
|
||||
* TextView + View 动态布局
|
||||
*/
|
||||
public class CustomLayout extends ViewGroup {
|
||||
//单行显示
|
||||
private static final int SINGLE_LINE = 0x01;
|
||||
//多行显示
|
||||
private static final int MULTI_LINE = 0x02;
|
||||
//显示到下一行
|
||||
private static final int NEXT_LINE = 0x03;
|
||||
//显示样式
|
||||
private int type;
|
||||
//绘制文字最后一行的顶部坐标
|
||||
private int lastLineTop;
|
||||
//绘制文字最后一行的右边坐标
|
||||
private float lastLineRight;
|
||||
|
||||
public CustomLayout(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public CustomLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public CustomLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
int childCount = getChildCount();
|
||||
final int w = MeasureSpec.getSize(widthMeasureSpec);
|
||||
if (childCount == 2) {
|
||||
TextView tv = null;
|
||||
if(getChildAt(0) instanceof TextView){
|
||||
tv = (TextView) getChildAt(0);
|
||||
initTextParams(tv.getText(), tv.getMeasuredWidth(), tv.getPaint());
|
||||
}else{
|
||||
throw new RuntimeException("CustomLayout first child view not a TextView");
|
||||
}
|
||||
|
||||
View sencodView = getChildAt(1);
|
||||
|
||||
//测量子view的宽高
|
||||
measureChildren(widthMeasureSpec, heightMeasureSpec);
|
||||
|
||||
final String textWidth=String.valueOf(tv.getMeasuredWidth());
|
||||
final String viewWidth=String.valueOf(sencodView.getMeasuredWidth());
|
||||
final String maxWidth=String.valueOf(tv.getMeasuredWidth()+sencodView.getMeasuredWidth());
|
||||
|
||||
//两个子view宽度相加小于该控件宽度的时候
|
||||
if (tv.getMeasuredWidth() + sencodView.getMeasuredWidth() <= w) {
|
||||
int width = tv.getMeasuredWidth()+sencodView.getMeasuredWidth();
|
||||
//计算高度
|
||||
int height = Math.max(tv.getMeasuredHeight(), sencodView.getMeasuredHeight());
|
||||
//设置该viewgroup的宽高
|
||||
setMeasuredDimension(width, height);
|
||||
type = SINGLE_LINE;
|
||||
return;
|
||||
}
|
||||
if (getChildAt(0) instanceof TextView) {
|
||||
//最后一行文字的宽度加上第二个view的宽度大于viewgroup宽度时第二个控件换行显示
|
||||
if (lastLineRight + sencodView.getMeasuredWidth() > w) {
|
||||
setMeasuredDimension(tv.getMeasuredWidth(), tv.getMeasuredHeight() + sencodView.getMeasuredHeight());
|
||||
type = NEXT_LINE;
|
||||
return;
|
||||
}
|
||||
|
||||
int height = Math.max(tv.getMeasuredHeight(), lastLineTop + sencodView.getMeasuredHeight());
|
||||
setMeasuredDimension(tv.getMeasuredWidth(), height);
|
||||
type = MULTI_LINE;
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("CustomLayout child count must is 2");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
if (type == SINGLE_LINE || type == MULTI_LINE) {
|
||||
TextView tv = (TextView) getChildAt(0);
|
||||
View v1 = getChildAt(1);
|
||||
//设置第二个view在Textview文字末尾位置
|
||||
tv.layout(0, 0, tv.getMeasuredWidth(), tv.getMeasuredHeight());
|
||||
int left = (int) lastLineRight;
|
||||
int top = lastLineTop;
|
||||
//最后一行的高度 注:通过staticLayout得到的行高不准确故采用这种方式
|
||||
int lastLineHeight = tv.getBottom()-tv.getPaddingBottom() -lastLineTop;
|
||||
//当第二view高度小于单行文字高度时竖直居中显示
|
||||
if(v1.getMeasuredHeight() < lastLineHeight){
|
||||
top = lastLineTop + (lastLineHeight - v1.getMeasuredHeight())/2;
|
||||
}
|
||||
v1.layout(left, top, left + v1.getMeasuredWidth(), top+v1.getMeasuredHeight());
|
||||
} else if (type == NEXT_LINE) {
|
||||
View v0 = getChildAt(0);
|
||||
View v1 = getChildAt(1);
|
||||
//设置第二个view换行显示
|
||||
v0.layout(0, 0, v0.getMeasuredWidth(), v0.getMeasuredHeight());
|
||||
v1.layout(0, v0.getMeasuredHeight(), v1.getMeasuredWidth(), v0.getMeasuredHeight() + v1.getMeasuredHeight());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到Textview绘制文字的基本信息
|
||||
* @param text Textview的文字内容
|
||||
* @param maxWidth Textview的宽度
|
||||
* @param paint 绘制文字的paint
|
||||
*/
|
||||
private void initTextParams(CharSequence text, int maxWidth, TextPaint paint) {
|
||||
System.out.println("text = " + text + ", maxWidth = " + maxWidth + ", paint = " + paint);
|
||||
StaticLayout staticLayout = new StaticLayout(text, paint, maxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
|
||||
int lineCount = staticLayout.getLineCount();
|
||||
lastLineTop = staticLayout.getLineTop(lineCount - 1);
|
||||
lastLineRight = staticLayout.getLineRight(lineCount - 1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package com.yunbao.common.views;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.text.TextPaint;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewParent;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.yunbao.common.R;
|
||||
|
||||
public class MainMessageChatListItemLayout extends LinearLayout {
|
||||
private static final String TAG = "消息列表佈局";
|
||||
|
||||
public int autoText = 0;
|
||||
|
||||
public MainMessageChatListItemLayout(Context context) {
|
||||
super(context);
|
||||
onLayoutChanged();
|
||||
}
|
||||
|
||||
public MainMessageChatListItemLayout(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MainMessageChatListItem_Layout);
|
||||
autoText = array.getResourceId(R.styleable.MainMessageChatListItem_Layout_autoTextEllipsize, 0);
|
||||
onLayoutChanged();
|
||||
}
|
||||
|
||||
public MainMessageChatListItemLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MainMessageChatListItem_Layout);
|
||||
autoText = array.getResourceId(R.styleable.MainMessageChatListItem_Layout_autoTextEllipsize, 0);
|
||||
onLayoutChanged();
|
||||
}
|
||||
|
||||
public MainMessageChatListItemLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
int itemIndex = 0;
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
super.onLayout(changed, l, t, r, b);
|
||||
/*int width = getWidth();
|
||||
int count = getChildCount();
|
||||
double max = 0;
|
||||
double autoTextViewMeasuredWidth = 0;
|
||||
double otherViewWidth = 0;
|
||||
int autoId = -1;
|
||||
for (int i = 0; i < count; i++) {
|
||||
View item = getChildAt(i);
|
||||
// item.layout(l, t, r, b);
|
||||
double itemWidth = item.getMeasuredWidth();
|
||||
int padding = item.getPaddingLeft() + item.getPaddingRight();
|
||||
if (item instanceof TextView) {
|
||||
TextPaint paint = ((TextView) item).getPaint();
|
||||
itemWidth = paint.measureText(((TextView) item).getText().toString());
|
||||
if (item.getId() == autoText) {
|
||||
autoId = i;
|
||||
autoTextViewMeasuredWidth = itemWidth;
|
||||
} else {
|
||||
otherViewWidth += itemWidth;
|
||||
}
|
||||
Log.i(TAG, "TextView: " + ((TextView) item).getText() + "|" + paint.measureText(((TextView) item).getText().toString()));
|
||||
} else {
|
||||
Log.i(TAG, "onLayout: 不是TextView");
|
||||
}
|
||||
max += itemWidth + padding;
|
||||
Log.i(TAG, "autoId = " + autoId + "vid = " + autoText + " item = " + item + " width = " + itemWidth + "changed = " + changed + ", l = " + l + ", t = " + t + ", r = " + r + ", b = " + b);
|
||||
}
|
||||
Log.i(TAG, "布局总宽度 = " + width + "|" + "item总宽度 = " + max);
|
||||
if (autoId != -1 && max > width) {
|
||||
int diffValue = (int) (width - otherViewWidth);
|
||||
diffValue=20;
|
||||
int layoutChildViewCurX = 0;
|
||||
for (int i = 0; i < count; i++) {
|
||||
View view = getChildAt(i);
|
||||
if (view.getId() == autoId) {
|
||||
view.layout(layoutChildViewCurX, t, layoutChildViewCurX+diffValue, b);
|
||||
layoutChildViewCurX += diffValue;
|
||||
} else {
|
||||
view.layout(layoutChildViewCurX, t, layoutChildViewCurX + view.getMeasuredWidth(), b);
|
||||
layoutChildViewCurX += view.getMeasuredWidth();
|
||||
}
|
||||
}
|
||||
*//*int layoutChildViewCurX = l, tr = r, tt = t, tb = b;
|
||||
for (int i = 0; i < count; i++) {
|
||||
View item = getChildAt(i);
|
||||
tr=item.getMeasuredWidth();
|
||||
if (item.getId() == autoId) {
|
||||
int diffValue = (int) (width - otherViewWidth);
|
||||
item.layout(layoutChildViewCurX, tt, layoutChildViewCurX+item.getMeasuredWidth(), tb);
|
||||
layoutChildViewCurX=item.getMeasuredWidth();
|
||||
continue;
|
||||
}
|
||||
item.layout(layoutChildViewCurX, tt, layoutChildViewCurX+item.getMeasuredWidth(), tb);
|
||||
layoutChildViewCurX=item.getMeasuredWidth();
|
||||
}*//*
|
||||
}*/
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
|
||||
}
|
||||
|
||||
void onLayoutChanged() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:width="68dp" android:height="37dp">
|
||||
<shape android:shape="rectangle">
|
||||
<stroke android:width="1dp" android:color="#EB6FFF" />
|
||||
<corners android:topLeftRadius="15dp" android:topRightRadius="15dp" android:bottomLeftRadius="15dp" android:bottomRightRadius="15dp" />
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
||||
@@ -3,6 +3,7 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:background="@color/white"
|
||||
android:orientation="vertical">
|
||||
|
||||
@@ -361,8 +362,10 @@
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/authenticationLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
tools:layout_width="match_parent"
|
||||
tools:layout_height="match_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:visibility="visible">
|
||||
|
||||
|
||||
@@ -659,7 +659,7 @@
|
||||
<string name="report">Report</string>
|
||||
<string name="reload">retry</string>
|
||||
<string name="refuse">refuse</string>
|
||||
<string name="save">Preservation</string>
|
||||
<string name="save">Save</string>
|
||||
<string name="reg">Register</string>
|
||||
<string name="no_more_mic">No one is currently in the voice link</string>
|
||||
<string name="welcome_pdlive">Welcome to PDLive</string>
|
||||
|
||||
@@ -659,7 +659,7 @@
|
||||
<string name="report">Report</string>
|
||||
<string name="reload">retry</string>
|
||||
<string name="refuse">refuse</string>
|
||||
<string name="save">Preservation</string>
|
||||
<string name="save">Save</string>
|
||||
<string name="reg">Register</string>
|
||||
<string name="no_more_mic">No one is currently in the voice link</string>
|
||||
<string name="welcome_pdlive">Welcome to PDLive</string>
|
||||
|
||||
@@ -138,4 +138,7 @@
|
||||
<item name="android:activityCloseEnterAnimation">@anim/out_to_right_abit</item>
|
||||
<item name="android:activityCloseExitAnimation">@anim/out_to_right</item>
|
||||
</style>
|
||||
<declare-styleable name="MainMessageChatListItem_Layout">
|
||||
<attr format="reference|enum" name="autoTextEllipsize"/>
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
Reference in New Issue
Block a user