Android:ExpandableTextView 的扩展

android ExpandableTextView-自定义可以动态展开/收缩显示长文本的TextView 前言:为了保持界面UI的整洁以及将尽可能多的内容显示在有限的空间中,往往需要将长度过长的TextView进行内容截取。本控件满足了TextView可在”完整内容”与”截取内容”两种模式下进行切换的需求,且可应用在ListView/RecyclerView中并可以动态更新内容。 阅读详情

ExpandableTextView这个库相信大家都用过,没用过的可以先了解下:
https://github.com/Manabu-GT/ExpandableTextView
这里简单介绍下使用方式,主要说的是遇到的问题以及对应的修改,文末会给出重写的ExpandableTextView。

首先ExpandableTextView给我们提供了以下几个可以设置的属性:

maxCollapsedLines :当TextView折叠时允许显示的最大文本行数,默认8

animDuration :textView展开/收缩的动画时间,默认300ms

animAlphaStart :动画启动时TextView的Alpha值(注)如果要禁用alpha 动画,请将此值设置为1。(后面会详细说这个问题)

expandDrawable:textview展开时的图标,这里默认是箭头。

collapseDrawable:textview收缩时的图标,这里默认是箭头。

接着在xml中写入布局:

<!-- sample xml -->
  <com.ms.square.android.expandabletextview.ExpandableTextView
      xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:expandableTextView="http://schemas.android.com/apk/res-auto"
      android:id="@+id/expand_text_view"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      expandableTextView:maxCollapsedLines="4"
      expandableTextView:animDuration="200">
      <TextView
          android:id="@id/expandable_text"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:layout_marginLeft="10dp"
          android:layout_marginRight="10dp"
          android:textSize="16sp"
          android:textColor="#666666" />
      <ImageButton
          android:id="@id/expand_collapse"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:padding="16dp"
          android:layout_gravity="right|bottom"
          android:background="@android:color/transparent"/>
  </com.ms.square.android.expandabletextview.ExpandableTextView>

注意:这里Textview和ImageButton的id值被事先定义在了ids.xml里面所以必须这么写了。

最后在代码中使用:

ExpandableTextView expTv1 = 
(ExpandableTextView)rootView.findViewById(R.id.sample1)
.findViewById(R.id.expand_text_view);

expTv1.setText(getString(R.string.dummy_text1));

通过以上几步就基本能完成一般需求了。如果有的时候我们想要的是带文字说明的,例如:(展开/收起),这样我们也可以自己写布局,这个会在后面说到,这里先了解下基本实现。其实ExpandableTextView的实现是继承自 LinearLayout(默认竖直方向,横向会抛出异常),里面包含一个Textview用于实现文本的显示,一个ImageButton用于显示箭头图标;在设置文本后会测量布局通过比较mTv.getLineCount()和 mMaxCollapsedLines 的大小来进行图标的显隐,以及布局高度的初始化等操作。

下面来说说会遇到的问题:
问题一、
如果你是直接拿demo里面的布局直接用的话,就会发现当文本点击伸缩的时候会出现闪烁的效果;结果当我拿给我们美工看的时候直接被无情的拒回(不知道其他的美工怎么看?)。其实这是一种透明度的动画效果,废话不多说看我们先看源码实现:

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
    private static void applyAlphaAnimation(View view, float alpha) {
        if (isPostHoneycomb()) {
            view.setAlpha(alpha);
        } else {
            AlphaAnimation alphaAnimation = new AlphaAnimation(alpha, alpha);
            // make it instant
            alphaAnimation.setDuration(0);
            alphaAnimation.setFillAfter(true);
            view.startAnimation(alphaAnimation);
        }
    }

这里就是根据版本不同来执行不同的透明度变化代码,再来看看调用它的地方,调用的地方一共有两个,第一个在onClick(View view)方法里面的onAnimationStart里面;第二个在ExpandCollapseAnimation这个内部类里面,这是自定义动画,不了解的可以百度下自定义动画。其实这里个人觉得既然在自定义动画里面调用了,那第一个地方根本不用调用了,有点重复。。。
下面看看调用代码:

@Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            int newHeight = (int) ((mEndHeight - mStartHeight) * interpolatedTime + mStartHeight);
            mTv.setMaxHeight(newHeight - mMarginBetweenTxtAndBottom);
            if (Float.compare(mAnimAlphaStart, 1.0f) != 0) {
                applyAlphaAnimation(mTv, mAnimAlphaStart + interpolatedTime * (1.0f - mAnimAlphaStart));
            }
            mTargetView.getLayoutParams().height = newHeight;
            mTargetView.requestLayout();
        }

我们可以看到if (Float.compare(mAnimAlphaStart, 1.0f) != 0) 这里有个判断可以决定是否调用透明度变化动画。Float.compare(mAnimAlphaStart, 1.0f) 这个方法作用是比较两个参数的大小:前面<后面 返回 -1;前面 = 后面 返回 0; 前面 > 后面 返回 1; 所以这里如果不想调用动画的话就得等于0;所以只需要设置mAnimAlphaStart的值为1即可;也就是
expandableTextView:animAlphaStart="1"
这个属性。

问题二、
当我们自己添加布局后,会发现如果想文本行数不够预设的值时想隐藏布局,然而ExpandableTextView没有给我们提供判断的方法,这里以在箭头旁边加一个显示的文本为例:

这里写图片描述

 <com.ichsy.whds.common.view.ExpandableTextView
        android:id="@+id/tv_personal_instruction"
        xmlns:expandableTextView="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        expandableTextView:animDuration="100"
        expandableTextView:animAlphaStart="1"
        expandableTextView:maxCollapsedLines="6">

        <TextView
            android:id="@id/expandable_text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:paddingLeft="15dp"
            android:paddingRight="15dp"
            android:paddingTop="20dp"
            android:paddingBottom="20dp"
            android:lineSpacingExtra="6dp"
            android:textColor="@color/color_btn_gray"
            android:textSize="@dimen/textsize_13"/>

           <RelativeLayout
                android:id="@+id/expand_collapse_rl"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="10dp">

                <TextView
                    android:id="@+id/expand_collapse_tv"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerInParent="true"
                    android:text="展开全部"
                    android:textColor="@color/color_standard_3"/>

                <ImageButton
                    android:id="@id/expand_collapse"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerVertical="true"
                    android:layout_toRightOf="@id/expand_collapse_tv"
                    android:background="@android:color/transparent"
                    android:paddingLeft="4dp"/>
            </RelativeLayout>
    </com.ichsy.whds.common.view.ExpandableTextView>

这里maxCollapsedLines 设置的是6,当文本不够6的时候会发现箭头隐藏了,但是我们的“展开全部”文本还没有隐藏,这里需要我们自己来扩展提供判断方法了。

查看源码“onMeasure(int widthMeasureSpec, int heightMeasureSpec)” 方法能找到答案:

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // If no change, measure and return
        if (!mRelayout || getVisibility() == View.GONE) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            return;
        }
        mRelayout = false;

        // Setup with optimistic case
        // i.e. Everything fits. No button needed
        mButton.setVisibility(View.GONE);
        mTv.setMaxLines(Integer.MAX_VALUE);

        // Measure
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        // If the text fits in collapsed mode, we are done.
        if (mTv.getLineCount() <= mMaxCollapsedLines) {
            return;
        }
        // Saves the text height w/ max lines
        mTextHeightWithMaxLines = getRealTextViewHeight(mTv);

        // Doesn't fit in collapsed mode. Collapse text view as needed. Show
        // button.
        if (mCollapsed) {
            mTv.setMaxLines(mMaxCollapsedLines);
        }
        mButton.setVisibility(View.VISIBLE);

        // Re-measure with new setup
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        if (mCollapsed) {
            // Gets the margin between the TextView's bottom and the ViewGroup's bottom
            mTv.post(new Runnable() {
                @Override
                public void run() {
                    mMarginBetweenTxtAndBottom = getHeight() - mTv.getHeight();
                }
            });
            // Saves the collapsed height of this ViewGroup
            mCollapsedHeight = getMeasuredHeight();
        }
    }

可以看到这行代码

if (mTv.getLineCount() <= mMaxCollapsedLines) {
            return;
        }

这里通过获取textview的行数和预设的行数做比较,如果小于等于预设值则直接return,下面的代码都不执行了,所以下面button的显示代码也没执行,所以按钮就会隐藏。好了,既然知道了是在这里判断的,那我们提供一个方法就好了。

改写:


    private int mTvLineCount;

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // If no change, measure and return
        if (!mRelayout || getVisibility() == View.GONE) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            return;
        }
        mRelayout = false;

        // Setup with optimistic case
        // i.e. Everything fits. No button needed
        mButton.setVisibility(View.GONE);
        mTv.setMaxLines(Integer.MAX_VALUE);

        // Measure
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        // If the text fits in collapsed mode, we are done.
        mTvLineCount = mTv.getLineCount();

        if (mTvLineCount <= mMaxCollapsedLines) {
            return;
        }
        // Saves the text height w/ max lines
        mTextHeightWithMaxLines = getRealTextViewHeight(mTv);

        // Doesn't fit in collapsed mode. Collapse text view as needed. Show
        // button.
        if (mCollapsed) {
            mTv.setMaxLines(mMaxCollapsedLines);
        }
        mButton.setVisibility(View.VISIBLE);

        // Re-measure with new setup
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        if (mCollapsed) {
            // Gets the margin between the TextView's bottom and the ViewGroup's bottom
            mTv.post(new Runnable() {
                @Override
                public void run() {
                    mMarginBetweenTxtAndBottom = getHeight() - mTv.getHeight();
                }
            });
            // Saves the collapsed height of this ViewGroup
            mCollapsedHeight = getMeasuredHeight();
        }
    }

    public boolean isShowExpand() {
        return mTvLineCount > mMaxCollapsedLines;
    }

当我们happy的以为只要在代码里面调用isShowExpand() 来显隐布局的时候,又会发现这个方法会一直返回 false !!!等等,冷静下来细细一想也对,因为view的绘制需要经过onMeasure、onLayout、onDraw,这之间需要时间,所以这个时候mTv.getLineCount() 才会一直获取不到值,不光这样,宽高也会获取不到。所以我们需要一个方法来知道view是否绘制结束!
这里我是通过addOnGlobalLayoutListener 来实现,首先添加一个Java接口类:

ViewOnGlobalLayoutInterface:

public interface ViewOnGlobalLayoutInterface {
    void onViewFinished(boolean isExpand); //true:展开状态   false:收缩状态
}

接着在ExpandableTextView 类里面添加一个方法:

public void addViewGlobalListener(final ViewOnGlobalLayoutInterface onGlobalLayoutInterface) {
        ViewTreeObserver vto = mTv.getViewTreeObserver();
        vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                mTv.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                if (onGlobalLayoutInterface != null) {
                    onGlobalLayoutInterface.onViewFinished(isShowExpand());
                }
            }
        });
    }

    private boolean isShowExpand() {
        return mTvLineCount > mMaxCollapsedLines;
    }

好了最后在代码里面调用:

expandableTextView.addViewGlobalListener(new ViewOnGlobalLayoutInterface() {
            @Override
            public void onViewFinished(boolean isExpand) {
                if (isExpand) {
                    expand_collapse_rl.setVisibility(View.VISIBLE);
                } else {
                    expand_collapse_rl.setVisibility(View.GONE);
                }
            }
        });

这里顺便说一句,我们添加的“展开全部”文本如果需要点击事件的话也是需要自己写的,如下:

expand_collapse_tv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                expandableTextView.onClick(v);
            }
        });

设置完点击事件监听后,直接调用ExpandableTextView里面的onClick()方法就好了。

问题三
当你遇到需要刷新页面,也就是文本行数变化了需要重新调用ExpandableTextView的setText("") 方法的时候,你会发现我们之前的布局显隐方法判断会导致布局发生变化;这里楼主的场景是:当前界面点击ExpandableTextView为展开状态,进入下一个页面然后返回,这个时候改变ExpandableTextView的文本行数刷新,会发现底部会多出一行空白或者文本由短变长的时候布局不显示了。为什么出现这个原因还得看源码,主要是onMeasure 方法:

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // If no change, measure and return
        if (!mRelayout || getVisibility() == View.GONE) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            return;
        }
        mRelayout = false;

        // Setup with optimistic case
        // i.e. Everything fits. No button needed
        mButton.setVisibility(View.GONE);
        mTv.setMaxLines(Integer.MAX_VALUE);

        // Measure
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        // If the text fits in collapsed mode, we are done.
        mTvLineCount = mTv.getLineCount();

        if (mTvLineCount <= mMaxCollapsedLines) {
            return;
        }
        // Saves the text height w/ max lines
        mTextHeightWithMaxLines = getRealTextViewHeight(mTv);

        // Doesn't fit in collapsed mode. Collapse text view as needed. Show
        // button.
        if (mCollapsed) {
            mTv.setMaxLines(mMaxCollapsedLines);
        }
        mButton.setVisibility(View.VISIBLE);

        // Re-measure with new setup
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        if (mCollapsed) {
            // Gets the margin between the TextView's bottom and the ViewGroup's bottom
            mTv.post(new Runnable() {
                @Override
                public void run() {
                    mMarginBetweenTxtAndBottom = getHeight() - mTv.getHeight();
                }
            });
            // Saves the collapsed height of this ViewGroup
            mCollapsedHeight = getMeasuredHeight();
        }
    }

分析:当布局为展开状态的时候mCollapsed 的值为false,也就是说再次刷新页面的时候上诉代码的最后一处:

if (mCollapsed) {
            // Gets the margin between the TextView's bottom and the ViewGroup's bottom
            mTv.post(new Runnable() {
                @Override
                public void run() {
                    mMarginBetweenTxtAndBottom = getHeight() - mTv.getHeight();
                }
            });
            // Saves the collapsed height of this ViewGroup
            mCollapsedHeight = getMeasuredHeight();
        }

这段代码是没有执行的!!!也就是说这个时候的mCollapsedHeight 和 mMarginBetweenTxtAndBottom 的值还是之前展开状态的值,所以会导致多出一段空白,既然知道了,那只要每次刷新页面的时候将mCollapsed 重置下就好了,对应的箭头图标也得重置,后续给出代码。

解决了上诉问题,那当文本由短变长的时候隐藏布局代码失效的问题呢?这里还是得看上面的onMeasure 方法;之前我们通过添加addViewGlobalListener 方法解决了布局的显隐问题,但是那个方法是在界面绘制完毕后才会调用的,然而现在我们只是重新刷新了下页面,所以当然不会调用,这里只能通过添加一个接口来监听改变了,这里我直接在ExpandableTextView 的 OnExpandStateChangeListener 接口里添加了一个方法void onViewStateChanged(boolean isExpanded, boolean isShowExpanded):

 public interface OnExpandStateChangeListener {
        /**
         * Called when the expand/collapse animation has been finished
         *
         * @param textView   - TextView being expanded/collapsed
         * @param isExpanded - true if the TextView has been expanded
         */
        void onExpandStateChanged(TextView textView, boolean isExpanded);

        /**
         * Called when the layout has changed
         *
         * @param isExpanded     - true if the TextView has been expanded
         * @param isShowExpanded - true if the layout has been show
         */
        void onViewStateChanged(boolean isExpanded, boolean isShowExpanded);
    }

然后在onMeasure 里面调用:

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // If no change, measure and return
        if (!mRelayout || getVisibility() == View.GONE) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            return;
        }
        mRelayout = false;

        // Setup with optimistic case
        // i.e. Everything fits. No button needed
        mButton.setVisibility(View.GONE);
        mTv.setMaxLines(Integer.MAX_VALUE);

        // Measure
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        // If the text fits in collapsed mode, we are done.
        mTvLineCount = mTv.getLineCount();

        if (mListener != null) {
            mListener.onViewStateChanged(!mCollapsed, isShowExpand());
        }

        if (mTvLineCount <= mMaxCollapsedLines) {
            return;
        }
        // Saves the text height w/ max lines
        mTextHeightWithMaxLines = getRealTextViewHeight(mTv);

        // Doesn't fit in collapsed mode. Collapse text view as needed. Show
        // button.
        if (mCollapsed) {
            mTv.setMaxLines(mMaxCollapsedLines);
        }
        mButton.setVisibility(View.VISIBLE);

        // Re-measure with new setup
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        if (mCollapsed) {
            // Gets the margin between the TextView's bottom and the ViewGroup's bottom
            mTv.post(new Runnable() {
                @Override
                public void run() {
                    mMarginBetweenTxtAndBottom = getHeight() - mTv.getHeight();
                }
            });
            // Saves the collapsed height of this ViewGroup
            mCollapsedHeight = getMeasuredHeight();
        }
    }

这里isShowExpanded 和 isExpanded 两个参数,一个是判断布局的显隐,一个是判断文本“展开/收缩”的状态。

最后在代码里面调用:

    @Bind(R.id.expand_collapse_ll)
    RelativeLayout expandCollapseLL;
    @Bind(R.id.tv_personal_instruction)
    ExpandableTextView expandableTextView;
    @Bind(R.id.expand_collapse_tv)
    TextView expand_collapse_tv;

expand_collapse_tv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                expandableTextView.onClick(v);
            }
        });

expandableTextView.setOnExpandStateChangeListener(new ExpandableTextView.OnExpandStateChangeListener() {
            @Override
            public void onExpandStateChanged(TextView textView, boolean isExpanded) {
                if (isExpanded) {
                    expand_collapse_tv.setText("收起");
                } else {
                    expand_collapse_tv.setText("展开全部");
                }
            }
            //页面刷新需要,textview发生变化,对应布局的改变
            @Override
            public void onViewStateChanged(boolean isExpanded, boolean isShowExpanded) {
                if (isShowExpanded) {
                    if (expandCollapseLL.getVisibility() != View.VISIBLE) expandCollapseLL.setVisibility(View.VISIBLE);
                    if (isExpanded) {
                        expand_collapse_tv.setText("收起");
                    } else {
                        expand_collapse_tv.setText("展开全部");
                    }
                } else {
                    if (expandCollapseLL.getVisibility() != View.GONE) expandCollapseLL.setVisibility(View.GONE);
                }
            }
        });

其实有了onViewStateChanged这个回调,问题二也可以解决了,也就不用调用addViewGlobalListener 这个方法了。

好了以上就是楼主在使用 ExpandableTextView 的时候遇到的问题以及解决方法,下面给出完整代码:
http://download.youkuaiyun.com/detail/mackkill/9885405

开源项目ExpandableTextView使用和源码分析 ExpandableTextView,可展开和收起的TextView,就像GooglePlay里面显示应用的描述那样。 项目地址: https://github.com/Manabu-GT/ExpandableTextView 其中包含项目源码和示例代码。 运行效果图: 在国内很多应用中,也可以看到这种效果的使用场景。如豌豆荚的详情页: 一、项目使用 (1 阅读详情

相关推荐

ExpandableTextView:一个简单的可扩展和可折叠的Android TextView

可扩展的文本视图 一个简单的可扩展和可折叠的Android TextView 如何使用 安装 将 maven 存储库添加到您的应用程序模块的build.gradle : repositories { maven { url 'https://dl.bintray.com/jonathanfinerty/maven' } } 然后在同一个build.gradle添加库依赖: dependencies { compile 'com.jonathanfinerty.expandabletextview:expandabletextview:0.0.2' } 执照 The MIT License (MIT) Copyright (c) 2015 Jonathan David Finerty Permission is hereby granted, free of cha

Android实现ExpandableTextView可扩展TextView

介绍在应用开发中,总会遇到一些类似于公告,说明等长文本的TextView,但是为了排版美观等因素,我们通常是要隐藏后半部的文本,只显示部分文字,然后在尾部会提供用户一个扩展/收缩的按钮,使得文本框可以在需要的时候扩展开来查看全文,这就需要实现一个ExpendableTextView,类似于ExpendableList。原理1、开始时使用android:lines来设置TextView的行数,点击按钮

来啊 快活啊 2247

Android更多条目收缩展开控件ExpandView的示例代码

本篇文章主要介绍了Android更多条目收缩展开控件ExpandView的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

探索 ExpandableTextView:一款强大的 Android 可扩展文本视图组件

探索 ExpandableTextView:一款强大的 Android 可扩展文本视图组件 在 Android 应用开发中,展示详尽信息和保持界面简洁性常常是一对矛盾体。为了解决这个问题,开发者社区提供了许多创新解决方案,其中一个值得注意的是 。这是一个轻量级、高度可定制的库,允许文本视图在单行摘要与多行详细内容之间切换,从而在有限的屏幕空间上实现更丰富的用户体验。 项目简介 Expandable...

gitblog_00088的博客 1009

5G 网络的移动性管理上下文对比介绍

5G 网络的移动性管理上下文对比介绍 4G/5G MM移动性管理机制对比 5G引入了新移动性管理状态,通过mobility pattern(移动方式)实现按需的移动性管理等。 MM的相关状态分为一下几种: RM状态(用户注册管理 注册态/非注册态)和CM状态(用户连接态/空闲态)独立;RM状态标识UE是否注册到网络,CM状态标识UE和核心网的信令连接是否存在。 RAN侧引入RRC-inactive state:UE(用户端)对于CN(核心网)而言处于连接态,对RAN(接入网)而言处于Ld..

m0_59032675的博客 4817

告别WSL!实测AMD ROCm7预览版在Windows下跑ComfyUI,速度提升与避坑全记录

本文详细记录了在Windows原生环境下部署AMD ROCm7+PyTorch+ComfyUI的全流程,相比WSL环境性能显著提升。涵盖硬件兼容性确认、开发环境配置、Python环境搭建、ComfyUI部署优化及性能对比测试,为AI绘图爱好者提供实用指南。

weixin_42528090的博客 668

Android 自定义 View 进阶实战全解析:从扩展控件与组合控件入门,到 onMeasure 测量、onDraw 绘制、手势交互处理及自定义布局容器实现的完整开发指南

本文系统讲解了Android自定义View的开发方法与实践技巧。主要内容包括: 自定义View的三种实现方式:扩展控件(继承现有控件)、组合控件(整合多个控件)和完全自定义View(从零实现测量、绘制和交互)。 详细演示了扩展控件开发流程,以验证码倒计时按钮为例,展示如何基于TextView扩展功能,包括计时逻辑实现和状态管理。 介绍了组合控件的实现方法,通过可折叠文本控件案例说明如何组合现有控件并支持XML属性配置。 深入讲解了完全自定义View的核心技术: onMeasure测量流程 onDraw图形绘

OuO-1 的博客 1500

保姆级教程:手把手带你复现APFNet论文的RGBT目标跟踪模型(附完整代码与数据集配置)

本文提供了一份详细的APFNet论文复现指南,涵盖从环境搭建到模型测试的全流程。通过解析多模态融合模块和渐进式训练流程,帮助读者高效完成RGBT目标跟踪模型的复现工作,特别针对训练和测试中的常见问题提供实用解决方案。

weixin_29056781的博客 341

Android文本交互的革命性突破:智能ExpandableTextView解决方案

在Android应用开发中,长文本展示一直是用户体验的痛点——要么内容被截断,要么界面臃肿。传统TextView无法智能处理文本折叠、链接识别和用户提及,导致开发者需要编写大量重复代码。ExpandableTextView应运而生,这款开源库通过创新的技术架构,彻底改变了Android文本交互体验,实现了微博级的内容展示效果。 ## 🔍 核心理念:智能文本交互的三个维度 Expandable

gitblog_00256的博客 824

Modkit

Nmod- 通过过滤器分类为具有指定碱基修饰的残基的调用数量。Ncanonical- 通过过滤器分类为未修饰的碱基的调用数量。确切的碱基必须通过修饰代码推断。例如,如果修饰代码是m(5mC),则未修饰的碱基是胞嘧啶。如果修饰代码是a,则未修饰的碱基是腺苷。Nother mod- 通过过滤器分类为修饰的调用数量,但修饰不同于列出的碱基(且相应的未修饰碱基相同)。例如,对于给定的胞嘧啶,可能有 3 个读取带有h调用,1 个带有未修饰调用,2 个带有m调用。在h的 bedMethyl 行中,N。

生物信息学 1264

医院网络设计(完整文档+思科拓扑图)

大家好,我是小华学长,一名计算机领域的博主。经过多年的学习和实践,我积累了丰富的计算机知识和经验,在这里我想与大家分享我的学习心得和技巧,帮助你成为更好的程序员。作为一名计算机博主,我一直专注于编程、算法、软件开发等领域,在这些方面积累了大量的经验。我相信分享是一种双赢的方式,通过分享,我可以帮助他人提升技术水平,同时也能够得到学习交流的机会。在我的文章中,你将会看到我对于各种编程语言、开发工具以及常见问题的解析和分析。我会结合自己的实际项目经验,为你提供实用的解决方案和优化技巧。

qq1325513482的博客 2万+

推荐开源项目:Android-ExpandableTextView - 让文本视图动起来!

推荐开源项目:Android-ExpandableTextView - 让文本视图动起来! 在移动应用开发领域,细节体验往往决定着用户的去留。今天,我们来探索一个为提升用户体验而生的优秀开源项目——Android-ExpandableTextView。这是一款专为安卓应用程序设计的扩展性TextView组件,支持版本自4.1起,它让文本展示变得灵活且交互性强。 项目介绍 Android-Expan...

gitblog_00304的博客 781

实时系统vxWorks - 虚拟机环境搭建

概述VxWorks 操作系统是美国WindRiver公司于1983年设计开发的一种嵌入式实时操作系统(RTOS),是嵌入式开发环境的关键组成部分。良好的持续发展能力、高性能的内核以及友好的...

不只会拍照的程序猿 7850

Android ExpandableTextView:智能文本交互控件的技术实现与性能优化

在Android应用开发中,文本内容的智能展示与交互一直是提升用户体验的关键环节。传统的TextView在面对长文本、@用户提及、URL链接等复杂场景时,往往需要开发者编写大量重复代码来实现展开/收起、链接高亮、点击响应等功能。ExpandableTextView作为一款专业的Android文本交互控件,通过一体化架构设计,将文本解析、样式渲染、状态管理、动画过渡等核心功能高度集成,为开发者提供了

gitblog_00994的博客 1096

如何使用 Conda 安装 Qiskit(详细教程)

本文介绍了使用conda安装Qiskit量子计算工具包的完整流程。首先创建Python 3.10的conda虚拟环境(qiskit_env),然后安装Qiskit核心包及可视化组件(注意Mac用户的安装命令差异)。接着注册IPython内核并测试环境,通过量子电路创建与可视化演示验证安装成功。该教程为量子计算开发提供了简洁的环境配置指南,适合研究者和开发者快速搭建Qiskit开发环境。

猿小白的博客 563

最优控制 (Optimal Control) 算法详解及案例分析

最优控制是一种通过优化控制输入,使系统在满足约束条件的情况下达到最优性能的控制方法。其目标是最小化或最大化一个性能指标。

闲人编程的博客 2090

Android ExpandableTextView 使用教程

Android ExpandableTextView 使用教程 本教程旨在引导您了解并使用 Blogcat/Android-ExpandableTextView 这个开源项目,它提供了一个易于使用的可扩展文本视图组件,适用于Android应用程序。 1. 项目目录结构及介绍 Android-ExpandableTextView的项目结构清晰地组织了其各个组成部分: Android-Expandab...

gitblog_00428的博客 686

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

解密Android智能文本交互:ExpandableTextView深度解析与实战应用

在Android应用开发领域,文本展示与交互是用户体验的核心环节。传统的TextView在处理长文本、@用户提及和超链接时常常显得力不从心,而**ExpandableTextView**作为一款创新的智能文本控件,彻底改变了这一现状。这款开源组件不仅实现了文本的智能折叠与展开,更集成了@用户识别、链接高亮、点击跳转等高级功能,让Android应用的文本交互体验提升10倍。 ## 🔥 价值主张:

gitblog_01140的博客 489

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Android-ExpandableTextView 项目推荐

Android-ExpandableTextView 项目推荐 1. 项目基础介绍和主要编程语言 Android-ExpandableTextView 是一个开源的 Android 项目,主要用于实现可展开和折叠的 TextView 功能。该项目的主要编程语言是 Java。通过使用这个库,开发者可以轻松地在 Android 应用中实现文本内容的展开和折叠效果,提升用户体验。 2. 项目的核心功能 ...

gitblog_00695的博客 991

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Android-ExpandableTextView 使用教程

Android-ExpandableTextView 使用教程 1. 项目介绍 Android-ExpandableTextView 是一个开源的 Android 库,旨在帮助开发者轻松实现可展开和折叠的 TextView。这个库的主要功能是允许 TextView 在默认情况下显示有限行数的文本,用户可以通过点击按钮展开查看全部内容,再次点击则可以收起文本。这种交互方式在显示长文本内容时非常有用,...

gitblog_00344的博客 840

Android文本交互控件的深度技术实现:ExpandableTextView源码解析

在Android应用开发中,文本内容的展示与交互是用户体验的核心环节。传统TextView在处理长文本、链接识别和用户提及等功能时存在诸多限制,而ExpandableTextView作为一款专业的文本交互控件,通过巧妙的设计模式和高效的渲染机制,为开发者提供了完整的解决方案。 ## 技术架构与设计模式 ExpandableTextView继承自AppCompatTextView,采用装饰器模式

gitblog_00055的博客 600

ExpandableTextView—可以伸缩的文本

介绍ExpandableTextView 是一个Android库,使开发人员能够轻松地创建一个TextView可以展开/折叠就像谷歌Play的应用说明。随意使用它所有你想在你的Android应用程序,只要你引用这个项目。控件一般用在应用详情页面的简介中,可伸缩扩展的。 展示图依赖GitHub源码 点击查看dependencies { compile 'com.ms-square:ex

程序病毒小队的博客 3231

Android-ExpandableTextView 项目常见问题解决方案

Android-ExpandableTextView 项目常见问题解决方案 项目基础介绍 Android-ExpandableTextView 是一个开源的 Android 库,旨在帮助开发者实现可展开和折叠的 TextView 功能。该项目的主要编程语言是 Java,适用于需要在 Android 应用中展示长文本内容并允许用户展开或折叠文本的场景。 新手使用注意事项及解决方案 1. 导入项目时出...

gitblog_00569的博客 692

ExpandableTextView的问题

今天使用ExpandableTextView这个控件遇到一个奇葩问题。我是将ExpandableTextView放到了一个item的布局中,要填充到ListView里。结果报了 android.view.InflateException: Binary XML file line #2: Error inflating class com.connxun.chinamedicine.

a569503963的博客 980

ExpandableTextView 常见问题 7 大清单:按钮不显示、动画错乱、状态丢失的解决方案

**ExpandableTextView** 是一款轻量级 Android 组件库,让普通 `TextView` 一键实现**展开/收起**效果:长文本默认折叠为若干行,底部出现"展开"按钮,点击后带动画平滑展开,再次点击可收起。本文整理了 7 个新手最常踩的坑——按钮不显示、动画错乱、列表中状态丢失等,并给出逐一排查与解决思路。 ## 一、先弄懂原理,排查才有方向 🧭 组件内部其实由两个

gitblog_00102的博客 970

Android折叠文本组件对比:为什么ExpandableTextView仍是最佳选择?

在Android应用开发中,文本展示是最基础也最常见的需求之一。当面对长文本内容时,一个优秀的折叠文本组件能极大提升用户体验。今天我们将深入对比各类Android折叠文本方案,并揭示为什么**ExpandableTextView**依然是2023年开发者的首选解决方案。 ## 折叠文本组件的重要性 长文本展示在移动应用中始终是个挑战。想象一下,当用户打开一篇文章或产品描述时,面对满屏的文字很容

gitblog_00162的博客 1020
上一篇: Android onNewIntent()需要注意的一些问题
下一篇: Android: 使用CMake 构建 JNI 项目
Mackkill
博客等级 码龄15年 65粉丝 39原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值