version:2.3
fix: update:接口优化,更换图标,增加可折叠TextView
This commit is contained in:
@@ -110,7 +110,7 @@ public class MainActivity extends BaseActivity implements MainContact.MainView {
|
||||
mFragments.add(mCustomFragment);
|
||||
|
||||
mMainPresenter.getSystemSettings();
|
||||
|
||||
mMainPresenter.getAdminSnSetting();
|
||||
ArrayList<DesktopIcon> desktopIcons = ApkUtils.queryFilterAppInfo(this);
|
||||
int x = 0;
|
||||
for (int i = 0; i <= desktopIcons.size(); i++) {
|
||||
@@ -318,7 +318,6 @@ public class MainActivity extends BaseActivity implements MainContact.MainView {
|
||||
}
|
||||
addData();
|
||||
mMainPresenter.sendRunningInfo();
|
||||
mMainPresenter.getAdminSnSetting();
|
||||
}
|
||||
|
||||
private static final String ENABLED_NOTIFICATION_LISTENERS = "enabled_notification_listeners";
|
||||
|
||||
@@ -183,25 +183,19 @@ public class AppListFragment extends BaseFragment {
|
||||
ToastUtil.show("电话功能被禁用");
|
||||
return;
|
||||
} else {
|
||||
ApkUtils.openPackage(v.getContext(), desktopIcon.getPackageName());
|
||||
ApkUtils.openPackage(v.getContext(), desktopIcon.getPackageName(), desktopIcon.getClassName());
|
||||
AppUsedTimeUtils.getInstance().setAppPackageName(desktopIcon.getPackageName());
|
||||
AppUsedTimeUtils.getInstance().setStartTime(System.currentTimeMillis());
|
||||
SendRunningApp(getActivity());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ApkUtils.openPackage(v.getContext(), desktopIcon.getPackageName());
|
||||
ApkUtils.openPackage(v.getContext(), desktopIcon.getPackageName(), desktopIcon.getClassName());
|
||||
AppUsedTimeUtils.getInstance().setAppPackageName(desktopIcon.getPackageName());
|
||||
AppUsedTimeUtils.getInstance().setStartTime(System.currentTimeMillis());
|
||||
SendRunningApp(getActivity());
|
||||
}
|
||||
}
|
||||
if (desktopIcon != null) {
|
||||
ApkUtils.openPackage(v.getContext(), desktopIcon.getPackageName());
|
||||
AppUsedTimeUtils.getInstance().setAppPackageName(desktopIcon.getPackageName());
|
||||
AppUsedTimeUtils.getInstance().setStartTime(System.currentTimeMillis());
|
||||
SendRunningApp(getActivity());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -521,7 +521,7 @@ public class CustomFragment extends BaseFragment implements CustomContact.Custom
|
||||
cl_appstore.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
ApkUtils.openApp(mContext, "com.uiuios.appstore");
|
||||
ApkUtils.openPackage(mContext, "com.uiuios.appstore");
|
||||
}
|
||||
});
|
||||
cl_wifi.setOnClickListener(new View.OnClickListener() {
|
||||
@@ -624,31 +624,7 @@ public class CustomFragment extends BaseFragment implements CustomContact.Custom
|
||||
}
|
||||
|
||||
private void checkContact() {
|
||||
NetInterfaceManager.getInstance().getContactList(new NetInterfaceManager.ContactCallback() {
|
||||
@Override
|
||||
public void setContact(List<Contact> contactList) {
|
||||
// if (contactList == null || contactList.size() == 0) {
|
||||
// showNoData("温馨提示", "请在小程序上设置通讯录");
|
||||
// } else {
|
||||
//
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmergencyContact(List<Contact> emergencyContact) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmpty() {
|
||||
// showNoData("温馨提示", "请在小程序上设置通讯录");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
startActivity(new Intent(mContext, ContactActivity.class));
|
||||
}
|
||||
});
|
||||
startActivity(new Intent(mContext, ContactActivity.class));
|
||||
}
|
||||
|
||||
private void initData() {
|
||||
@@ -681,7 +657,7 @@ public class CustomFragment extends BaseFragment implements CustomContact.Custom
|
||||
}
|
||||
});
|
||||
initAmap();
|
||||
// getAlarmClock();
|
||||
getAlarmClock();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -698,7 +674,6 @@ public class CustomFragment extends BaseFragment implements CustomContact.Custom
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
// setAlarm();
|
||||
getAlarmClock();
|
||||
setSosNumber();
|
||||
setQuickApp();
|
||||
checkActivation();
|
||||
@@ -707,8 +682,7 @@ public class CustomFragment extends BaseFragment implements CustomContact.Custom
|
||||
private void checkActivation() {
|
||||
int activation = Settings.Global.getInt(mContext.getContentResolver(), "uiui_activation", 0);
|
||||
if (activation == 0) {
|
||||
tv_name.setText("未" +
|
||||
"激活");
|
||||
tv_name.setText("未激活");
|
||||
} else {
|
||||
tv_name.setText("已激活");
|
||||
}
|
||||
@@ -763,7 +737,7 @@ public class CustomFragment extends BaseFragment implements CustomContact.Custom
|
||||
dialog.setMessage("绑定手机才能使用");
|
||||
dialog.show();
|
||||
} else {
|
||||
ApkUtils.openApp(mContext, "com.uiui.health");
|
||||
ApkUtils.openPackage(mContext, "com.uiui.health");
|
||||
SchemeUtils.openScheme(mContext, uri);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,7 +355,7 @@ public class NetInterfaceManager {
|
||||
public void getActivityList(boolean refresh, BehaviorSubject<FragmentEvent> lifecycle, ActivitiesListCallback callback) {
|
||||
ConnectMode connectMode = ConnectMode.ONE_MINUTE;
|
||||
if (refresh) {
|
||||
connectMode = ConnectMode.DEFAULT;
|
||||
connectMode = ConnectMode.ONE_MINUTE;
|
||||
}
|
||||
if (ConnectManager.getInstance().isNeedConnect(URLAddress.GET_ACTIVITY_LIST, connectMode)) {
|
||||
getActivityList(lifecycle, callback);
|
||||
@@ -463,9 +463,9 @@ public class NetInterfaceManager {
|
||||
}
|
||||
|
||||
public void getDemandList(boolean refresh, BehaviorSubject<FragmentEvent> lifecycle, DemandListCallback callback) {
|
||||
ConnectMode connectMode = ConnectMode.ONE_MINUTE;
|
||||
ConnectMode connectMode = ConnectMode.ONE_HOUR;
|
||||
if (refresh) {
|
||||
connectMode = ConnectMode.DEFAULT;
|
||||
connectMode = ConnectMode.ONE_MINUTE;
|
||||
}
|
||||
if (ConnectManager.getInstance().isNeedConnect(URLAddress.GET_DEMAND_LIST, connectMode)) {
|
||||
getDemandList(lifecycle, callback);
|
||||
@@ -581,9 +581,9 @@ public class NetInterfaceManager {
|
||||
}
|
||||
|
||||
public void getHealthCode(boolean refresh, BehaviorSubject<ActivityEvent> lifecycle, HealthCodeCallback callback) {
|
||||
ConnectMode connectMode = ConnectMode.ONE_MINUTE;
|
||||
ConnectMode connectMode = ConnectMode.ONE_HOUR;
|
||||
if (refresh) {
|
||||
connectMode = ConnectMode.DEFAULT;
|
||||
connectMode = ConnectMode.ONE_MINUTE;
|
||||
}
|
||||
if (ConnectManager.getInstance().isNeedConnect(URLAddress.GET_HEALTH_CODE, connectMode)) {
|
||||
getHealthCode(lifecycle, callback);
|
||||
|
||||
@@ -13,9 +13,14 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.Protocol;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
import okio.Buffer;
|
||||
|
||||
/**
|
||||
* v1.0 2022-07-15 16:16:52
|
||||
*/
|
||||
public class RepeatRequestInterceptor implements Interceptor {
|
||||
private static final String TAG = RepeatRequestInterceptor.class.getSimpleName();
|
||||
|
||||
@@ -26,13 +31,18 @@ public class RepeatRequestInterceptor implements Interceptor {
|
||||
@Override
|
||||
public Response intercept(@NotNull Chain chain) throws IOException {
|
||||
Request request = chain.request();
|
||||
Response response = chain.proceed(request);
|
||||
ResponseBody responseBody = response.body();
|
||||
|
||||
Response response = chain.proceed(chain.request());
|
||||
String content = response.body().string();
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.e(TAG, "请求体返回:| Response:" + content);
|
||||
//会消费请求,导致请求多次
|
||||
String content = responseBody.string();
|
||||
// Response copy = response.newBuilder().body(responseBody).build();
|
||||
ResponseBody copy = ResponseBody.create(responseBody.contentType(), content);
|
||||
if (BuildConfig.DEBUG) {
|
||||
// Log.e(TAG, "请求体返回:| Response: " + request.url().encodedPath() + "\t body: " + content);
|
||||
}
|
||||
//相同的请求
|
||||
String requestKey = MD5Util.getUpperMD5Str(request.method() + request.url().toString() + request.body());
|
||||
String requestKey = MD5Util.getUpperMD5Str(request.method() + request.url().toString() + requestBodyToString(request.body()));
|
||||
long time = System.currentTimeMillis();//请求时间
|
||||
try {
|
||||
if (requestIdsMap.size() > 0 && requestIdsMap.containsKey(requestKey)) {
|
||||
@@ -48,7 +58,7 @@ public class RepeatRequestInterceptor implements Interceptor {
|
||||
log("注册请求:", requestKey, request);
|
||||
// RepeatRequestInterceptor.Builder builder = request.newBuilder();
|
||||
// builder.addHeader("header", jsonObject.toString());
|
||||
return chain.proceed(request);
|
||||
return response.newBuilder().body(copy).build();
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "intercept: " + e.getMessage());
|
||||
throw e;
|
||||
@@ -78,8 +88,20 @@ public class RepeatRequestInterceptor implements Interceptor {
|
||||
}
|
||||
return buffer.readUtf8();
|
||||
} catch (Exception e) {
|
||||
return "-" + e.getMessage();
|
||||
return "-";
|
||||
}
|
||||
}
|
||||
|
||||
private static String requestBodyToString(RequestBody body) {
|
||||
try {
|
||||
final Buffer buffer = new Buffer();
|
||||
body.writeTo(buffer);
|
||||
if (buffer.size() > 4096) {
|
||||
return "-too long";
|
||||
}
|
||||
return buffer.readUtf8();
|
||||
} catch (Exception e) {
|
||||
return "-";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,9 +23,9 @@ import com.uiuios.aios.bean.AlarmClockData;
|
||||
import com.uiuios.aios.bean.BaseResponse;
|
||||
import com.uiuios.aios.network.NetInterfaceManager;
|
||||
import com.uiuios.aios.utils.ApkUtils;
|
||||
import com.uiuios.aios.utils.AppUsedTimeUtils;
|
||||
import com.uiuios.aios.utils.CmdUtil;
|
||||
import com.uiuios.aios.utils.ForegroundAppUtil;
|
||||
import com.uiuios.aios.utils.AppUsedTimeUtils;
|
||||
import com.uiuios.aios.utils.ToastUtil;
|
||||
import com.uiuios.aios.utils.Utils;
|
||||
|
||||
@@ -110,6 +110,9 @@ public class MainService extends BaseService implements MainSContact.MainSView,
|
||||
if (mTimeChangedReceiver != null) {
|
||||
unregisterReceiver(mTimeChangedReceiver);
|
||||
}
|
||||
if (lockScreenReceiver != null) {
|
||||
unregisterReceiver(lockScreenReceiver);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -418,7 +421,7 @@ public class MainService extends BaseService implements MainSContact.MainSView,
|
||||
@Download.onTaskComplete
|
||||
void taskComplete(DownloadTask task) {
|
||||
//在这里处理任务完成的状态
|
||||
Log.e(TAG, "taskComplete: "+task.getFilePath() );
|
||||
Log.e(TAG, "taskComplete: " + task.getFilePath());
|
||||
}
|
||||
|
||||
@Download.onTaskFail
|
||||
|
||||
@@ -327,6 +327,20 @@ public class ApkUtils {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean openPackage(Context context, String packageName, String className) {
|
||||
if (TextUtils.isEmpty(className)) {
|
||||
return openPackage(context, packageName);
|
||||
}
|
||||
ComponentName cn = new ComponentName(packageName, className);
|
||||
Intent intent = new Intent();
|
||||
intent.setComponent(cn);
|
||||
if (context != null) {
|
||||
context.startActivity(intent);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Context getPackageContext(Context context, String packageName) {
|
||||
Context pkgContext = null;
|
||||
if (context.getPackageName().equals(packageName)) {
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
package com.uiuios.aios.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.text.Layout;
|
||||
import android.text.StaticLayout;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.AppCompatTextView;
|
||||
|
||||
public class ExpandTextView extends AppCompatTextView {
|
||||
/**
|
||||
* true:展开,false:收起
|
||||
*/
|
||||
boolean mExpanded;
|
||||
/**
|
||||
* 状态回调
|
||||
*/
|
||||
Callback mCallback;
|
||||
/**
|
||||
* 源文字内容
|
||||
*/
|
||||
String mText = "";
|
||||
/**
|
||||
* 最多展示的行数
|
||||
*/
|
||||
final int maxLineCount = 3;
|
||||
/**
|
||||
* 省略文字
|
||||
*/
|
||||
final String ellipsizeText = "...";
|
||||
|
||||
public ExpandTextView(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
// 文字计算辅助工具
|
||||
StaticLayout sl = new StaticLayout(mText, getPaint(), getMeasuredWidth() - getPaddingLeft() - getPaddingRight()
|
||||
, Layout.Alignment.ALIGN_CENTER, 1, 0, true);
|
||||
// 总计行数
|
||||
int lineCount = sl.getLineCount();
|
||||
if (lineCount > maxLineCount) {
|
||||
if (mExpanded) {
|
||||
setText(mText);
|
||||
mCallback.onExpand();
|
||||
} else {
|
||||
lineCount = maxLineCount;
|
||||
|
||||
// 省略文字的宽度
|
||||
float dotWidth = getPaint().measureText(ellipsizeText);
|
||||
|
||||
// 找出第 showLineCount 行的文字
|
||||
int start = sl.getLineStart(lineCount - 1);
|
||||
int end = sl.getLineEnd(lineCount - 1);
|
||||
String lineText = mText.substring(start, end);
|
||||
|
||||
// 将第 showLineCount 行最后的文字替换为 ellipsizeText
|
||||
int endIndex = 0;
|
||||
for (int i = lineText.length() - 1; i >= 0; i--) {
|
||||
String str = lineText.substring(i, lineText.length());
|
||||
// 找出文字宽度大于 ellipsizeText 的字符
|
||||
if (getPaint().measureText(str) >= dotWidth) {
|
||||
endIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 新的第 showLineCount 的文字
|
||||
String newEndLineText = lineText.substring(0, endIndex) + ellipsizeText;
|
||||
// 最终显示的文字
|
||||
setText(mText.substring(0, start) + newEndLineText);
|
||||
|
||||
mCallback.onCollapse();
|
||||
}
|
||||
} else {
|
||||
setText(mText);
|
||||
mCallback.onLoss();
|
||||
}
|
||||
|
||||
// 重新计算高度
|
||||
int lineHeight = 0;
|
||||
for (int i = 0; i < lineCount; i++) {
|
||||
Rect lineBound = new Rect();
|
||||
sl.getLineBounds(i, lineBound);
|
||||
lineHeight += lineBound.height();
|
||||
}
|
||||
lineHeight += getPaddingTop() + getPaddingBottom();
|
||||
setMeasuredDimension(getMeasuredWidth(), lineHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置要显示的文字以及状态
|
||||
* @param text
|
||||
* @param expanded true:展开,false:收起
|
||||
* @param callback
|
||||
*/
|
||||
public void setText(String text, boolean expanded, Callback callback) {
|
||||
mText = text;
|
||||
mExpanded = expanded;
|
||||
mCallback = callback;
|
||||
|
||||
// 设置要显示的文字,这一行必须要,否则 onMeasure 宽度测量不正确
|
||||
setText(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* 展开收起状态变化
|
||||
* @param expanded
|
||||
*/
|
||||
public void setChanged(boolean expanded) {
|
||||
mExpanded = expanded;
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
public interface Callback {
|
||||
/**
|
||||
* 展开状态
|
||||
*/
|
||||
void onExpand();
|
||||
|
||||
/**
|
||||
* 收起状态
|
||||
*/
|
||||
void onCollapse();
|
||||
|
||||
/**
|
||||
* 行数小于最小行数,不满足展开或者收起条件
|
||||
*/
|
||||
void onLoss();
|
||||
}
|
||||
}
|
||||
358
app/src/main/java/com/uiuios/aios/view/FoldTextView.java
Normal file
358
app/src/main/java/com/uiuios/aios/view/FoldTextView.java
Normal file
@@ -0,0 +1,358 @@
|
||||
package com.uiuios.aios.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.text.Layout;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextPaint;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.widget.AppCompatTextView;
|
||||
|
||||
import com.uiuios.aios.R;
|
||||
|
||||
|
||||
/**
|
||||
* Created by zhangzhihao on 2018/6/28 10:26.
|
||||
* 折叠textView
|
||||
*/
|
||||
|
||||
public class FoldTextView extends AppCompatTextView {
|
||||
private static final String TAG = "FoldTextView";
|
||||
private static final String ELLIPSIZE_END = "...";
|
||||
private static final int MAX_LINE = 4;
|
||||
private static final String EXPAND_TIP_TEXT = " 收起全文";
|
||||
private static final String FOLD_TIP_TEXT = "全文";
|
||||
private static final int TIP_COLOR = 0xFFFFFFFF;
|
||||
/**
|
||||
* 全文显示的位置
|
||||
*/
|
||||
private static final int END = 0;
|
||||
private int mShowMaxLine;
|
||||
/**
|
||||
* 折叠文本
|
||||
*/
|
||||
private String mFoldText;
|
||||
/**
|
||||
* 展开文本
|
||||
*/
|
||||
private String mExpandText;
|
||||
/**
|
||||
* 原始文本
|
||||
*/
|
||||
private CharSequence mOriginalText;
|
||||
/**
|
||||
* 是否展开
|
||||
*/
|
||||
private boolean isExpand;
|
||||
/**
|
||||
* 全文显示的位置
|
||||
*/
|
||||
private int mTipGravity;
|
||||
/**
|
||||
* 全文文字的颜色
|
||||
*/
|
||||
private int mTipColor;
|
||||
/**
|
||||
* 全文是否可点击
|
||||
*/
|
||||
private boolean mTipClickable;
|
||||
private boolean flag;
|
||||
private Paint mPaint;
|
||||
|
||||
/**
|
||||
* 展开后是否显示文字提示
|
||||
*/
|
||||
private boolean isShowTipAfterExpand;
|
||||
|
||||
|
||||
/**
|
||||
* 提示文字坐标
|
||||
*/
|
||||
float minX;
|
||||
float maxX;
|
||||
float minY;
|
||||
float maxY;
|
||||
/**
|
||||
* 收起全文不在一行显示时
|
||||
*/
|
||||
float middleY;
|
||||
/**
|
||||
* 原始文本的行数
|
||||
*/
|
||||
int originalLineCount;
|
||||
|
||||
/**
|
||||
* 点击时间
|
||||
*/
|
||||
private long clickTime;
|
||||
/**
|
||||
* 是否超过最大行数
|
||||
*/
|
||||
private boolean isOverMaxLine;
|
||||
private onTipClickListener onTipClickListener;
|
||||
|
||||
|
||||
public FoldTextView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
|
||||
public FoldTextView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTextColor(int color) {
|
||||
super.setTextColor(color);
|
||||
}
|
||||
|
||||
public FoldTextView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mShowMaxLine = MAX_LINE;
|
||||
if (attrs != null) {
|
||||
TypedArray arr = context.obtainStyledAttributes(attrs, R.styleable.FoldTextView);
|
||||
mShowMaxLine = arr.getInt(R.styleable.FoldTextView_showMaxLine, MAX_LINE);
|
||||
mTipGravity = arr.getInt(R.styleable.FoldTextView_tipGravity, END);
|
||||
mTipColor = arr.getColor(R.styleable.FoldTextView_tipColor, TIP_COLOR);
|
||||
mTipClickable = arr.getBoolean(R.styleable.FoldTextView_tipClickable, false);
|
||||
mFoldText = arr.getString(R.styleable.FoldTextView_foldText);
|
||||
mExpandText = arr.getString(R.styleable.FoldTextView_expandText);
|
||||
isShowTipAfterExpand = arr.getBoolean(R.styleable.FoldTextView_showTipAfterExpand, false);
|
||||
arr.recycle();
|
||||
}
|
||||
if (TextUtils.isEmpty(mExpandText)) {
|
||||
mExpandText = EXPAND_TIP_TEXT;
|
||||
}
|
||||
if (TextUtils.isEmpty(mFoldText)) {
|
||||
mFoldText = FOLD_TIP_TEXT;
|
||||
}
|
||||
if (mTipGravity == END) {
|
||||
mFoldText = " ".concat(mFoldText);
|
||||
}
|
||||
mPaint = new Paint();
|
||||
mPaint.setTextSize(getTextSize());
|
||||
mPaint.setColor(mTipColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(final CharSequence text, final TextView.BufferType type) {
|
||||
mOriginalText = text;
|
||||
if (TextUtils.isEmpty(text) || mShowMaxLine == 0) {
|
||||
super.setText(text, type);
|
||||
} else if (isExpand) {
|
||||
//文字展开
|
||||
SpannableStringBuilder spannable = new SpannableStringBuilder(mOriginalText);
|
||||
if (isShowTipAfterExpand) {
|
||||
spannable.append(mExpandText);
|
||||
spannable.setSpan(new ForegroundColorSpan(mTipColor), spannable.length() - mExpandText.length(), spannable.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
super.setText(spannable, type);
|
||||
int mLineCount = getLineCount();
|
||||
Layout layout = getLayout();
|
||||
minX = getPaddingLeft() + layout.getPrimaryHorizontal(spannable.toString().lastIndexOf(mExpandText.charAt(0)) - 1);
|
||||
maxX = getPaddingLeft() + layout.getSecondaryHorizontal(spannable.toString().lastIndexOf(mExpandText.charAt(mExpandText.length() - 1)) + 1);
|
||||
Rect bound = new Rect();
|
||||
if (mLineCount > originalLineCount) {
|
||||
//不在同一行
|
||||
layout.getLineBounds(originalLineCount - 1, bound);
|
||||
minY = getPaddingTop() + bound.top;
|
||||
middleY = minY + getPaint().getFontMetrics().descent - getPaint().getFontMetrics().ascent;
|
||||
maxY = middleY + getPaint().getFontMetrics().descent - getPaint().getFontMetrics().ascent;
|
||||
} else {
|
||||
//同一行
|
||||
layout.getLineBounds(originalLineCount - 1, bound);
|
||||
minY = getPaddingTop() + bound.top;
|
||||
maxY = minY + getPaint().getFontMetrics().descent - getPaint().getFontMetrics().ascent;
|
||||
}
|
||||
} else {
|
||||
if (!flag) {
|
||||
getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
|
||||
@Override
|
||||
public boolean onPreDraw() {
|
||||
getViewTreeObserver().removeOnPreDrawListener(this);
|
||||
flag = true;
|
||||
formatText(text, type);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
formatText(text, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void formatText(CharSequence text, final TextView.BufferType type) {
|
||||
Layout layout = getLayout();
|
||||
if (layout == null || !layout.getText().equals(mOriginalText)) {
|
||||
super.setText(mOriginalText, type);
|
||||
layout = getLayout();
|
||||
}
|
||||
if (layout == null) {
|
||||
getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
getViewTreeObserver().removeOnGlobalLayoutListener(this);
|
||||
translateText(getLayout(), type);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
translateText(layout, type);
|
||||
}
|
||||
}
|
||||
|
||||
private void translateText(Layout layout, TextView.BufferType type) {
|
||||
originalLineCount = layout.getLineCount();
|
||||
if (layout.getLineCount() > mShowMaxLine) {
|
||||
isOverMaxLine = true;
|
||||
SpannableStringBuilder span = new SpannableStringBuilder();
|
||||
int start = layout.getLineStart(mShowMaxLine - 1);
|
||||
int end = layout.getLineEnd(mShowMaxLine - 1);
|
||||
if (mTipGravity == END) {
|
||||
TextPaint paint = getPaint();
|
||||
StringBuilder builder = new StringBuilder(ELLIPSIZE_END).append(mFoldText);
|
||||
end -= paint.breakText(mOriginalText, start, end, false, paint.measureText(builder.toString()), null);
|
||||
float x = getWidth() - getPaddingLeft() - getPaddingRight() - getTextWidth(mFoldText);
|
||||
while (layout.getPrimaryHorizontal(end - 1) + getTextWidth(mOriginalText.subSequence(end - 1, end).toString()) < x) {
|
||||
end++;
|
||||
}
|
||||
end--;
|
||||
} else {
|
||||
end--;
|
||||
}
|
||||
CharSequence ellipsize = mOriginalText.subSequence(0, end);
|
||||
span.append(ellipsize);
|
||||
span.append(ELLIPSIZE_END);
|
||||
if (mTipGravity != END) {
|
||||
span.append("\n");
|
||||
}
|
||||
super.setText(span, type);
|
||||
} else {
|
||||
isOverMaxLine = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void setShowMaxLine(int mShowMaxLine) {
|
||||
this.mShowMaxLine = mShowMaxLine;
|
||||
}
|
||||
|
||||
public void setFoldText(String mFoldText) {
|
||||
this.mFoldText = mFoldText;
|
||||
}
|
||||
|
||||
public void setExpandText(String mExpandText) {
|
||||
this.mExpandText = mExpandText;
|
||||
}
|
||||
|
||||
public void setTipGravity(int mTipGravity) {
|
||||
this.mTipGravity = mTipGravity;
|
||||
}
|
||||
|
||||
public void setTipColor(int mTipColor) {
|
||||
this.mTipColor = mTipColor;
|
||||
}
|
||||
|
||||
public void setTipClickable(boolean mTipClickable) {
|
||||
this.mTipClickable = mTipClickable;
|
||||
}
|
||||
|
||||
|
||||
public void setShowTipAfterExpand(boolean showTipAfterExpand) {
|
||||
isShowTipAfterExpand = showTipAfterExpand;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
if (isOverMaxLine && !isExpand) {
|
||||
//折叠
|
||||
if (mTipGravity == END) {
|
||||
minX = getWidth() - getPaddingLeft() - getPaddingRight() - getTextWidth(mFoldText);
|
||||
maxX = getWidth() - getPaddingLeft() - getPaddingRight();
|
||||
minY = getHeight() - (getPaint().getFontMetrics().descent - getPaint().getFontMetrics().ascent) - getPaddingBottom();
|
||||
maxY = getHeight() - getPaddingBottom();
|
||||
canvas.drawText(mFoldText, minX,
|
||||
getHeight() - getPaint().getFontMetrics().descent - getPaddingBottom(), mPaint);
|
||||
} else {
|
||||
minX = getPaddingLeft();
|
||||
maxX = minX + getTextWidth(mFoldText);
|
||||
minY = getHeight() - (getPaint().getFontMetrics().descent - getPaint().getFontMetrics().ascent) - getPaddingBottom();
|
||||
maxY = getHeight() - getPaddingBottom();
|
||||
canvas.drawText(mFoldText, minX, getHeight() - getPaint().getFontMetrics().descent - getPaddingBottom(), mPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private float getTextWidth(String text) {
|
||||
Paint paint = getPaint();
|
||||
return paint.measureText(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if (mTipClickable) {
|
||||
switch (event.getActionMasked()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
clickTime = System.currentTimeMillis();
|
||||
if (!isClickable()) {
|
||||
if (isInRange(event.getX(), event.getY())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
case MotionEvent.ACTION_UP:
|
||||
long delTime = System.currentTimeMillis() - clickTime;
|
||||
clickTime = 0L;
|
||||
if (delTime < ViewConfiguration.getTapTimeout() && isInRange(event.getX(), event.getY())) {
|
||||
isExpand = !isExpand;
|
||||
setText(mOriginalText);
|
||||
if (onTipClickListener != null) {
|
||||
onTipClickListener.onTipClick(isExpand);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
|
||||
private boolean isInRange(float x, float y) {
|
||||
if (minX < maxX) {
|
||||
return x >= minX && x <= maxX && y >= minY && y <= maxY;
|
||||
} else {
|
||||
return x <= maxX && y >= middleY && y <= maxY || x >= minX && y >= minY && y <= middleY;
|
||||
}
|
||||
}
|
||||
|
||||
public FoldTextView setExpand(boolean expand) {
|
||||
isExpand = expand;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public FoldTextView setOnTipClickListener(FoldTextView.onTipClickListener onTipClickListener) {
|
||||
this.onTipClickListener = onTipClickListener;
|
||||
return this;
|
||||
}
|
||||
|
||||
public interface onTipClickListener {
|
||||
void onTipClick(boolean flag);
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 11 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 6.9 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 11 KiB |
@@ -79,9 +79,7 @@
|
||||
android:id="@+id/tv_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/dp_16"
|
||||
android:layout_marginTop="@dimen/dp_16"
|
||||
android:layout_marginEnd="@dimen/dp_16"
|
||||
android:layout_margin="@dimen/dp_16"
|
||||
android:textSize="@dimen/sp_13"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
@@ -89,6 +87,4 @@
|
||||
app:layout_constraintTop_toBottomOf="@+id/iv_img" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</ScrollView>
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -22,23 +22,30 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/dp_4"
|
||||
android:layout_marginEnd="@dimen/dp_8"
|
||||
android:text="中医专家谈寒露养生 “晨饮盐水晚喝蜂蜜”更健康"
|
||||
android:text=""
|
||||
android:textColor="@color/black"
|
||||
android:textSize="@dimen/sp_12"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/iv_img"
|
||||
app:layout_constraintTop_toTopOf="@+id/iv_img" />
|
||||
|
||||
<TextView
|
||||
<com.uiuios.aios.view.FoldTextView
|
||||
android:id="@+id/tv_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:text="中医专家谈寒露养生 “晨饮盐水晚喝蜂蜜”更健康"
|
||||
android:layout_marginTop="@dimen/dp_4"
|
||||
android:maxLines="4"
|
||||
android:text=""
|
||||
android:textSize="@dimen/sp_9"
|
||||
app:layout_constraintBottom_toTopOf="@+id/tv_read"
|
||||
app:layout_constraintEnd_toEndOf="@+id/tv_title"
|
||||
app:layout_constraintStart_toStartOf="@+id/tv_title"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tv_title" />
|
||||
app:layout_constraintTop_toBottomOf="@+id/tv_title"
|
||||
app:showMaxLine="4"
|
||||
app:showTipAfterExpand="true"
|
||||
app:tipClickable="true"
|
||||
app:tipColor="@color/colorPrimary"
|
||||
app:tipGravity="0" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_read"
|
||||
@@ -46,9 +53,9 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/buying_bg"
|
||||
android:text="阅读全文"
|
||||
android:layout_marginBottom="@dimen/dp_8"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="@dimen/sp_10"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/iv_img"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="@+id/tv_content" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -16,6 +16,17 @@
|
||||
<attr name="left_bottom_radius" format="dimension" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="FoldTextView">
|
||||
<attr name="showMaxLine" format="integer" />
|
||||
<attr name="tipGravity" format="integer" />
|
||||
<attr name="tipColor" format="reference|color" />
|
||||
<attr name="tipClickable" format="boolean" />
|
||||
<attr name="foldText" format="string" />
|
||||
<attr name="expandText" format="string" />
|
||||
<attr name="showTipAfterExpand" format="boolean" />
|
||||
<attr name="isSetParentClick" format="boolean"/>
|
||||
</declare-styleable>
|
||||
|
||||
<string-array name="entryvalues_font_size" translatable="false">
|
||||
<!-- <item>0.85</item>-->
|
||||
<item>1.0</item>
|
||||
|
||||
Reference in New Issue
Block a user