From 08f990de651b5b00b17c5df6112bfadf897b2291 Mon Sep 17 00:00:00 2001 From: ZhanGSKen Date: Thu, 27 Mar 2025 10:42:58 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=97=A5=E5=BF=97=E7=AA=97?= =?UTF-8?q?=E5=8F=A3=E6=A0=87=E7=AD=BE=E6=9F=A5=E6=89=BE=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- appbase/build.properties | 4 +- libappbase/build.properties | 4 +- .../cc/winboll/studio/libappbase/LogView.java | 122 +++++++++++++++++- .../libappbase/views/HorizontalListView.java | 84 ++++++++++-- libappbase/src/main/res/layout/view_log.xml | 10 +- 5 files changed, 208 insertions(+), 16 deletions(-) diff --git a/appbase/build.properties b/appbase/build.properties index 9acc40d..5f18ea0 100644 --- a/appbase/build.properties +++ b/appbase/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Wed Mar 26 16:59:16 GMT 2025 +#Thu Mar 27 02:41:16 GMT 2025 stageCount=1 libraryProject=libappbase baseVersion=15.1 publishVersion=15.1.0 -buildCount=42 +buildCount=91 baseBetaVersion=15.1.1 diff --git a/libappbase/build.properties b/libappbase/build.properties index 9acc40d..5f18ea0 100644 --- a/libappbase/build.properties +++ b/libappbase/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Wed Mar 26 16:59:16 GMT 2025 +#Thu Mar 27 02:41:16 GMT 2025 stageCount=1 libraryProject=libappbase baseVersion=15.1 publishVersion=15.1.0 -buildCount=42 +buildCount=91 baseBetaVersion=15.1.1 diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/LogView.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/LogView.java index 9b8721d..85a0194 100644 --- a/libappbase/src/main/java/cc/winboll/studio/libappbase/LogView.java +++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/LogView.java @@ -10,6 +10,7 @@ import android.content.ClipboardManager; import android.content.Context; import android.os.Handler; import android.os.Message; +import android.text.TextWatcher; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; @@ -18,6 +19,7 @@ import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.BaseAdapter; import android.widget.CheckBox; +import android.widget.EditText; import android.widget.RelativeLayout; import android.widget.ScrollView; import android.widget.Spinner; @@ -31,6 +33,9 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; +import java.util.Objects; +import android.text.Editable; +import android.widget.HorizontalScrollView; public class LogView extends RelativeLayout { @@ -42,6 +47,7 @@ public class LogView extends RelativeLayout { Context mContext; ScrollView mScrollView; TextView mTextView; + EditText metTagSearch; CheckBox mSelectableCheckBox; CheckBox mSelectAllTAGCheckBox; TAGListAdapter mTAGListAdapter; @@ -107,9 +113,41 @@ public class LogView extends RelativeLayout { // mScrollView = findViewById(cc.winboll.studio.libappbase.R.id.viewlogScrollViewLog); mTextView = findViewById(cc.winboll.studio.libappbase.R.id.viewlogTextViewLog); + metTagSearch = findViewById(cc.winboll.studio.libappbase.R.id.tagsearch_et); // 获取Log Level spinner实例 mLogLevelSpinner = findViewById(cc.winboll.studio.libappbase.R.id.viewlogSpinner1); + metTagSearch.addTextChangedListener(new TextWatcher() { + + @Override + public void afterTextChanged(Editable editable) { + } + + @Override + public void beforeTextChanged(CharSequence charSequence, int p, int p1, int p2) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + LogUtils.d(TAG, s.toString()); + if (s.length() > 0) { + scrollToTag(s.toString()); + } else { + HorizontalScrollView hsRoot = findViewById(R.id.viewlogHorizontalScrollView1); + hsRoot.smoothScrollTo(0, 0); + mListViewTags.resetScrollToStart(); + } +// mListViewTags.postDelayed(new Runnable() { +// @Override +// public void run() { +// mListViewTags.scrollToItem(5); +// } +// }, 100); + } + // 其他方法留空或按需实现 + }); + + (findViewById(cc.winboll.studio.libappbase.R.id.viewlogButtonClean)).setOnClickListener(new View.OnClickListener(){ @Override @@ -233,6 +271,60 @@ public class LogView extends RelativeLayout { scrollLogUp(); } + public void scrollToTag(final String prefix) { + if (mTAGListAdapter == null || prefix == null || prefix.length() == 0) { + LogUtils.d(TAG, "参数为空,无法滚动"); + return; + } + + final List itemList = mTAGListAdapter.getItemList(); + + mListViewTags.post(new Runnable() { + @Override + public void run() { + // 查找匹配的标签位置 + int targetPosition = -1; + + for (int i = 0; i < itemList.size(); i++) { + String tag = itemList.get(i).getTag(); + if (tag != null && tag.toLowerCase().startsWith(prefix.toLowerCase())) { + targetPosition = i; + + break; + } + } + + if (targetPosition != -1) { + // 优化滚动逻辑 + //mListViewTags.setSelection(targetPosition); + //mListViewTags.invalidateViews(); // 强制刷新所有可见项 + + // 单独刷新目标视图 +// View targetView = mListViewTags.getChildAt(targetPosition); +// if (targetView != null) { +// targetView.requestLayout(); +// targetView.requestFocus(); +// } + + final int scrollPosition = targetPosition; + + // 延迟滚动确保布局完成 + mListViewTags.postDelayed(new Runnable() { + @Override + public void run() { + LogUtils.d(TAG, String.format("scrollPosition %d", scrollPosition)); + mListViewTags.scrollToItem(scrollPosition); + } + }, 100); + } else { + LogUtils.d(TAG, "未找到匹配的标签前缀:" + prefix); + } + } + }); + } + + + class LogViewHandler extends Handler { final static int MSG_LOGVIEW_UPDATE = 0; @@ -300,6 +392,30 @@ public class LogView extends RelativeLayout { public void setChecked(boolean checked) { isChecked = checked; } + + // getter/setter... + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + TAGItemModel that = (TAGItemModel) o; + // 手动处理空值比较(Java 6 不支持 Objects.equals) + if (tag == null) { + return that.tag == null; + } else { + return tag.equals(that.tag); + } + } + + @Override + public int hashCode() { + return tag == null ? 0 : tag.hashCode(); // 手动处理空值 + } } @@ -315,6 +431,10 @@ public class LogView extends RelativeLayout { loadMap(mapOrigin); } + public List getItemList() { + return itemList; + } + @Override public int getCount() { return itemList.size(); @@ -344,7 +464,7 @@ public class LogView extends RelativeLayout { loadMap(mapOrigin); super.notifyDataSetChanged(); } - + @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/views/HorizontalListView.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/views/HorizontalListView.java index 782d8fa..083b3a4 100644 --- a/libappbase/src/main/java/cc/winboll/studio/libappbase/views/HorizontalListView.java +++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/views/HorizontalListView.java @@ -9,23 +9,34 @@ import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.widget.ListView; +import android.widget.Scroller; import cc.winboll.studio.libappbase.LogUtils; public class HorizontalListView extends ListView { - public static final String TAG = "HorizontalListView"; - int verticalOffset = 0; + private int verticalOffset = 0; + private Scroller scroller; + private int totalWidth; public HorizontalListView(Context context) { super(context); + init(); } public HorizontalListView(Context context, AttributeSet attrs) { super(context, attrs); + init(); } public HorizontalListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); + init(); + } + + private void init() { + scroller = new Scroller(getContext()); + setHorizontalScrollBarEnabled(true); + setVerticalScrollBarEnabled(false); } public void setVerticalOffset(int verticalOffset) { @@ -38,28 +49,81 @@ public class HorizontalListView extends ListView { int childCount = getChildCount(); int left = getPaddingLeft(); int viewHeight = getMeasuredHeight() - getPaddingTop() - getPaddingBottom(); - LogUtils.d(TAG, String.format("HorizontalListView的高度 %d", viewHeight)); - + totalWidth = left; + for (int i = 0; i < childCount; i++) { View child = getChildAt(i); - // 计算每个子视图的宽度和高度 int width = child.getMeasuredWidth(); int height = child.getMeasuredHeight(); - //LogUtils.d(TAG, String.format("child : width %d , height %d", width, height)); - // 设置子视图的位置,实现水平布局 - child.layout(left, verticalOffset, left + width, verticalOffset + height); left += width; } + totalWidth = left + getPaddingRight(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int newHeightMeasureSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); - //super.onMeasure(widthMeasureSpec, newHeightMeasureSpec); int newWidthMeasureSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); - //LogUtils.d(TAG, String.format("newWidthMeasureSpec %d, newHeightMeasureSpec %d", newWidthMeasureSpec, newHeightMeasureSpec)); super.onMeasure(newWidthMeasureSpec, newHeightMeasureSpec); } + + @Override + public void computeScroll() { + if (scroller.computeScrollOffset()) { + scrollTo(scroller.getCurrX(), scroller.getCurrY()); + postInvalidate(); + } + } + + public void smoothScrollTo(int x, int y) { + int dx = x - getScrollX(); + int dy = y - getScrollY(); + scroller.startScroll(getScrollX(), getScrollY(), dx, dy, 300); // 300ms平滑动画 + invalidate(); + } + + @Override + public int computeHorizontalScrollRange() { + return totalWidth; + } + + @Override + public int computeHorizontalScrollOffset() { + return getScrollX(); + } + + @Override + public int computeHorizontalScrollExtent() { + return getWidth(); + } + + public void scrollToItem(int position) { + if (position < 0 || position >= getChildCount()) { + LogUtils.d(TAG, "无效的position: " + position); + return; + } + + View targetView = getChildAt(position); + int targetLeft = targetView.getLeft(); + int scrollX = targetLeft - getPaddingLeft(); + + // 修正最大滚动范围计算 + int maxScrollX = totalWidth; + scrollX = Math.max(0, Math.min(scrollX, maxScrollX)); + + // 强制重新布局和绘制 + requestLayout(); + invalidateViews(); + smoothScrollTo(scrollX, 0); + LogUtils.d(TAG, String.format("滚动到position: %d, scrollX: %d computeHorizontalScrollRange() %d", position, scrollX, computeHorizontalScrollRange())); + } + + public void resetScrollToStart() { + // 强制重新布局和绘制 + requestLayout(); + invalidateViews(); + smoothScrollTo(0, 0); + } } diff --git a/libappbase/src/main/res/layout/view_log.xml b/libappbase/src/main/res/layout/view_log.xml index f0857d4..cb03dba 100644 --- a/libappbase/src/main/res/layout/view_log.xml +++ b/libappbase/src/main/res/layout/view_log.xml @@ -83,13 +83,21 @@ android:layout_marginLeft="5dp" android:layout_marginRight="5dp"/> + + + android:layout_weight="1.0" + android:id="@+id/viewlogHorizontalScrollView1">