适应多行长文本的Android TextView

简易实现 TextView单行文本水平触摸滑动效果 最近做应用的时候有用到TextView单行长文本,当文本内容过长时候又想实现触摸水平滑动效果。网上找了很多,都没有看到有效解决方案。 其中,最常见的也是最笨拙滴采用重写TextView并继承实现touch 和 Gesture手势。 后来经提醒发现了其实最简单的方案: 直接使用 EditText 就好了。因为edittext需要编辑和移动光标的缘故,使得它是可以水平滑动的。因此我们只需要设置其 阅读详情

本文来自http://blog.youkuaiyun.com/hellogv/ ,引用必须注明出处!

       大家经常会用到系统默认的TextView,TextView可以很好地适应单行长文本(尾部自动打上省略号),以及可以完整显示多行文本(TextView的宽高足够大)。但如果是很多行的文本而TextView又足够大的时候,则会出现以下这种情况.......超出的文本受TextView大小限制,不能完全显示。

      本文主要实现一个能够适应多行长文本的TextView,自动缩减长文本并在结尾补上省略号。如下图:红色部分为普通的TextView,绿色部分为本文实现的TextView。

 
       本文的源码可以到  http://download.youkuaiyun.com/detail/hellogv/4298631 下载,本文的TextViewMultilineEllipse.java改自 http://code.google.com/p/android-textview-multiline-ellipse/ 以及 http://code.google.com/p/android/ 的MyClipTextView.java,相对于前面2者,本文使用哈希表来保存每次onMeasure()计算所得的宽高,大幅减少重复计算宽高。

 

本文的主Activity的源码如下:

public class AutoFixTextViewActivity extends Activity {
	private LinearLayout linearLayout1;
	private TextViewMultilineEllipse tvMultilineEllipse;
	private TextView tvNormal;
	
	//水调歌头,大家懂的
	private final String text="明月几时有?把酒问青天。不知天上宫阙,今夕是何年。\n"
			+"我欲乘风归去,又恐琼楼玉宇,高处不胜寒。\n"
			+"起舞弄清影,何似在人间。\n"
			+"转朱阁,低绮户,照无眠。不应有恨,何事长向别时圆?\n"
			+"人有悲欢离合,月有阴晴圆缺,此事古难全。\n"
			+"但愿人长久,千里共婵娟。";
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        this.setTitle("适应多行文本的Android TextView---hellogv");
        
        //共同的宽高
        LayoutParams lp=new LayoutParams(LayoutParams.FILL_PARENT,100);
        //----用TextView来显示换行长文本----//
        tvNormal=(TextView)this.findViewById(R.id.tvNormal);
        tvNormal.setLayoutParams(lp); //限制TextView的宽高
        tvNormal.setEllipsize(TextUtils.TruncateAt.END);
        tvNormal.setSingleLine(false);
        tvNormal.setMaxLines(5);
        tvNormal.setText(text);
        
        
        //----用TextViewMultilineEllipse来显示换行长文本----//
        linearLayout1=(LinearLayout) this.findViewById(R.id.linearLayout1);
        
        tvMultilineEllipse = new TextViewMultilineEllipse(this);
		tvMultilineEllipse.setLayoutParams(lp);//限制TextView的宽高
		tvMultilineEllipse.setEllipsis("...");//...替换剩余字符串
		tvMultilineEllipse.setMaxLines(5);
		tvMultilineEllipse.setTextSize((int)tvNormal.getTextSize());//设置文字大小
		tvMultilineEllipse.setTextColor(Color.WHITE);
		tvMultilineEllipse.setText(text);//设置文本
		
		//在代码里添加tvMultilineEllipse,暂时不支持Layout里直接添加
		linearLayout1.addView(tvMultilineEllipse);
		
    }
 
    
}


PS:TextViewMultilineEllipse是在代码里动态构建和使用,而不能直接在Layout.xml里使用。

main.xml的源码如下:

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/tvNormal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Medium Text"
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <LinearLayout
        android:id="@+id/linearLayout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dip" >
    </LinearLayout>

</LinearLayout>


TextViewMultilineEllipse.java源码如下,有点多,读者可以直接忽略:

public class TextViewMultilineEllipse extends TextView{

    private TextPaint mTextPaint;
    private String mText;
    private int mAscent;
    private String mStrEllipsis;
    private String mStrEllipsisMore;
    private int mMaxLines;
    private boolean mDrawEllipsizeMoreString;
    private int mColorEllipsizeMore;
    private boolean mRightAlignEllipsizeMoreString;
    private boolean mExpanded;
    private LineBreaker mBreakerExpanded;
    private LineBreaker mBreakerCollapsed;
    /**hashMapW是优化的关键点,通过哈希表来减少计算次数*/
    private HashMap<Integer,Integer> hashMapW=new HashMap<Integer,Integer>();
    public TextViewMultilineEllipse(Context context) {
        super(context);
     // TODO Auto-generated constructor stub
        mExpanded = false;
        mDrawEllipsizeMoreString = true;
        mRightAlignEllipsizeMoreString = false;
        mMaxLines = -1;
        mStrEllipsis = "...";
        mStrEllipsisMore = "";
        mColorEllipsizeMore = 0xFF0000FF;
        
        mBreakerExpanded = new LineBreaker();        
        mBreakerCollapsed = new LineBreaker();
        
        // Default font size and color.
        mTextPaint = new TextPaint();
        mTextPaint.setAntiAlias(true);
        mTextPaint.setTextSize(13);
        mTextPaint.setColor(0xFF000000);
        mTextPaint.setTextAlign(Align.LEFT);
        setDrawingCacheEnabled(true);
    }
    
    /**
     * Sets the text to display in this widget.
     * @param text The text to display.
     */
    public void setText(String text) {
        mText = text;
        requestLayout();
        invalidate();
    }

    /**
     * Sets the text size for this widget.
     * @param size Font size.
     */
    public void setTextSize(int size) {
        mTextPaint.setTextSize(size);
        requestLayout();
        invalidate();
    }

    /**
     * Sets the text color for this widget.
     * @param color ARGB value for the text.
     */
    public void setTextColor(int color) {
        mTextPaint.setColor(color);
        invalidate();
    }

    /**
     * The string to append when ellipsizing. Must be shorter than the available
     * width for a single line!
     * @param ellipsis The ellipsis string to use, like "...", or "-----".
     */
    public void setEllipsis(String ellipsis) {
        mStrEllipsis = ellipsis;
    }
    
    /**
     * Optional extra ellipsize string. This
     * @param ellipsisMore
     */
    public void setEllipsisMore(String ellipsisMore) {
        mStrEllipsisMore = ellipsisMore;
    }
    
    /**
     * The maximum number of lines to allow, height-wise.
     * @param maxLines
     */
    public void setMaxLines(int maxLines) {
        mMaxLines = maxLines;
    }
    
    /**
     * Turn drawing of the optional ellipsizeMore string on or off.
     * @param drawEllipsizeMoreString Yes or no.
     */
    public void setDrawEllipsizeMoreString(boolean drawEllipsizeMoreString) {
        mDrawEllipsizeMoreString = drawEllipsizeMoreString;
    }
    
    /**
     * Font color to use for the optional ellipsizeMore string.
     * @param color ARGB color.
     */
    public void setColorEllpsizeMore(int color) {
        mColorEllipsizeMore = color;
    }
    
    /**
     * When drawing the ellipsizeMore string, either draw it wherever ellipsizing on the last
     * line occurs, or always right align it. On by default.
     * @param rightAlignEllipsizeMoreString Yes or no.
     */
    public void setRightAlignEllipsizeMoreString(boolean rightAlignEllipsizeMoreString) {
        mRightAlignEllipsizeMoreString = rightAlignEllipsizeMoreString;
    }
    
    /**
     * @see android.view.View#measure(int, int)
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(
            measureWidth(widthMeasureSpec),
            measureHeight(heightMeasureSpec));
    }

    /**
     * Determines the width of this view
     * @param measureSpec A measureSpec packed into an int
     * @return The width of the view, honoring constraints from measureSpec
     */
    private int measureWidth(int measureSpec) {
        int result = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if (specMode == MeasureSpec.EXACTLY) {
            // We were told how big to be.
            result = specSize;
            
            // Format the text using this exact width, and the current mode.
            breakWidth(specSize);
        } 
        else {
            if (specMode == MeasureSpec.AT_MOST) {
                // Use the AT_MOST size - if we had very short text, we may need even less
                // than the AT_MOST value, so return the minimum.
                result = breakWidth(specSize);
                result = Math.min(result, specSize);
            }
            else {
                // We're not given any width - so in this case we assume we have an unlimited
                // width?
                breakWidth(specSize);
            }
        }

        return result;
    }

    /**
     * Determines the height of this view
     * @param measureSpec A measureSpec packed into an int
     * @return The height of the view, honoring constraints from measureSpec
     */
    private int measureHeight(int measureSpec) {
        int result = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        mAscent = (int) mTextPaint.ascent();
        if (specMode == MeasureSpec.EXACTLY) {
            // We were told how big to be, so nothing to do.
            result = specSize;
        } 
        else {
            // The lines should already be broken up. Calculate our max desired height
            // for our current mode.
            int numLines;
            if (mExpanded) {
                numLines = mBreakerExpanded.getLines().size();
            }
            else {
                numLines = mBreakerCollapsed.getLines().size();
            }
            result = numLines * (int) (-mAscent + mTextPaint.descent())
                   + getPaddingTop()
                   + getPaddingBottom();

            // Respect AT_MOST value if that was what is called for by measureSpec.
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
        }
        return result;
    }

    /**
     * Render the text
     * 
     * @see android.view.View#onDraw(android.graphics.Canvas)
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        List<int[]> lines;
        LineBreaker breaker;
        if (mExpanded) {
            breaker = mBreakerExpanded;
            lines = mBreakerExpanded.getLines();
        }
        else {
            breaker = mBreakerCollapsed;
            lines = mBreakerCollapsed.getLines();
        }
        
        float x = getPaddingLeft();
        float y = getPaddingTop() + (-mAscent);
        for (int i = 0; i < lines.size(); i++) {
            // Draw the current line.
            int[] pair = lines.get(i);
            canvas.drawText(mText, pair[0], pair[1]+1, x, y, mTextPaint);
            
            // Draw the ellipsis if necessary.
            if (i == lines.size() - 1) {
                if (breaker.getRequiredEllipsis()) {
                    canvas.drawText(mStrEllipsis, x + breaker.getLengthLastEllipsizedLine(), y, mTextPaint);
                    if (mDrawEllipsizeMoreString) {
                        int lastColor = mTextPaint.getColor();
                        mTextPaint.setColor(mColorEllipsizeMore);
                        if (mRightAlignEllipsizeMoreString) {
                            // Seems to not be right...
                            canvas.drawText(mStrEllipsisMore, canvas.getWidth()-(breaker.getLengthEllipsisMore()+getPaddingRight()+getPaddingLeft()), y, mTextPaint);
                        }
                        else {
                            canvas.drawText(mStrEllipsisMore, x + breaker.getLengthLastEllipsizedLinePlusEllipsis(), y, mTextPaint);
                        }
                        mTextPaint.setColor(lastColor);
                    }
                }
            }
            
            y += (-mAscent + mTextPaint.descent());
            if (y > canvas.getHeight()) {
                break;
            }
        }
    }
    
    public boolean getIsExpanded() {
        return mExpanded;
    }
    
    public void expand() {
        mExpanded = true;
        requestLayout();
        invalidate();
    }
    
    public void collapse() {
        mExpanded = false;
        requestLayout();
        invalidate();
    }
    

    private int breakWidth(int availableWidth) {
    	if(hashMapW.containsKey(availableWidth))
    		return hashMapW.get(availableWidth);
    	
        int widthUsed = 0;
        if (mExpanded) {
            widthUsed =
              mBreakerExpanded.breakText(
                 mText, 
                availableWidth - getPaddingLeft() - getPaddingRight(), 
                mTextPaint);
        }
        else {
            widthUsed =
              mBreakerCollapsed.breakText(
                mText, 
                mStrEllipsis, 
                mStrEllipsisMore, 
                mMaxLines, 
                availableWidth - getPaddingLeft() - getPaddingRight(), 
                mTextPaint);
        }
        hashMapW.put(availableWidth, widthUsed + getPaddingLeft() + getPaddingRight());
        return widthUsed + getPaddingLeft() + getPaddingRight();
    }
    
    
    /**
     * Used internally to break a string into a list of integer pairs. The pairs are
     * start and end locations for lines given the current available layout width.
     */
    private static class LineBreaker
    {
        /** Was the input text long enough to need an ellipsis? */
        private boolean mRequiredEllipsis;
        
        /** Beginning and end indices for the input string. */
        private ArrayList<int[]> mLines;
        
        /** The width in pixels of the last line, used to draw the ellipsis if necessary. */
        private float mLengthLastLine;
        
        /** The width of the ellipsis string, so we know where to draw the ellipsisMore string
         *  if necessary.
         */
        private float mLengthEllipsis;
        
        /** The width of the ellipsizeMore string, same use as above. */
        private float mLengthEllipsisMore;
        
        
        public LineBreaker() {
            mRequiredEllipsis = false;
            mLines = new ArrayList<int[]>();
        }

        /**
         * Used for breaking text in 'expanded' mode, which needs no ellipse.
         * Uses as many lines as is necessary to accomodate the entire input
         * string.
         * @param input String to be broken.
         * @param maxWidth Available layout width.
         * @param tp Current paint object with styles applied to it.
         */
        public int breakText(String input, 
                                int maxWidth, 
                             TextPaint tp) 
        {
            return breakText(input, null, null, -1, maxWidth, tp);
        }

        /**
         * Used for breaking text, honors ellipsizing. The string will be broken into lines using
         * the available width. The last line will subtract the physical width of the ellipsis
         * string from maxWidth to reserve room for the ellipsis. If the ellpsisMore string is set,
         * then space will also be reserved for its length as well.
         * @param input String to be broken.
         * @param ellipsis Ellipsis string, like "..."
         * @param ellipsisMore Optional space reservation after the ellipsis, like " Read More!"
         * @param maxLines Max number of lines to allow before ellipsizing.
         * @param maxWidth Available layout width.
         * @param tp Current paint object with styles applied to it.
         */
        public int breakText(String input, 
                                String ellipsis,
                                String ellipsisMore,
                             int maxLines, 
                             int maxWidth, 
                             TextPaint tp) 
        {
            mLines.clear();
            mRequiredEllipsis = false;
            mLengthLastLine = 0.0f;
            mLengthEllipsis = 0.0f;
            mLengthEllipsisMore = 0.0f;
            
            // If maxWidth is -1, interpret that as meaning to render the string on a single
            // line. Skip everything.
            if (maxWidth == -1) {
                mLines.add(new int[]{ 0, input.length() });
                return (int)(tp.measureText(input) + 0.5f);
            }

            // Measure the ellipsis string, and the ellipsisMore string if valid.
            if (ellipsis != null) {
                mLengthEllipsis = tp.measureText(ellipsis);
            }
            if (ellipsisMore != null) {
                mLengthEllipsisMore = tp.measureText(ellipsisMore);
            }

            // Start breaking.
            int posStartThisLine = -1;
            float lengthThisLine = 0.0f;
            boolean breakWords = true;
            int pos = 0;
            while (pos < input.length()) {
                
                if (posStartThisLine == -1) {
                    posStartThisLine = pos;
                }
                
                if (mLines.size() == maxLines) {
                    mRequiredEllipsis = true;
                    break;
                }
                
                float widthOfChar = tp.measureText(input.charAt(pos) + "");
                boolean newLineRequired = false;
                
                if(!hasChinese(input)){/**english*/
                    // Check for a new line character or if we've run over max width.
                    if (input.charAt(pos) == '\n') {
                        newLineRequired = true;
                        
                        // We want the current line to go up to the character right before the
                        // new line char, and we want the next line to start at the char after
                        // this new line char.
                        mLines.add(new int[] { posStartThisLine, pos-1 });
                    }else if (lengthThisLine + widthOfChar >= maxWidth) {
                        newLineRequired = true;
                        // We need to backup if we are in the middle of a word.
                        if (input.charAt(pos) == ' ' || breakWords == false) {
                            // Backup one character, because it doesn't fit on this line.
                            pos--;
                            
                            // So this line includes up to the character before the space.
                            mLines.add(new int[] { posStartThisLine, pos });
                        }else {
                            // Backup until we are at a space.
                            Log.v("*******", "*********************************now char = " + input.charAt(pos));
                            while (input.charAt(pos) != ' ') {
                                pos--;
                            }
                            
                            // This line includes up to the space.
                            mLines.add(new int[] { posStartThisLine, pos });
                        }
                    }
                }else{/**chinese*/
                    // Check for a new line character or if we've run over max width.
                    if (input.charAt(pos) == '\n') {
                        newLineRequired = true;
                        
                        // We want the current line to go up to the character right before the
                        // new line char, and we want the next line to start at the char after
                        // this new line char.
                        mLines.add(new int[] { posStartThisLine, pos-1 });
                    }else if (lengthThisLine + widthOfChar >= maxWidth) {
                        newLineRequired = true;
                            // This line includes up to the space.
                            mLines.add(new int[] { posStartThisLine, pos });
                    }
                }
                
                
                if (newLineRequired) {
                    // The next cycle should reset the position if it sees it's -1 (to whatever i is).
                    posStartThisLine = -1;
                    
                    // Reset line length for next iteration.
                    lengthThisLine = 0.0f;
                    
                    // When we get to the last line, subtract the width of the ellipsis.
                    if (mLines.size() == maxLines - 1) {
                        maxWidth -= (mLengthEllipsis + mLengthEllipsisMore);
                        // We also don't need to break on a full word, it'll look a little
                        // cleaner if all breaks on the final lines break in the middle of
                        // the last word.
                        breakWords = false;
                    }
                }else {
                    if(!hasChinese(input)){/**english*/
                        lengthThisLine += widthOfChar;
                    }else{/**chinese*/
                        lengthThisLine += (widthOfChar + 0.5f);
                    }
                    
                    // If we're on the last character of the input string, add on whatever we have leftover.
                    if (pos == input.length() - 1) {
                        mLines.add(new int[] { posStartThisLine, pos });
                    }
                }
                
                pos++;
            }
            
            // If we ellipsized, then add the ellipsis string to the end.
            if (mRequiredEllipsis) {
                int[] pairLast = mLines.get(mLines.size()-1);
                mLengthLastLine = tp.measureText(input.substring(pairLast[0], pairLast[1] + 1));
            }
            
            // If we required only one line, return its length, otherwise we used
            // whatever the maxWidth supplied was.
            if (mLines.size() == 0) {
                return 0;
            }
            else if (mLines.size() == 1) {
                return (int)(tp.measureText(input) + 0.5f);
            }
            else {
                return maxWidth;
            }
        }
        
        public boolean getRequiredEllipsis() {
            return mRequiredEllipsis;
        }
        
        public List<int[]> getLines() {
            return mLines;
        }
        
        public float getLengthLastEllipsizedLine() {
            return mLengthLastLine;
        }
        
        public float getLengthLastEllipsizedLinePlusEllipsis() {
            return mLengthLastLine + mLengthEllipsis;
        }
        
        public float getLengthEllipsis() {
            return mLengthEllipsis;
        }
        
        public float getLengthEllipsisMore() {
            return mLengthEllipsisMore;
        }
        
        /**
         * 判断文本中是否含有中文
         */
        private boolean hasChinese(String input){
            return input.getBytes().length != input.length();
        }
    }

}


 

 

 

自适应多行长文本的Android TextView高级指南 TextView是Android开发中最基本的组件之一,用于在界面上显示文本。它提供了多种属性,允许开发者灵活地定义文本的样式和行为。简单地使用TextView,开发者只需要在布局文件中声明它并指定其属性即可显示文本。自定义TextView子类的过程不仅提升了开发者对界面元素的掌控度,而且在创建复杂的文本展示逻辑时提供了极大的便利。本章将深入探讨创建自定义TextView子类的原因和步骤,为开发人员提供更灵活的文本显示解决方案。在Android开发中,虽然TextView。 阅读详情

相关推荐

SAP财务模块必看:BAPI_ACC_DOCUMENT_POST扩展字段全攻略(含FIBF配置)

本文详细解析了SAP财务模块中如何利用BAPI_ACC_DOCUMENT_POST的EXTENSION1参数扩展自定义字段。文章从需求分析入手,对比了传统增强与BTE(业务交易事件)两种技术路径,并重点提供了基于FIBF配置的完整实战指南,包括数据结构理解、函数模块开发及配置步骤,帮助ABAP开发者和财务顾问高效、可维护地实现如WBS元素、税务代码等字段的灵活传递。

weixin_29290963的博客 395

TextView 多行文本上下循环滚动,超简单

有个模块需要显示新闻消息,大量文本用textview上下循环滚动,百度搜的写法自己都不太满意,搞的复杂了,所以就想了个简单容易实现的方法。if (viewHeight > textHeight) { //textview高度大于文本高度,则不用循环。核心:handler循环发消息,textview.scrollto(0,mPosition);//就从textview底部重来。if(mPosition>textHeight){ //如果播放完文本。作为个人的记录,不好用勿喷。

西决的博客 2068

ComfyUI-controlnet控制出图

提供加载预处理器节点。

Bu2n的博客 5494

Android textview显示多行

android:id="@id/mypage_bio"      android:layout_width="0dp"      android:layout_height="wrap_content"      android:layout_weight="4"      android:layout_gravity="center_vertical"      android:lay

cjneo的专栏 5411

unity中简单全景搭建

全景场景能够直观的展现一部分区域的全貌,在全景场景中我们能360°观看周围的景象,仿佛自身就在这个场景中,在场景的外部,我们能发现场景就是一个密封的球体,我们是处在球体的内部观察周围,在球内部观察四周看到的都是球的内表面,所以我们看到的全景其实就是贴在密封球体内的一张全景图片。接下来要介绍的就是如何在unity中用一个球体来搭建全景场景。

qq_31791999的博客 3637

IS-IS协议深度解析(二):LSDB同步机制与骨干网实战部署

本文深度解析IS-IS协议的LSDB同步机制与骨干网实战部署。详细阐述了DIS角色如何通过CSNP/PSNP报文高效管理链路状态数据库同步,并与OSPF DR机制进行对比。重点介绍了Level-2骨干网作为逻辑高速公路系统的工作原理,以及通过ATT比特位实现跨区域路由的自动化。最后提供了高可靠性骨干网的实战配置要点与验证方法。

kite3的博客 643

android textview 设置多行显示,Android设置TextView显示一行或多行

在listView的item中或者是特殊的业务需求中,会要求TextView的内容不完全显示,只有通过一个指定的操作后才显示所有的,比如说一个按钮或者是其它的什么控件。要想实现这个效果并不难,只要控制好TextView的行数就行。文章中介绍了两种实现方法,一种是给button添加Flag,另一种是给button添加Tag,两种方法都可以,具体说不上哪种更好,哪种适合用哪种。第一种方法的布局,注意T...

weixin_34837971的博客 5230

TC3XX - MCAL知识点(三十三):基于EB Tresos配置Tc3xx的MCAL代码如何产生中心对称的三相六路发波波形

本文用于记录如何在英飞凌 tc3xx 芯片的应用开发中,借助 EB Tresos 配置工具生成的配置代码与 MCAL 源码相结合,进而实现三相六路中心对称互补的 PWM 输出效果。外部资源需求:EB Tresos23.0以上、Tasking\Hightec编译器、示波器\逻辑分析仪。

梦想技术家 1207

[Android实例] 适应多行长文本的Android TextView

大家经常会用到系统默认的TextView,TextView可以很好地适应单行长文本(尾部自动打上省略号),以及可以完整显示多行文本(TextView的宽高足够大)。但如果是很多行的文本而TextView又足够大的时候,则会出现以下这种情况.......超出的文本受TextView大小限制,不能完全显示。 本文主要实现一个能够适应多行长文本的TextView,自动缩减长文本并在

xiangyong2008的专栏 7024

pytorch实现基本的logistic和softmax回归实验(手动+torch)

前提:不是前馈神经网络,没有隐藏层。 一:Logistic回归实验–人工构造数据集,手动构造模型 要求: 动手从0实现logistic回归,实现二分类,人工构造数据集,并分析loss、训练集、测试集的准确率。(要求从零实现二元交叉熵) 实验过程: 1.1人工构造数据集 1. # #自定义数据---训练集 2. num_inputs = 2 3. n_data = torch.ones(1500, num_inputs) # 数据的基本形态 4. x1 = torch.normal(2 * n_d

qq_37534947的博客 1万+

红米K70至尊版修复“nv损坏”主板电阻图示 mtk芯片工程固件刷写与步骤说明

💝💝💝红米K70至尊版 机型代码:rothko,搭载天玑9300+旗舰芯片.后置5000万像素索尼IMX906高动态OIS主摄,800万像素超广角镜头,200万像素微距镜头,前置2000万像素摄像头,也适用于以下型号的小米机型:2407FPN8EG,2407FPN8ER,XIG06,A402XM,2407FRK8EC。 💝💝💝通过博文了解 1💝💝💝-----此机型工程固件的资源刷写注意事项 2💝💝💝-----此机型刷写工程固件预览界面 3💝💝💝------红米K

小马哥的专栏 1458

后期开发可能用到的功能

Android中截取当前屏幕的功能 http://blog.youkuaiyun.com/cjjky/article/details/7281746 android 如何判断程序是否在前台运行 http://blog.youkuaiyun.com/id19870510/article/details/7017017 Android 安装和启动另外一个应用 http://blog.cs

duanyu218的专栏 551

Android So加载机制分析----基于Android14源码

本文深入分析Android 14系统中SO(共享库)的两种加载机制:System.loadLibrary()和System.load()。前者通过ClassLoader查找标准路径加载,后者直接加载指定路径的SO文件。文档详细追踪了从Java层到动态链接器的完整加载链路,包括ClassLoader路径查找、JNI桥接、ART虚拟机处理以及底层linker的符号解析和重定位过程。同时还分析了Namespace隔离、JNI_OnLoad机制等核心内容,为开发者提供全面的SO加载技术解析和问题排查指南。

保持专注,保持热爱 349

Android控件笔记——使用TextView实现跑马灯效果

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34310369的博客 155

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

上一篇: Android MediaPlayer与Http Proxy结合之基础篇
下一篇: Android MediaPlayer与Http Proxy结合之提高篇
欧巴Godwin
欧巴Godwin 领域专家: 操作系统技术领域 领域专家: 操作系统技术领域
博客等级 码龄20年 9690粉丝 141原创
评论 22
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值