Android 自定義控件TextView點擊顯示更多

前言

公司的項目中用到了一個TextView 的點擊加載更多,這個時候一般的Textview滿足不了這個要求了就需要我們自定義TextView,今天也在這個地方總結和寫一下自定義的TextView點擊顯示更多。

名言
想而奮進的過程,其意義遠大於未知的結果。


我們這裏就先來看看效果圖吧。

這裏寫圖片描述

接下來我們來看看是怎麼實現的,全部代碼會在文章底部給出。


第一步:繼承了LinearLayout重寫了3個構造函數

public class MyTextview extends LinearLayout {

    public MyTextview(Context context) {
        super(context);
    }

    public MyTextview(Context context, AttributeSet attrs) {
        super(context, attrs);  
    }

    public MyTextview(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
}

第二步:寫出我們需要的自定義控件

public void initView() {
        setOrientation(VERTICAL);
        setGravity(Gravity.RIGHT);
        int padding = dip2px(getContext(), 10);
        textView = new TextView(getContext());
        //行間距
        textView.setLineSpacing(3f, 1f);
        addView(textView, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        img = new ImageView(getContext());
        img.setPadding(padding, padding, padding, padding);
        //imageview設置圖片
        img.setImageResource(R.mipmap.textimg);
        LayoutParams llp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        addView(img, llp);
    }

第三步:自定義控件的屬性
在res—>values—>創建attrs.xml
如圖
這裏寫圖片描述

然後在attrs文件中寫上我們的自定義屬性
textSize字體大小
textColor字體顏色
maxLine最大行數
text文字

<resources>
    <declare-styleable name="MyTextStyle">
        <attr name="textSize" format="dimension" />
        <attr name="textColor" format="color" />
        <attr name="maxLine" format="integer" />
        <attr name="text" format="string" />
    </declare-styleable>
</resources>

第四步:在自定義view的代碼中引入自定義屬性,修改構造函數

public void initAttrs(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyTextStyle);
        textColor = typedArray.getColor(R.styleable.MyTextStyle_textColor, defaultTextColor);
        textSize = typedArray.getDimensionPixelSize(R.styleable.MyTextStyle_textSize, defaultTextSize);
        maxLine = typedArray.getInt(R.styleable.MyTextStyle_maxLine, defaultLine);
        text = typedArray.getString(R.styleable.MyTextStyle_text);
        setMyView(textColor, textSize, maxLine, text);
        //用完 回收一下
        typedArray.recycle();
    }

這個地方context通過調用obtainStyledAttributes方法來獲取一個TypeArray,然後由該TypeArray來對屬性進行設置。設置完以後必須要回收一下typedArray.recycle();


第五步:自定義的屬性引入進來了我們就要設置在我們TextView上面啊。

protected void setMyView(int color, float size, final int line, String text) {
        //文本設置顏色
        textView.setTextColor(color);
        //字體大小
        textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);
        //設置文字
        textView.setText(text);
        //設置TextView的高度
        textView.setHeight(textView.getLineHeight() * line);
        //線程更新UI
        post(new Runnable() {
            @Override
            public void run() {
                if (textView.getLineCount() > line) {
                    img.setVisibility(VISIBLE);
                } else {
                    img.setVisibility(GONE);
                }
            }
        });
    }

看看這一段

textView.getLineHeight()* line

獲取textview每一行的高度*有多少行,就是我們TextView的高度

   public void run() {
         if (textView.getLineCount() > line) {
              img.setVisibility(VISIBLE);
            } else {
              img.setVisibility(GONE);
             }
      }

這個地方需要在線程中來更新UI,假如textView.getLineCount()(textview的總的行數大於了初始行數)圖片就顯示出來,反之不顯示。


第六步:監聽

protected void textListener() {
        setOnClickListener(new OnClickListener() {
            boolean isGo;

            @Override
            public void onClick(View v) {
                isGo = !isGo;
                textView.clearAnimation();
                //相差的高度
                final int deltaValue;
                //初始的高度
                final int startValue = textView.getHeight();
                //動畫播放的時間
                int duration = 1000;
                if (isGo) {
                    //Image圖片打開的動畫
                    deltaValue = textView.getLineHeight() * textView.getLineCount() - startValue;
                    RotateAnimation animation = new RotateAnimation(0, 180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
                    animation.setDuration(duration);
                    animation.setFillAfter(true);
                    img.startAnimation(animation);
                } else {
                    //Image圖片關閉的動畫
                    deltaValue = textView.getLineHeight() * maxLine - startValue;
                    RotateAnimation animation = new RotateAnimation(180, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
                    animation.setDuration(duration);
                    animation.setFillAfter(true);
                    img.startAnimation(animation);
                }
                //打開或者關閉的時候textview下面的展開動畫
                Animation animation = new Animation() {
                    protected void applyTransformation(float interpolatedTime, Transformation t) {
                        textView.setHeight((int) (startValue + deltaValue * interpolatedTime));
                    }
                };
                //這裏給這個設置了一個回彈效果
                animation.setInterpolator(new BounceInterpolator());
                animation.setDuration(duration);
                textView.startAnimation(animation);
            }
        });
    }

第七步:把設置文字暴露外部

public void setText(CharSequence charSequence) {
        textView.setText(charSequence);
    }

這裏就差不多就完成了,然後我們再來看看xml文件中

  <com.example.beiduo.testmytext.MyTextview
  xmlns:more="http://schemas.android.com/apk/res-auto"
        android:background="#ffdfdf"
        android:id="@+id/tv"
        android:padding="5dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        more:maxLine="2"
        more:text=""
        more:textColor="#434343"
        more:textSize="20sp"></com.example.beiduo.testmytext.MyTextview>
 xmlns:more="http://schemas.android.com/apk/res-auto"這句話是相當重要的,沒有這句話你是用不起你自己自定義的屬性的more可以隨你自己改,想改什麼改什麼。
more:maxLine="2"    maxline是初始的最大行數

MainActivity中

public class MainActivity extends AppCompatActivity {

    private MyTextview myTextview = null;

    private String str = "曾經有一份真誠的愛情放在我面前,我沒有珍惜,等我失去的時候我才後悔莫及,人世間最痛苦的事莫過於此。 \n" +
            "如果上天能夠給我一個再來一次的機會,我會對那個女孩子說三個字:我愛你。 \n" +
            "如果非要在這份愛上加上一個期限,我希望是…… \n" +
            "一萬年";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myTextview = (MyTextview) findViewById(R.id.tv);
        myTextview.setText(str);
    }
}

這樣就搞定了。
然後我給出自定義控件的所有代碼

public class MyTextview extends LinearLayout {
    private TextView textView = null;
    private ImageView img = null;

    //字體顏色
    protected int textColor;
    //字體大小
    protected float textSize;
    //最大行數
    protected int maxLine;
    //文字
    protected String text;

    //默認顏色
    public int defaultTextColor = Color.BLACK;
    //默認字體大小
    public int defaultTextSize = 14;
    //默認行數
    public int defaultLine = 2;


    public MyTextview(Context context) {
        super(context);
        initView();
    }

    public MyTextview(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView();
        initAttrs(context, attrs);
        textListener();
    }

    public MyTextview(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView();
        initAttrs(context, attrs);
        textListener();
    }

    public void initAttrs(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyTextStyle);
        textColor = typedArray.getColor(R.styleable.MyTextStyle_textColor, defaultTextColor);
        textSize = typedArray.getDimensionPixelSize(R.styleable.MyTextStyle_textSize, defaultTextSize);
        maxLine = typedArray.getInt(R.styleable.MyTextStyle_maxLine, defaultLine);
        text = typedArray.getString(R.styleable.MyTextStyle_text);
        setMyView(textColor, textSize, maxLine, text);
        //用完 回收一下
        typedArray.recycle();
    }

    public void initView() {
        setOrientation(VERTICAL);
        setGravity(Gravity.RIGHT);
        int padding = dip2px(getContext(), 10);
        textView = new TextView(getContext());
        //行間距
        textView.setLineSpacing(3f, 1f);
        addView(textView, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        img = new ImageView(getContext());
        img.setPadding(padding, padding, padding, padding);
        //imageview設置圖片
        img.setImageResource(R.mipmap.textimg);
        LayoutParams llp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        addView(img, llp);
    }


    protected void setMyView(int color, float size, final int line, String text) {
        //文本設置顏色
        textView.setTextColor(color);
        //字體大小
        textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);
        //設置文字
        textView.setText(text);
        //設置TextView的高度
        textView.setHeight(textView.getLineHeight() * line);

        //線程更新UI
        post(new Runnable() {
            @Override
            public void run() {
                if (textView.getLineCount() > line) {
                    img.setVisibility(VISIBLE);
                } else {
                    img.setVisibility(GONE);
                }
            }
        });
    }


    protected void textListener() {
        setOnClickListener(new OnClickListener() {
            boolean isGo;

            @Override
            public void onClick(View v) {
                isGo = !isGo;
                textView.clearAnimation();
                //相差的高度
                final int deltaValue;
                //初始的高度
                final int startValue = textView.getHeight();
                //動畫播放的時間
                int duration = 1000;
                if (isGo) {
                    //Image圖片打開的動畫
                    deltaValue = textView.getLineHeight() * textView.getLineCount() - startValue;
                    RotateAnimation animation = new RotateAnimation(0, 180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
                    animation.setDuration(duration);
                    animation.setFillAfter(true);
                    img.startAnimation(animation);
                } else {
                    //Image圖片關閉的動畫
                    deltaValue = textView.getLineHeight() * maxLine - startValue;
                    RotateAnimation animation = new RotateAnimation(180, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
                    animation.setDuration(duration);
                    animation.setFillAfter(true);
                    img.startAnimation(animation);
                }
                //打開或者關閉的時候textview下面的展開動畫
                Animation animation = new Animation() {
                    protected void applyTransformation(float interpolatedTime, Transformation t) {
                        textView.setHeight((int) (startValue + deltaValue * interpolatedTime));
                    }
                };
                animation.setInterpolator(new BounceInterpolator());
                animation.setDuration(duration);
                textView.startAnimation(animation);
            }
        });
    }


    public TextView getTextView() {
        return textView;
    }

    public void setText(CharSequence charSequence) {
        textView.setText(charSequence);
    }

    public static int dip2px(Context context, float dipValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dipValue * scale + 0.5f);
    }
}

謝謝~~~假若有說的不對的地方還望留言指正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章