热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Android自定义控件之TextView的展开与折叠

还是先描述一下需求,这个在其余的app中应该也经常看见,就是当一个段文字很长的时候,我们往往为了展示的时候节约展示的空间,需要将我们的文字折叠起来,如果用户想看里面的详细内容话,则需要用户去

还是先描述一下需求,这个在其余的app中应该也经常看见,就是当一个段文字很长的时候,我们往往为了展示的时候节约展示的空间,需要将我们的文字折叠起来,如果用户想看里面的详细内容话,则需要用户去点击一下改控件,然后TextView展开,显示全部的内容。由于我在本次的项目中有这个需求,所以我将其独立成了一个自定义控件,方便在以后的开发中能直接使用。下面是效果图


先来说说大致思路,其实也是很简单的一个控件,首先该控件是继承LinearLayout的,其中的布局文件包括一个TextView和一个下拉三角的ImageView,当用户在单击这个LinearLayout的时候,我会开一个子线程,让改线程睡20ms,睡完后再向主线程中发送一个handler,在主线程中重新设置一下TextView的显示行数,一次循环,直到显示全部内容为止,在折叠起来的时候设计思路也是一样的,当然在该控件中我用了一个isExp来标记该控件是否展开是否折叠。好了,大致的设计思路就是这样,很简单,接下来贴代码了,可以复制粘贴后直接使用


下面是布局文件




    

    


下面是页面处理的逻辑代码

package com.renrui.job.widget;

import com.renrui.job.R;

import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

/**
 * 可折叠的TextView
 */
public class FoldTextView extends LinearLayout
{
	FoldTextViewHolder mFoldTextViewHolder;
	View myView;

	/**
	 * 真实行数
	 */
	int realLineCounts = 0;
	
	/**
	 * 默认行数
	 */
	int defaultLineCounts = 4;

	/**
	 * 真实高度
	 */
	int realHeight = 0;

	/**
	 * 折叠后的高度
	 */
	int foldHeight = 0;

	boolean isFirstLoad = true;

	/**
	 * Icon状态 展开动画
	 */
	RotateAnimation expIconAnimation;

	/**
	 * Icon状态 折叠动画
	 */
	RotateAnimation foldIconAnimation;

	/**
	 * 当前是否展开
	 */
	boolean isExp = false;
	
	/**
	 * 展开TextView
	 */
	final int TEXT_OPEN = 1;
	
	/**
	 * 关闭TextView
	 */
	final int TEXT_CLOSE = 2;

	Handler mHander = new Handler()
	{
		LayoutParams layoutParma;
		public void handleMessage(android.os.Message msg)
		{
			int lines = (Integer) msg.obj;
			switch (msg.what)
			{
			case TEXT_OPEN:	//打开,增加高度
				mFoldTextViewHolder.tvFold.setMaxLines(lines);
				break;
			case TEXT_CLOSE://关闭,减少高度
				mFoldTextViewHolder.tvFold.setMaxLines(lines);
				break;
			}
		};
	};

	public FoldTextView(Context context)
	{
		super(context);

		init();
	}

	public FoldTextView(Context context, AttributeSet attrs)
	{
		super(context, attrs);

		init();
	}

	@TargetApi(Build.VERSION_CODES.HONEYCOMB)
	public FoldTextView(Context context, AttributeSet attrs, int defStyle)
	{
		super(context, attrs, defStyle);

		init();
	}

	private void init()
	{
		LayoutInflater inflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);

		LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
		myView = inflater.inflate(R.layout.view_widget_foldtextview, null);
		this.addView(myView, layoutParams);

		//设置小箭头展开时的旋转动画
		expIcOnAnimation= new RotateAnimation(0f, 180f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
		expIconAnimation.setDuration(300);
		expIconAnimation.setFillAfter(true);

		//设置小箭头关闭时的旋转动画
		foldIcOnAnimation= new RotateAnimation(180f, 0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
		foldIconAnimation.setDuration(300);
		foldIconAnimation.setFillAfter(true);

		mFoldTextViewHolder = new FoldTextViewHolder(this);
	}

	public void setText(String text)
	{
		mFoldTextViewHolder.tvFold.setText(text);

		ViewTreeObserver vto = mFoldTextViewHolder.tvFold.getViewTreeObserver();
		vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener()
		{
			@Override
			public void onGlobalLayout()
			{
				if (!isFirstLoad)
				{
					return;
				}

				//获取真实行数
				realLineCounts = mFoldTextViewHolder.tvFold.getLineCount();
				realHeight = mFoldTextViewHolder.tvFold.getMeasuredHeight();

				//如果真实行数大于默认的显示行数,则默认将其折叠起来  isExp为false
				if (realLineCounts > defaultLineCounts)
				{
					mFoldTextViewHolder.tvFold.setMaxLines(defaultLineCounts);
					mFoldTextViewHolder.tvFold.measure(0, 0);
					foldHeight = mFoldTextViewHolder.tvFold.getMeasuredHeight();
					mFoldTextViewHolder.ivFold.setVisibility(View.VISIBLE);

					mFoldTextViewHolder.tvFold.setOnClickListener(FoldOnclick);
					mFoldTextViewHolder.ivFold.setOnClickListener(FoldOnclick);
					isExp = false;
				}
				//如果真实行数小于默认行数,则直接展示出来。isExp为true;
				else
				{
					mFoldTextViewHolder.ivFold.setVisibility(View.GONE);
					isExp = true;
				}

				isFirstLoad = false;
			}
		});
	}

	View.OnClickListener FoldOnclick= new OnClickListener()
	{
		@Override
		public void onClick(View v)
		{
			if (isExp)
			{
				new Thread(new Runnable()
				{
					@Override
					public void run()
					{
						int endcount = realLineCounts;
						while(endcount-- > defaultLineCounts){
							Message msg = Message.obtain();
							msg.what = TEXT_CLOSE;
							msg.obj = endcount;
							mHander.sendMessage(msg);
							try
							{
								Thread.sleep(20);
							} catch (InterruptedException e)
							{
								e.printStackTrace();
							}
							
						}
					}
				}).start();
				
				mFoldTextViewHolder.ivFold.setAnimation(foldIconAnimation);
				foldIconAnimation.startNow();

				isExp = false;
			} else
			{
				new Thread(new Runnable()
				{
					
					@Override
					public void run()
					{
						int startcount = defaultLineCounts;
						while(startcount++  
 
好了  以上就是该控件的全部代码了,不多,但是有时候还是挺好用的

PS:由于本人技术有限,如果上面有错误的地方还希望大家指正,感激不尽




推荐阅读
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • 转载至:http:blog.csdn.netlmj623565791articledetails24252901不过对原作进行了相关细节优化,所以才有此文..首先我们看一 ... [详细]
  • AndroidTextView跑马灯效果效果图TextView跑马灯继承TextView重写isFocused方法还有配置singline属性第一种方式:XML布局为:<?xmlversio ... [详细]
  • 我们在电视或者手机上开发的时候,经常会遇到如下情况,在屏幕上布局了多个TextView,ImageView,ImageBut ... [详细]
  • Android TextView利用measureText自适应文本字体大小宽度
    AndroidTextView利用measureText自适应文本字体大小宽度常常有这种情况,UI设计师限定一个文本TextView的宽度值比如80dip,但是该文本长度 ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • 在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板
    本文介绍了在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板的方法和步骤,包括将ResourceDictionary添加到页面中以及在ResourceDictionary中实现模板的构建。通过本文的阅读,读者可以了解到在Xamarin XAML语言中构建控件模板的具体操作步骤和语法形式。 ... [详细]
  • 带添加按钮的GridView,item的删除事件
    先上图片效果;gridView无数据时显示添加按钮,有数据时,第一格显示添加按钮,后面显示数据:布局文件:addr_manage.xml<?xmlve ... [详细]
  • 在一对一直播源码使用过程中,有时会出现软键盘切换闪屏问题,就是当切换表情的时候屏幕会跳动,因此要对一对一直播源码表情面板无缝切换进行优化。 ... [详细]
  • scroll-在Android上使TextView可滚动我在textview中显示文本似乎太长而不适合进入一个屏幕。我需要让我的TextView可滚动。我能怎么做那? ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • 微信小程序导航跟随的实现方法
    本文介绍了在微信小程序中实现导航跟随的方法。通过设置导航的position属性和绑定滚动事件,可以实现页面向下滚动到导航位置时,导航固定在页面最上方;页面向上滚动到导航位置时,导航恢复到原始位置;点击导航可以平滑跳转到相应位置。代码示例也给出了具体实现方法。 ... [详细]
  • Sleuth+zipkin链路追踪SpringCloud微服务的解决方案
    在庞大的微服务群中,随着业务扩展,微服务个数增多,系统调用链路复杂化。Sleuth+zipkin是解决SpringCloud微服务定位和追踪的方案。通过TraceId将不同服务调用的日志串联起来,实现请求链路跟踪。通过Feign调用和Request传递TraceId,将整个调用链路的服务日志归组合并,提供定位和追踪的功能。 ... [详细]
  • SmartRefreshLayout自定义头部刷新和底部加载
    1.添加依赖implementation‘com.scwang.smartrefresh:SmartRefreshLayout:1.0.3’implementation‘com.s ... [详细]
  • 详解Android  自定义UI模板设计_由浅入深
    学习安卓已有一些日子,前段时间整理了不少笔记,但是发现笔记不变分享与携带。今天开始整理博客,全当是与大家分享交流与自身学习理解的过程吧。结合最近在做的一个新闻类app及学习中的问题,一点一点整理一下, ... [详细]
author-avatar
祗想抱著伱
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有