首页 > 系统 > Android > 正文

Android开发之仿微信显示更多文字的View

2019-11-09 17:53:34
字体:
来源:转载
供稿:网友
    最近开发需求中要模仿微信朋友圈文章的展开收起功能,网上找了找,发现都有问题,于是乎自己在前辈的基础上进行了一定量的修改,下边将源码贴出来供大家参考: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);                }            }        }    }}
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表