├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── gradle.xml ├── misc.xml ├── modules.xml └── runConfigurations.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── drawn │ │ └── lltvcn │ │ └── com │ │ └── textdemo │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ ├── res.zip │ │ └── ttf │ │ │ ├── 01方正经黑简体.TTF │ │ │ ├── 02方正静蕾体.TTF │ │ │ ├── 03方正兰亭纤黑简体.ttf │ │ │ ├── 04汉仪铸字童年体.ttf │ │ │ ├── 05汉仪乐喵字体.ttf │ │ │ ├── 06汉仪良品线简5.0.ttf │ │ │ ├── 07兰亭特黑简.TTF │ │ │ ├── 08华康娃娃体W5.TTF │ │ │ ├── 09造字工房朗倩.ttf │ │ │ ├── 10新蒂下午茶体.ttf │ │ │ ├── 11迷你汉真广标.ttf │ │ │ ├── 12方正咆哮体.TTF │ │ │ ├── 13造字工房静黑.ttf │ │ │ ├── 14钱氏字体.ttf │ │ │ ├── 15华康海报体.ttf │ │ │ ├── 16Aa小鹿.ttf │ │ │ ├── 17腾祥麦黑简.ttf │ │ │ ├── 18汉仪乐体.ttf │ │ │ ├── 19华康翩翩体.ttf │ │ │ ├── 20张海山锐线体2.0.ttf │ │ │ └── 21新蒂黑板报底字体.ttf │ ├── java │ │ └── drawn │ │ │ └── lltvcn │ │ │ └── com │ │ │ ├── span │ │ │ ├── BaseSpan.java │ │ │ ├── ClipTxtSpan.java │ │ │ ├── LightSpan.java │ │ │ ├── LineColorSpan.java │ │ │ ├── LineImgSpan.java │ │ │ ├── OffsetTxtSpan.java │ │ │ ├── RandomBgSpan.java │ │ │ ├── ShaderShadowSpan.java │ │ │ ├── ShakeTxtSpan.java │ │ │ ├── SingleTxtBgSpan.java │ │ │ ├── SingleTxtRotateSpan.java │ │ │ ├── StokeTxtSpan.java │ │ │ └── TxtSpan.java │ │ │ ├── textdemo │ │ │ ├── CodeActivity.java │ │ │ ├── DemoActivity.java │ │ │ ├── EditActivity.java │ │ │ ├── ListActivity.java │ │ │ ├── MainActivity.java │ │ │ ├── MainApplication.java │ │ │ ├── ParamProvider.java │ │ │ ├── ParamProviderImpl.java │ │ │ ├── ReviewActivity.java │ │ │ ├── ReviewAniActivity.java │ │ │ ├── TxtShader2.java │ │ │ ├── TxtShader2Ext.java │ │ │ ├── controller │ │ │ │ ├── AddLayerViewController.java │ │ │ │ ├── EditParamViewController.java │ │ │ │ ├── EditTxtController.java │ │ │ │ └── SelectController.java │ │ │ └── data │ │ │ │ ├── BgData.java │ │ │ │ ├── FontData.java │ │ │ │ └── FontStyleData.java │ │ │ └── util │ │ │ ├── FileUtil.java │ │ │ ├── FontUtil.java │ │ │ ├── SUtil.java │ │ │ └── ZipUtil.java │ └── res │ │ ├── drawable-xhdpi │ │ ├── f.png │ │ ├── fore.png │ │ ├── jjj.9.png │ │ ├── line.png │ │ ├── line_bottom.png │ │ ├── paint.png │ │ ├── paint3.png │ │ ├── shader.png │ │ └── timg_4.jpg │ │ ├── layout │ │ ├── activity_demo.xml │ │ ├── activity_main.xml │ │ ├── item_array.xml │ │ ├── item_ck.xml │ │ ├── item_demo.xml │ │ ├── item_enum.xml │ │ ├── item_layer.xml │ │ ├── item_normal.xml │ │ ├── layout_add_layer.xml │ │ ├── layout_code.xml │ │ ├── layout_edit.xml │ │ ├── layout_edit_txt.xml │ │ ├── layout_edit_v2.xml │ │ ├── layout_general_layer.xml │ │ ├── layout_list.xml │ │ ├── layout_review.xml │ │ ├── layout_review_ani.xml │ │ └── layout_scroll.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── drawn │ └── lltvcn │ └── com │ └── textdemo │ └── ExampleUnitTest.java ├── build.gradle ├── freefont ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── lltvcn │ │ └── freefont │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── lltvcn │ │ │ └── freefont │ │ │ └── core │ │ │ ├── animation │ │ │ ├── A.java │ │ │ ├── Animation2IA.java │ │ │ ├── AnimationQueen.java │ │ │ ├── BaseAnimation.java │ │ │ ├── BaseAnimation2IA.java │ │ │ ├── ICanvasTransform.java │ │ │ ├── TA.java │ │ │ ├── TAnimation.java │ │ │ ├── TAnimationQueen.java │ │ │ └── TAnimationSet.java │ │ │ ├── annotation │ │ │ ├── Description.java │ │ │ ├── Font.java │ │ │ └── Img.java │ │ │ ├── data │ │ │ ├── AniData.java │ │ │ ├── BlurParam.java │ │ │ ├── ClipParam.java │ │ │ ├── DrawData.java │ │ │ ├── IDispatchDraw.java │ │ │ ├── IShaderData.java │ │ │ ├── IndexParam.java │ │ │ ├── LayerData.java │ │ │ ├── LineData.java │ │ │ ├── OffsetParam.java │ │ │ ├── ShadeRadiusParam.java │ │ │ ├── ShaderBitmapParam.java │ │ │ ├── ShaderLinearParam.java │ │ │ ├── ShaderParam.java │ │ │ ├── ShaderSweepParam.java │ │ │ ├── ShadowParam.java │ │ │ └── StokeParam.java │ │ │ ├── layer │ │ │ ├── BaseLayer.java │ │ │ ├── ClipDrawer.java │ │ │ ├── DrawDiapatcher.java │ │ │ ├── FontStyle.java │ │ │ ├── ILayer.java │ │ │ ├── ImgLayer.java │ │ │ ├── LayerDataFactory.java │ │ │ ├── LayerSpan.java │ │ │ ├── MultiLayer.java │ │ │ ├── OffsetDrawer.java │ │ │ ├── PaintHandler.java │ │ │ ├── SingleWarpSpan.java │ │ │ ├── SourceLoader.java │ │ │ └── TxtLayer.java │ │ │ ├── linedrawer │ │ │ ├── BackgroundDrawer.java │ │ │ ├── ForegroundDrawer.java │ │ │ ├── Gravity.java │ │ │ ├── LineDrawer.java │ │ │ ├── LineImgBackgroundDrawer.java │ │ │ ├── LineImgDrawer.java │ │ │ └── LineImgForegroundDrawer.java │ │ │ ├── util │ │ │ └── CU.java │ │ │ └── view │ │ │ ├── STextView.java │ │ │ ├── ShadeEditText.java │ │ │ └── ShadeTextView.java │ └── res │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── lltvcn │ └── freefont │ └── ExampleUnitTest.java ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── res └── res.gif └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | 47 | 48 | 49 | 50 | 1.8 51 | 52 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FreeText 2 | >Android 字体 文字 特效 动画效果库 3 | 4 | ## freefont库 功能简介: 5 | >1.该库是基于TextView中Spnned等接口扩展,实现的单个文字特效,整段文字的特效,并且拥有动画框架可实现单个文字以及段落文字的动画效果。

6 | >2.单个文字特效,整段特效,动画分别是三个框架,可以在框架的基础或思路上扩展各种特效。

7 | >3.不仅可以通过代码实现多种文字特效,并且支持把特效转化为持久化的数据,集成库的app只需要加载特效数据就可以显示特效。
8 | >4.文字特效兼容性比较好,基本不影响TextView其他功能,可以任意切换字体,字号,颜色,添加各种spnne
9 | 10 | ## Demo功能简介: 11 | >1.demo最强大的莫过于创建字体特效功能,通过创建界面,可以手动编辑出各种文字特效。(注:该功能还不够严谨,存在bug甚至崩溃,但不影响生成的特效数据正确性。)

12 | >2.demo集成了一部分示例文字特效,可以通过预览界面预览。

13 | >3.freeText库目前只通过代码实现了几种动画,可以通过预览动画节目观看效果。(注:时间问题库暂时还不支持数据驱动动画,需要的同学可以自行扩展)。

14 | 15 | ## 以下仅仅是示例,运用动画和特效框架可以得到任何你想要的效果 16 |  ![](https://github.com/lltvcn/FreeText/raw/master/res/res.gif) 17 | 18 | 19 | ## 集成说明 20 | >暂不支持jcenter,直接把freefont库作为model即可。
21 | >具体使用流程:
22 | >>步骤1:由于有些api不支持硬件加速,建议xml文件中要取消硬件加速,如果想用硬件加速,可以通过修改源码解决兼容性问题

23 | ``` 24 |      ``` android:layerType="software"/>```

25 | >>步骤2:代码中只需要调用STextView的setData方法设置特效数据,通过getTAnimation方法获取TAnimation来操作动画。

26 | >>注:如果想用代码驱动方式写特效,请参考STextView的实现
27 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "25.0.3" 6 | defaultConfig { 7 | applicationId "drawn.lltvcn.com.textdemo" 8 | minSdkVersion 15 9 | targetSdkVersion 25 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | 21 | dataBinding { 22 | enabled = true 23 | } 24 | 25 | } 26 | 27 | dependencies { 28 | compile fileTree(include: ['*.jar'], dir: 'libs') 29 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 30 | exclude group: 'com.android.support', module: 'support-annotations' 31 | }) 32 | compile 'com.android.support:appcompat-v7:25.3.1' 33 | testCompile 'junit:junit:4.12' 34 | compile 'com.android.support:support-v4:25.0.0' 35 | compile 'com.android.support:recyclerview-v7:25.0.0' 36 | compile 'com.google.code.gson:gson:2.8.2' 37 | compile project(':freefont') 38 | } 39 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/zhaolei/Documents/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/drawn/lltvcn/com/textdemo/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.textdemo; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("drawn.lltvcn.com.textdemo", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 33 | 34 | 35 | 38 | 39 | 40 | 43 | 44 | 45 | 48 | 49 | 50 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /app/src/main/assets/res.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lltvcn/FreeText/d8d6daa5bb6872017e04b7f72f3e54b239a16798/app/src/main/assets/res.zip -------------------------------------------------------------------------------- /app/src/main/assets/ttf/01方正经黑简体.TTF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lltvcn/FreeText/d8d6daa5bb6872017e04b7f72f3e54b239a16798/app/src/main/assets/ttf/01方正经黑简体.TTF -------------------------------------------------------------------------------- /app/src/main/assets/ttf/02方正静蕾体.TTF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lltvcn/FreeText/d8d6daa5bb6872017e04b7f72f3e54b239a16798/app/src/main/assets/ttf/02方正静蕾体.TTF -------------------------------------------------------------------------------- /app/src/main/assets/ttf/03方正兰亭纤黑简体.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lltvcn/FreeText/d8d6daa5bb6872017e04b7f72f3e54b239a16798/app/src/main/assets/ttf/03方正兰亭纤黑简体.ttf -------------------------------------------------------------------------------- /app/src/main/assets/ttf/04汉仪铸字童年体.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lltvcn/FreeText/d8d6daa5bb6872017e04b7f72f3e54b239a16798/app/src/main/assets/ttf/04汉仪铸字童年体.ttf -------------------------------------------------------------------------------- /app/src/main/assets/ttf/05汉仪乐喵字体.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lltvcn/FreeText/d8d6daa5bb6872017e04b7f72f3e54b239a16798/app/src/main/assets/ttf/05汉仪乐喵字体.ttf -------------------------------------------------------------------------------- /app/src/main/assets/ttf/06汉仪良品线简5.0.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lltvcn/FreeText/d8d6daa5bb6872017e04b7f72f3e54b239a16798/app/src/main/assets/ttf/06汉仪良品线简5.0.ttf -------------------------------------------------------------------------------- /app/src/main/assets/ttf/07兰亭特黑简.TTF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lltvcn/FreeText/d8d6daa5bb6872017e04b7f72f3e54b239a16798/app/src/main/assets/ttf/07兰亭特黑简.TTF -------------------------------------------------------------------------------- /app/src/main/assets/ttf/08华康娃娃体W5.TTF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lltvcn/FreeText/d8d6daa5bb6872017e04b7f72f3e54b239a16798/app/src/main/assets/ttf/08华康娃娃体W5.TTF -------------------------------------------------------------------------------- /app/src/main/assets/ttf/09造字工房朗倩.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lltvcn/FreeText/d8d6daa5bb6872017e04b7f72f3e54b239a16798/app/src/main/assets/ttf/09造字工房朗倩.ttf -------------------------------------------------------------------------------- /app/src/main/assets/ttf/10新蒂下午茶体.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lltvcn/FreeText/d8d6daa5bb6872017e04b7f72f3e54b239a16798/app/src/main/assets/ttf/10新蒂下午茶体.ttf -------------------------------------------------------------------------------- /app/src/main/assets/ttf/11迷你汉真广标.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lltvcn/FreeText/d8d6daa5bb6872017e04b7f72f3e54b239a16798/app/src/main/assets/ttf/11迷你汉真广标.ttf -------------------------------------------------------------------------------- /app/src/main/assets/ttf/12方正咆哮体.TTF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lltvcn/FreeText/d8d6daa5bb6872017e04b7f72f3e54b239a16798/app/src/main/assets/ttf/12方正咆哮体.TTF -------------------------------------------------------------------------------- /app/src/main/assets/ttf/13造字工房静黑.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lltvcn/FreeText/d8d6daa5bb6872017e04b7f72f3e54b239a16798/app/src/main/assets/ttf/13造字工房静黑.ttf -------------------------------------------------------------------------------- /app/src/main/assets/ttf/14钱氏字体.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lltvcn/FreeText/d8d6daa5bb6872017e04b7f72f3e54b239a16798/app/src/main/assets/ttf/14钱氏字体.ttf -------------------------------------------------------------------------------- /app/src/main/assets/ttf/15华康海报体.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lltvcn/FreeText/d8d6daa5bb6872017e04b7f72f3e54b239a16798/app/src/main/assets/ttf/15华康海报体.ttf -------------------------------------------------------------------------------- /app/src/main/assets/ttf/16Aa小鹿.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lltvcn/FreeText/d8d6daa5bb6872017e04b7f72f3e54b239a16798/app/src/main/assets/ttf/16Aa小鹿.ttf -------------------------------------------------------------------------------- /app/src/main/assets/ttf/17腾祥麦黑简.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lltvcn/FreeText/d8d6daa5bb6872017e04b7f72f3e54b239a16798/app/src/main/assets/ttf/17腾祥麦黑简.ttf -------------------------------------------------------------------------------- /app/src/main/assets/ttf/18汉仪乐体.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lltvcn/FreeText/d8d6daa5bb6872017e04b7f72f3e54b239a16798/app/src/main/assets/ttf/18汉仪乐体.ttf -------------------------------------------------------------------------------- /app/src/main/assets/ttf/19华康翩翩体.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lltvcn/FreeText/d8d6daa5bb6872017e04b7f72f3e54b239a16798/app/src/main/assets/ttf/19华康翩翩体.ttf -------------------------------------------------------------------------------- /app/src/main/assets/ttf/20张海山锐线体2.0.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lltvcn/FreeText/d8d6daa5bb6872017e04b7f72f3e54b239a16798/app/src/main/assets/ttf/20张海山锐线体2.0.ttf -------------------------------------------------------------------------------- /app/src/main/assets/ttf/21新蒂黑板报底字体.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lltvcn/FreeText/d8d6daa5bb6872017e04b7f72f3e54b239a16798/app/src/main/assets/ttf/21新蒂黑板报底字体.ttf -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/span/BaseSpan.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.span; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.Paint; 5 | import android.text.Spanned; 6 | import android.text.style.RelativeSizeSpan; 7 | import android.text.style.ReplacementSpan; 8 | import android.util.Log; 9 | 10 | /** 11 | * Created by zhaolei on 2017/9/2. 12 | */ 13 | 14 | public class BaseSpan extends ReplacementSpan{ 15 | 16 | protected BaseSpan pre,sizeSpan; 17 | protected int horSpace,singleWidth,singleHeight; 18 | protected Paint txtPaint; 19 | 20 | public BaseSpan(){ 21 | 22 | } 23 | 24 | public final BaseSpan addNext(BaseSpan span){ 25 | if(span!=null){ 26 | span.pre = this; 27 | return span; 28 | }else{ 29 | return this; 30 | } 31 | } 32 | 33 | public BaseSpan setSizeSpan(BaseSpan span){ 34 | if(span!=this){ 35 | sizeSpan = span; 36 | } 37 | return this; 38 | } 39 | 40 | public void setHorSpace(int space){ 41 | horSpace = space; 42 | } 43 | 44 | @Override 45 | public final int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) { 46 | txtPaint = paint; 47 | if(sizeSpan!=null){ 48 | return sizeSpan.getSize(paint,text,start,end,fm); 49 | } 50 | if (fm != null) { 51 | Paint.FontMetricsInt fontMetricsInt = paint.getFontMetricsInt(); 52 | fm.ascent = fontMetricsInt.ascent; 53 | fm.descent = fontMetricsInt.descent; 54 | fm.top = fontMetricsInt.top; 55 | fm.bottom = fontMetricsInt.bottom; 56 | handleFont(fm); 57 | } 58 | int size = (int) (paint.measureText(text,start,end)/(end-start)); 59 | return measureWidth(paint,text,start,end);//需要整部分的长度,才可以正确量度其他字体位置 60 | } 61 | 62 | public void handleFont(Paint.FontMetricsInt fontMetricsInt){ 63 | 64 | } 65 | 66 | private int measureWidth(Paint paint,CharSequence text, int start, int end){ 67 | return (int) paint.measureText(text,start,end)+horSpace*(end-start-1); 68 | } 69 | 70 | 71 | @Override 72 | public final void draw(Canvas c, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint p) { 73 | int width = measureWidth(p,text,start,end); 74 | // if(pre!=null){ 75 | // pre.beforeDrawText(c,(int)x,top, (int) (x+width),bottom,p); 76 | // } 77 | beforeDrawText(c,(int)x,top, (int) (x+width),bottom,p); 78 | // if(pre!=null){ 79 | // pre.drawText(c,text,start,end,x,top,y,bottom,p); 80 | // } 81 | if(horSpace!=0){ 82 | for (int i = start; i < end; i++) { 83 | // c.drawCircle(x+i*2*offsetX+offsetX,offsetY+top,4,p); 84 | drawText(c,text,i,i+1,x+measureWidth(p,text,start,i),top,y,bottom,p); 85 | } 86 | }else{ 87 | drawText(c,text,start,end,x,top,y,bottom,p); 88 | } 89 | // if(pre!=null){ 90 | // pre.afterDrawText(c,(int)x,top, (int) (x+width),bottom,p); 91 | // } 92 | afterDrawText(c,(int)x,top, (int) (x+width),bottom,p); 93 | } 94 | 95 | protected void beforeDrawText(Canvas c, int left, int top, int right, int bottom, Paint p){ 96 | if(pre!=null){ 97 | pre.beforeDrawText(c,left,top,right,bottom,p); 98 | } 99 | } 100 | 101 | protected void afterDrawText(Canvas c, int left, int top, int right, int bottom, Paint p){ 102 | if(pre!=null){ 103 | pre.afterDrawText(c,left,top,right,bottom,p); 104 | } 105 | } 106 | 107 | protected void drawText(Canvas c, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint p){ 108 | if(pre!=null){ 109 | pre.drawText(c,text,start,end,x,top,y,bottom,p); 110 | }else{ 111 | c.drawText(text,start,end,x,y,p); 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/span/ClipTxtSpan.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.span; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.Canvas; 5 | import android.graphics.Color; 6 | import android.graphics.Paint; 7 | import android.graphics.PorterDuff; 8 | import android.graphics.PorterDuffXfermode; 9 | import android.graphics.Rect; 10 | import android.graphics.RectF; 11 | import android.util.Log; 12 | 13 | import drawn.lltvcn.com.span.BaseSpan; 14 | 15 | /** 16 | * Created by zhaolei on 2017/9/1. 17 | */ 18 | 19 | public class ClipTxtSpan extends BaseSpan { 20 | 21 | 22 | private Paint paint = new Paint(); 23 | private static Canvas canvas; 24 | private static Bitmap bitmap; 25 | private Rect from = new Rect(); 26 | private RectF to = new RectF(); 27 | 28 | 29 | 30 | static { 31 | bitmap = Bitmap.createBitmap(1280,720, Bitmap.Config.ARGB_8888); 32 | canvas = new Canvas(bitmap); 33 | } 34 | 35 | private float relativeSpan; 36 | private int span; 37 | 38 | public ClipTxtSpan(float rspan){ 39 | this.relativeSpan = rspan; 40 | } 41 | 42 | 43 | @Override 44 | public void handleFont(Paint.FontMetricsInt fm) { 45 | span = (int) (txtPaint.getTextSize()*relativeSpan); 46 | fm.ascent -= span/2; 47 | fm.descent += span/2; 48 | fm.top -= span/2; 49 | fm.bottom += span/2;//拉高measure的高度 50 | } 51 | 52 | @Override 53 | protected void drawText(Canvas c, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint p) { 54 | top = (int) (y+p.getFontMetrics().top); 55 | bottom = (int) (y+p.getFontMetrics().bottom); 56 | int width = (int) p.measureText(text,start,end); 57 | int height = bottom-top; 58 | paint.setColor(Color.TRANSPARENT); 59 | paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); 60 | canvas.drawPaint(paint); 61 | super.drawText(canvas,text,start,end,0,0,y-top,bottom-top,p); 62 | c.save(); 63 | from.set(0,0,width,height/2); 64 | to.set(x,top,x+width,top+height/2); 65 | to.offset(0,-span/2); 66 | c.drawBitmap(bitmap,from,to,null); 67 | from.offset(0,height/2); 68 | to.offset(0,height/2+span); 69 | c.drawBitmap(bitmap,from,to,null); 70 | c.restore(); 71 | } 72 | 73 | 74 | } 75 | -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/span/LightSpan.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.span; 2 | 3 | import android.graphics.BlurMaskFilter; 4 | import android.graphics.Canvas; 5 | import android.graphics.Paint; 6 | 7 | /** 8 | * Created by zhaolei on 2017/9/14. 9 | */ 10 | 11 | public class LightSpan extends BaseSpan{ 12 | Paint paint = new Paint(); 13 | 14 | public LightSpan(){ 15 | paint.setAntiAlias(true); 16 | } 17 | 18 | @Override 19 | protected void drawText(Canvas c, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint p) { 20 | paint.set(p); 21 | paint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.SOLID)); 22 | super.drawText(c, text, start, end, x, top, y, bottom, paint); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/span/LineColorSpan.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.span; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.Paint; 5 | 6 | /** 7 | * Created by zhaolei on 2017/9/4. 8 | */ 9 | 10 | public class LineColorSpan extends BaseSpan { 11 | 12 | private boolean isForeground; 13 | private Paint paint; 14 | 15 | public LineColorSpan(int color,boolean isForeground){ 16 | paint = new Paint(); 17 | paint.setColor(color); 18 | paint.setAntiAlias(true); 19 | paint.setStyle(Paint.Style.FILL); 20 | this.isForeground = isForeground; 21 | } 22 | 23 | 24 | @Override 25 | protected void afterDrawText(Canvas c, int left, int top, int right, int bottom, Paint p) { 26 | if(isForeground){ 27 | c.drawRect(left,top,right,bottom,paint); 28 | } 29 | } 30 | 31 | @Override 32 | protected void beforeDrawText(Canvas c, int left, int top, int right, int bottom, Paint p) { 33 | if(!isForeground){ 34 | c.drawRect(left-5,top,right+5,bottom,paint); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/span/LineImgSpan.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.span; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.Canvas; 5 | import android.graphics.Color; 6 | import android.graphics.Paint; 7 | import android.graphics.Rect; 8 | import android.graphics.drawable.BitmapDrawable; 9 | import android.util.Log; 10 | import android.view.Gravity; 11 | 12 | /** 13 | * Created by zhaolei on 2017/9/4. 14 | */ 15 | 16 | public class LineImgSpan extends BaseSpan { 17 | 18 | protected Bitmap bitmap; 19 | private Paint paint; 20 | private int gravity; 21 | private float span; 22 | private boolean isForeground,isFit; 23 | private Rect from,to; 24 | 25 | 26 | public LineImgSpan(Bitmap bm, int gravity){ 27 | this(bm,gravity,0,false); 28 | } 29 | 30 | public LineImgSpan(Bitmap bm, int gravity, float span){ 31 | this(bm,gravity,span,false); 32 | } 33 | 34 | 35 | public LineImgSpan(Bitmap bm, int gravity, float span, boolean isForeground){ 36 | this(bm,gravity,span,isForeground,false); 37 | } 38 | 39 | public LineImgSpan(Bitmap bm, int gravity, float span, boolean isForeground,boolean isFit){ 40 | bitmap = bm; 41 | paint = new Paint(); 42 | paint.setStyle(Paint.Style.FILL); 43 | paint.setColor(Color.BLUE); 44 | this.span = span; 45 | this.gravity = gravity; 46 | this.isForeground = isForeground; 47 | this.isFit = isFit; 48 | from = new Rect(); 49 | to = new Rect(); 50 | from.set(0,0,bitmap.getWidth(),bitmap.getHeight()); 51 | } 52 | 53 | @Override 54 | public void handleFont(Paint.FontMetricsInt fm) { 55 | 56 | if(span>0){ 57 | int spanInt = (int) (txtPaint.getTextSize()*span); 58 | switch (getGravity()){ 59 | case Gravity.TOP: 60 | fm.descent += spanInt; 61 | fm.bottom += spanInt;//拉高measure的高度 62 | break; 63 | case Gravity.CENTER: 64 | fm.ascent -= spanInt/2; 65 | fm.descent += spanInt/2; 66 | fm.top -= spanInt/2; 67 | fm.bottom += spanInt/2;//拉高measure的高度 68 | break; 69 | case Gravity.BOTTOM: 70 | fm.ascent -= spanInt/2; 71 | fm.descent += spanInt/2; 72 | fm.top -= spanInt/2; 73 | fm.bottom += spanInt/2;//拉高measure的高度 74 | // fm.ascent -= spanInt; 75 | // fm.top -= spanInt; 76 | break; 77 | } 78 | } 79 | if(isFit){ 80 | 81 | } 82 | } 83 | 84 | private int getGravity(){ 85 | if((gravity&Gravity.TOP)==Gravity.TOP){ 86 | return Gravity.TOP; 87 | } 88 | if((gravity&Gravity.CENTER)==Gravity.CENTER){ 89 | return Gravity.CENTER; 90 | } 91 | if((gravity&Gravity.BOTTOM)==Gravity.BOTTOM){ 92 | return Gravity.BOTTOM; 93 | } 94 | return gravity; 95 | } 96 | 97 | 98 | @Override 99 | protected void beforeDrawText(Canvas c, int left, int top, int right, int bottom, Paint p) { 100 | if(!isForeground){ 101 | drawImg(c,left,top,right,bottom,p); 102 | } 103 | } 104 | 105 | @Override 106 | protected void afterDrawText(Canvas c, int left, int top, int right, int bottom, Paint p) { 107 | if(isForeground){ 108 | drawImg(c,left,top,right,bottom,p); 109 | } 110 | } 111 | 112 | 113 | private void drawImg(Canvas c, int left, int top, int right, int bottom, Paint p){ 114 | Log.i("kkkkk","drawImg"+left+":::"+top); 115 | paint.setStyle(Paint.Style.FILL); 116 | c.save(); 117 | float scale = 1; 118 | if(isFit){ 119 | scale = ((float)(bottom-top)/bitmap.getHeight()); 120 | } 121 | to.set(0,0, (int) (bitmap.getWidth()*scale), (int) (bitmap.getHeight()*scale)); 122 | to.offset(left,top); 123 | int moreH = bottom-top-to.height(); 124 | if(moreH!=0){ 125 | switch (getGravity()){ 126 | case Gravity.CENTER: 127 | to.offset(0,moreH/2); 128 | break; 129 | case Gravity.BOTTOM: 130 | to.offset(0,moreH); 131 | break; 132 | } 133 | } 134 | 135 | drawBitmap(c,from,to,right-left); 136 | c.restore(); 137 | } 138 | 139 | protected void drawBitmap(Canvas c,Rect from,Rect to,int width){ 140 | int count = width/to.width(); 141 | if(count==0){ 142 | count = 1; 143 | } 144 | to.offset((width-(to.width()*count))/2,0); 145 | for (int i = 0; i < count; i++) { 146 | c.drawBitmap(bitmap,from,to,null); 147 | to.offset(to.width(),0); 148 | } 149 | } 150 | 151 | 152 | } 153 | -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/span/OffsetTxtSpan.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.span; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.Canvas; 5 | import android.graphics.Color; 6 | import android.graphics.Paint; 7 | import android.graphics.PorterDuff; 8 | import android.graphics.PorterDuffXfermode; 9 | import android.graphics.Rect; 10 | import android.graphics.RectF; 11 | 12 | /** 13 | * Created by zhaolei on 2017/9/5. 14 | */ 15 | 16 | public class OffsetTxtSpan extends BaseSpan { 17 | private Paint paint = new Paint(); 18 | private static Canvas canvas; 19 | private static Bitmap bitmap; 20 | private Rect from = new Rect(); 21 | private RectF to = new RectF(); 22 | 23 | 24 | static { 25 | bitmap = Bitmap.createBitmap(720,1280, Bitmap.Config.ARGB_8888); 26 | canvas = new Canvas(bitmap); 27 | } 28 | 29 | 30 | private float[] positions,offsets; 31 | 32 | 33 | public OffsetTxtSpan(float[] positions, float[] offsets){ 34 | this.positions = positions; 35 | this.offsets = offsets; 36 | if(positions==null&&offsets==null){ 37 | 38 | }else{ 39 | if(positions.length!=offsets.length){ 40 | throw new RuntimeException("param length wrong!"); 41 | } 42 | } 43 | 44 | } 45 | 46 | 47 | @Override 48 | protected void drawText(Canvas c, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint p) { 49 | int width = (int) p.measureText(text,start,end); 50 | int height = bottom-top; 51 | paint.setColor(Color.TRANSPARENT); 52 | paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); 53 | canvas.drawPaint(paint); 54 | super.drawText(canvas,text,start,end,0,0,y-top,bottom-top,p); 55 | // canvas.drawText(text,start,end,0,y-top,p);//减去top是为了画在bitmap的最上端 56 | if(positions!=null){ 57 | c.save(); 58 | c.translate(x,top); 59 | int offsetY = 0; 60 | for (int i = 0; i < positions.length; i++) { 61 | from.set(0,offsetY,width,offsetY+=height*positions[i]); 62 | to.set(0,from.top,width,from.bottom); 63 | to.offset(offsets[i]*p.getTextSize(),0); 64 | c.drawBitmap(bitmap,from,to,null); 65 | } 66 | c.restore(); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/span/RandomBgSpan.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.span; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.Canvas; 5 | import android.graphics.Rect; 6 | 7 | import java.util.Random; 8 | 9 | /** 10 | * Created by zhaolei on 2017/9/4. 11 | */ 12 | 13 | public class RandomBgSpan extends LineImgSpan { 14 | 15 | 16 | public RandomBgSpan(Bitmap bm, int gravity, int span, boolean isForeground, boolean isFit) { 17 | super(bm, gravity, span, isForeground, isFit); 18 | } 19 | 20 | public RandomBgSpan(Bitmap bm, int gravity, int span, boolean isForeground) { 21 | this(bm, gravity, span, isForeground, true); 22 | } 23 | 24 | 25 | @Override 26 | protected void drawBitmap(Canvas c, Rect from, Rect to, int width) { 27 | // int count = width/to.width(); 28 | // to.offset((width-(to.width()*count))/2,0); 29 | // for (int i = 0; i < count; i++) { 30 | // c.drawBitmap(img,from,to,null); 31 | // to.offset(to.width(),0); 32 | // } 33 | int end = to.width(); 34 | int offset = 0; 35 | Random random = new Random(500); 36 | 37 | while (end<=width){ 38 | c.drawBitmap(bitmap,from,to,null); 39 | offset = random.nextInt(to.width()/2)+to.width()/2; 40 | if(end+offset>width){ 41 | offset = width-end; 42 | if(offset==0){ 43 | break; 44 | } 45 | } 46 | to.offset(offset,0); 47 | end += offset; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/span/ShaderShadowSpan.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.span; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.BitmapShader; 5 | import android.graphics.Canvas; 6 | import android.graphics.Paint; 7 | import android.graphics.Shader; 8 | 9 | /** 10 | * Created by zhaolei on 2017/9/4. 11 | */ 12 | 13 | public class ShaderShadowSpan extends BaseSpan { 14 | 15 | private BitmapShader shader; 16 | 17 | 18 | public ShaderShadowSpan(Bitmap bitmap){ 19 | shader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); 20 | } 21 | 22 | 23 | @Override 24 | protected void drawText(Canvas c, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint p) { 25 | drawShadowText(c, text, start, end, x, top, y, bottom, p); 26 | } 27 | 28 | private void drawShadowText(Canvas c, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint p){ 29 | Shader tshader = p.getShader(); 30 | p.setShader(shader); 31 | super.drawText(c, text, start, end, x+5, top, y+5, bottom, p); 32 | p.setShader(tshader); 33 | super.drawText(c, text, start, end, x, top, y, bottom, p); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/span/ShakeTxtSpan.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.span; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.Color; 5 | import android.graphics.Paint; 6 | 7 | /** 8 | * Created by zhaolei on 2017/9/5. 9 | */ 10 | 11 | public class ShakeTxtSpan extends BaseSpan { 12 | 13 | 14 | @Override 15 | protected void drawText(Canvas c, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint p) { 16 | int color = p.getColor(); 17 | int alpha = p.getAlpha(); 18 | p.setAlpha(100); 19 | p.setColor(Color.rgb(80,236,204)); 20 | super.drawText(c, text, start, end, x-3, top, y-3, bottom, p); 21 | p.setColor(Color.rgb(222,7,84)); 22 | super.drawText(c, text, start, end, x+3, top, y+3, bottom, p); 23 | p.setAlpha(alpha); 24 | p.setColor(color); 25 | super.drawText(c, text, start, end, x, top, y, bottom, p); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/span/SingleTxtBgSpan.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.span; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.Canvas; 5 | import android.graphics.Paint; 6 | import android.graphics.Rect; 7 | import android.view.Gravity; 8 | 9 | /** 10 | * Created by zhaolei on 2017/9/11. 11 | */ 12 | 13 | public class SingleTxtBgSpan extends BaseSpan{ 14 | 15 | public static final int MODE_NO = 0; 16 | public static final int MODE_FITX = 1; 17 | public static final int MODE_FITY = 2; 18 | public static final int MODE_FIT_CENTER = 3; 19 | private Bitmap bm; 20 | private int fit; 21 | private Rect from,to; 22 | 23 | public SingleTxtBgSpan(Bitmap bg,int fitMode){ 24 | bm = bg; 25 | fit = fitMode; 26 | from = new Rect(); 27 | to = new Rect(); 28 | from.set(0,0,bg.getWidth(),bg.getHeight()); 29 | to.set(0,0,bg.getWidth(),bg.getHeight()); 30 | } 31 | 32 | 33 | @Override 34 | protected void drawText(Canvas c, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint p) { 35 | float scale = 1; 36 | to.set(from.left,from.top,from.right,from.bottom); 37 | switch (fit){ 38 | case MODE_NO: 39 | // scale = ((float)(bottom-top)/bm.getHeight()); 40 | break; 41 | } 42 | to.offset((int) x,top); 43 | int moreH = bottom-top-to.height(); 44 | int moreW = (int) (p.getTextSize()-to.width()); 45 | to.offset(moreW/2,moreH/2); 46 | for (int i = start; i < end; i++) { 47 | // c.drawCircle(x+i*2*offsetX+offsetX,offsetY+top,4,p); 48 | c.drawBitmap(bm,from,to,null); 49 | to.offset((int) p.getTextSize(),0); 50 | } 51 | super.drawText(c,text,start,end,x,top,y,bottom,p); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/span/SingleTxtRotateSpan.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.span; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.Paint; 5 | import android.view.Surface; 6 | 7 | /** 8 | * Created by zhaolei on 2017/9/11. 9 | */ 10 | 11 | public class SingleTxtRotateSpan extends BaseSpan{ 12 | private float degree; 13 | 14 | public SingleTxtRotateSpan(float degree){ 15 | this.degree = degree; 16 | } 17 | 18 | 19 | @Override 20 | protected void drawText(Canvas c, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint p) { 21 | float offsetX = p.getTextSize()/2; 22 | float offsetY = (bottom-top)/2; 23 | for (int i = 0; i < end-start; i++) { 24 | c.drawCircle(x+i*2*offsetX+offsetX,offsetY+top,4,p); 25 | c.save(); 26 | c.rotate(-degree,x+i*(2*offsetX)+offsetX,offsetY+top); 27 | super.drawText(c, text, i+start, i+1+start, x+i*(2*offsetX), top, y, bottom, p); 28 | c.restore(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/span/StokeTxtSpan.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.span; 2 | 3 | import android.graphics.BlurMaskFilter; 4 | import android.graphics.Canvas; 5 | import android.graphics.Color; 6 | import android.graphics.CornerPathEffect; 7 | import android.graphics.Paint; 8 | import android.graphics.PathEffect; 9 | 10 | /** 11 | * Created by zhaolei on 2017/9/4. 12 | */ 13 | 14 | public class StokeTxtSpan extends BaseSpan { 15 | 16 | private Paint paint = new Paint(); 17 | private float relativeWidth; 18 | private int color; 19 | 20 | public StokeTxtSpan(float rWidth,int color){ 21 | this.color = color; 22 | relativeWidth = rWidth; 23 | } 24 | 25 | 26 | @Override 27 | protected void drawText(Canvas c, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint p) { 28 | paint.set(p); 29 | paint.setStyle(Paint.Style.FILL_AND_STROKE); 30 | paint.setStrokeJoin(Paint.Join.ROUND); 31 | paint.setStrokeWidth(p.getTextSize()*relativeWidth); 32 | paint.setColor(color); 33 | // paint.setMaskFilter(new BlurMaskFilter(p.getTextSize()*relativeWidth/2F, BlurMaskFilter.Blur.SOLID)); 34 | paint.setShadowLayer(p.getTextSize()*relativeWidth*2,0.5f,0.5f, Color.argb(100,Color.red(color),Color.green(color),Color.blue(color))); 35 | super.drawText(c, text, start, end, x, top, y, bottom, paint); 36 | super.drawText(c, text, start, end, x, top, y, bottom, p); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/span/TxtSpan.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.span; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.Color; 5 | import android.graphics.Paint; 6 | 7 | /** 8 | * Created by zhaolei on 2017/9/21. 9 | */ 10 | 11 | public class TxtSpan extends BaseSpan{ 12 | 13 | private static Paint savePaint = new Paint(); 14 | private PaintHandler handler; 15 | 16 | public TxtSpan setPaintHandler(PaintHandler handler){ 17 | this.handler = handler; 18 | return this; 19 | } 20 | 21 | @Override 22 | protected void drawText(Canvas c, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint p) { 23 | savePaint.set(p); 24 | handler.handlePaint(savePaint); 25 | super.drawText(c, text, start, end, x, top, y, bottom, savePaint); 26 | } 27 | 28 | public interface PaintHandler{ 29 | void handlePaint(Paint p); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/textdemo/DemoActivity.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.textdemo; 2 | 3 | import android.app.Activity; 4 | import android.graphics.Color; 5 | import android.graphics.drawable.ColorDrawable; 6 | import android.os.Bundle; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.BaseAdapter; 11 | import android.widget.ListView; 12 | import android.widget.TextView; 13 | 14 | import com.lltvcn.freefont.core.animation.A; 15 | import com.lltvcn.freefont.core.data.AniData; 16 | import com.lltvcn.freefont.core.data.DrawData; 17 | import com.lltvcn.freefont.core.view.STextView; 18 | 19 | import java.util.ArrayList; 20 | 21 | import drawn.lltvcn.com.util.FileUtil; 22 | import drawn.lltvcn.com.util.FontUtil; 23 | import drawn.lltvcn.com.util.SUtil; 24 | 25 | /** 26 | * Created by zhaolei on 2018/1/5. 27 | */ 28 | 29 | public class DemoActivity extends Activity{ 30 | 31 | private ListView listView; 32 | 33 | 34 | @Override 35 | protected void onCreate(Bundle savedInstanceState) { 36 | super.onCreate(savedInstanceState); 37 | setContentView(R.layout.activity_demo); 38 | getWindow().setBackgroundDrawable(new ColorDrawable(Color.WHITE)); 39 | 40 | datas = new ArrayList<>(); 41 | Data d1 = new Data(); 42 | d1.title = "组合动画"; 43 | d1.data = FileUtil.getDrawData("文字颜色顺序变化"); 44 | d1.font = "15华康海报体.ttf"; 45 | d1.data.aniType = A.BOTTOM_IN_SCALE_UP_OUT; 46 | datas.add(d1); 47 | 48 | d1 = new Data(); 49 | d1.title = "淡入淡出动画"; 50 | d1.data = FileUtil.getDrawData("文字颜色顺序变化"); 51 | d1.font = "15华康海报体.ttf"; 52 | d1.data.aniType = A.SINGLE_RIGHT_FADE_INF_LEFT_FADE_OUT; 53 | datas.add(d1); 54 | 55 | d1 = new Data(); 56 | d1.title = "单字旋转动画"; 57 | d1.data = FileUtil.getDrawData("文字颜色顺序变化"); 58 | d1.data.aniType = A.SINGLE_ROTATE; 59 | d1.font = "15华康海报体.ttf"; 60 | datas.add(d1); 61 | 62 | d1 = new Data(); 63 | d1.title = "整体旋转动画"; 64 | d1.data = FileUtil.getDrawData("文字颜色顺序变化"); 65 | d1.data.aniType = A.ROTATE_REPEAT; 66 | d1.font = "15华康海报体.ttf"; 67 | datas.add(d1); 68 | 69 | d1 = new Data(); 70 | d1.title = "上下移动动画"; 71 | d1.data = FileUtil.getDrawData("文字颜色顺序变化"); 72 | d1.data.aniType = A.SINGLE_UP_DOWN; 73 | d1.font = "15华康海报体.ttf"; 74 | datas.add(d1); 75 | 76 | 77 | d1 = new Data(); 78 | d1.title = "下划线+发光"; 79 | d1.data = FileUtil.getDrawData("下划线+发光"); 80 | d1.font = "15华康海报体.ttf"; 81 | datas.add(d1); 82 | 83 | d1 = new Data(); 84 | d1.title = "中划线"; 85 | d1.data = FileUtil.getDrawData("中划线"); 86 | d1.font = "15华康海报体.ttf"; 87 | datas.add(d1); 88 | 89 | d1 = new Data(); 90 | d1.title = "抖音效果2"; 91 | d1.data = FileUtil.getDrawData("抖音2"); 92 | d1.font = "15华康海报体.ttf"; 93 | datas.add(d1); 94 | 95 | d1 = new Data(); 96 | d1.title = "缩放效果"; 97 | d1.data = FileUtil.getDrawData("缩放效果"); 98 | d1.font = "15华康海报体.ttf"; 99 | datas.add(d1); 100 | 101 | 102 | d1 = new Data(); 103 | d1.title = "每个文字叠加图片"; 104 | d1.data = FileUtil.getDrawData("单个字叠加图片"); 105 | d1.font = "15华康海报体.ttf"; 106 | datas.add(d1); 107 | 108 | d1 = new Data(); 109 | d1.title = "每个文字渐变"; 110 | d1.data = FileUtil.getDrawData("单个文字渐变"); 111 | d1.font = "15华康海报体.ttf"; 112 | datas.add(d1); 113 | 114 | d1 = new Data(); 115 | d1.title = "每个文字加背景图"; 116 | d1.data = FileUtil.getDrawData("背景图"); 117 | d1.font = "15华康海报体.ttf"; 118 | datas.add(d1); 119 | 120 | d1 = new Data(); 121 | d1.title = "切割文字"; 122 | d1.data = FileUtil.getDrawData("切割文字"); 123 | d1.font = "15华康海报体.ttf"; 124 | datas.add(d1); 125 | 126 | listView = (ListView) findViewById(R.id.list_view); 127 | listView.setAdapter(new MyAdapter()); 128 | 129 | } 130 | 131 | 132 | 133 | 134 | private class Data{ 135 | String title; 136 | String font; 137 | DrawData data; 138 | } 139 | 140 | private ArrayList datas; 141 | 142 | private class MyAdapter extends BaseAdapter{ 143 | 144 | @Override 145 | public int getCount() { 146 | return datas==null?0:datas.size(); 147 | } 148 | 149 | @Override 150 | public Data getItem(int position) { 151 | return datas.get(position); 152 | } 153 | 154 | @Override 155 | public long getItemId(int position) { 156 | return position; 157 | } 158 | 159 | @Override 160 | public View getView(int position, View convertView, ViewGroup parent) { 161 | ViewHolder holder = null; 162 | if(convertView == null){ 163 | convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_demo,parent,false); 164 | holder = new ViewHolder(); 165 | holder.tvTitle = (TextView) convertView.findViewById(R.id.tv_title); 166 | holder.tvContent = (STextView) convertView.findViewById(R.id.tv_content); 167 | holder.tvContent.setLocalSourcePath(FileUtil.getImgDir()); 168 | convertView.setTag(holder); 169 | }else{ 170 | holder = (ViewHolder) convertView.getTag(); 171 | } 172 | Data data = getItem(position); 173 | holder.tvTitle.setText(data.title); 174 | holder.tvTitle.setVisibility(View.GONE); 175 | holder.tvContent.setText(data.title); 176 | holder.tvContent.setTypeface(FontUtil.getTypeface(data.font)); 177 | if(holder.tvContent.getTAnimation()!=null){ 178 | holder.tvContent.getTAnimation().stop(); 179 | } 180 | holder.tvContent.setData(data.data); 181 | if(holder.tvContent.getTAnimation()!=null){ 182 | holder.tvContent.getTAnimation().start(); 183 | } 184 | return convertView; 185 | } 186 | } 187 | 188 | private class ViewHolder{ 189 | TextView tvTitle; 190 | STextView tvContent; 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/textdemo/ListActivity.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.textdemo; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | import android.widget.EditText; 8 | 9 | /** 10 | * Created by zhaolei on 2017/10/20. 11 | */ 12 | 13 | public class ListActivity extends Activity{ 14 | 15 | @Override 16 | protected void onCreate(Bundle savedInstanceState) { 17 | super.onCreate(savedInstanceState); 18 | setContentView(R.layout.layout_list); 19 | } 20 | 21 | 22 | public void toEdit(View view){ 23 | startActivity(new Intent(this,EditActivity.class)); 24 | } 25 | 26 | public void toReview(View view){ 27 | startActivity(new Intent(this,ReviewActivity.class)); 28 | } 29 | 30 | public void toDemo(View view) {startActivity(new Intent(this,DemoActivity.class));} 31 | 32 | public void toReviewAni(View view){ 33 | startActivity(new Intent(this,ReviewAniActivity.class)); 34 | 35 | } 36 | 37 | public void toCode(View view){ 38 | startActivity(new Intent(this,CodeActivity.class)); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/textdemo/MainApplication.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.textdemo; 2 | 3 | import android.app.Application; 4 | 5 | import java.io.File; 6 | import java.io.IOException; 7 | 8 | import drawn.lltvcn.com.util.FileUtil; 9 | import drawn.lltvcn.com.util.ZipUtil; 10 | 11 | /** 12 | * Created by zhaolei on 2017/10/19. 13 | */ 14 | 15 | public class MainApplication extends Application{ 16 | 17 | private static MainApplication instance; 18 | public static MainApplication getInstance(){ 19 | return instance; 20 | } 21 | 22 | @Override 23 | public void onCreate() { 24 | super.onCreate(); 25 | instance = this; 26 | if(!new File(FileUtil.getRootPath()+"e.e").exists()){ 27 | try { 28 | ZipUtil.decompress(getAssets().open("res.zip"),FileUtil.getRootPath(),false); 29 | new File(FileUtil.getRootPath()+"e.e").createNewFile(); 30 | } catch (IOException e) { 31 | e.printStackTrace(); 32 | } 33 | 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/textdemo/ParamProvider.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.textdemo; 2 | 3 | /** 4 | * Created by zhaolei on 2017/8/17. 5 | */ 6 | 7 | public interface ParamProvider { 8 | 9 | int getInt(int index,int def); 10 | 11 | float getFloat(int index,float def); 12 | 13 | int getIntCount(); 14 | 15 | int getFloatCount(); 16 | 17 | void setInt(int index,int param); 18 | 19 | void setFloat(int index,float param); 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/textdemo/ParamProviderImpl.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.textdemo; 2 | 3 | import android.util.SparseArray; 4 | 5 | import java.util.ArrayList; 6 | 7 | /** 8 | * Created by zhaolei on 2017/8/17. 9 | */ 10 | 11 | public class ParamProviderImpl implements ParamProvider{ 12 | 13 | private SparseArray integers = new SparseArray<>(1); 14 | private SparseArray floats = new SparseArray<>(1); 15 | 16 | @Override 17 | public int getInt(int index, int def) { 18 | if(integers.get(index)==null){ 19 | integers.put(index,def); 20 | } 21 | return integers.get(index); 22 | } 23 | 24 | @Override 25 | public float getFloat(int index, float def) { 26 | if(floats.get(index)==null){ 27 | floats.put(index,def); 28 | } 29 | return floats.get(index); 30 | } 31 | 32 | @Override 33 | public int getIntCount() { 34 | return integers.size(); 35 | } 36 | 37 | @Override 38 | public int getFloatCount() { 39 | return floats.size(); 40 | } 41 | 42 | @Override 43 | public void setInt(int index, int param) { 44 | integers.put(index,param); 45 | } 46 | 47 | @Override 48 | public void setFloat(int index, float param) { 49 | floats.put(index,param); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/textdemo/ReviewActivity.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.textdemo; 2 | 3 | import android.app.Activity; 4 | import android.graphics.Color; 5 | import android.graphics.Paint; 6 | import android.os.Bundle; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.EditText; 10 | 11 | import com.google.gson.Gson; 12 | import com.lltvcn.freefont.core.animation.A; 13 | import com.lltvcn.freefont.core.data.DrawData; 14 | import com.lltvcn.freefont.core.view.STextView; 15 | 16 | import java.io.File; 17 | import java.io.FileNotFoundException; 18 | import java.io.FileReader; 19 | import java.io.IOException; 20 | import java.util.ArrayList; 21 | 22 | import drawn.lltvcn.com.textdemo.controller.EditParamViewController; 23 | import drawn.lltvcn.com.textdemo.controller.SelectController; 24 | import drawn.lltvcn.com.util.FileUtil; 25 | import drawn.lltvcn.com.util.FontUtil; 26 | import drawn.lltvcn.com.util.SUtil; 27 | 28 | /** 29 | * Created by zhaolei on 2017/11/21. 30 | */ 31 | 32 | public class ReviewActivity extends Activity{ 33 | STextView tv; 34 | SelectController selectController; 35 | String[] fileNames; 36 | String[] fontNames; 37 | 38 | @Override 39 | protected void onCreate(Bundle savedInstanceState) { 40 | super.onCreate(savedInstanceState); 41 | setContentView(R.layout.layout_review); 42 | fontNames = FontUtil.getFontNames(); 43 | tv = (STextView) findViewById(R.id.tv); 44 | tv.setText(SUtil.getTxt()); 45 | tv.setLocalSourcePath(FileUtil.getImgDir()); 46 | selectController = new SelectController(); 47 | selectController.init((ViewGroup) findViewById(R.id.fl_cotainer), new EditParamViewController.VisiableListener() { 48 | @Override 49 | public void onVisable(boolean visiable) { 50 | } 51 | }); 52 | File file = new File(FileUtil.getDataDir()); 53 | fileNames = file.list(); 54 | findViewById(R.id.btn_add).setOnClickListener(new View.OnClickListener() { 55 | @Override 56 | public void onClick(View v) { 57 | selectController.show(fileNames, false, new SelectController.ResultListener() { 58 | @Override 59 | public void onConfrim(ArrayList result) { 60 | String name = result.get(0); 61 | String dir = FileUtil.getDataDirByName(name); 62 | try { 63 | FileReader reader = new FileReader(dir+File.separator+name+".txt"); 64 | DrawData data = new Gson().fromJson(reader,DrawData.class); 65 | reader.close(); 66 | tv.setData(data); 67 | if(tv.getTAnimation()!=null){ 68 | tv.getTAnimation().start(); 69 | } 70 | } catch (FileNotFoundException e) { 71 | e.printStackTrace(); 72 | } catch (IOException e) { 73 | e.printStackTrace(); 74 | } 75 | } 76 | }); 77 | } 78 | }); 79 | findViewById(R.id.btn_font).setOnClickListener(new View.OnClickListener() { 80 | @Override 81 | public void onClick(View v) { 82 | selectController.show(fontNames, false, new SelectController.ResultListener() { 83 | @Override 84 | public void onConfrim(ArrayList result) { 85 | if(result!=null&&result.size()>0){ 86 | tv.setTypeface(FontUtil.getTypeface(result.get(0))); 87 | }else{ 88 | tv.setTypeface(null); 89 | } 90 | } 91 | }); 92 | } 93 | }); 94 | 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/textdemo/ReviewAniActivity.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.textdemo; 2 | 3 | import android.app.Activity; 4 | import android.graphics.Color; 5 | import android.graphics.Paint; 6 | import android.os.Bundle; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.EditText; 10 | 11 | import com.google.gson.Gson; 12 | import com.lltvcn.freefont.core.animation.A; 13 | import com.lltvcn.freefont.core.data.DrawData; 14 | import com.lltvcn.freefont.core.view.STextView; 15 | 16 | import java.io.File; 17 | import java.io.FileNotFoundException; 18 | import java.io.FileReader; 19 | import java.io.IOException; 20 | import java.util.ArrayList; 21 | 22 | import drawn.lltvcn.com.textdemo.controller.EditParamViewController; 23 | import drawn.lltvcn.com.textdemo.controller.SelectController; 24 | import drawn.lltvcn.com.util.FileUtil; 25 | import drawn.lltvcn.com.util.FontUtil; 26 | import drawn.lltvcn.com.util.SUtil; 27 | 28 | /** 29 | * Created by zhaolei on 2017/11/21. 30 | */ 31 | 32 | public class ReviewAniActivity extends Activity{ 33 | STextView tv; 34 | SelectController selectController; 35 | String[] fileNames,aniNames,fontNames; 36 | DrawData drawData; 37 | int[] aniTypes; 38 | 39 | { 40 | aniNames = new String[]{"出现1","出现2(单字旋转)","出现4(大->小)","出现7(淡入淡出)","基础2(单字上下抖动)","基础3(所有字旋转)","基础4(单字缩放)","基础1(X)"}; 41 | aniTypes = new int[]{A.BOTTOM_IN_SCALE_UP_OUT,A.SINGLE_ROTATE,A.SCALE_SHOW,A.SINGLE_RIGHT_FADE_INF_LEFT_FADE_OUT,A.SINGLE_UP_DOWN,A.ROTATE_REPEAT,A.SINGLE_SCALE,A.SINGLE_X}; 42 | } 43 | 44 | @Override 45 | protected void onCreate(Bundle savedInstanceState) { 46 | super.onCreate(savedInstanceState); 47 | setContentView(R.layout.layout_review_ani); 48 | tv = (STextView) findViewById(R.id.tv); 49 | fontNames = FontUtil.getFontNames(); 50 | tv.setLocalSourcePath(FileUtil.getImgDir()); 51 | tv.setText(SUtil.getTxt()); 52 | selectController = new SelectController(); 53 | selectController.init((ViewGroup) findViewById(R.id.fl_cotainer), new EditParamViewController.VisiableListener() { 54 | @Override 55 | public void onVisable(boolean visiable) { 56 | } 57 | }); 58 | File file = new File(FileUtil.getDataDir()); 59 | fileNames = file.list(); 60 | findViewById(R.id.btn_add).setOnClickListener(new View.OnClickListener() { 61 | @Override 62 | public void onClick(View v) { 63 | selectController.show(fileNames, false, new SelectController.ResultListener() { 64 | @Override 65 | public void onConfrim(ArrayList result) { 66 | String name = result.get(0); 67 | String dir = FileUtil.getDataDirByName(name); 68 | try { 69 | FileReader reader = new FileReader(dir+File.separator+name+".txt"); 70 | DrawData data = new Gson().fromJson(reader,DrawData.class); 71 | drawData = data; 72 | reader.close(); 73 | tv.setData(data); 74 | if(tv.getTAnimation()!=null){ 75 | tv.getTAnimation().start(); 76 | } 77 | } catch (FileNotFoundException e) { 78 | e.printStackTrace(); 79 | } catch (IOException e) { 80 | e.printStackTrace(); 81 | } 82 | } 83 | }); 84 | } 85 | }); 86 | findViewById(R.id.btn_ani).setOnClickListener(new View.OnClickListener() { 87 | @Override 88 | public void onClick(View v) { 89 | selectController.show(aniNames, false, new SelectController.ResultListener() { 90 | @Override 91 | public void onConfrim(ArrayList result) { 92 | for (int i = 0; i < aniNames.length; i++) { 93 | if(aniNames[i].equals(result.get(0))){ 94 | if(drawData!=null){ 95 | drawData.aniType = aniTypes[i]; 96 | if(tv.getTAnimation()!=null){ 97 | tv.getTAnimation().stop(); 98 | } 99 | tv.setData(drawData); 100 | if(tv.getTAnimation()!=null){ 101 | tv.getTAnimation().start(); 102 | } 103 | } 104 | } 105 | } 106 | } 107 | }); 108 | } 109 | }); 110 | 111 | findViewById(R.id.btn_font).setOnClickListener(new View.OnClickListener() { 112 | @Override 113 | public void onClick(View v) { 114 | selectController.show(fontNames, false, new SelectController.ResultListener() { 115 | @Override 116 | public void onConfrim(ArrayList result) { 117 | if(result!=null&&result.size()>0){ 118 | tv.setTypeface(FontUtil.getTypeface(result.get(0))); 119 | }else{ 120 | tv.setTypeface(null); 121 | } 122 | } 123 | }); 124 | } 125 | }); 126 | 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/textdemo/TxtShader2.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.textdemo; 2 | 3 | import android.widget.TextView; 4 | 5 | /** 6 | * Created by zhaolei on 2017/8/15. 7 | */ 8 | 9 | public interface TxtShader2 { 10 | 11 | void onShade(TextView textView); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/textdemo/TxtShader2Ext.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.textdemo; 2 | 3 | import android.widget.TextView; 4 | 5 | /** 6 | * Created by zhaolei on 2017/8/17. 7 | */ 8 | 9 | public abstract class TxtShader2Ext implements TxtShader2{ 10 | 11 | 12 | private ParamProvider paramProvider; 13 | 14 | 15 | public final ParamProvider getParamProvider(){ 16 | if(paramProvider==null){ 17 | paramProvider = new ParamProviderImpl(); 18 | } 19 | return paramProvider; 20 | } 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/textdemo/controller/EditTxtController.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.textdemo.controller; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.view.animation.Animation; 8 | import android.view.animation.TranslateAnimation; 9 | import android.view.inputmethod.InputMethodManager; 10 | import android.widget.EditText; 11 | 12 | import drawn.lltvcn.com.textdemo.R; 13 | 14 | /** 15 | * Created by zhaolei on 2017/10/13. 16 | */ 17 | 18 | public class EditTxtController { 19 | 20 | private View view; 21 | private EditText et; 22 | private ViewGroup parent; 23 | 24 | 25 | public void init(ViewGroup parent){ 26 | this.parent = parent; 27 | this.view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_edit_txt,parent,false); 28 | parent.addView(view); 29 | view.setVisibility(View.GONE); 30 | et = (EditText) view.findViewById(R.id.et_edit); 31 | view.findViewById(R.id.btn_et_confirm).setOnClickListener(new View.OnClickListener() { 32 | @Override 33 | public void onClick(View v) { 34 | if (confirmListener!=null){ 35 | confirmListener.onConfirm(et.getText().toString()); 36 | } 37 | dismiss(); 38 | } 39 | }); 40 | view.findViewById(R.id.btn_et_cancel).setOnClickListener(new View.OnClickListener() { 41 | @Override 42 | public void onClick(View v) { 43 | dismiss(); 44 | } 45 | }); 46 | } 47 | 48 | public interface OnConfirmListener{ 49 | void onConfirm(String content); 50 | } 51 | 52 | OnConfirmListener confirmListener; 53 | public void show(OnConfirmListener confirmListener){ 54 | view.setVisibility(View.VISIBLE); 55 | parent.setVisibility(View.VISIBLE); 56 | et.setText(null); 57 | this.confirmListener = confirmListener; 58 | TranslateAnimation ta = new TranslateAnimation(Animation.RELATIVE_TO_SELF,0f,Animation.RELATIVE_TO_SELF,0f,Animation.RELATIVE_TO_SELF,-1,Animation.RELATIVE_TO_SELF,0); 59 | ta.setDuration(400); 60 | view.startAnimation(ta); 61 | view.postDelayed(new Runnable() { 62 | @Override 63 | public void run() { 64 | et.requestFocus(); 65 | InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); 66 | imm.showSoftInput(et,InputMethodManager.SHOW_IMPLICIT); 67 | } 68 | },400); 69 | } 70 | 71 | public void dismiss(){ 72 | TranslateAnimation ta = new TranslateAnimation(Animation.RELATIVE_TO_SELF,0f,Animation.RELATIVE_TO_SELF,0f,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,-1); 73 | ta.setDuration(400); 74 | ta.setAnimationListener(new Animation.AnimationListener() { 75 | @Override 76 | public void onAnimationStart(Animation animation) { 77 | 78 | } 79 | 80 | @Override 81 | public void onAnimationEnd(Animation animation) { 82 | view.setVisibility(View.GONE); 83 | dismissParent(); 84 | } 85 | 86 | @Override 87 | public void onAnimationRepeat(Animation animation) { 88 | 89 | } 90 | }); 91 | view.startAnimation(ta); 92 | InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); 93 | imm.hideSoftInputFromWindow(et.getWindowToken(),InputMethodManager.HIDE_NOT_ALWAYS); 94 | } 95 | 96 | 97 | private void dismissParent(){ 98 | for (int i = 0; i < parent.getChildCount(); i++) { 99 | if(parent.getChildAt(i).getVisibility() == View.VISIBLE){ 100 | return; 101 | } 102 | } 103 | parent.setVisibility(View.GONE); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/textdemo/controller/SelectController.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.textdemo.controller; 2 | 3 | import android.support.v7.widget.LinearLayoutManager; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.view.animation.Animation; 9 | import android.view.animation.TranslateAnimation; 10 | import android.widget.CheckBox; 11 | 12 | import java.util.ArrayList; 13 | 14 | import drawn.lltvcn.com.textdemo.R; 15 | 16 | /** 17 | * Created by zhaolei on 2017/10/17. 18 | */ 19 | 20 | public class SelectController { 21 | 22 | private ViewGroup parent; 23 | private View view; 24 | private RecyclerView rv; 25 | public String[] data; 26 | private MyAdapter adapter = new MyAdapter(); 27 | 28 | private EditParamViewController.VisiableListener listener; 29 | 30 | public void init(ViewGroup parent, EditParamViewController.VisiableListener listener){ 31 | this.parent = parent; 32 | this.listener = listener; 33 | view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_edit_v2,parent,false); 34 | parent.addView(view); 35 | rv = (RecyclerView) findViewById(R.id.rv); 36 | rv.setAdapter(adapter); 37 | rv.setLayoutManager(new LinearLayoutManager(view.getContext(),LinearLayoutManager.VERTICAL,false)); 38 | // rv.setLayoutManager(new GridLayoutManager(parent.getContext(),3, LinearLayoutManager.HORIZONTAL,false)); 39 | findViewById(R.id.btn_confirm).setOnClickListener(new View.OnClickListener() { 40 | @Override 41 | public void onClick(View v) { 42 | ArrayList result = new ArrayList(); 43 | for (int i = 0; i < rv.getChildCount(); i++) { 44 | CheckBox ck = (CheckBox) rv.getChildAt(i).findViewById(R.id.ck); 45 | if(ck.isChecked()){ 46 | result.add(data[i]); 47 | } 48 | } 49 | resultLis.onConfrim(result); 50 | dismiss(); 51 | } 52 | }); 53 | findViewById(R.id.btn_cancel).setOnClickListener(new View.OnClickListener() { 54 | @Override 55 | public void onClick(View v) { 56 | dismiss(); 57 | } 58 | }); 59 | } 60 | 61 | private View findViewById(int id){ 62 | return view.findViewById(id); 63 | } 64 | 65 | private class MyAdapter extends RecyclerView.Adapter{ 66 | 67 | @Override 68 | public Holder onCreateViewHolder(ViewGroup parent, int viewType) { 69 | return new Holder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_ck,parent,false)); 70 | } 71 | 72 | @Override 73 | public void onBindViewHolder(Holder holder, int position) { 74 | String content = data[position]; 75 | holder.ck.setText(content); 76 | } 77 | 78 | @Override 79 | public int getItemCount() { 80 | return data==null?0:data.length; 81 | } 82 | } 83 | 84 | private CheckBox lastCK; 85 | private boolean isMulti; 86 | 87 | private class Holder extends RecyclerView.ViewHolder{ 88 | private CheckBox ck; 89 | 90 | public Holder(View itemView) { 91 | super(itemView); 92 | ck = (CheckBox) itemView.findViewById(R.id.ck); 93 | ck.setChecked(false); 94 | ck.setClickable(false); 95 | ck.setFocusable(false); 96 | itemView.setOnClickListener(new View.OnClickListener() { 97 | @Override 98 | public void onClick(View v) { 99 | ArrayList str = new ArrayList(); 100 | str.add(data[rv.getChildAdapterPosition(v)]); 101 | resultLis.onConfrim(str); 102 | dismiss(); 103 | } 104 | }); 105 | // ck.setOnClickListener(new View.OnClickListener() { 106 | // @Override 107 | // public void onClick(View v) { 108 | // if(!isMulti){ 109 | // if(ck.isChecked()){ 110 | // if(lastCK!=null&&lastCK!=ck){ 111 | // lastCK.setChecked(false); 112 | // } 113 | // lastCK = ck; 114 | // } 115 | // } 116 | // 117 | // } 118 | // }); 119 | } 120 | } 121 | 122 | public interface ResultListener{ 123 | void onConfrim(ArrayList result); 124 | } 125 | 126 | private ResultListener resultLis; 127 | public void show(String[] data,boolean isMulti,ResultListener listener){ 128 | this.resultLis = listener; 129 | this.data = data; 130 | this.isMulti = isMulti; 131 | adapter.notifyDataSetChanged(); 132 | show(); 133 | } 134 | 135 | public void show(){ 136 | view.setVisibility(View.VISIBLE); 137 | parent.setVisibility(View.VISIBLE); 138 | TranslateAnimation ta = new TranslateAnimation(Animation.RELATIVE_TO_SELF,0f,Animation.RELATIVE_TO_SELF,0f,Animation.RELATIVE_TO_SELF,1,Animation.RELATIVE_TO_SELF,0); 139 | ta.setDuration(400); 140 | view.startAnimation(ta); 141 | listener.onVisable(true); 142 | } 143 | 144 | public void dismiss(){ 145 | lastCK = null; 146 | TranslateAnimation ta = new TranslateAnimation(Animation.RELATIVE_TO_SELF,0f,Animation.RELATIVE_TO_SELF,0f,Animation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,1); 147 | ta.setDuration(400); 148 | ta.setAnimationListener(new Animation.AnimationListener() { 149 | @Override 150 | public void onAnimationStart(Animation animation) { 151 | 152 | } 153 | 154 | @Override 155 | public void onAnimationEnd(Animation animation) { 156 | view.setVisibility(View.GONE); 157 | listener.onVisable(false); 158 | dismissParent(); 159 | } 160 | 161 | @Override 162 | public void onAnimationRepeat(Animation animation) { 163 | 164 | } 165 | }); 166 | view.startAnimation(ta); 167 | } 168 | 169 | private void dismissParent(){ 170 | for (int i = 0; i < parent.getChildCount(); i++) { 171 | if(parent.getChildAt(i).getVisibility() == View.VISIBLE){ 172 | return; 173 | } 174 | } 175 | parent.setVisibility(View.GONE); 176 | } 177 | 178 | 179 | } 180 | -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/textdemo/data/BgData.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.textdemo.data; 2 | 3 | import com.lltvcn.freefont.core.annotation.Description; 4 | import com.lltvcn.freefont.core.annotation.Img; 5 | 6 | /** 7 | * Created by zhaolei on 2017/10/18. 8 | */ 9 | 10 | public class BgData { 11 | 12 | @Description(name = "背景图",cls = Img.class) 13 | public String bitmap; 14 | 15 | @Description(name = "背景色") 16 | public String bgColor; 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/textdemo/data/FontData.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.textdemo.data; 2 | 3 | import java.util.HashMap; 4 | 5 | import com.lltvcn.freefont.core.data.DrawData; 6 | 7 | /** 8 | * Created by zhaolei on 2017/10/18. 9 | */ 10 | 11 | public class FontData { 12 | 13 | public DrawData drawData; 14 | 15 | public HashMap dependImgs; 16 | 17 | public HashMap dependFonts; 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/textdemo/data/FontStyleData.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.textdemo.data; 2 | 3 | import com.lltvcn.freefont.core.annotation.Description; 4 | import com.lltvcn.freefont.core.layer.FontStyle; 5 | 6 | /** 7 | * Created by zhaolei on 2017/10/18. 8 | */ 9 | 10 | public class FontStyleData { 11 | 12 | @Description(name = "字体风格") 13 | public FontStyle fontStyle; 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/util/FontUtil.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.util; 2 | 3 | import android.content.Context; 4 | import android.graphics.Typeface; 5 | 6 | import java.io.IOException; 7 | 8 | import drawn.lltvcn.com.textdemo.MainApplication; 9 | 10 | /** 11 | * Created by zhaolei on 2018/1/4. 12 | */ 13 | 14 | public class FontUtil { 15 | 16 | private static Context context = MainApplication.getInstance(); 17 | private static String[] assetFonts,fileFonts,result; 18 | 19 | static { 20 | fileFonts = FileUtil.getFontNames(); 21 | try { 22 | assetFonts = context.getAssets().list("ttf"); 23 | } catch (IOException e) { 24 | e.printStackTrace(); 25 | } 26 | int length = 0; 27 | if(fileFonts!=null){ 28 | length += fileFonts.length; 29 | } 30 | if(assetFonts!=null){ 31 | length += assetFonts.length; 32 | } 33 | result = new String[length]; 34 | int index = 0; 35 | if(fileFonts!=null){ 36 | System.arraycopy(fileFonts,0,result,0,fileFonts.length); 37 | index += fileFonts.length; 38 | } 39 | if(assetFonts!=null){ 40 | System.arraycopy(assetFonts,0,result,index,assetFonts.length); 41 | } 42 | } 43 | 44 | public static String[] getFontNames(){ 45 | return result; 46 | } 47 | 48 | public static Typeface getTypeface(String name){ 49 | if(contain(fileFonts,name)){ 50 | return Typeface.createFromFile(FileUtil.getFontPath(name)); 51 | }else if(contain(assetFonts,name)){ 52 | return Typeface.createFromAsset(context.getAssets(),"ttf/"+name); 53 | }else { 54 | return null; 55 | } 56 | } 57 | 58 | private static boolean contain(String[] strs,String name){ 59 | if(strs==null||strs.length==0) 60 | return false; 61 | for (String str : 62 | strs) { 63 | if(str.equals(name)) 64 | return true; 65 | } 66 | return false; 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/util/SUtil.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.util; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * Created by zhaolei on 2018/1/5. 7 | */ 8 | 9 | public class SUtil { 10 | 11 | private static Random random = new Random(500); 12 | private static String[] strs; 13 | 14 | static { 15 | strs = new String[]{ 16 | "人生若只如初见,何事秋风悲画扇。", 17 | "我来不及认真地年轻,待明白过来时,只能选择认真地老去。", 18 | "人生本来如此:喜欢的事自然可以坚持,不喜欢的怎么也长久不了。", 19 | "愿时光如玉,别有温润,滚滚凡尘,浮生尽欢", 20 | "今天会很残酷,明天会更残酷" 21 | }; 22 | } 23 | 24 | public static String getTxt(){ 25 | return strs[random.nextInt(strs.length)]; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/drawn/lltvcn/com/util/ZipUtil.java: -------------------------------------------------------------------------------- 1 | package drawn.lltvcn.com.util; 2 | 3 | import java.io.BufferedInputStream; 4 | import java.io.BufferedOutputStream; 5 | import java.io.File; 6 | import java.io.FileInputStream; 7 | import java.io.FileNotFoundException; 8 | import java.io.FileOutputStream; 9 | import java.io.IOException; 10 | import java.io.InputStream; 11 | import java.util.zip.ZipEntry; 12 | import java.util.zip.ZipInputStream; 13 | import java.util.zip.ZipOutputStream; 14 | 15 | public class ZipUtil { 16 | 17 | public static boolean decompress(String zipFilePath,String aimDir,boolean deleteOld){ 18 | try { 19 | return decompress(new FileInputStream(zipFilePath), aimDir, deleteOld); 20 | } catch (FileNotFoundException e) { 21 | e.printStackTrace(); 22 | return false; 23 | } 24 | } 25 | 26 | public static boolean decompress(InputStream inputStream ,String aimDir,boolean deleteOld){ 27 | long startTime=System.currentTimeMillis(); 28 | try { 29 | ZipInputStream Zin=new ZipInputStream(inputStream);//输入源zip路径 30 | BufferedInputStream Bin=new BufferedInputStream(Zin); 31 | File Fout=null; 32 | ZipEntry entry; 33 | File file = new File(aimDir); 34 | if(!file.exists()){ 35 | file.mkdirs(); 36 | }else{ 37 | if(deleteOld){ 38 | file.delete(); 39 | file.mkdirs(); 40 | } 41 | } 42 | 43 | while((entry = Zin.getNextEntry())!=null){ 44 | if(entry.isDirectory()) { 45 | continue; 46 | } 47 | Fout=new File(aimDir,entry.getName()); 48 | if(!Fout.exists()){ 49 | (new File(Fout.getParent())).mkdirs(); 50 | } 51 | FileOutputStream out=new FileOutputStream(Fout); 52 | BufferedOutputStream Bout=new BufferedOutputStream(out); 53 | int b; 54 | while((b=Bin.read())!=-1){ 55 | Bout.write(b); 56 | } 57 | Bout.close(); 58 | out.close(); 59 | System.out.println(Fout+"解压成功"); 60 | } 61 | Bin.close(); 62 | Zin.close(); 63 | long endTime=System.currentTimeMillis(); 64 | System.out.println("耗费时间: "+(endTime-startTime)+" ms"); 65 | return true; 66 | } catch (Exception e) { 67 | e.printStackTrace(); 68 | return false; 69 | } 70 | } 71 | 72 | /** 73 | * 将存放在sourceFilePath目录下的源文件,打包成fileName名称的zip文件,并存放到zipFilePath路径下 74 | * @param sourceFilePath :待压缩的文件路径 75 | * @param zipFilePath :压缩后存放路径 76 | * @param fileName :压缩后文件的名称 77 | * @return 78 | */ 79 | public static boolean compress(String sourceFilePath,String zipFilePath,String fileName){ 80 | boolean flag = false; 81 | File sourceFile = new File(sourceFilePath); 82 | FileInputStream fis = null; 83 | BufferedInputStream bis = null; 84 | FileOutputStream fos = null; 85 | ZipOutputStream zos = null; 86 | 87 | if(sourceFile.exists() == false){ 88 | System.out.println("待压缩的文件目录:"+sourceFilePath+"不存在."); 89 | }else{ 90 | try { 91 | File zipFile = new File(zipFilePath + "/" + fileName +".zip"); 92 | if(zipFile.exists()){ 93 | System.out.println(zipFilePath + "目录下存在名字为:" + fileName +".zip" +"打包文件."); 94 | }else{ 95 | File[] sourceFiles = sourceFile.listFiles(); 96 | if(null == sourceFiles || sourceFiles.length<1){ 97 | System.out.println("待压缩的文件目录:" + sourceFilePath + "里面不存在文件,无需压缩."); 98 | }else{ 99 | fos = new FileOutputStream(zipFile); 100 | zos = new ZipOutputStream(new BufferedOutputStream(fos)); 101 | byte[] bufs = new byte[1024*10]; 102 | for(int i=0;i 2 | 9 | 10 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 31 | 32 | 41 | 42 | 46 | 47 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_array.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 13 | 14 | 18 | 19 | 24 | 25 |