├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── misc.xml ├── modules.xml └── runConfigurations.xml ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── mariostudio │ │ └── texteditorpanel │ │ ├── activitys │ │ ├── BaseActivity.java │ │ ├── MainActivity.java │ │ ├── OtherActivity.java │ │ └── ShowActivity.java │ │ └── weights │ │ └── RoundImageView.java │ └── res │ ├── drawable │ └── shape_btn_sign.xml │ ├── layout │ ├── activity_main.xml │ ├── activity_show.xml │ ├── activity_test.xml │ └── universal_div.xml │ ├── menu │ └── menu_main.xml │ ├── mipmap-hdpi │ ├── a9c.png │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ ├── back.png │ ├── ic_launcher.png │ ├── more.png │ └── photo.jpg │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ ├── values-v21 │ └── styles.xml │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── attrs.xml │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── 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 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | SpannableStringDemo -------------------------------------------------------------------------------- /.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/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 23 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Android 12 | 13 | 14 | Android > Lint > Correctness 15 | 16 | 17 | Java 18 | 19 | 20 | Java language level migration aidsJava 21 | 22 | 23 | 24 | 25 | Android 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 47 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.3" 6 | 7 | defaultConfig { 8 | applicationId "com.mariostudio.texteditorpanel" 9 | minSdkVersion 14 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | testCompile 'junit:junit:4.12' 25 | compile 'com.android.support:appcompat-v7:23.4.0' 26 | compile 'com.android.support:design:23.4.0' 27 | } 28 | -------------------------------------------------------------------------------- /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 E:\android-sdk_r24.3.2-windows/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/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/mariostudio/texteditorpanel/activitys/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.mariostudio.texteditorpanel.activitys; 2 | 3 | import android.annotation.TargetApi; 4 | import android.app.Activity; 5 | import android.os.Build; 6 | import android.os.Bundle; 7 | import android.view.View; 8 | import android.view.Window; 9 | import android.view.WindowManager; 10 | 11 | import com.mariostudio.texteditorpanel.R; 12 | 13 | /** 14 | * Created by MarioStudio on 2016/5/30. 15 | */ 16 | 17 | public class BaseActivity extends Activity { 18 | 19 | @Override 20 | protected void onCreate(Bundle savedInstanceState) { 21 | super.onCreate(savedInstanceState); 22 | //判断SDK版本是否大于等于19,大于就让他显示,小于就要隐藏,不然低版本会多出来一个 23 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 24 | setTranslucentStatus(); 25 | //还有设置View的高度,因为每个型号的手机状态栏高度都不相同 26 | } 27 | } 28 | 29 | @Override 30 | public void setContentView(int layoutResID) { 31 | super.setContentView(layoutResID); 32 | View status = findViewById(android.R.id.custom); 33 | if(status != null) { 34 | status.getLayoutParams().height = getStatusBarHeight(); 35 | } 36 | } 37 | 38 | @TargetApi(19) 39 | private void setTranslucentStatus() { 40 | Window window = getWindow(); 41 | WindowManager.LayoutParams params = window.getAttributes(); 42 | params.flags |= WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; 43 | // params.screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_FULL; // 设置Activity高亮显示 44 | window.setAttributes(params); 45 | } 46 | 47 | public int getStatusBarHeight() { 48 | int result = 0; 49 | int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); 50 | if (resourceId > 0) { 51 | result = getResources().getDimensionPixelSize(resourceId); 52 | } 53 | return result; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/mariostudio/texteditorpanel/activitys/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.mariostudio.texteditorpanel.activitys; 2 | 3 | import android.content.Intent; 4 | import android.graphics.Color; 5 | import android.graphics.Typeface; 6 | import android.os.Bundle; 7 | import android.os.Handler; 8 | import android.os.Message; 9 | import android.text.SpannableString; 10 | import android.text.Spanned; 11 | import android.text.TextPaint; 12 | import android.text.method.LinkMovementMethod; 13 | import android.text.style.BackgroundColorSpan; 14 | import android.text.style.ClickableSpan; 15 | import android.text.style.ForegroundColorSpan; 16 | import android.text.style.RelativeSizeSpan; 17 | import android.text.style.StrikethroughSpan; 18 | import android.text.style.StyleSpan; 19 | import android.text.style.SuperscriptSpan; 20 | import android.text.style.URLSpan; 21 | import android.view.View; 22 | import android.widget.TextView; 23 | 24 | import com.mariostudio.texteditorpanel.R; 25 | 26 | public class MainActivity extends BaseActivity { 27 | 28 | private int position = 0; 29 | private String string; 30 | 31 | private TextView textView01; 32 | private TextView textView02; 33 | private TextView textView03; 34 | private TextView textView04; 35 | private TextView textView05; 36 | private TextView textView06; 37 | private TextView textView07; 38 | 39 | @Override 40 | protected void onCreate(Bundle savedInstanceState) { 41 | super.onCreate(savedInstanceState); 42 | setContentView(R.layout.activity_test); 43 | 44 | textView01 = (TextView) findViewById(R.id.text01); 45 | textView02 = (TextView) findViewById(R.id.text02); 46 | textView03 = (TextView) findViewById(R.id.text03); 47 | textView04 = (TextView) findViewById(R.id.text04); 48 | textView06 = (TextView) findViewById(R.id.text06); 49 | textView07 = (TextView) findViewById(R.id.text07); 50 | String string01 = textView01.getText().toString(); 51 | String string02 = textView02.getText().toString(); 52 | String string03 = textView03.getText().toString(); 53 | String string04 = textView04.getText().toString(); 54 | String string06 = textView06.getText().toString(); 55 | textView05 = (TextView) findViewById(R.id.text05); 56 | string = textView05.getText().toString(); 57 | 58 | SpannableString spannableString01 = new SpannableString(string01); 59 | 60 | ForegroundColorSpan colorSpan01 = new ForegroundColorSpan(Color.parseColor("#0099FF")); 61 | spannableString01.setSpan(colorSpan01, 7, spannableString01.length() - 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 62 | 63 | RelativeSizeSpan sizeSpan01 = new RelativeSizeSpan(1.3f); 64 | spannableString01.setSpan(sizeSpan01, 7, spannableString01.length() - 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 65 | 66 | StyleSpan styleSpan01 = new StyleSpan(Typeface.BOLD); 67 | spannableString01.setSpan(styleSpan01, 7, spannableString01.length() - 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 68 | 69 | textView01.setText(spannableString01); 70 | 71 | SpannableString spannableString02 = new SpannableString(string02); 72 | 73 | URLSpan urlSpan = new URLSpan("http://www.jianshu.com/users/dbae9ac95c78"); 74 | textView02.setHighlightColor(Color.parseColor("#16646464")); 75 | spannableString02.setSpan(urlSpan, 9, spannableString02.length() - 8, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 76 | ForegroundColorSpan colorSpan02 = new ForegroundColorSpan(Color.parseColor("#0099FF")); 77 | spannableString02.setSpan(colorSpan02, 9, spannableString02.length() - 8, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 78 | textView02.setText(spannableString02); 79 | textView02.setMovementMethod(LinkMovementMethod.getInstance()); 80 | 81 | // 82 | // UnderlineSpan underlineSpan02 = new UnderlineSpan(); 83 | // spannableString02.setSpan(underlineSpan02, 9, spannableString02.length() - 8, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 84 | 85 | 86 | SpannableString spannableString03 = new SpannableString(string03); 87 | 88 | ForegroundColorSpan colorSpan03 = new ForegroundColorSpan(Color.parseColor("#EE0000")); 89 | spannableString03.setSpan(colorSpan03, 0, spannableString03.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 90 | 91 | RelativeSizeSpan sizeSpan03 = new RelativeSizeSpan(1.2f); 92 | spannableString03.setSpan(sizeSpan03, 1, spannableString03.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 93 | 94 | StyleSpan styleSpan03 = new StyleSpan(Typeface.BOLD); 95 | spannableString03.setSpan(styleSpan03, 1, spannableString03.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 96 | 97 | textView03.setText(spannableString03); 98 | 99 | SpannableString spannableString04 = new SpannableString(string04); 100 | StrikethroughSpan strikethroughSpan = new StrikethroughSpan(); 101 | spannableString04.setSpan(strikethroughSpan, 0, spannableString04.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 102 | 103 | textView04.setText(spannableString04); 104 | 105 | handler.sendEmptyMessage(0x158); 106 | 107 | 108 | SpannableString spannableString06 = new SpannableString(string06); 109 | ClickableSpan clickableSpan = new MyClickableSpan("123456789"); 110 | ForegroundColorSpan colorSpan04 = new ForegroundColorSpan(Color.parseColor("#FFFFFF")); 111 | BackgroundColorSpan backgroundColorSpan = new BackgroundColorSpan(Color.parseColor("#0099EE")); 112 | spannableString06.setSpan(colorSpan04, 2, 9, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 113 | spannableString06.setSpan(clickableSpan, 2, 9, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 114 | spannableString06.setSpan(backgroundColorSpan, 2, 9, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 115 | textView06.setText(spannableString06); 116 | textView06.setMovementMethod(LinkMovementMethod.getInstance()); 117 | 118 | SpannableString spannableString07 = new SpannableString("22 + 32 = 13"); 119 | SuperscriptSpan superscriptSpan01 = new SuperscriptSpan(); 120 | SuperscriptSpan superscriptSpan02 = new SuperscriptSpan(); 121 | spannableString07.setSpan(superscriptSpan01, 1, 2 ,Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 122 | spannableString07.setSpan(superscriptSpan02, 6, 7 ,Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 123 | RelativeSizeSpan sizeSpan05 = new RelativeSizeSpan(0.5f); 124 | RelativeSizeSpan sizeSpan06 = new RelativeSizeSpan(0.5f); 125 | spannableString07.setSpan(sizeSpan05, 1, 2 ,Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 126 | spannableString07.setSpan(sizeSpan06, 6, 7 ,Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 127 | 128 | textView07.setText(spannableString07); 129 | } 130 | 131 | class MyClickableSpan extends ClickableSpan { 132 | 133 | private String content; 134 | 135 | public MyClickableSpan(String content) { 136 | this.content = content; 137 | } 138 | 139 | @Override 140 | public void updateDrawState(TextPaint ds) { 141 | ds.setUnderlineText(false); 142 | } 143 | 144 | @Override 145 | public void onClick(View widget) { 146 | Intent intent = new Intent(MainActivity.this, OtherActivity.class); 147 | Bundle bundle = new Bundle(); 148 | bundle.putString("content", content); 149 | intent.putExtra("bundle", bundle); 150 | startActivity(intent); 151 | } 152 | } 153 | 154 | Handler handler = new Handler() { 155 | 156 | @Override 157 | public void handleMessage(Message msg) { 158 | super.handleMessage(msg); 159 | switch (msg.what) { 160 | case 0x158: 161 | SpannableString spannableString = new SpannableString(string); 162 | 163 | RelativeSizeSpan sizeSpan = new RelativeSizeSpan(1.2f); 164 | spannableString.setSpan(sizeSpan, position, position + 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 165 | textView05.setText(spannableString); 166 | position++; 167 | if(position >= textView05.getText().toString().length()) { 168 | position = 0; 169 | } 170 | handler.sendEmptyMessageDelayed(0x158, 150); 171 | break; 172 | } 173 | } 174 | }; 175 | } 176 | -------------------------------------------------------------------------------- /app/src/main/java/com/mariostudio/texteditorpanel/activitys/OtherActivity.java: -------------------------------------------------------------------------------- 1 | package com.mariostudio.texteditorpanel.activitys; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.widget.TextView; 6 | 7 | import com.mariostudio.texteditorpanel.R; 8 | 9 | /** 10 | * Created by MarioStudio on 2016/6/5. 11 | */ 12 | public class OtherActivity extends BaseActivity { 13 | 14 | @Override 15 | protected void onCreate(Bundle savedInstanceState) { 16 | super.onCreate(savedInstanceState); 17 | setContentView(R.layout.activity_main); 18 | 19 | TextView textView = (TextView) findViewById(R.id.text01); 20 | Intent intent = getIntent(); 21 | if(intent != null) { 22 | Bundle bundle = intent.getBundleExtra("bundle"); 23 | if(bundle != null) { 24 | String content = bundle.getString("content"); 25 | textView.setText("这是传过来的内容:" + content); 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/mariostudio/texteditorpanel/activitys/ShowActivity.java: -------------------------------------------------------------------------------- 1 | package com.mariostudio.texteditorpanel.activitys; 2 | 3 | import android.content.Intent; 4 | import android.graphics.Color; 5 | import android.graphics.Rasterizer; 6 | import android.graphics.Typeface; 7 | import android.graphics.drawable.Drawable; 8 | import android.os.Bundle; 9 | import android.text.SpannableString; 10 | import android.text.SpannableStringBuilder; 11 | import android.text.Spanned; 12 | import android.text.TextPaint; 13 | import android.text.method.LinkMovementMethod; 14 | import android.text.method.MovementMethod; 15 | import android.text.style.BackgroundColorSpan; 16 | import android.text.style.ClickableSpan; 17 | import android.text.style.DynamicDrawableSpan; 18 | import android.text.style.ForegroundColorSpan; 19 | import android.text.style.ImageSpan; 20 | import android.text.style.RasterizerSpan; 21 | import android.text.style.RelativeSizeSpan; 22 | import android.text.style.StrikethroughSpan; 23 | import android.text.style.StyleSpan; 24 | import android.text.style.SubscriptSpan; 25 | import android.text.style.SuperscriptSpan; 26 | import android.text.style.URLSpan; 27 | import android.text.style.UnderlineSpan; 28 | import android.view.View; 29 | import android.widget.TextView; 30 | 31 | import com.mariostudio.texteditorpanel.R; 32 | 33 | /** 34 | * Created by MarioStudio on 2016/6/5. 35 | */ 36 | 37 | public class ShowActivity extends BaseActivity { 38 | 39 | @Override 40 | protected void onCreate(Bundle savedInstanceState) { 41 | super.onCreate(savedInstanceState); 42 | setContentView(R.layout.activity_show); 43 | TextView textView = (TextView) findViewById(R.id.text01); 44 | 45 | // SpannableString spannableString = new SpannableString("万丈高楼平地起"); 46 | // 47 | // RelativeSizeSpan sizeSpan01 = new RelativeSizeSpan(1.2f); 48 | // RelativeSizeSpan sizeSpan02 = new RelativeSizeSpan(1.4f); 49 | // RelativeSizeSpan sizeSpan03 = new RelativeSizeSpan(1.6f); 50 | // RelativeSizeSpan sizeSpan04 = new RelativeSizeSpan(1.8f); 51 | // RelativeSizeSpan sizeSpan05 = new RelativeSizeSpan(1.6f); 52 | // RelativeSizeSpan sizeSpan06 = new RelativeSizeSpan(1.4f); 53 | // RelativeSizeSpan sizeSpan07 = new RelativeSizeSpan(1.2f); 54 | // 55 | // spannableString.setSpan(sizeSpan01, 0, 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 56 | // spannableString.setSpan(sizeSpan02, 1, 2, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 57 | // spannableString.setSpan(sizeSpan03, 2, 3, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 58 | // spannableString.setSpan(sizeSpan04, 3, 4, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 59 | // spannableString.setSpan(sizeSpan05, 4, 5, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 60 | // spannableString.setSpan(sizeSpan06, 5, 6, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 61 | // spannableString.setSpan(sizeSpan07, 6, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 62 | 63 | 64 | 65 | // SpannableString spannableString = new SpannableString("设置文字的前景色为淡蓝色"); 66 | // ForegroundColorSpan colorSpan = new ForegroundColorSpan(Color.parseColor("#0099EE")); 67 | // spannableString.setSpan(colorSpan, 9, spannableString.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 68 | 69 | 70 | 71 | // SpannableString spannableString = new SpannableString("设置文字的背景色为淡绿色"); 72 | // BackgroundColorSpan colorSpan = new BackgroundColorSpan(Color.parseColor("#AC00FF30")); 73 | // spannableString.setSpan(colorSpan, 9, spannableString.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 74 | 75 | 76 | 77 | // SpannableString spannableString = new SpannableString("为文字设置下划线"); 78 | // UnderlineSpan underlineSpan = new UnderlineSpan(); 79 | // spannableString.setSpan(underlineSpan, 5, spannableString.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 80 | 81 | 82 | 83 | // SpannableString spannableString = new SpannableString("为文字设置删除线"); 84 | // StrikethroughSpan strikethroughSpan = new StrikethroughSpan(); 85 | // spannableString.setSpan(strikethroughSpan, 5, spannableString.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 86 | 87 | 88 | 89 | // SpannableString spannableString = new SpannableString("为文字设置上标"); 90 | // SuperscriptSpan superscriptSpan = new SuperscriptSpan(); 91 | // spannableString.setSpan(superscriptSpan, 5, spannableString.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 92 | 93 | 94 | 95 | // SpannableString spannableString = new SpannableString("为文字设置下标"); 96 | // SubscriptSpan subscriptSpan = new SubscriptSpan(); 97 | // spannableString.setSpan(subscriptSpan, 5, spannableString.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 98 | 99 | 100 | 101 | // SpannableString spannableString = new SpannableString("为文字设置超链接"); 102 | // URLSpan urlSpan = new URLSpan("http://www.jianshu.com/users/dbae9ac95c78"); 103 | // spannableString.setSpan(urlSpan, 5, spannableString.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 104 | // textView.setMovementMethod(LinkMovementMethod.getInstance()); 105 | // textView.setHighlightColor(Color.parseColor("#36969696")); 106 | 107 | 108 | 109 | // SpannableString spannableString = new SpannableString("为文字设置点击事件"); 110 | // MyClickableSpan clickableSpan = new MyClickableSpan("http://www.jianshu.com/users/dbae9ac95c78"); 111 | // spannableString.setSpan(clickableSpan, 5, spannableString.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 112 | // textView.setMovementMethod(LinkMovementMethod.getInstance()); 113 | // textView.setHighlightColor(Color.parseColor("#36969696")); 114 | 115 | 116 | 117 | // SpannableString spannableString = new SpannableString("为文字设置粗体、斜体风格"); 118 | // StyleSpan styleSpan_B = new StyleSpan(Typeface.BOLD); 119 | // StyleSpan styleSpan_I = new StyleSpan(Typeface.ITALIC); 120 | // spannableString.setSpan(styleSpan_B, 5, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 121 | // spannableString.setSpan(styleSpan_I, 8, 10, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 122 | // textView.setMovementMethod(LinkMovementMethod.getInstance()); 123 | // textView.setHighlightColor(Color.parseColor("#36969696")); 124 | 125 | 126 | 127 | // SpannableString spannableString = new SpannableString("在文本中添加表情(表情)"); 128 | // Drawable drawable = getResources().getDrawable(R.mipmap.a9c); 129 | // drawable.setBounds(0, 0, 42, 42); 130 | // ImageSpan imageSpan = new ImageSpan(drawable); 131 | // spannableString.setSpan(imageSpan, 6, 8, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 132 | // textView.setMovementMethod(LinkMovementMethod.getInstance()); 133 | // textView.setHighlightColor(Color.parseColor("#36969696")); 134 | 135 | 136 | 137 | // SpannableString spannableString = new SpannableString("为文字设置图片(图片)"); 138 | // Drawable drawable = getResources().getDrawable(R.mipmap.ic_launcher); 139 | // drawable.setBounds(0, 0, 36, 36); 140 | // ImageSpan imageSpan = new ImageSpan(drawable); 141 | // spannableString.setSpan(imageSpan, 5, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 142 | // textView.setMovementMethod(LinkMovementMethod.getInstance()); 143 | // textView.setHighlightColor(Color.parseColor("#36969696")); 144 | 145 | // textView.setText(spannableString); 146 | } 147 | 148 | class MyClickableSpan extends ClickableSpan { 149 | 150 | private String content; 151 | 152 | public MyClickableSpan(String content) { 153 | this.content = content; 154 | } 155 | 156 | @Override 157 | public void updateDrawState(TextPaint ds) { 158 | ds.setUnderlineText(false); 159 | } 160 | 161 | @Override 162 | public void onClick(View widget) { 163 | Intent intent = new Intent(ShowActivity.this, OtherActivity.class); 164 | Bundle bundle = new Bundle(); 165 | bundle.putString("content", content); 166 | intent.putExtra("bundle", bundle); 167 | startActivity(intent); 168 | } 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /app/src/main/java/com/mariostudio/texteditorpanel/weights/RoundImageView.java: -------------------------------------------------------------------------------- 1 | package com.mariostudio.texteditorpanel.weights; 2 | 3 | /** 4 | * Created by MarioStudio on 2016/3/16. 5 | */ 6 | 7 | import android.content.Context; 8 | import android.content.res.TypedArray; 9 | import android.graphics.Bitmap; 10 | import android.graphics.BitmapShader; 11 | import android.graphics.Canvas; 12 | import android.graphics.Matrix; 13 | import android.graphics.Paint; 14 | import android.graphics.PixelFormat; 15 | import android.graphics.RectF; 16 | import android.graphics.Shader.TileMode; 17 | import android.graphics.drawable.BitmapDrawable; 18 | import android.graphics.drawable.Drawable; 19 | import android.graphics.drawable.NinePatchDrawable; 20 | import android.os.Bundle; 21 | import android.os.Parcelable; 22 | import android.util.AttributeSet; 23 | import android.util.Log; 24 | import android.util.TypedValue; 25 | import android.widget.ImageView; 26 | 27 | import com.mariostudio.texteditorpanel.R; 28 | 29 | public class RoundImageView extends ImageView { 30 | 31 | /** 32 | * 图片的类型,圆形or圆角 33 | */ 34 | private int type; 35 | public static final int TYPE_ROUND = 1; 36 | public static final int TYPE_CIRCLE = 0; 37 | 38 | /** 39 | * 圆角大小的默认值 40 | */ 41 | private static final int BODER_RADIUS_DEFAULT = 10; 42 | /** 43 | * 圆角的大小 44 | */ 45 | private int mBorderRadius; 46 | /** 47 | * 绘图的Paint 48 | */ 49 | private Paint mBitmapPaint; 50 | /** 51 | * 圆角的半径 52 | * */ 53 | private int mRadius; 54 | /** 55 | * 3x3 矩阵,主要用于缩小放大 56 | * */ 57 | private Matrix mMatrix; 58 | /** 59 | * 渲染图像,使用图像为绘制图形着色 60 | */ 61 | private BitmapShader mBitmapShader; 62 | /** 63 | * view的宽度 64 | * */ 65 | private int mWidth; 66 | private RectF mRoundRect; 67 | 68 | public RoundImageView(Context context, AttributeSet attrs) { 69 | super(context, attrs); 70 | mMatrix = new Matrix(); 71 | mBitmapPaint = new Paint(); 72 | mBitmapPaint.setAntiAlias(true); 73 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundImageView); 74 | mBorderRadius = a.getDimensionPixelSize(R.styleable.RoundImageView_borderRadius, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, BODER_RADIUS_DEFAULT, getResources().getDisplayMetrics())); 75 | type = a.getInt(R.styleable.RoundImageView_type, TYPE_CIRCLE); 76 | a.recycle(); 77 | } 78 | 79 | public RoundImageView(Context context) { 80 | this(context, null); 81 | } 82 | 83 | @Override 84 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 85 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 86 | /** 87 | * 如果类型是圆形,则强制改变view的宽高一致,以小值为准 88 | * */ 89 | if (type == TYPE_CIRCLE) { 90 | mWidth = Math.min(getMeasuredWidth(), getMeasuredHeight()); 91 | mRadius = mWidth / 2; 92 | setMeasuredDimension(mWidth, mWidth); 93 | } 94 | } 95 | 96 | /** 97 | * 初始化BitmapShader 98 | */ 99 | private boolean setUpShader() { 100 | Drawable drawable = getDrawable(); 101 | if (drawable == null) { 102 | return false; 103 | } 104 | Bitmap bmp = drawableToBitamp(drawable); 105 | if(bmp==null) { 106 | return false; 107 | } 108 | // 将bmp作为着色器,就是在指定区域内绘制bmp 109 | mBitmapShader = new BitmapShader(bmp, TileMode.CLAMP, TileMode.CLAMP); 110 | float scale = 1.0f; 111 | if (type == TYPE_CIRCLE) { 112 | // 拿到bitmap宽或高的小值 113 | int bSize = Math.min(bmp.getWidth(), bmp.getHeight()); 114 | scale = mWidth * 1.0f / bSize; 115 | } 116 | else if (type == TYPE_ROUND) { 117 | Log.e("TAG", "b'w = " + bmp.getWidth() + " , " + "b'h = " + bmp.getHeight()); 118 | if (!(bmp.getWidth() == getWidth() && bmp.getHeight() == getHeight())) { 119 | // 如果图片的宽或者高与view的宽高不匹配,计算出需要缩放的比例; 120 | // 缩放后的图片的宽高,一定要大于我们view的宽高;所以我们这里取大值; 121 | scale = Math.max(getWidth() * 1.0f / bmp.getWidth(), getHeight() * 1.0f / bmp.getHeight()); 122 | } 123 | } 124 | // shader的变换矩阵,我们这里主要用于放大或者缩小 125 | mMatrix.setScale(scale, scale); 126 | // 设置变换矩阵 127 | mBitmapShader.setLocalMatrix(mMatrix); 128 | // 设置shader 129 | mBitmapPaint.setShader(mBitmapShader); 130 | return true; 131 | } 132 | 133 | @Override 134 | protected void onDraw(Canvas canvas) { 135 | Log.e("TAG", "onDraw"); 136 | if (getDrawable() == null) { 137 | return; 138 | } 139 | if(setUpShader()){ 140 | if (type == TYPE_ROUND) { 141 | canvas.drawRoundRect(mRoundRect, mBorderRadius, mBorderRadius, mBitmapPaint); 142 | } 143 | else { 144 | canvas.drawCircle(mRadius, mRadius, mRadius, mBitmapPaint); 145 | } 146 | } 147 | } 148 | 149 | @Override 150 | protected void onSizeChanged(int w, int h, int oldw, int oldh) { 151 | super.onSizeChanged(w, h, oldw, oldh); 152 | // 圆角图片的范围 153 | if (type == TYPE_ROUND){ 154 | mRoundRect = new RectF(0, 0, w, h); 155 | } 156 | } 157 | 158 | /** 159 | * drawable转bitmap 160 | * @param drawable 161 | * @return 162 | */ 163 | private Bitmap drawableToBitamp(Drawable drawable) { 164 | if (drawable instanceof BitmapDrawable) { 165 | BitmapDrawable bd = (BitmapDrawable) drawable; 166 | return bd.getBitmap(); 167 | }else if(drawable instanceof NinePatchDrawable) { 168 | Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565); 169 | Canvas canvas = new Canvas(bitmap); 170 | drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); 171 | drawable.draw(canvas); 172 | return bitmap; 173 | }else { 174 | return null; 175 | } 176 | // int w = drawable.getIntrinsicWidth(); 177 | // int h = drawable.getIntrinsicHeight(); 178 | // Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); 179 | // Canvas canvas = new Canvas(bitmap); 180 | // drawable.setBounds(0, 0, w, h); 181 | // drawable.draw(canvas); 182 | // return bitmap; 183 | } 184 | 185 | private static final String STATE_INSTANCE = "state_instance"; 186 | private static final String STATE_TYPE = "state_type"; 187 | private static final String STATE_BORDER_RADIUS = "state_border_radius"; 188 | 189 | @Override 190 | protected Parcelable onSaveInstanceState() { 191 | Bundle bundle = new Bundle(); 192 | bundle.putParcelable(STATE_INSTANCE, super.onSaveInstanceState()); 193 | bundle.putInt(STATE_TYPE, type); 194 | bundle.putInt(STATE_BORDER_RADIUS, mBorderRadius); 195 | return bundle; 196 | } 197 | 198 | @Override 199 | protected void onRestoreInstanceState(Parcelable state) { 200 | if (state instanceof Bundle) { 201 | Bundle bundle = (Bundle) state; 202 | super.onRestoreInstanceState(((Bundle) state).getParcelable(STATE_INSTANCE)); 203 | this.type = bundle.getInt(STATE_TYPE); 204 | this.mBorderRadius = bundle.getInt(STATE_BORDER_RADIUS); 205 | } 206 | else { 207 | super.onRestoreInstanceState(state); 208 | } 209 | } 210 | 211 | public void setBorderRadius(int borderRadius) { 212 | int pxVal = dp2px(borderRadius); 213 | if (this.mBorderRadius != pxVal) { 214 | this.mBorderRadius = pxVal; 215 | invalidate(); 216 | } 217 | } 218 | 219 | public void setType(int type) { 220 | if (this.type != type) { 221 | this.type = type; 222 | if (this.type != TYPE_ROUND && this.type != TYPE_CIRCLE) { 223 | this.type = TYPE_CIRCLE; 224 | } 225 | requestLayout(); 226 | } 227 | } 228 | 229 | public int dp2px(int dpVal) { 230 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal, getResources().getDisplayMetrics()); 231 | } 232 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_btn_sign.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | 17 | 18 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_show.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | 17 | 18 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_test.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 15 | 19 | 20 | 26 | 27 | 34 | 35 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 58 | 59 | 65 | 66 | 72 | 73 | 79 | 80 | 88 | 89 | 90 | 100 | 101 | 102 | 112 | 113 | 121 | 122 | 123 | 134 | 135 | 142 | 143 | 144 | 155 | 156 | 162 | 163 | 164 | 175 | 176 | 183 | 184 | 194 | 195 | 196 | 202 | 203 | 211 | 212 | 213 | -------------------------------------------------------------------------------- /app/src/main/res/layout/universal_div.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/a9c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WuLiFei/SpannableStringDemo/c31f7c7d09af352d9f175f96a4c54fb29c09a9c7/app/src/main/res/mipmap-hdpi/a9c.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WuLiFei/SpannableStringDemo/c31f7c7d09af352d9f175f96a4c54fb29c09a9c7/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WuLiFei/SpannableStringDemo/c31f7c7d09af352d9f175f96a4c54fb29c09a9c7/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WuLiFei/SpannableStringDemo/c31f7c7d09af352d9f175f96a4c54fb29c09a9c7/app/src/main/res/mipmap-xhdpi/back.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WuLiFei/SpannableStringDemo/c31f7c7d09af352d9f175f96a4c54fb29c09a9c7/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/more.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WuLiFei/SpannableStringDemo/c31f7c7d09af352d9f175f96a4c54fb29c09a9c7/app/src/main/res/mipmap-xhdpi/more.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/photo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WuLiFei/SpannableStringDemo/c31f7c7d09af352d9f175f96a4c54fb29c09a9c7/app/src/main/res/mipmap-xhdpi/photo.jpg -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WuLiFei/SpannableStringDemo/c31f7c7d09af352d9f175f96a4c54fb29c09a9c7/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WuLiFei/SpannableStringDemo/c31f7c7d09af352d9f175f96a4c54fb29c09a9c7/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | > 2 | 3 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 16dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | TextEditorPanel 3 | Settings 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 15 | 16 |