Android开发之仿微信显示更多文字的View
最近开发需求中要模仿微信朋友圈文章的展开收起功能,网上找了找,发现都有问题,于是乎自己在前辈的基础上进行了一定量的修改,下边将源码贴出来供大家参考:
1.主Activity布局文件就不粘贴了,很简单,就一个ListView.
2.主Activity功能实现:
- <font face="宋体" size="3">package com.example.textviewdemo;
- import java.util.HashMap;
- import android.app.Activity;
- import android.content.Context;
- import android.os.Bundle;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.BaseAdapter;
- import android.widget.ListView;
- import android.widget.TextView;
- import android.widget.TextView.BufferType;
- public class MainActivity extends Activity {
- String mStr;
- int type;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- Globl.map = new HashMap<Integer, Boolean>();
- ListView listview = (ListView) findViewById(R.id.listview);
- mStr = "手指在ListView上下滚动时,ListViewItem背景变黑,因为在滚动的时候为了提升性能做了优化,为提高滚动的性能,Android 框 架在ListView中引入CacheColorHint属性。如果该值为非0,则说明该ListView绘制在单色不透明的背景上,在默认情况下该值 为 #191919,也就是黑色主题中的黑色背景颜色值,这样当ListView滚动的时候";
- listview.setAdapter(new MyListAdpter(this));
- }
- class MyListAdpter extends BaseAdapter {
- Context con;
- CollapsibleTextView tv;
- public MyListAdpter(Context con) {
- this.con = con;
- }
- @Override
- public int getCount() {
- // TODO Auto-generated method stub
- return 10;
- }
- @Override
- public Object getItem(int position) {
- // TODO Auto-generated method stub
- return null;
- }
- @Override
- public long getItemId(int position) {
- // TODO Auto-generated method stub
- return 0;
- }
- HashMap<Integer, View> hashM = new HashMap<Integer, View>();
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- Holder holder = null;
- View view;
- if (hashM.get(position) == null) {
- holder = new Holder();
- view = LayoutInflater.from(con).inflate(R.layout.item_list, null);
- holder.tv = (CollapsibleTextView) view.findViewById(R.id.tv_text);
- holder.tvcount = (TextView) view.findViewById(R.id.tvcount);
- view.setTag(holder);
- hashM.put(position, view);
- } else {
- view = hashM.get(position);
- holder = (Holder) view.getTag();
- }
- // if (Globl.map.get(position) == false) {
- // Globl.map.put(position, false);
- // type = 2;
- // } else {
- // type = 1;
- // }
- // tv.setNowType(type);
- // int typeNow = tv.getNowType();
- holder.tvcount.setText(position + "");
- holder.tv.setDesc(mStr, holder.tv, BufferType.NORMAL);
- return view;
- }
- class Holder {
- CollapsibleTextView tv;
- TextView tvcount;
- }
- }
- }
3.自定义控件CollapsibleTextView 源码:
- <font face="宋体" size="3">/**
- * @Explain: Text过长收起 带有查看全文/收起功能控件;
- * @Author:LYl
- * @Time:2014-11-27 下午4:33:05
- * @Version V2.1.54
- */
- public class CollapsibleTextView extends LinearLayout implements
- OnClickListener {
- /** 最大显示的行数 */
- private static final int DEFAULT_MAX_LINE_COUNT = 8;
- /** 实际展示的行数 */
- private static final int DEFAULT_SHOW_LINE_COUNT = 6;
- private static final int COLLAPSIBLE_STATE_NONE = 0;
- /** View处于展开状态 **/
- private static final int COLLAPSIBLE_STATE_SHRINKUP = 1;
- /** view收缩时状态 **/
- private static final int COLLAPSIBLE_STATE_SPREAD = 2;
- /** 显示内容的View */
- private TextView tv_context;
- /** 展开/收起按钮 */
- private TextView bt_spread;
- private String shrinkup;
- private String spread;
- /** 当前正处于的状态 */
- // private int mState;
- private boolean flag;
- private int nowType;
- private CollapsibleTextView coTextView;
- /** 判断是不是点击了查看更多、收起 */
- private boolean isClicke = false;
- private int lookCount = 0;
- public CollapsibleTextView(Context context, AttributeSet attrs) {
- super(context, attrs);
- shrinkup = "收起";
- spread = "查看全文";
- View view = inflate(context, R.layout.collapsible_textview, this);
- view.setPadding(0, -1, 0, 0);
- tv_context = (TextView) view.findViewById(R.id.tv_context);
- bt_spread = (TextView) view.findViewById(R.id.bt_spread);
- bt_spread.setOnClickListener(this);
- }
- public CollapsibleTextView(Context context) {
- this(context, null);
- }
- /**
- * 赋值
- */
- public final void setDesc(CharSequence charSequence,
- CollapsibleTextView tv, BufferType bufferType) {
- this.coTextView = tv;
- // 对内容中的网址进行处理;
- tv_context.setAutoLinkMask(Linkify.WEB_URLS);
- tv_context.setMovementMethod(LinkMovementMethod.getInstance());
- tv_context.setText(charSequence, bufferType);
- // 初始类型
- if (lookCount == 0) {
- coTextView.setNowType(COLLAPSIBLE_STATE_SPREAD);
- }
- lookCount += 1;
- // TODO LYL 放到ListView中需要加下句:falg=false;一般情况去掉就可
- flag = false;
- requestLayout();
- }
- @Override
- public void onClick(View v) {
- flag = false;
- isClicke = true;
- requestLayout();
- }
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- super.onLayout(changed, l, t, r, b);
- if (!flag) {
- flag = true;
- if (tv_context.getLineCount() <= DEFAULT_MAX_LINE_COUNT) {
- bt_spread.setVisibility(View.GONE);
- tv_context.setMaxLines(DEFAULT_MAX_LINE_COUNT + 1);
- coTextView.setNowType(COLLAPSIBLE_STATE_NONE);
- } else {
- post(new InnerRunnable());
- }
- }
- }
- class InnerRunnable implements Runnable {
- @Override
- public void run() {
- int zType = 0;
- // 第一次进入操作(没有点击并且是第一次进入);
- System.out.println("lookCount:" + lookCount);
- if (!isClicke && lookCount == 1) {
- if (coTextView.getNowType() == COLLAPSIBLE_STATE_SPREAD) {
- tv_context.setMaxLines(DEFAULT_SHOW_LINE_COUNT);
- bt_spread.setVisibility(View.VISIBLE);
- bt_spread.setText(spread);
- zType = COLLAPSIBLE_STATE_SHRINKUP;
- } else if (coTextView.getNowType() == COLLAPSIBLE_STATE_SHRINKUP) {
- tv_context.setMaxLines(Integer.MAX_VALUE);
- bt_spread.setVisibility(View.VISIBLE);
- bt_spread.setText(shrinkup);
- zType = COLLAPSIBLE_STATE_SPREAD;
- }
- coTextView.setNowType(zType);
- // 点击了查看更多、收起转换状态;
- } else if (isClicke) {
- isClicke = false;
- if (coTextView.getNowType() == COLLAPSIBLE_STATE_SPREAD) {
- tv_context.setMaxLines(DEFAULT_SHOW_LINE_COUNT);
- bt_spread.setVisibility(View.VISIBLE);
- bt_spread.setText(spread);
- coTextView.setNowType(COLLAPSIBLE_STATE_SHRINKUP);
- } else if (coTextView.getNowType() == COLLAPSIBLE_STATE_SHRINKUP) {
- tv_context.setMaxLines(Integer.MAX_VALUE);
- bt_spread.setVisibility(View.VISIBLE);
- bt_spread.setText(shrinkup);
- coTextView.setNowType(COLLAPSIBLE_STATE_SPREAD);
- }
- // 滑动listView 从新载入到可见界面 不做操作,保持原有状态;(为了后面看得人能够更理解写上)
- } else if (!isClicke && lookCount != 1) {
- }
- }
- }
- public int getNowType() {
- return nowType;
- }
- public void setNowType(int nowType) {
- this.nowType = nowType;
- }
- }
public class CollapsiblePanel extends LinearLayout {
/**
* TAG
*/
private static final String TAG = "CollapsiblePanel";
/**
* DEBUG
*/
private static final boolean DEBUG = BuildConfig.DEBUG;
/**
* 内容View
*/
private View mContentView;
/**
* 可收缩的View
*/
private View mCollapsibleView;
/**
* 可收缩的大小
*/
private int mCollapsibleSize;
/**
* 收缩的监听器
*/
private OnCollapsibleListener mCollapsibleListener;
/**
* 收缩动画的时间
*/
private int mAnimDuration = 0; //SUPPRESS CHECKSTYLE
/**
* 判断当前可收缩View是否是打开状态
*/
private boolean mIsOpened = false;
/**
* 可收缩View默认是否可见
*/
private boolean mCollapsibleViewDefaultVisible = false;
/**
* Toggle是否可用
*/
private boolean mToggleEnable = true;
/**
* 不使用Alpha动画
*/
private boolean mWithoutAlphaAnim = true;
/**
* 收缩是否有动画效果
*/
private boolean mDoAnimation = true;
public interface OnCollapsibleListener {
/**
* 动画结束监听
*
* @param isOpened 当前的stretchView是否是打开的,
*/
void onCollapsibleFinished(boolean isOpened);
/**
* 动画过程中使用Transformation的接口
*
* @param from from
* @param to to
* @param interpolatedTime interpolatedTime
*/
void applyTransformation(int from, int to, float interpolatedTime);
}
/**
* 构造方法
*
* @param context context
*/
public CollapsiblePanel(Context context) {
super(context);
init(context, null);
}
/**
* 构造方法
*
* @param context context
* @param attrs attrs
*/
public CollapsiblePanel(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
/**
* 构造方法
*
* @param context context
* @param attrs attrs
* @param defStyle defStyle
*/
@SuppressLint("NewApi")
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public CollapsiblePanel(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
}
/**
* 初始化
*
* @param context context
* @param attrs attrs
*/
private void init(Context context, AttributeSet attrs) {
setOrientation(LinearLayout.VERTICAL);
mAnimDuration = 280;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mCollapsibleSize == 0 && mCollapsibleView != null) {
mCollapsibleView.measure(widthMeasureSpec, MeasureSpec.UNSPECIFIED);
if (LinearLayout.VERTICAL == getOrientation()) {
mCollapsibleSize = mCollapsibleView.getMeasuredHeight();
if (!mCollapsibleViewDefaultVisible) {
mCollapsibleView.getLayoutParams().height = 0;
}
} else {
mCollapsibleSize = mCollapsibleView.getMeasuredWidth();
if (!mCollapsibleViewDefaultVisible) {
mCollapsibleView.getLayoutParams().width = 0;
}
}
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
/**
* 设置控件初始时是否可见
*
* @param visible 是否可见
*/
public void setCollapsibleViewDefaultVisible(boolean visible) {
mCollapsibleViewDefaultVisible = visible;
// 默认可见的话,则认为是展开的
mIsOpened = visible;
}
/**
* 控件初始时是否可见
*
* @return visible
*/
public boolean getCollapsibleViewDefaultVisible() {
return mCollapsibleViewDefaultVisible;
}
/**
* 设置toggle是否可用,如果设置为false,则{@link #toggle()}接口无效
*
* @param enable enable
*/
public void setToggleEnable(boolean enable) {
mToggleEnable = enable;
}
/**
* 获取当前的主View
*
* @return view
*/
public View getContentView() {
return mContentView;
}
/**
* 获取当前的扩展View
*
* @return view
*/
public View getStretchView() {
return mCollapsibleView;
}
/**
* 设置主View
*
* @param view view
*/
public void setContentView(View view) {
if (view != null) {
if (mContentView != null) {
removeView(this.mContentView);
}
mContentView = view;
addView(mContentView, 0);
}
}
/**
* 设置收缩的View
*
* @param collapsibleView 可以收缩的View
*/
public void setCollapsibleView(View collapsibleView) {
if (collapsibleView != null) {
if (mCollapsibleView != null) {
removeView(mCollapsibleView);
// 在重新设置时,将该值置为0,否则新view将不能显示正确的高度
mCollapsibleSize = 0;
}
mCollapsibleView = collapsibleView;
addView(mCollapsibleView);
}
}
/**
* 得到可收缩View的大小
*
* @return 可收缩View的大小
*/
public int getCollapsibleSize() {
return mCollapsibleSize;
}
/**
* 设置收缩的监听
*
* @param listener listener
*/
public void setOnCollapsibleListener(OnCollapsibleListener listener) {
mCollapsibleListener = listener;
}
/**
* 当前的视图是否已经展开
*
* @return true/false
*/
public boolean isCollapsibleViewOpened() {
return mIsOpened;
}
/**
* 设置展开(或者收缩)动画的时间,默认280ms
*
* @param durationMs durationMs
*/
public void setCollapsibleAnimDuration(int durationMs) {
if (durationMs >= 0) {
mAnimDuration = durationMs;
} else {
throw new IllegalArgumentException("Animation duration cannot be negative");
}
}
/**
* 展开/收起View
*
* @return true/false
*/
public boolean toggle() {
// 如果不允许展开
if (!mToggleEnable) {
return false;
}
// 如果动画正在进行,不执行任何操作
if (isAnimationPlaying()) {
return false;
}
if (mIsOpened) {
closeCollapsibleView();
} else {
openCollapsibleView();
}
return true;
}
/**
* 展开视图
*/
public void openCollapsibleView() {
if (mCollapsibleView == null) {
return;
}
post(new Runnable() {
@Override
public void run() {
if (mDoAnimation) {
CollapsibleAnimation animation = new CollapsibleAnimation(0, mCollapsibleSize, 0.0f, 1.0f);
animation.setDuration(mAnimDuration);
animation.setAnimationListener(mCollapsibleAnimListener);
mCollapsibleView.startAnimation(animation);
invalidate();
} else {
setCollapsibleViewSize(mCollapsibleSize);
onCollapsibleEnd();
}
}
});
}
/**
* 收起视图
*/
public void closeCollapsibleView() {
if (mCollapsibleView == null) {
return;
}
post(new Runnable() {
@Override
public void run() {
if (mDoAnimation) {
CollapsibleAnimation animation = new CollapsibleAnimation(mCollapsibleSize, 0, 1.0f, 0.0f);
animation.setDuration(mAnimDuration);
animation.setAnimationListener(mCollapsibleAnimListener);
mCollapsibleView.startAnimation(animation);
invalidate();
} else {
setCollapsibleViewSize(0);
onCollapsibleEnd();
}
}
});
}
/**
* 收缩View展开或收缩时调用
*
* @param isOpened isOpened
*/
protected void onCollapsibleFinished(boolean isOpened) {
}
/**
* 重置大小
*/
protected void resetCollapsibleSize() {
mCollapsibleSize = 0;
requestLayout();
}
/**
* 设置收缩View的大小
*
* @param size size
*/
private void setCollapsibleViewSize(int size) {
if (null == mCollapsibleView) {
return;
}
LayoutParams params = (LayoutParams) mCollapsibleView.getLayoutParams();
if (null != params) {
if (LinearLayout.VERTICAL == getOrientation()) {
params.height = size;
} else {
params.width = size;
}
mCollapsibleView.setLayoutParams(params);
}
}
/**
* 判断动画是否正在播放
*
* @return true/false
*/
private boolean isAnimationPlaying() {
if (null != mCollapsibleView) {
Animation anim = mCollapsibleView.getAnimation();
if (null != anim && !anim.hasEnded()) {
return true;
}
}
return false;
}
/**
* 动画的监听器
*/
private AnimationListener mCollapsibleAnimListener = new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
onCollapsibleEnd();
}
};
/**
* 收缩结束时调用
*/
private void onCollapsibleEnd() {
mIsOpened = !mIsOpened;
if (mCollapsibleListener != null) {
mCollapsibleListener.onCollapsibleFinished(mIsOpened);
}
if (null != mCollapsibleView) {
mCollapsibleView.setAnimation(null);
}
onCollapsibleFinished(mIsOpened);
}
/**
* 伸缩动画
*/
private class CollapsibleAnimation extends Animation {
/**
* 开始的大小
*/
private int mFromSize;
/**
* 结束的大小
*/
private int mToSize;
/**
* 开始的Alpha
*/
private float mFromAlpha;
/**
* 结束的Alpha
*/
private float mToAlpha;
/**
* 构造方法
*
* @param fromSize 初始的大小
* @param toSize 结束的大小
* @param fromAlpha 初始的透明度
* @param toAlpha 结束的透明度
*/
public CollapsibleAnimation(int fromSize, int toSize, float fromAlpha, float toAlpha) {
mFromSize = fromSize;
mToSize = toSize;
mFromAlpha = fromAlpha;
mToAlpha = toAlpha;
}
@Override
public boolean willChangeBounds() {
return true;
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
if (mCollapsibleView != null) {
if (mWithoutAlphaAnim) {
// Do nothing
} else {
// 改变透明度
final float alpha = mFromAlpha;
t.setAlpha(alpha + ((mToAlpha - alpha) * interpolatedTime));
}
// 改变大小
final int fromSize = mFromSize;
int size = (int) (fromSize + (mToSize - fromSize) * interpolatedTime);
setCollapsibleViewSize(size);
if (null != mCollapsibleListener) {
mCollapsibleListener.applyTransformation(mFromSize, mToSize, interpolatedTime);
}
}
}
}
}
Android开发之仿微信显示更多文字的View相关推荐
- Android编程之仿微信显示更多文字的View
微信朋友圈中,如果好友发表的文字过长,会自动收缩起来,底下有提示,当点击"显示更多"时才会展开. 首先定义布局文件(很简单,不解释): <?xml version=" ...
- android 微信朋友圈 全功能,Android仿微信朋友圈文字展开全文功能 Android自定义TextView仿微信朋友圈文字展开全文功能...
Android自定义TextView仿微信朋友圈文字信息,展开全文功能 代码及注释如下: 首先写一个xml文件 showmore.xml: android:orientation="vert ...
- android 微信朋友圈 全功能,Android自定义TextView仿微信朋友圈文字展开全文功能
Android自定义TextView仿微信朋友圈文字信息,展开全文功能 代码及注释如下: 首先写一个xml文件 showmore.xml: android:orientation="vert ...
- Android开发之仿微信底部导航切换(Compose版本)附加源码下载
老套路,先上(献上)效果图 实际上这个页面在Android开发中太常见了.所以学些了下Compose版本 说下核心: 1.需要记录每次切换的页面position var currentNavigati ...
- android开发百度地图坐标偏差,利用百度地图Android sdk高仿微信发送位置功能及遇到的问题...
接触了百度地图开发平台半个月了,这2天试着模仿了微信给好友发送位置功能,对百度地图的操作能力又上了一个台阶 我在实现这个功能的时候,遇到一些困难,可能也是别人将会遇到的困难,特在此列出 1.在微信发送 ...
- android仿微信图片上传进度,Android开发之模仿微信打开网页的进度条效果(高仿)...
一,为什么说是真正的高仿? 阐述这个问题前,先说下之前网上的,各位可以复制这段字,去百度一下 "仿微信打开网页的进度条效果",你会看到有很多类似的文章,不过他们有个共同点,就是实 ...
- android仿微信 进度条,Android开发之模仿微信打开网页的进度条效果(高仿)
一,为什么说是真正的高仿? 阐述这个问题前,先说下之前网上的,各位可以复制这段字,去百度一下 "仿微信打开网页的进度条效果" ,你会看到有很多类似的文章,不过他们有个共同点,就是 ...
- Android 仿微信显示的聊天照片
Android 仿微信显示的聊天照片 Android 仿微信显示的聊天照片,效果如下图所示: 这种显示的样式就是和微信的显示照片的样式是一样的,微信的实现我不知道是否和我一样,今天我来和大家介绍一下我 ...
- 自定义控件 仿微信朋友圈文字展开全文功能
自定义TextView仿微信朋友圈文字信息,展开全文功能 代码及注释如下: 首先写一个xml文件 showmore.xml: <?xml version="1.0" enco ...
最新文章
- Python 爬虫练手项目—酒店信息爬取
- java中static作用详解
- PHP中空格占位数吗,HTML空格占位
- 把激光雷达放在iPad上是怎样的体验?看到“测距仪”App的效果我震惊了
- iOS流媒体直播整个框架介绍(HLS、RTSP)
- (JAVA学习笔记) static关键字详解
- 工程制图 ( 标准件与常用件)
- ionic移动开发流程api
- C#使用七牛云存储上传下载文件、自定义回调
- 2019 年总结 | 31岁,不过是另一个开始
- nginx+kibana代理以及简单认证
- Java中的基本类型和引用类型(未完)
- 10A 的GROUP和CUI使用
- java 获取上传文件后缀_java 文件上传相关知识及得到后缀名
- 最新kali之arping
- 别细看|请收藏|堆垛机故障大全及解决办法
- Java 1072 开学寄语
- 《python3网络爬虫开发实战》学习笔记:pc与安卓代理证书都安装好但是无法监听——记自己的踩坑路径
- jQuery中index的用法
- 请注意:黑客开始用云隐藏IP地址
热门文章
- MATLAB实现的彩色数字水印算法
- 织梦的网站地图怎么做html,织梦(dedecms)网站地图改变生成目录的方法
- serv服务器怎么设置欢迎消息,serv-u登陆欢迎信息参数设置技巧_其他工具教程
- 关于selenium自动化测试退出登录网易163邮箱的总结感想
- 企业直播营销的商业价值是什么?
- c语言程序设计工资纳税系统,c语言程序设计,纳税工资系统(29页)-原创力文档...
- vsco怎么两个滤镜叠加_别再乱套滤镜了!这4款VSCO滤镜好看到哭!
- MAC 开机自动连接iPad
- ViTag :在线 WiFi 精细时间测量辅助多人环境中的视觉-运动身份关联
- NGUI制作头顶血条个人小问题解决方法