自定义View学习的小记录之第二篇

  • 自定义View学习之玩转字体变色
    • 如何实现
      • 1.分析想要得到什么效果
      • 2.确定自定义属性,编写attrs.xml
      • 3.定义布局
      • 4.在自定义View中获取自定义属性
      • 5.onDraw()方法
      • 6.设置进度、颜色、方向
    • 如何使用
    • 每日一道面试题

自定义View学习之玩转字体变色

如何实现

1.分析想要得到什么效果

首先我们需要需要实现字体颜色的变化,然后再考虑把它用到相应的控件中去。字体颜色的变化要怎么做呢,如果只是简单的把HelloWorld变成红色是很简单的,开始用黑色画笔画,后面用红色画笔画就好了。那么如果是只画一半,比如我原来的字为黑色,我现在想让Hello变成红色,World仍然为黑色,该怎么做呢?这就要用到裁剪了,通过裁剪Hello区域,在第二次画的时候只画这个区域就好了。这个时候我们就能想到如果我们要裁剪的区域首先是H然后是He以此类推,是不是不断变换裁剪区域就好了。
其次我们还要考虑滑动的方向,是自左向右还是自右向左,方向的变化也决定了子的颜色首先是哪边开始改变。
最后就是把自定义的View用到相应的位置。

2.确定自定义属性,编写attrs.xml

首先我们分析下需要哪些自定义属性:
由于我们是继承TextView,像字体大小这种属性都是本身就有的,我们只要改变画笔的颜色就好了。

  1. 开始的颜色
  2. 改变后的颜色
<?xml version="1.0" encoding="utf-8"?>
<resources><declare-styleable name="ColorTrackTextView"><attr name="originColor" format="color"/><attr name="changeColor" format="color"/></declare-styleable>
</resources>

3.定义布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"android:orientation="vertical">//显示栏<LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:paddingTop="10dp"android:paddingBottom="10dp"android:id="@+id/indicator_view"/><androidx.viewpager.widget.ViewPagerandroid:layout_width="match_parent"android:layout_height="0dp"android:id="@+id/view_pager"android:layout_weight="1"/>
</LinearLayout>

4.在自定义View中获取自定义属性

      TypedArray array=context.obtainStyledAttributes(attrs,R.styleable.ColorTrackTextView);int originColor=array.getColor(R.styleable.ColorTrackTextView_originColor,getTextColors().getDefaultColor());int changeColor=array.getColor(R.styleable.ColorTrackTextView_changeColor,getTextColors().getDefaultColor());mOriginPaint=getPaintByColor(originColor);mChangePaint=getPaintByColor(changeColor);array.recycle();

5.onDraw()方法

这里不要重写onMeasure()方法了,因为我们是继承TextView的。

@Overrideprotected void onDraw(Canvas canvas) {//super.onDraw(canvas); 不能用这个啦,不然调用这个就掉入TextView也就是它父亲的手里了//根据进度获得要改变的区域int middle=(int)(mCurrentProgress*getWidth());if(mDirection==Direction.LEFT_TO_RIGHT){//左边是红色右边是黑色drawText(canvas,mChangePaint,0,middle);drawText(canvas,mOriginPaint,middle,getWidth());}else{//右边是红色左边是黑色drawText(canvas,mChangePaint,getWidth()-middle,getWidth());drawText(canvas,mOriginPaint,0,getWidth()-middle);}}//为了降低代码冗余度,封装成方法private void drawText(Canvas canvas, Paint paint, int start, int end) {canvas.save();//canvas.clipRect();  裁剪区域Rect rect=new Rect(start,0,end,getHeight());canvas.clipRect(rect);//始终要自己找到文本框的位置,要自己来画String text=getText().toString();Rect bounds=new Rect();paint.getTextBounds(text,0,text.length(),bounds);//获取字体的位置int x=getWidth()/2-bounds.width()/2;//找基线Paint.FontMetricsInt fontMetrics=paint.getFontMetricsInt();int dy=(fontMetrics.bottom-fontMetrics.top)/2-fontMetrics.bottom;int baseLine=dy+getHeight()/2;canvas.drawText(text,x,baseLine,paint);canvas.restore();}

6.设置进度、颜色、方向

由于这都是开发者的个人爱好,肯定是用这个的人来定义这些,所以我们把它封装成相应方法,使用者通过调用相应的方法来完成自己的喜好选择。

     //设置进度public  void setCurrentProgress(float currentProgress){this.mCurrentProgress=currentProgress;invalidate();}//设置方向public  void setDirection(Direction direction){this.mDirection=direction;}//设置改变的字体颜色public  void setChangeColor(int changeColor){this.mChangePaint.setColor(changeColor);}

如何使用

MainActivity,java:

package com.example.view_study2;import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.viewpager.widget.ViewPager;import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.ViewGroup;
import android.widget.LinearLayout;import java.util.ArrayList;
import java.util.List;public class MainActivity extends AppCompatActivity {private  String[] items={"直播","推荐","视频","图片","段子","精华"};private LinearLayout mIndicatorContainer;private List<ColorTrackTextView> mIndicators;private ViewPager mViewPager;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mIndicators = new ArrayList<>();mIndicatorContainer = (LinearLayout) findViewById(R.id.indicator_view);mViewPager = (ViewPager) findViewById(R.id.view_pager);initIndicator();initViewPager();}/*** 初始化可变色的指示器*/private void initIndicator() {for(int i=0;i<items.length;i++){//动态添加颜色跟踪的TextViewLinearLayout.LayoutParams params=new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);params.weight=1;ColorTrackTextView colorTrackTextView=new ColorTrackTextView(this);// 设置颜色colorTrackTextView.setTextSize(20);colorTrackTextView.setChangeColor(Color.RED);colorTrackTextView.setText(items[i]);colorTrackTextView.setLayoutParams(params);// 把新的加入LinearLayout容器mIndicatorContainer.addView(colorTrackTextView);//加入集合mIndicators.add(colorTrackTextView);}}/*** 初始化viewPager*/private void initViewPager() {mViewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {@Overridepublic Fragment getItem(int position) {return ItemFragment.newInstance(items[position]);}@Overridepublic int getCount() {return items.length;}@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {}});mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {@Overridepublic void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {//让mIndicators使用ColorTrackViewLog.v("position->"+position,"positionOffset->"+positionOffset);ColorTrackTextView left=mIndicators.get(position);left.setDirection(ColorTrackTextView.Direction.RIGHT_TO_LEFT);left.setCurrentProgress(1-positionOffset);try{ColorTrackTextView right=mIndicators.get(position+1);right.setDirection(ColorTrackTextView.Direction.LEFT_TO_RIGHT);right.setCurrentProgress(positionOffset);}catch (Exception e){}}@Overridepublic void onPageSelected(int position) {}@Overridepublic void onPageScrollStateChanged(int state) {}});}
}

Item_Fragment.java:

package com.example.view_study2;import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;public class ItemFragment extends Fragment {public static ItemFragment newInstance(String item) {Bundle bundle = new Bundle();ItemFragment fragment = new ItemFragment();bundle.putString("title",item);fragment.setArguments(bundle);return fragment;}@Nullable@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {View view=inflater.inflate(R.layout.fragment_item,null);TextView tv=(TextView)view.findViewById(R.id.text);Bundle bundle=getArguments();tv.setText(bundle.getString("title"));return view;}
}

每日一道面试题

1.为什么UI更新要放在主线程中而不是子线程?
更新UI 一般会调用setText() setImageView() 调回调到这里面来 ViewRootImpl checkThread()方法
checkThread() 用来检测线程

if (mThread != Thread.currentThread()) {        throw new CalledFromWrongThreadException(              "Only the original thread that created a view hierarchy can touch its views.");}

而这里mThread可以理解为主线程,Thread.currentThread()为当前线程,很明显如果在子线程中他们就不会相等就会抛出异常。

自定义View学习之玩转字体变色相关推荐

  1. 自定义View学习之仿QQ运动步数进度效果

    自定义View学习的小记录之第一篇 自定义View学习之QQ计步器 如何实现 1.分析想要得到什么效果 2.确定自定义属性,编写attrs.xml 3.在布局中使用 4.在自定义View中获取自定义属 ...

  2. android自定义View学习(一)----创建一个视图类

    创建一个视图类 精心设计的自定义视图与其他精心设计的类非常相似.它使用易于使用的界面封装了一组特定的功能,它可以高效地使用CPU和内存,等等.不过,作为一个设计良好的班级,自定义视图应该: 符合And ...

  3. Android 自定义控件玩转字体变色 打造炫酷ViewPager指示器

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 转载请标 ...

  4. 自定义view学习-手把手教你制作一个可扩展日历控件

    来看看效果图先,手把手教你实现一个简易,但高扩展度的日历控件,可自由扩展成签到,单选,多选日期. 首先我们来分析实现思路.对于上图的效果,很明显是一个6x7的表格. 我们可以两个for循环控制绘制每个 ...

  5. 自定义view学习-创建自己的九宫格解锁view

    先上效果图 效果如上,接下来是如何实现,并没有那么快上代码,不看代码不舒服的请迅速下翻. 九宫格解锁还是比较经典的,作为学习自定义view的入门. 对于九宫格解锁,我的实现思路是这样的: 1.先在屏幕 ...

  6. Android 自定义控件玩转字体变色 打造炫酷ViewPager指示器

    转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/44098729,本文出自: [张鸿洋的博客] 1.概述 本篇博客的产生呢,是因为 ...

  7. 自定义View学习篇之绘制一个圆环动画

    前言 我们都知道,现实生活中画一幅画需要笔和纸,另外还需要各式各样的绘画技巧,那么同样的自定义view也需要这些.正好Android也给我们提供了这两样东西:Paint和Canvas,一个是画笔而另一 ...

  8. Android自定义View 学习整理

    Paint类:画笔 Canvas类:画布,画出成品:与屏幕显示不是一个概念,相当于一个透明图层 ARGB 不在onDraw()中创建变量:因为当需要重绘时就会调用onDraw(),创建的变量会一直被重 ...

  9. android自定义View学习(二)----自定义绘图

    自定义绘图 自定义视图中最重要的部分是它的外观.根据您的应用需求,自定义绘图可以很容易或复杂.本篇涵盖了一些最常见的操作 onDraw() 绘制自定义视图中最重要的步骤是重写该onDraw()方法.参 ...

  10. 自定义View学习——九宫格解锁(LockPatternView)

    虽然现在的应用很少在使用九宫格解锁,不过系统的应用锁还是可以见到的.实现的效果如下: 分析 首先需要绘制出九宫格,每一个单元格有两个半径不同的同心圆. 当我们的手指在九宫格上触摸时,如果我们触摸在某个 ...

最新文章

  1. 利用stub技术进行单元测试
  2. mongo忘记密码并删除用户
  3. 信息系统项目管理知识--项目整合管理
  4. Spring Boot整合Spring Data Redis-整合步骤
  5. oracle 中时间类型 date 与 long 互转
  6. 修改Linux主机名
  7. 贪心 or 动态规划 求解“最大字段和”问题(洛谷P1115题题解,Java语言描述)
  8. Goalng笔记——排序和查找
  9. c++ break跳出几个循环_必须知道的C语言知识细节:break、continue语句区别
  10. 比较JSF、Spring MVC、Stripes、Struts 2、Tapestry、Wicket
  11. Python3爬取淘宝网商品数据
  12. WebRTC桌面共享手动停止
  13. 如何提高计算机打字,如何练电脑打字速度,教你如何科学提高打字速度
  14. 整理了 47 个 Python 人工智能库
  15. Android学习计划[转载Sammy_Snail]
  16. html字体打印效果,基于jQuery实现文字打印动态效果
  17. java-IO流-搜索含java字符的文件问题
  18. unity 关于搜索
  19. 将自己电脑做成服务器让别人访问(不是局域网)
  20. Another Day 超好听的BGM

热门文章

  1. 系统运维工程师都要会什么?
  2. 分形--朱利亚集合图形1
  3. EcmaScript 2022中的新特性
  4. 7-2 求交错序列前N项和 (10 分)
  5. matlab柱状图设置条纹,matlab代码画条纹柱状图
  6. 微信小程序全栈开发实践 第一章 重新认识微信小程序、及新功能介绍
  7. 双IP双线路实现方式 先来说说双线单IP和双线双IP的区别
  8. 程序员工资到底有多高?国内哪个城市挣得最多?有没有你在的城市
  9. 凯撒加密的python语言程序_python语言编程实现凯撒密码、凯撒加解密算法、
  10. C语言程序设计——计算图形面积(圆形,矩形,三角形,梯形)