【ANDROID自定义控件】可扩展的TextView,ExpandableTextView与Scroller类的使用

简介:
package com.sahadev.sildingfinishlayout;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.Scroller;
import android.widget.TextView;

public class ExpandableTextView extends RelativeLayout {
        private TextView mTextView;
        private Button mButton;
        private int mTextViewId = 567576458;// 这里注意不要随便填一个简单的数字,可能会和R中的ID冲突造成无效
        private Scroller mScroller;
        private int mHeight, mWidthMeasureSpec, mButtonHeight, paddingSize = 1;
        private boolean isExpanded, WSettedFlag, HSettedFlag, onceFlag;
        private int times = 2;// 缩小的倍数,默认2倍

        public ExpandableTextView(Context context) {
                this(context, null);
        }

        public ExpandableTextView(Context context, AttributeSet attrs) {
                this(context, attrs, 0);
        }

        public ExpandableTextView(Context context, AttributeSet attrs, int defStyle) {
                super(context, attrs, defStyle);
                mTextView = new TextView(context);
                mTextView.setId(mTextViewId);

                mButton = new Button(context);
                mButton.setText("扩    展");
                mScroller = new Scroller(context);

                LayoutParams lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);

                lp.addRule(RelativeLayout.BELOW, mTextViewId);
                lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT, TRUE);
                lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, TRUE);

                mButton.setOnClickListener(new OnClickListener() {

                        @Override
                        public void onClick(View v) {
                                if (!isExpanded) {
                                        // 展开来
                                        mScroller.startScroll(0, mHeight / times, 0, mHeight / times);
                                        postInvalidate();
                                        isExpanded = true;
                                } else {
                                        // 收回去
                                        mScroller.startScroll(0, mHeight, 0, -mHeight / times);
                                        postInvalidate();
                                        isExpanded = false;
                                }
                        }
                });

                addView(mTextView);
                addView(mButton, lp);

        }

        @Override
        public void computeScroll() {
                super.computeScroll();
                if (mScroller.computeScrollOffset()) {

                        mTextView.setHeight(mScroller.getCurrY());
                        postInvalidate();
                        return;
                }
        }

        public void setTimes(int times) {
                if (times == 0) {
                        throw new ArithmeticException("倍数不能为0");
                }
                this.times = times;
        }

        public void setTextViewPadding(int pixels) {
                mTextView.setPadding(pixels, pixels, pixels, 0);
                paddingSize = pixels;
        }

        public void setButtonTips(CharSequence text) {
                mButton.setText(text);
        }

        public void setText(CharSequence text) {
                mTextView.setText(text);
        }

        public void setTextColor(int color) {
                mTextView.setTextColor(color);
        }

        public void setTextSize(float size) {
                mTextView.setTextSize(size);
        }

        public void setBackgroundColor(int color) {
                mTextView.setBackgroundColor(color);
        }

        public void setWidth(int width) {
                mWidthMeasureSpec = width;
                mTextView.setWidth(width - paddingSize * 2);
                WSettedFlag = true;
        }

        public void setHeight(int height) {
                mHeight = (height - mButtonHeight) * 2;
                HSettedFlag = true;
        }

        /* onMeasure方法在重绘的时候会一直被调用 */
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
                super.onMeasure(widthMeasureSpec, heightMeasureSpec);

                /* 此步骤只用执行一次,获取到textView的宽度以及Button的高度以及一些初始化的值 */
                if (!WSettedFlag) {
                        WSettedFlag = true;
                        mWidthMeasureSpec = mTextView.getMeasuredWidth();
                }

                if (!HSettedFlag) {
                        HSettedFlag = true;
                        mHeight = mTextView.getMeasuredHeight();
                        OtherTools.showLog("mHeight----" + mHeight);
                }

                if (!onceFlag) {
                        onceFlag = true;
                        mButtonHeight = mButton.getMeasuredHeight();
                        OtherTools.showLog("mButtonHeight----" + mButtonHeight);
                        // mTextView.setHeight(mHeight / times + mButtonHeight >
                        // heightMeasureSpec ? heightMeasureSpec - mButtonHeight : mHeight /
                        // times);
                        mTextView.setHeight(mHeight / times);
                }
                // int tempHeight = mHeight / 2 + mButtonHeight;
                // tempHeight = tempHeight > heightMeasureSpec ? heightMeasureSpec :
                // tempHeight;
                setMeasuredDimension(mWidthMeasureSpec, mButtonHeight + mTextView.getMeasuredHeight());
        }
}

目录
相关文章
|
3月前
|
缓存 搜索推荐 Android开发
安卓开发中的自定义控件实践
【10月更文挑战第4天】在安卓开发的海洋中,自定义控件是那片璀璨的星辰。它不仅让应用界面设计变得丰富多彩,还提升了用户体验。本文将带你探索自定义控件的核心概念、实现过程以及优化技巧,让你的应用在众多竞争者中脱颖而出。
|
1月前
|
搜索推荐 Android开发 开发者
安卓应用开发中的自定义控件实践
在安卓应用开发的广阔天地中,自定义控件如同璀璨的星辰,点亮了用户界面设计的夜空。它们不仅丰富了交互体验,更赋予了应用独特的个性。本文将带你领略自定义控件的魅力,从基础概念到实际应用,一步步揭示其背后的原理与技术细节。我们将通过一个简单的例子——打造一个具有独特动画效果的按钮,来展现自定义控件的强大功能和灵活性。无论你是初学者还是资深开发者,这篇文章都将为你打开一扇通往更高阶UI设计的大门。
|
3月前
|
缓存 搜索推荐 Android开发
安卓开发中的自定义控件基础与进阶
【10月更文挑战第5天】在Android应用开发中,自定义控件是提升用户体验和界面个性化的重要手段。本文将通过浅显易懂的语言和实例,引导你了解自定义控件的基本概念、创建流程以及高级应用技巧,帮助你在开发过程中更好地掌握自定义控件的使用和优化。
65 10
|
2月前
|
前端开发 Android开发 UED
安卓应用开发中的自定义控件实践
【10月更文挑战第35天】在移动应用开发中,自定义控件是提升用户体验、增强界面表现力的重要手段。本文将通过一个安卓自定义控件的创建过程,展示如何从零开始构建一个具有交互功能的自定义视图。我们将探索关键概念和步骤,包括继承View类、处理测量与布局、绘制以及事件处理。最终,我们将实现一个简单的圆形进度条,并分析其性能优化。
|
3月前
|
JSON 调度 数据库
Android面试之5个Kotlin深度面试题:协程、密封类和高阶函数
本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点。文章详细解析了Kotlin中的协程、扩展函数、高阶函数、密封类及`inline`和`reified`关键字在Android开发中的应用,帮助读者更好地理解和使用这些特性。
48 1
|
3月前
|
前端开发 搜索推荐 Android开发
安卓开发中的自定义控件实践
【10月更文挑战第4天】在安卓开发的世界里,自定义控件如同画家的画笔,能够绘制出独一无二的界面。通过掌握自定义控件的绘制技巧,开发者可以突破系统提供的界面元素限制,创造出既符合品牌形象又提供卓越用户体验的应用。本文将引导你了解自定义控件的核心概念,并通过一个简单的例子展示如何实现一个基本的自定义控件,让你的安卓应用在视觉和交互上与众不同。
|
2月前
|
前端开发 Java 测试技术
android MVP契约类架构模式与MVVM架构模式,哪种架构模式更好?
android MVP契约类架构模式与MVVM架构模式,哪种架构模式更好?
92 0
|
3月前
|
XML 存储 Java
浅谈Android的TextView控件
浅谈Android的TextView控件
50 0
|
安全 Java Android开发
【Android 逆向】类加载器 ClassLoader ( Android 的八种类加载器 | ClassLoader | BaseDexClassLoader | DexClassLoader )
【Android 逆向】类加载器 ClassLoader ( Android 的八种类加载器 | ClassLoader | BaseDexClassLoader | DexClassLoader )
248 0
【Android 逆向】类加载器 ClassLoader ( Android 的八种类加载器 | ClassLoader | BaseDexClassLoader | DexClassLoader )
|
Java Android开发
【Android 逆向】类加载器 ClassLoader ( 类加载时机 | 隐式加载 | 显示加载 | 类加载步骤 | 装载 | 链接 | 初始化 )
【Android 逆向】类加载器 ClassLoader ( 类加载时机 | 隐式加载 | 显示加载 | 类加载步骤 | 装载 | 链接 | 初始化 )
206 0
【Android 逆向】类加载器 ClassLoader ( 类加载时机 | 隐式加载 | 显示加载 | 类加载步骤 | 装载 | 链接 | 初始化 )