├── .gitignore ├── .idea ├── caches │ └── build_file_checksums.ser ├── codeStyles │ └── Project.xml ├── gradle.xml ├── inspectionProfiles │ └── Project_Default.xml ├── misc.xml └── runConfigurations.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro ├── screenshoots │ ├── 2.gif │ ├── 3.png │ ├── collapse.gif │ ├── 基础.gif │ ├── 折叠Text.gif │ ├── 效果1.gif │ ├── 效果2.gif │ └── 设置paddin_bottom.png └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── example │ │ └── apple │ │ ├── keyboarddemo │ │ ├── RedDotView.java │ │ ├── Register2Activity.java │ │ ├── RegisterActivity.java │ │ ├── SessionActivity.java │ │ ├── SplashActivity.java │ │ ├── collapse │ │ │ ├── CollapseActivity.java │ │ │ └── ExpandLayout.java │ │ ├── expand │ │ │ └── ExpandTextView.java │ │ ├── focus │ │ │ └── SoftFocusActivity.java │ │ ├── keyboard_num │ │ │ ├── CustomNumKeyboardView.java │ │ │ ├── KeyBoardNumberActivity.java │ │ │ └── KeyboardNumUtil.java │ │ ├── shelter_aty │ │ │ └── ShelterActivity.java │ │ ├── top_dismiss │ │ │ ├── TopDismissFirstActivity.java │ │ │ ├── TopDismissSecondActivity.java │ │ │ └── TopDismissThirdActivity.java │ │ └── topic │ │ │ ├── BottomDialog.java │ │ │ ├── BottomSheetBar.java │ │ │ ├── RichEditText.java │ │ │ └── TopicActivity.java │ │ └── todo.txt │ └── res │ ├── drawable-v24 │ └── ic_launcher_foreground.xml │ ├── drawable │ ├── bg_border_color_black.xml │ ├── bg_comment.xml │ ├── bg_splash.jpg │ ├── ic_bg_edit.xml │ ├── ic_bg_edit_active.xml │ ├── ic_bg_edit_normal.xml │ ├── ic_launcher_background.xml │ ├── ic_selector_checkbox.xml │ ├── iconmbile.png │ ├── keyboard_btn_bg.xml │ ├── keyboard_btn_normal.9.png │ ├── keyboard_btn_normal_bg.xml │ ├── keyboard_btn_pressed.9.png │ ├── keyboard_cofirm_btn_bg.xml │ ├── keyboard_confirm_btn.9.png │ ├── keyboard_confirm_btn_pressed.9.png │ ├── keyboard_delete_btn.9.png │ ├── keyboard_delete_btn_bg.xml │ ├── keyboard_delete_btn_pressed.9.png │ ├── keyboard_delete_icon.png │ ├── keyboard_fold_icon.png │ ├── selector_edit_focus.xml │ ├── shape_bottom_gray.xml │ ├── shape_bottom_green.xml │ ├── shape_session_btn_send.xml │ └── shape_session_btn_voice_normal.xml │ ├── layout │ ├── activity_collapse.xml │ ├── activity_keyboard_number.xml │ ├── activity_register.xml │ ├── activity_register2.xml │ ├── activity_session.xml │ ├── activity_shelter.xml │ ├── activity_soft_focus.xml │ ├── activity_splash.xml │ ├── activity_top_dismiss_first.xml │ ├── activity_top_dismiss_second.xml │ ├── activity_top_dismiss_third.xml │ ├── activity_topic.xml │ ├── layout_bottom_sheet_comment_bar.xml │ ├── layout_test.xml │ └── textview_expand_shink.xml │ ├── mipmap-anydpi-v26 │ ├── ic_launcher.xml │ └── ic_launcher_round.xml │ ├── mipmap-hdpi │ ├── ic_cheat_add.png │ ├── ic_cheat_emo.png │ ├── ic_cheat_voice.png │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-mdpi │ ├── ic_back2.png │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xhdpi │ ├── ic_expand_down.png │ ├── ic_expand_up.png │ ├── ic_launcher.png │ ├── ic_launcher_round.png │ └── keyicon.png │ ├── mipmap-xxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxxhdpi │ ├── form_checkbox_checked.png │ ├── form_checkbox_normal.png │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── values-v19 │ └── styles.xml │ ├── values │ ├── colors.xml │ ├── dimens.xml │ ├── layout_style.xml │ ├── strings.xml │ └── styles.xml │ └── xml │ └── keyboard_num_woith_dot.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/libraries 5 | /.idea/modules.xml 6 | /.idea/workspace.xml 7 | .DS_Store 8 | /build 9 | /captures 10 | .externalNativeBuild 11 | -------------------------------------------------------------------------------- /.idea/caches/build_file_checksums.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyzhangxl/KeyBoardDemo/d7c1bd3eb087e3bb542e29b0686c89f9f28b8843/.idea/caches/build_file_checksums.ser -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 21 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 36 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 37 | 38 | 39 | 40 | 41 | 42 | 44 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # KeyBoardDemo 2 | ## 1. 简介 3 | 本篇博客将实现一个自定义软键盘实现数字录入的小Demo,也是为之后可能遇到的输入手机号,支付键盘等做一些知识上的储备,也是希望能够帮到处于学习的同学, 4 | 在写的不对的地方希望各位能够指出来。含有demo。 5 | ## 2.运行效果: 6 |
7 | 8 |
9 |               10 |
11 | 12 |
13 |

14 |               15 | 16 | ## 3. 折叠TextView以及折叠Layout展示 17 |               18 |
19 | 20 |
21 | 22 |
23 | 24 |
25 | 26 | ## 4. [博客地址](https://blog.csdn.net/crazyZhangxl/article/details/83141724) 27 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 26 5 | defaultConfig { 6 | applicationId "com.example.apple.keyboarddemo" 7 | minSdkVersion 16 8 | targetSdkVersion 26 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | implementation fileTree(dir: 'libs', include: ['*.jar']) 23 | implementation 'com.android.support:appcompat-v7:26.1.0' 24 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 25 | testImplementation 'junit:junit:4.12' 26 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 27 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 28 | implementation 'com.android.support:design:26.1.0' 29 | implementation 'com.lqr.emoji:library:1.0.2' 30 | implementation 'cn.yc:YCRedDotViewLib:1.0.3' 31 | } 32 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/screenshoots/2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyzhangxl/KeyBoardDemo/d7c1bd3eb087e3bb542e29b0686c89f9f28b8843/app/screenshoots/2.gif -------------------------------------------------------------------------------- /app/screenshoots/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyzhangxl/KeyBoardDemo/d7c1bd3eb087e3bb542e29b0686c89f9f28b8843/app/screenshoots/3.png -------------------------------------------------------------------------------- /app/screenshoots/collapse.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyzhangxl/KeyBoardDemo/d7c1bd3eb087e3bb542e29b0686c89f9f28b8843/app/screenshoots/collapse.gif -------------------------------------------------------------------------------- /app/screenshoots/基础.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyzhangxl/KeyBoardDemo/d7c1bd3eb087e3bb542e29b0686c89f9f28b8843/app/screenshoots/基础.gif -------------------------------------------------------------------------------- /app/screenshoots/折叠Text.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyzhangxl/KeyBoardDemo/d7c1bd3eb087e3bb542e29b0686c89f9f28b8843/app/screenshoots/折叠Text.gif -------------------------------------------------------------------------------- /app/screenshoots/效果1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyzhangxl/KeyBoardDemo/d7c1bd3eb087e3bb542e29b0686c89f9f28b8843/app/screenshoots/效果1.gif -------------------------------------------------------------------------------- /app/screenshoots/效果2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyzhangxl/KeyBoardDemo/d7c1bd3eb087e3bb542e29b0686c89f9f28b8843/app/screenshoots/效果2.gif -------------------------------------------------------------------------------- /app/screenshoots/设置paddin_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyzhangxl/KeyBoardDemo/d7c1bd3eb087e3bb542e29b0686c89f9f28b8843/app/screenshoots/设置paddin_bottom.png -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 14 | 15 | 18 | 21 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 34 | 38 | 41 | 45 | 49 | 52 | 56 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/apple/keyboarddemo/RedDotView.java: -------------------------------------------------------------------------------- 1 | package com.example.apple.keyboarddemo; 2 | 3 | import android.content.Context; 4 | import android.graphics.Color; 5 | import android.graphics.Typeface; 6 | import android.graphics.drawable.ShapeDrawable; 7 | import android.graphics.drawable.shapes.RoundRectShape; 8 | import android.os.Build; 9 | import android.support.v7.widget.AppCompatTextView; 10 | import android.util.AttributeSet; 11 | import android.util.TypedValue; 12 | import android.view.Gravity; 13 | 14 | /** 15 | * Created by apple on 2019/7/25. 16 | * description: 17 | */ 18 | public class RedDotView extends AppCompatTextView { 19 | public RedDotView(Context context) { 20 | this(context,null); 21 | } 22 | 23 | public RedDotView(Context context, AttributeSet attrs) { 24 | this(context, attrs,0); 25 | } 26 | 27 | public RedDotView(Context context, AttributeSet attrs, int defStyleAttr) { 28 | super(context, attrs, defStyleAttr); 29 | initViews(); 30 | } 31 | 32 | private void initViews() { 33 | setTextView(); 34 | } 35 | 36 | private void setTextView() { 37 | setTextColor(Color.WHITE); 38 | setTypeface(Typeface.DEFAULT_BOLD); 39 | setTextSize(TypedValue.COMPLEX_UNIT_SP, 10); 40 | setPadding(dip2Px(5), dip2Px(1), dip2Px(5), dip2Px(1)); 41 | setBackground(9, Color.parseColor("#f14850")); 42 | setGravity(Gravity.CENTER); 43 | } 44 | 45 | private int dip2Px(float dip) { 46 | return (int) (dip * getContext().getResources().getDisplayMetrics().density + 0.5f); 47 | } 48 | 49 | /** 50 | * 设置背景颜色 51 | * @param dipRadius 半径 52 | * @param badgeColor 颜色 53 | */ 54 | private void setBackground(int dipRadius, int badgeColor) { 55 | int radius = dip2Px(dipRadius); 56 | float[] radiusArray = new float[]{radius, radius, radius, radius, 57 | radius, radius, radius, radius}; 58 | RoundRectShape roundRect = new RoundRectShape(radiusArray, null, null); 59 | ShapeDrawable bgDrawable = new ShapeDrawable(roundRect); 60 | bgDrawable.getPaint().setColor(badgeColor); 61 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 62 | setBackground(bgDrawable); 63 | } 64 | } 65 | 66 | /** 67 | * 设置红点的数字 68 | * @param count 数字 69 | */ 70 | public void setBadgeCount(int count) { 71 | //设置参数,超过99显示99+ 72 | if (count == 0){ 73 | setVisibility(GONE); 74 | return; 75 | } 76 | if (getVisibility() == GONE){ 77 | setVisibility(VISIBLE); 78 | } 79 | setBadgeCount(count > 99 ? "99+" : String.valueOf(count)); 80 | } 81 | 82 | private void setBadgeCount(String count) { 83 | setText(count); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/apple/keyboarddemo/Register2Activity.java: -------------------------------------------------------------------------------- 1 | package com.example.apple.keyboarddemo; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.view.View; 6 | import android.view.WindowManager; 7 | import android.widget.LinearLayout; 8 | import android.widget.RelativeLayout; 9 | 10 | /** 11 | * @author crazyZhangxl on 2018-12-22 19:43:19. 12 | * Describe: 13 | */ 14 | 15 | public class Register2Activity extends AppCompatActivity { 16 | private LinearLayout mLinearLayout; 17 | private RelativeLayout mRelativeLayout; 18 | @Override 19 | protected void onCreate(Bundle savedInstanceState) { 20 | super.onCreate(savedInstanceState); 21 | getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); 22 | setContentView(R.layout.activity_register2); 23 | mLinearLayout = findViewById(R.id.ll); 24 | mRelativeLayout = findViewById(R.id.rl); 25 | mLinearLayout.setOnClickListener(new View.OnClickListener() { 26 | @Override 27 | public void onClick(View v) { 28 | mRelativeLayout.setVisibility(View.VISIBLE); 29 | } 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/apple/keyboarddemo/RegisterActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.apple.keyboarddemo; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.graphics.Rect; 6 | import android.os.Build; 7 | import android.support.annotation.RequiresApi; 8 | import android.support.v7.app.AlertDialog; 9 | import android.support.v7.app.AppCompatActivity; 10 | import android.os.Bundle; 11 | import android.util.DisplayMetrics; 12 | import android.util.Log; 13 | import android.view.View; 14 | import android.view.ViewTreeObserver; 15 | import android.view.inputmethod.InputMethodManager; 16 | import android.widget.Button; 17 | import android.widget.EditText; 18 | import android.widget.LinearLayout; 19 | 20 | import com.example.apple.keyboarddemo.shelter_aty.ShelterActivity; 21 | 22 | /** 23 | * @author crazyZhangxl on 2018-12-22 13:27:56. 24 | * Describe: 25 | */ 26 | 27 | public class RegisterActivity extends AppCompatActivity { 28 | private Button mBtn; 29 | private LinearLayout mLinearLayout; 30 | private int mButtonHeight; 31 | private ViewTreeObserver mTreeObserver; 32 | private ViewTreeObserver.OnGlobalLayoutListener mListener; 33 | @Override 34 | protected void onCreate(Bundle savedInstanceState) { 35 | super.onCreate(savedInstanceState); 36 | setContentView(R.layout.activity_register); 37 | initViews(); 38 | initListener(); 39 | } 40 | 41 | private void initListener() { 42 | 43 | findViewById(R.id.ivToolbarNavigation).setOnClickListener(new View.OnClickListener() { 44 | @Override 45 | public void onClick(View v) { 46 | hideSoft(); 47 | startActivity(new Intent(RegisterActivity.this, ShelterActivity.class)); 48 | } 49 | }); 50 | 51 | mBtn.setOnClickListener(new View.OnClickListener() { 52 | @Override 53 | public void onClick(View v) { 54 | showDialog(); 55 | } 56 | }); 57 | 58 | buttonBeyondKeyboardLayout(mLinearLayout,mBtn); 59 | } 60 | 61 | @Override 62 | protected void onResume() { 63 | super.onResume(); 64 | 65 | } 66 | 67 | private void initViews() { 68 | mLinearLayout = findViewById(R.id.content); 69 | mBtn = findViewById(R.id.btnNext); 70 | 71 | } 72 | 73 | /** 74 | * 移动的布局 75 | * @param root 需要移动的布局 76 | * @param button 最底部的布局 77 | */ 78 | private void buttonBeyondKeyboardLayout(final View root,final View button) { 79 | mListener = new ViewTreeObserver.OnGlobalLayoutListener() { 80 | @Override 81 | public void onGlobalLayout() { 82 | Log.e("测试", "-------统计测量------" ); 83 | Rect rect = new Rect(); 84 | // 获得当前窗口的可视区域的大小 85 | getWindow().getDecorView().getWindowVisibleDisplayFrame(rect); 86 | // 当前窗口的高度 - 可见区域的底部 = 不可见窗体的大小[即软件盘的高度] 87 | int rootInvisibleHeight = getWindow().getDecorView().getHeight() - rect.bottom; 88 | 89 | // 事件为弹出软键盘时,软件盘至少有100px吧 这里100可以替换为软件盘的高度 90 | if (rootInvisibleHeight > 100) { 91 | int[] location = new int[2]; 92 | // 获得按钮即所要检测的视图的高 93 | button.getLocationInWindow(location); 94 | // 按钮的底部------ 95 | int buttonHeight = button.getHeight() + location[1]; 96 | // ************** 判断是否需要进行移动 ************** 97 | if (rect.bottom > buttonHeight) { 98 | // 如果不需要移动那么直接移除 99 | if (mListener != null && mTreeObserver.isAlive()) { 100 | mTreeObserver.removeOnGlobalLayoutListener(this); 101 | } 102 | mListener = null; 103 | } else { 104 | // 计算向上移动的高度 105 | mButtonHeight = (buttonHeight - rect.bottom + dpToPx(20)); 106 | Log.e("软键盘", "onGlobalLayout: = "+mButtonHeight); 107 | // 注意scroll,移动的是内容 108 | root.scrollTo(0, mButtonHeight); 109 | } 110 | } else { 111 | // 软键盘隐藏进行还原 112 | root.scrollTo(0, 0); 113 | } 114 | } 115 | }; 116 | mTreeObserver = root.getViewTreeObserver(); 117 | mTreeObserver.addOnGlobalLayoutListener(mListener); 118 | } 119 | 120 | @Override 121 | protected void onDestroy() { 122 | if (mListener != null && mTreeObserver != null && mTreeObserver.isAlive()) { 123 | mTreeObserver.removeOnGlobalLayoutListener(mListener); 124 | } 125 | super.onDestroy(); 126 | } 127 | 128 | private void hideSoft(){ 129 | InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); 130 | // 隐藏软键盘 imm.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), 0); 131 | // 延迟个0.1秒是因为 可能推出太快导致软键盘刚刚被回收,前面的界面出现断层 132 | try { 133 | Thread.sleep(50); 134 | } catch (InterruptedException e) { 135 | e.printStackTrace(); 136 | } 137 | } 138 | 139 | private int dpToPx(int dp){ 140 | DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); 141 | return Math.round(displayMetrics.density*dp); 142 | } 143 | 144 | /** 145 | * 用于测试是否弹出dialog会重新绘制布局 146 | * 147 | * ------------- 经过测试是不会影响布局的[可以放心的使用] ---------- 148 | */ 149 | private void showDialog(){ 150 | AlertDialog alertDialog = new AlertDialog.Builder(this).setTitle("测试标题") 151 | .setMessage("只是用于测试弹出框是否影响布局重绘制") 152 | .setNegativeButton("取消", null) 153 | .setPositiveButton("对", null) 154 | .create(); 155 | alertDialog.show(); 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/apple/keyboarddemo/SessionActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.apple.keyboarddemo; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.text.Editable; 6 | import android.text.TextWatcher; 7 | import android.view.View; 8 | import android.view.WindowManager; 9 | import android.widget.Button; 10 | import android.widget.EditText; 11 | import android.widget.FrameLayout; 12 | import android.widget.ImageView; 13 | import android.widget.LinearLayout; 14 | 15 | import com.lqr.emoji.EmotionKeyboard; 16 | import com.lqr.emoji.EmotionLayout; 17 | 18 | /** 19 | * @author crazyZhangxl on 2018-12-22 16:31:38. 20 | * Describe: 模拟聊天布局 21 | */ 22 | 23 | public class SessionActivity extends AppCompatActivity { 24 | private EditText mEtContent; 25 | private Button mBtnSend; 26 | private ImageView mIvMore; 27 | 28 | @Override 29 | protected void onCreate(Bundle savedInstanceState) { 30 | super.onCreate(savedInstanceState); 31 | getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); 32 | setContentView(R.layout.activity_session); 33 | initViews(); 34 | initListener(); 35 | } 36 | 37 | private void initListener() { 38 | mEtContent.addTextChangedListener(new TextWatcher() { 39 | @Override 40 | public void beforeTextChanged(CharSequence s, int start, int count, int after) { 41 | 42 | } 43 | 44 | @Override 45 | public void onTextChanged(CharSequence s, int start, int before, int count) { 46 | if (mEtContent.getText().toString().trim().length() > 0) { 47 | // 如果输入框中有内容 那么进行更多的切换 48 | mBtnSend.setVisibility(View.VISIBLE); 49 | mIvMore.setVisibility(View.GONE); 50 | // 这个表示用户正在输入 ==== 51 | } else { 52 | mBtnSend.setVisibility(View.GONE); 53 | mIvMore.setVisibility(View.VISIBLE); 54 | } 55 | } 56 | 57 | @Override 58 | public void afterTextChanged(Editable s) { 59 | 60 | } 61 | }); 62 | } 63 | 64 | private void initViews() { 65 | mEtContent = findViewById(R.id.etContent); 66 | mBtnSend = findViewById(R.id.btnSend); 67 | mIvMore = findViewById(R.id.ivMore); 68 | 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/apple/keyboarddemo/SplashActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.apple.keyboarddemo; 2 | 3 | import android.content.Intent; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | 8 | import com.example.apple.keyboarddemo.focus.SoftFocusActivity; 9 | import com.example.apple.keyboarddemo.keyboard_num.KeyBoardNumberActivity; 10 | import com.example.apple.keyboarddemo.shelter_aty.ShelterActivity; 11 | import com.example.apple.keyboarddemo.top_dismiss.TopDismissFirstActivity; 12 | import com.example.apple.keyboarddemo.top_dismiss.TopDismissSecondActivity; 13 | import com.example.apple.keyboarddemo.top_dismiss.TopDismissThirdActivity; 14 | import com.example.apple.keyboarddemo.topic.TopicActivity; 15 | 16 | /** 17 | * @author crazyZhangxl on 2018-10-25 9:51:12. 18 | * Describe: 软键盘入口活动 19 | */ 20 | 21 | public class SplashActivity extends AppCompatActivity { 22 | 23 | @Override 24 | protected void onCreate(Bundle savedInstanceState) { 25 | super.onCreate(savedInstanceState); 26 | setContentView(R.layout.activity_splash); 27 | findViewById(R.id.btnNum).setOnClickListener(new View.OnClickListener() { 28 | @Override 29 | public void onClick(View v) { 30 | startActivity(new Intent(SplashActivity.this, KeyBoardNumberActivity.class)); 31 | } 32 | }); 33 | 34 | findViewById(R.id.btnTopic).setOnClickListener(new View.OnClickListener() { 35 | @Override 36 | public void onClick(View v) { 37 | startActivity(new Intent(SplashActivity.this, TopicActivity.class)); 38 | } 39 | }); 40 | 41 | findViewById(R.id.btnShelter).setOnClickListener(new View.OnClickListener() { 42 | @Override 43 | public void onClick(View v) { 44 | startActivity(new Intent(SplashActivity.this, ShelterActivity.class)); 45 | } 46 | }); 47 | 48 | findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() { 49 | @Override 50 | public void onClick(View v) { 51 | startActivity(new Intent(SplashActivity.this,RegisterActivity.class)); 52 | } 53 | }); 54 | 55 | findViewById(R.id.btnChat).setOnClickListener(new View.OnClickListener() { 56 | @Override 57 | public void onClick(View v) { 58 | startActivity(new Intent(SplashActivity.this,SessionActivity.class)); 59 | } 60 | }); 61 | 62 | findViewById(R.id.btnRg2).setOnClickListener(new View.OnClickListener() { 63 | @Override 64 | public void onClick(View v) { 65 | startActivity(new Intent(SplashActivity.this,Register2Activity.class)); 66 | } 67 | }); 68 | 69 | findViewById(R.id.btnTopMiss1).setOnClickListener(new View.OnClickListener() { 70 | @Override 71 | public void onClick(View v) { 72 | startActivity(new Intent(SplashActivity.this, TopDismissFirstActivity.class)); 73 | } 74 | }); 75 | 76 | findViewById(R.id.btnTopMiss2).setOnClickListener(new View.OnClickListener() { 77 | @Override 78 | public void onClick(View v) { 79 | startActivity(new Intent(SplashActivity.this, TopDismissSecondActivity.class)); 80 | } 81 | }); 82 | findViewById(R.id.btnTopMiss3).setOnClickListener(new View.OnClickListener() { 83 | @Override 84 | public void onClick(View v) { 85 | startActivity(new Intent(SplashActivity.this, TopDismissThirdActivity.class)); 86 | } 87 | }); 88 | 89 | findViewById(R.id.focus).setOnClickListener(new View.OnClickListener() { 90 | @Override 91 | public void onClick(View v) { 92 | startActivity(new Intent(SplashActivity.this, SoftFocusActivity.class)); 93 | } 94 | }); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/apple/keyboarddemo/collapse/CollapseActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.apple.keyboarddemo.collapse; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.view.View; 6 | import android.widget.ImageView; 7 | import android.widget.RelativeLayout; 8 | 9 | import com.example.apple.keyboarddemo.R; 10 | 11 | /** 12 | * 可折叠的Activity 13 | */ 14 | public class CollapseActivity extends AppCompatActivity { 15 | private RelativeLayout mLayout; 16 | private ImageView mIvArrow; 17 | @Override 18 | protected void onCreate(Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | setContentView(R.layout.activity_collapse); 21 | mLayout = (RelativeLayout) findViewById(R.id.linear); 22 | mIvArrow = (ImageView)findViewById(R.id.ivArrow); 23 | initExpandView(); 24 | } 25 | 26 | private ExpandLayout mExpandLayout; 27 | 28 | public void initExpandView() { 29 | mExpandLayout = (ExpandLayout) findViewById(R.id.expandLayout); 30 | if (mExpandLayout != null) { 31 | mExpandLayout.initExpand(false,mIvArrow); 32 | } 33 | mLayout.setOnClickListener(new View.OnClickListener() { 34 | @Override 35 | public void onClick(View v) { 36 | mExpandLayout.toggleExpand(); 37 | } 38 | }); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/apple/keyboarddemo/collapse/ExpandLayout.java: -------------------------------------------------------------------------------- 1 | package com.example.apple.keyboarddemo.collapse; 2 | 3 | import android.animation.ObjectAnimator; 4 | import android.animation.ValueAnimator; 5 | import android.content.Context; 6 | import android.util.AttributeSet; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.ImageView; 10 | import android.widget.LinearLayout; 11 | 12 | /** 13 | * modify by zxl on 2019/7/22 . 14 | *

15 | * 带过渡动画的折叠收缩布局 16 | */ 17 | public class ExpandLayout extends LinearLayout { 18 | 19 | public ExpandLayout(Context context) { 20 | this(context, null); 21 | } 22 | 23 | public ExpandLayout(Context context, AttributeSet attrs) { 24 | this(context, attrs, 0); 25 | } 26 | 27 | public ExpandLayout(Context context, AttributeSet attrs, int defStyle) { 28 | super(context, attrs, defStyle); 29 | initView(); 30 | } 31 | 32 | private View layoutView; 33 | private int viewHeight; 34 | private boolean isExpand; 35 | private long animationDuration; 36 | private boolean lock; 37 | private ImageView mImageView; 38 | 39 | private void initView() { 40 | setOrientation(VERTICAL); 41 | layoutView = this; 42 | isExpand = true; 43 | animationDuration = 300; 44 | setViewDimensions(); 45 | } 46 | 47 | /** 48 | * @param isExpand 初始状态是否折叠 49 | */ 50 | public void initExpand(boolean isExpand, ImageView imageView) { 51 | this.mImageView = imageView; 52 | this.isExpand = isExpand; 53 | setViewDimensions(); 54 | } 55 | 56 | /** 57 | * 设置动画时间 58 | * 59 | * @param animationDuration 动画时间 60 | */ 61 | public void setAnimationDuration(long animationDuration) { 62 | this.animationDuration = animationDuration; 63 | } 64 | 65 | /** 66 | * 获取subView的总高度 67 | * View.post()的runnable对象中的方法会在View的measure、layout等事件后触发 68 | */ 69 | private void setViewDimensions() { 70 | layoutView.post(new Runnable() { 71 | @Override 72 | public void run() { 73 | if (viewHeight <= 0) { 74 | viewHeight = layoutView.getMeasuredHeight(); 75 | } 76 | setViewHeight(layoutView, isExpand ? viewHeight : 0); 77 | } 78 | }); 79 | } 80 | 81 | 82 | public static void setViewHeight(View view, int height) { 83 | final ViewGroup.LayoutParams params = view.getLayoutParams(); 84 | params.height = height; 85 | view.requestLayout(); 86 | } 87 | 88 | /** 89 | * 切换动画实现 90 | */ 91 | private void animateToggle(long animationDuration) { 92 | ValueAnimator heightAnimation = isExpand ? 93 | ValueAnimator.ofFloat(0f, viewHeight) : ValueAnimator.ofFloat(viewHeight, 0f); 94 | heightAnimation.setDuration(animationDuration / 2); 95 | heightAnimation.setStartDelay(animationDuration / 2); 96 | 97 | heightAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 98 | @Override 99 | public void onAnimationUpdate(ValueAnimator animation) { 100 | int value = (int) (float) animation.getAnimatedValue(); 101 | setViewHeight(layoutView, value); 102 | if (value == viewHeight || value == 0) { 103 | lock = false; 104 | } 105 | } 106 | }); 107 | 108 | heightAnimation.start(); 109 | lock = true; 110 | } 111 | 112 | public boolean isExpand() { 113 | return isExpand; 114 | } 115 | 116 | /** 117 | * 折叠view 118 | */ 119 | public void collapse() { 120 | isExpand = false; 121 | animateToggle(animationDuration); 122 | } 123 | 124 | /** 125 | * 展开view 126 | */ 127 | public void expand() { 128 | isExpand = true; 129 | animateToggle(animationDuration); 130 | } 131 | 132 | public void toggleExpand() { 133 | if (lock) { 134 | return; 135 | } 136 | if (isExpand) { 137 | ObjectAnimator.ofFloat(mImageView, View.ROTATION.getName(), -180, 0).start(); 138 | collapse(); 139 | } else { 140 | ObjectAnimator.ofFloat(mImageView, View.ROTATION.getName(), 180, 0).start(); 141 | expand(); 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/apple/keyboarddemo/expand/ExpandTextView.java: -------------------------------------------------------------------------------- 1 | package com.example.apple.keyboarddemo.expand; 2 | 3 | import android.animation.Animator; 4 | import android.animation.ValueAnimator; 5 | import android.content.Context; 6 | import android.graphics.drawable.Drawable; 7 | import android.support.annotation.Nullable; 8 | import android.support.v4.content.ContextCompat; 9 | import android.text.TextUtils; 10 | import android.util.AttributeSet; 11 | import android.util.Log; 12 | import android.view.LayoutInflater; 13 | import android.view.MotionEvent; 14 | import android.view.View; 15 | import android.widget.LinearLayout; 16 | import android.widget.TextView; 17 | import com.example.apple.keyboarddemo.R; 18 | 19 | /** 20 | * Created by apple on 2019/7/23. 21 | * description: 可折叠的TextView 22 | */ 23 | public class ExpandTextView extends LinearLayout implements View.OnClickListener { 24 | private TextView mTvContent,mTvExpand; 25 | 26 | /*是否有重新绘制*/ 27 | private boolean mRelayout; 28 | 29 | /*默认收起*/ 30 | private boolean mCollapsed = true; 31 | 32 | /*动画执行时间*/ 33 | private int mAnimationDuration = 300; 34 | /*是否正在执行动画*/ 35 | private boolean mAnimating; 36 | 37 | /*设置内容最大行数,超过隐藏*/ 38 | private int mMaxCollapsedLines = 2; 39 | 40 | /*这个linerlayout容器的高度*/ 41 | private int mCollapsedHeight; 42 | 43 | /*内容tv真实高度(含padding)*/ 44 | private int mTextHeightWithMaxLines; 45 | 46 | /*内容tvMarginTopAmndBottom高度*/ 47 | private int mMarginBetweenTxtAndBottom; 48 | 49 | /*展开图片*/ 50 | private Drawable mExpandDrawable; 51 | /*收起图片*/ 52 | private Drawable mCollapseDrawable; 53 | 54 | public ExpandTextView(Context context) { 55 | this(context,null); 56 | } 57 | 58 | public ExpandTextView(Context context, @Nullable AttributeSet attrs) { 59 | this(context, attrs,0); 60 | } 61 | 62 | public ExpandTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 63 | super(context, attrs, defStyleAttr); 64 | init(attrs); 65 | } 66 | 67 | /** 68 | * 设置orientation 必须为垂直 69 | * @param orientation 70 | */ 71 | @Override 72 | public void setOrientation(int orientation) { 73 | if (LinearLayout.HORIZONTAL == orientation) { 74 | throw new IllegalArgumentException("ExpandableTextView only supports Vertical Orientation."); 75 | } 76 | super.setOrientation(orientation); 77 | } 78 | 79 | /** 80 | * 依据参数属性 设置排列方式 81 | * @param attrs 82 | */ 83 | private void init(AttributeSet attrs) { 84 | Log.e("expand", "init: 初始化了" ); 85 | mExpandDrawable = ContextCompat.getDrawable(getContext(), R.mipmap.ic_expand_down); 86 | mExpandDrawable.setBounds(0,0,25,25); 87 | mCollapseDrawable = ContextCompat.getDrawable(getContext(), R.mipmap.ic_expand_up); 88 | mCollapseDrawable.setBounds(0,0,25,25); 89 | setOrientation(VERTICAL); 90 | // 在加载前设置不可见... 91 | setVisibility(GONE); 92 | } 93 | 94 | /** 95 | * 渲染完成后初始化view 96 | */ 97 | @Override 98 | protected void onFinishInflate() { 99 | super.onFinishInflate(); 100 | initViews(); 101 | } 102 | 103 | 104 | @Override 105 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 106 | // 如果没有改变则返回 107 | if (!mRelayout || getVisibility() == View.GONE){ 108 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 109 | return; 110 | } 111 | mRelayout = false; 112 | mTvExpand.setVisibility(GONE); 113 | mTvContent.setMaxLines(Integer.MAX_VALUE); 114 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 115 | 116 | //如果内容真实行数小于等于最大行数,不处理 117 | if (mTvContent.getLineCount() <= mMaxCollapsedLines) { 118 | return; 119 | } 120 | // 获取内容tv真实高度(含padding)进行保存 121 | mTextHeightWithMaxLines = getRealTextViewHeight(mTvContent); 122 | 123 | // 如果是收起状态,重新设置最大行数 124 | if (mCollapsed) { 125 | mTvContent.setMaxLines(mMaxCollapsedLines); 126 | } 127 | mTvExpand.setVisibility(View.VISIBLE); 128 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 129 | 130 | if (mCollapsed) { 131 | // Gets the margin between the TextView's bottom and the ViewGroup's bottom 132 | mTvContent.post(new Runnable() { 133 | @Override 134 | public void run() { 135 | mMarginBetweenTxtAndBottom = getHeight() - mTvContent.getHeight(); 136 | } 137 | }); 138 | // 保存这个容器的测量高度 139 | mCollapsedHeight = getMeasuredHeight(); 140 | } 141 | 142 | } 143 | 144 | @Override 145 | public boolean onInterceptTouchEvent(MotionEvent ev) { 146 | // 当动画还在执行状态时,拦截事件,不让child处理 147 | return mAnimating; 148 | } 149 | 150 | private void initViews() { 151 | LayoutInflater.from(getContext()).inflate(R.layout.textview_expand_shink,this); 152 | mTvContent = findViewById(R.id.expand_content); 153 | mTvContent.setOnClickListener(this); 154 | mTvExpand = findViewById(R.id.expand_collapse); 155 | mTvExpand.setText(mCollapsed ? "全文" : "收起"); 156 | mTvExpand.setCompoundDrawables(null, null, mCollapsed ? mExpandDrawable : mCollapseDrawable, null); 157 | mTvExpand.setOnClickListener(this); 158 | } 159 | 160 | /** 161 | * 点击事件 162 | * @param v 163 | */ 164 | @Override 165 | public void onClick(View v) { 166 | if (mTvExpand.getVisibility() != VISIBLE){ 167 | return; 168 | } 169 | mCollapsed = !mCollapsed; 170 | mTvExpand.setText(mCollapsed ? "全文" : "收起"); 171 | mTvExpand.setCompoundDrawables(null, null, mCollapsed ? mExpandDrawable : mCollapseDrawable, null); 172 | // 执行展开/收起动画 173 | mAnimating = true; 174 | ValueAnimator valueAnimator; 175 | if (mCollapsed) { 176 | valueAnimator = ValueAnimator.ofInt(getHeight(), mCollapsedHeight); 177 | } else { 178 | valueAnimator = ValueAnimator.ofInt(getHeight(), getHeight() + 179 | mTextHeightWithMaxLines - mTvContent.getHeight()); 180 | } 181 | valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener(){ 182 | @Override 183 | public void onAnimationUpdate(ValueAnimator valueAnimator) { 184 | int animatedValue = (int) valueAnimator.getAnimatedValue(); 185 | mTvContent.setMaxHeight(animatedValue - mMarginBetweenTxtAndBottom); 186 | getLayoutParams().height = animatedValue; 187 | requestLayout(); 188 | } 189 | }); 190 | valueAnimator.addListener(new Animator.AnimatorListener() { 191 | @Override 192 | public void onAnimationStart(Animator animator) { 193 | 194 | } 195 | @Override 196 | public void onAnimationEnd(Animator animator) { 197 | // 动画结束后发送结束的信号 198 | /// clear the animation flag 199 | mAnimating = false; 200 | if (mCollapsed){ 201 | mTvContent.setMaxLines(mMaxCollapsedLines); 202 | mTvContent.setEllipsize(TextUtils.TruncateAt.END); 203 | } 204 | } 205 | @Override 206 | public void onAnimationCancel(Animator animator) { 207 | 208 | } 209 | @Override 210 | public void onAnimationRepeat(Animator animator) { 211 | 212 | } 213 | }); 214 | valueAnimator.setDuration(mAnimationDuration); 215 | valueAnimator.start(); 216 | } 217 | 218 | 219 | 220 | /** 221 | * 设置内容 222 | * @param text 223 | */ 224 | public void setText( CharSequence text) { 225 | mRelayout = true; 226 | mTvContent.setText(text); 227 | setVisibility(TextUtils.isEmpty(text) ? View.GONE : View.VISIBLE); 228 | } 229 | 230 | /** 231 | * 获取内容 232 | * @return 233 | */ 234 | public CharSequence getText() { 235 | if (mTvContent == null) { 236 | return ""; 237 | } 238 | return mTvContent.getText(); 239 | } 240 | 241 | /** 242 | * 获取内容tv真实高度(含padding) 243 | * @param textView 244 | * @return 245 | */ 246 | private static int getRealTextViewHeight( TextView textView) { 247 | int textHeight = textView.getLayout().getLineTop(textView.getLineCount()); 248 | int padding = textView.getCompoundPaddingTop() + textView.getCompoundPaddingBottom(); 249 | return textHeight + padding; 250 | } 251 | } 252 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/apple/keyboarddemo/focus/SoftFocusActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.apple.keyboarddemo.focus; 2 | 3 | import android.content.Context; 4 | import android.os.IBinder; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.os.Bundle; 7 | import android.view.Gravity; 8 | import android.view.View; 9 | import android.view.inputmethod.InputMethodManager; 10 | import android.widget.EditText; 11 | import android.widget.LinearLayout; 12 | 13 | import com.example.apple.keyboarddemo.R; 14 | import com.example.apple.keyboarddemo.RedDotView; 15 | import com.example.apple.keyboarddemo.expand.ExpandTextView; 16 | import com.ycbjie.ycreddotviewlib.YCRedDotView; 17 | 18 | /** 19 | * created by apple on 2019/7/23 20 | * 21 | * 软键盘焦点活动 22 | */ 23 | public class SoftFocusActivity extends AppCompatActivity { 24 | private View mRootView; 25 | private EditText mEtSend,mEtTheme; 26 | private ExpandTextView mExpandTextView; 27 | private LinearLayout mLinear; 28 | private RedDotView mRedDotView; 29 | @Override 30 | protected void onCreate(Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | setContentView(R.layout.activity_soft_focus); 33 | initViews(); 34 | initListener(); 35 | initData(); 36 | } 37 | 38 | 39 | private void initViews() { 40 | mRootView = findViewById(R.id.llRoot); 41 | mEtSend = findViewById(R.id.etSend); 42 | mEtTheme = findViewById(R.id.etTheme); 43 | mExpandTextView = findViewById(R.id.expandTextView); 44 | mLinear = findViewById(R.id.linear); 45 | mRedDotView = findViewById(R.id.redDot); 46 | mRedDotView.setBadgeCount(0); 47 | } 48 | 49 | 50 | private void initListener() { 51 | mRootView.setOnClickListener(new View.OnClickListener() { 52 | @Override 53 | public void onClick(View v) { 54 | if (getCurrentFocus() != null){ 55 | mEtSend.clearFocus(); 56 | mEtTheme.clearFocus(); 57 | hideKeyboard(mRootView,getCurrentFocus().getWindowToken()); 58 | } 59 | } 60 | }); 61 | } 62 | 63 | 64 | private void initData() { 65 | mEtSend.requestFocus(); 66 | mEtSend.setSelection(mEtSend.getText().toString().length()); 67 | mExpandTextView.setText("我是谁我是谁我是谁我是谁我是谁我是谁我是谁我是谁我是谁我是谁我是谁我是谁我是谁我是谁我是谁我是谁我是谁我是谁我是谁我是谁我是谁我是谁我是谁我是谁我是谁我是谁我是谁我是谁我是谁我是谁我是谁我是谁我是谁"); 68 | } 69 | 70 | private void initRedDot(){ 71 | 72 | } 73 | 74 | 75 | 76 | private void hideKeyboard(final View view, IBinder windowToken) { 77 | if(windowToken == null){ 78 | return; 79 | } 80 | InputMethodManager inputMethodManager = (InputMethodManager) view.getContext().getApplicationContext() 81 | .getSystemService(Context.INPUT_METHOD_SERVICE); 82 | if (inputMethodManager == null){ 83 | return; 84 | } 85 | boolean active = inputMethodManager.isActive(); 86 | if (active) { 87 | inputMethodManager.hideSoftInputFromWindow(windowToken, 0); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/apple/keyboarddemo/keyboard_num/CustomNumKeyboardView.java: -------------------------------------------------------------------------------- 1 | package com.example.apple.keyboarddemo.keyboard_num; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Paint; 6 | import android.graphics.Rect; 7 | import android.graphics.Typeface; 8 | import android.graphics.drawable.Drawable; 9 | import android.inputmethodservice.Keyboard; 10 | import android.inputmethodservice.KeyboardView; 11 | import android.util.AttributeSet; 12 | 13 | import com.example.apple.keyboarddemo.R; 14 | 15 | import java.util.Iterator; 16 | 17 | /** 18 | * @author crazyZhangxl on 2018/10/17. 19 | * Describe: 自定义基本使用技巧 ------ 有待强化一些技能哦哦 20 | */ 21 | public class CustomNumKeyboardView 22 | extends KeyboardView 23 | { 24 | private Context mContext; 25 | private Keyboard mKeyboard; 26 | private boolean mConFirmBtnEnabled = true; 27 | 28 | 29 | public CustomNumKeyboardView(Context paramContext, AttributeSet paramAttributeSet) 30 | { 31 | super(paramContext, paramAttributeSet); 32 | this.mContext = paramContext; 33 | } 34 | 35 | public CustomNumKeyboardView(Context paramContext, AttributeSet paramAttributeSet, int paramInt) 36 | { 37 | super(paramContext, paramAttributeSet, paramInt); 38 | this.mContext = paramContext; 39 | } 40 | 41 | private void drawIcon(Canvas paramCanvas, Keyboard.Key paramKey) 42 | { 43 | if (paramKey.icon != null) 44 | { 45 | paramKey.icon.setBounds( 46 | paramKey.x + (paramKey.width - paramKey.icon.getIntrinsicWidth()) / 2, 47 | paramKey.y + (paramKey.height - paramKey.icon.getIntrinsicHeight()) / 2, 48 | paramKey.x + (paramKey.width - paramKey.icon.getIntrinsicWidth()) / 2 + paramKey.icon.getIntrinsicWidth(), 49 | paramKey.y + (paramKey.height - paramKey.icon.getIntrinsicHeight()) / 2 + paramKey.icon.getIntrinsicHeight()); 50 | paramKey.icon.draw(paramCanvas); 51 | } 52 | } 53 | 54 | // 绘制背景 55 | private void drawKeyBackground(int paramInt, Canvas paramCanvas, Keyboard.Key paramKey) 56 | { 57 | Drawable localDrawable = this.mContext.getResources().getDrawable(paramInt); 58 | int[] arrayOfInt = paramKey.getCurrentDrawableState(); 59 | if (paramKey.codes[0] != 0) { 60 | localDrawable.setState(arrayOfInt); 61 | } 62 | localDrawable.setBounds(paramKey.x, paramKey.y, 63 | paramKey.x + paramKey.width, 64 | paramKey.y + paramKey.height); 65 | localDrawable.draw(paramCanvas); 66 | } 67 | 68 | // 绘制文字 69 | private void drawText(Canvas paramCanvas, Keyboard.Key paramKey, float paramFloat, int paramInt, Typeface paramTypeface) 70 | { 71 | Rect localRect = new Rect(); 72 | Paint localPaint = new Paint(); 73 | localPaint.setTextAlign(Paint.Align.CENTER); 74 | localPaint.setAntiAlias(true); 75 | localPaint.setColor(paramInt); 76 | if (paramKey.label != null) 77 | { 78 | // 字体大小 79 | localPaint.setTextSize(paramFloat); 80 | localPaint.setTypeface(paramTypeface); 81 | localPaint.getTextBounds(paramKey.label.toString(), 0, paramKey.label.toString().length(), localRect); 82 | paramFloat = paramKey.x + paramKey.width / 2; 83 | paramInt = paramKey.y; 84 | int i = paramKey.height / 2; 85 | paramCanvas.drawText(paramKey.label.toString(), paramFloat, localRect.height() / 2 + (paramInt + i), localPaint); 86 | } 87 | } 88 | 89 | /* 90 | key值对应关系 91 | public static final int KEYCODE_SHIFT = -1; 92 | public static final int KEYCODE_MODE_CHANGE = -2; 93 | public static final int KEYCODE_CANCEL = -3; 94 | public static final int KEYCODE_DONE = -4; 95 | public static final int KEYCODE_DELETE = -5; 96 | public static final int KEYCODE_ALT = -6;*/ 97 | 98 | @Override 99 | public void onDraw(Canvas paramCanvas) 100 | { 101 | super.onDraw(paramCanvas); 102 | this.mKeyboard = getKeyboard(); 103 | Iterator localIterator = this.mKeyboard.getKeys().iterator(); 104 | while (localIterator.hasNext()) 105 | { 106 | Keyboard.Key localKey = (Keyboard.Key)localIterator.next(); 107 | if (localKey.codes[0] == -5) 108 | { 109 | // 绘制删除键 110 | drawKeyBackground(R.drawable.keyboard_delete_btn_bg, paramCanvas, localKey); 111 | drawIcon(paramCanvas, localKey); 112 | } else if (localKey.codes[0] == -4) 113 | { 114 | // 绘制确认键 115 | if (this.mConFirmBtnEnabled) { 116 | drawKeyBackground(R.drawable.keyboard_cofirm_btn_bg, paramCanvas, localKey); 117 | drawText(paramCanvas, localKey, getResources().getDimension(R.dimen.fontsize36), -1, Typeface.DEFAULT); 118 | }else { 119 | drawKeyBackground(R.drawable.keyboard_cofirm_btn_bg, paramCanvas, localKey); 120 | drawText(paramCanvas, localKey, getResources().getDimension(R.dimen.fontsize36), -7829368, Typeface.DEFAULT); 121 | } 122 | }else if (localKey.codes[0] == -3){ 123 | // 绘制键盘图标 124 | drawKeyBackground(R.drawable.keyboard_btn_normal_bg, paramCanvas, localKey); 125 | drawIcon(paramCanvas, localKey); 126 | } else { 127 | // 绘制其他的数字 这里和 xml是对应的关系 128 | drawKeyBackground(R.drawable.keyboard_btn_normal_bg, paramCanvas, localKey); 129 | drawText(paramCanvas, localKey, getResources().getDimension(R.dimen.fontsize36), R.color.color_red, Typeface.DEFAULT); 130 | } 131 | } 132 | } 133 | 134 | public boolean isConfirmBtnEnabled() 135 | { 136 | return this.mConFirmBtnEnabled; 137 | } 138 | 139 | 140 | public void setConfirmBtnEnabled(boolean paramBoolean) 141 | { 142 | this.mConFirmBtnEnabled = paramBoolean; 143 | invalidate(); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/apple/keyboarddemo/keyboard_num/KeyBoardNumberActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.apple.keyboarddemo.keyboard_num; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.widget.EditText; 6 | import android.widget.Toast; 7 | 8 | import com.example.apple.keyboarddemo.R; 9 | 10 | /** 11 | * @author crazyZhangxl on 2018-10-18 8:36:33. 12 | * Describe: 13 | */ 14 | 15 | public class KeyBoardNumberActivity extends AppCompatActivity implements KeyboardNumUtil.NumKeyboardListener { 16 | private EditText mEditText; 17 | private CustomNumKeyboardView mCustomNumKeyboardView; 18 | private KeyboardNumUtil mKeyboardNumUtil; 19 | @Override 20 | protected void onCreate(Bundle savedInstanceState) { 21 | super.onCreate(savedInstanceState); 22 | setContentView(R.layout.activity_keyboard_number); 23 | 24 | mEditText = findViewById(R.id.editText); 25 | mCustomNumKeyboardView = findViewById(R.id.keyboardView); 26 | mKeyboardNumUtil = new KeyboardNumUtil(this,mCustomNumKeyboardView); 27 | mKeyboardNumUtil.attachEditText(mEditText); 28 | mKeyboardNumUtil.setNumKeyboardListener(this); 29 | mKeyboardNumUtil.showNumKeyboard(); 30 | } 31 | 32 | @Override 33 | public void onClose() { 34 | Toast.makeText(this, "关闭软键盘", Toast.LENGTH_SHORT).show(); 35 | } 36 | 37 | @Override 38 | public void onConfirm() { 39 | Toast.makeText(this, "确定", Toast.LENGTH_SHORT).show(); 40 | } 41 | 42 | @Override 43 | public void onNumberChanged(String paramString) { 44 | // 键盘录入时 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/apple/keyboarddemo/keyboard_num/KeyboardNumUtil.java: -------------------------------------------------------------------------------- 1 | package com.example.apple.keyboarddemo.keyboard_num; 2 | 3 | import android.content.Context; 4 | import android.inputmethodservice.Keyboard; 5 | import android.inputmethodservice.KeyboardView; 6 | import android.view.inputmethod.InputMethodManager; 7 | import android.widget.EditText; 8 | 9 | import com.example.apple.keyboarddemo.R; 10 | 11 | import java.lang.reflect.InvocationTargetException; 12 | import java.lang.reflect.Method; 13 | 14 | /** 15 | * @author crazyZhangxl on 2018/10/18. 16 | * Describe: 17 | */ 18 | public class KeyboardNumUtil { 19 | private int keyboardLayout; 20 | private Context mContext; 21 | private EditText mEditText; 22 | private KeyboardView mKeyboardView; 23 | private InputMethodManager mInputMethodManager; 24 | private NumKeyboardListener mNumKeyboardListener; 25 | private KeyboardView.OnKeyboardActionListener mOnKeyboardActionListener = new KeyboardView.OnKeyboardActionListener() { 26 | @Override 27 | public void onPress(int primaryCode) { 28 | 29 | } 30 | 31 | @Override 32 | public void onRelease(int primaryCode) { 33 | 34 | } 35 | 36 | @Override 37 | public void onKey(int primaryCode, int[] keyCodes) { 38 | if (primaryCode == Keyboard.KEYCODE_CANCEL) { 39 | // 取消 -------- 进行隐藏的效果 --------- 40 | // -------------------------- 41 | if (mNumKeyboardListener != null){ 42 | mNumKeyboardListener.onClose(); 43 | } 44 | } else if (primaryCode == Keyboard.KEYCODE_DELETE) { 45 | // 回退 --------- 删除该数据 --------- 46 | if (mEditText != null){ 47 | int start = mEditText.getSelectionStart(); 48 | if (start >= 1){ 49 | mEditText.getText().delete(start-1,start); 50 | } 51 | } 52 | } else if (primaryCode == Keyboard.KEYCODE_DONE){ 53 | // 确定提交-------------- 54 | if (mNumKeyboardListener != null){ 55 | mNumKeyboardListener.onConfirm(); 56 | } 57 | }else { 58 | // 具体的数值 59 | String num = Character.toString((char) primaryCode); 60 | if (mEditText != null){ 61 | int length = mEditText.getText().toString().length(); 62 | mEditText.getText().insert(length,num); 63 | } 64 | if (mNumKeyboardListener != null){ 65 | mNumKeyboardListener.onNumberChanged(num); 66 | } 67 | } 68 | } 69 | 70 | @Override 71 | public void onText(CharSequence text) { 72 | 73 | } 74 | 75 | @Override 76 | public void swipeLeft() { 77 | 78 | } 79 | 80 | @Override 81 | public void swipeRight() { 82 | 83 | } 84 | 85 | @Override 86 | public void swipeDown() { 87 | 88 | } 89 | 90 | @Override 91 | public void swipeUp() { 92 | 93 | } 94 | }; 95 | 96 | public KeyboardNumUtil(Context mContext, KeyboardView keyboardView){ 97 | this.mContext = mContext; 98 | this.mKeyboardView = keyboardView; 99 | this.mInputMethodManager = ((InputMethodManager)this.mContext.getSystemService(Context.INPUT_METHOD_SERVICE)); 100 | } 101 | 102 | public void attachEditText(EditText editText){ 103 | this.mEditText = editText; 104 | } 105 | 106 | /** 107 | * 展示keyboard 108 | */ 109 | public void showNumKeyboard(){ 110 | mKeyboardView.setKeyboard(new Keyboard(this.mContext, R.xml.keyboard_num_woith_dot)); 111 | mKeyboardView.setEnabled(true); 112 | mKeyboardView.setPreviewEnabled(false); 113 | mKeyboardView.setOnKeyboardActionListener(this.mOnKeyboardActionListener); 114 | } 115 | 116 | 117 | /** 118 | * 隐藏系统的软键盘 119 | */ 120 | private void hideSystemKeyboard(){ 121 | Method localMethod = null; 122 | try { 123 | localMethod = EditText.class.getMethod("setShowSoftInputOnFocus", Boolean.TYPE); 124 | localMethod.setAccessible(true); 125 | try { 126 | localMethod.invoke(this.mEditText, Boolean.FALSE); 127 | } catch (IllegalAccessException e) { 128 | e.printStackTrace(); 129 | } catch (InvocationTargetException e) { 130 | e.printStackTrace(); 131 | } 132 | this.mInputMethodManager.hideSoftInputFromWindow(this.mEditText.getWindowToken(), 0); 133 | } catch (NoSuchMethodException e) { 134 | e.printStackTrace(); 135 | } 136 | 137 | } 138 | 139 | public void setNumKeyboardListener(NumKeyboardListener numKeyboardListener){ 140 | this.mNumKeyboardListener = numKeyboardListener; 141 | } 142 | 143 | 144 | public interface NumKeyboardListener{ 145 | void onClose(); 146 | void onConfirm(); 147 | void onNumberChanged(String paramString); 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/apple/keyboarddemo/shelter_aty/ShelterActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.apple.keyboarddemo.shelter_aty; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.view.WindowManager; 6 | 7 | import com.example.apple.keyboarddemo.R; 8 | 9 | /** 10 | * @author crazyZhangxl on 2018-10-25 16:17:06. 11 | * Describe: 活动中软键盘的遮挡问题探究 12 | */ 13 | 14 | public class ShelterActivity extends AppCompatActivity { 15 | 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); 20 | setContentView(R.layout.activity_shelter); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/apple/keyboarddemo/top_dismiss/TopDismissFirstActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.apple.keyboarddemo.top_dismiss; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | 6 | import com.example.apple.keyboarddemo.R; 7 | 8 | /** 9 | * @author crazyZhangxl on 2019-1-3 20:18:36. 10 | * Describe: 什么也不添加 11 | */ 12 | 13 | public class TopDismissFirstActivity extends AppCompatActivity { 14 | @Override 15 | protected void onCreate(Bundle savedInstanceState) { 16 | super.onCreate(savedInstanceState); 17 | setContentView(R.layout.activity_top_dismiss_first); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/apple/keyboarddemo/top_dismiss/TopDismissSecondActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.apple.keyboarddemo.top_dismiss; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | 6 | import com.example.apple.keyboarddemo.R; 7 | 8 | /** 9 | * @author crazyZhangxl on 2019-1-3 20:19:30. 10 | * Describe: 11 | */ 12 | 13 | public class TopDismissSecondActivity extends AppCompatActivity { 14 | 15 | @Override 16 | protected void onCreate(Bundle savedInstanceState) { 17 | super.onCreate(savedInstanceState); 18 | setContentView(R.layout.activity_top_dismiss_first); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/apple/keyboarddemo/top_dismiss/TopDismissThirdActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.apple.keyboarddemo.top_dismiss; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.view.WindowManager; 6 | 7 | import com.example.apple.keyboarddemo.R; 8 | 9 | /** 10 | * @author crazyZhangxl on 2019-1-3 20:29:38. 11 | * Describe: 12 | */ 13 | 14 | public class TopDismissThirdActivity extends AppCompatActivity { 15 | 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); 20 | setContentView(R.layout.activity_top_dismiss_first); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/apple/keyboarddemo/topic/BottomDialog.java: -------------------------------------------------------------------------------- 1 | package com.example.apple.keyboarddemo.topic; 2 | 3 | import android.content.Context; 4 | import android.content.DialogInterface; 5 | import android.support.annotation.NonNull; 6 | import android.support.design.widget.BottomSheetBehavior; 7 | import android.support.design.widget.BottomSheetDialog; 8 | import android.support.design.widget.CoordinatorLayout; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.view.Window; 12 | import android.view.WindowManager; 13 | 14 | /** 15 | * @author crazyZhangxl on 2018/10/25. 16 | * Describe: 17 | */ 18 | public class BottomDialog extends BottomSheetDialog { 19 | 20 | private BottomSheetBehavior behavior; 21 | 22 | public BottomDialog(@NonNull Context context, int theme,boolean isTranslucentStatus) { 23 | super(context, theme); 24 | Window window = getWindow(); 25 | if (window != null) { 26 | window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | 27 | WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); 28 | if (isTranslucentStatus) { 29 | window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 30 | } 31 | } 32 | } 33 | 34 | @Override 35 | public void setContentView(View view) { 36 | super.setContentView(view); 37 | initialize(view); 38 | setOnDismissListener(new DialogInterface.OnDismissListener() { 39 | @Override 40 | public void onDismiss(DialogInterface dialog) { 41 | if (behavior != null) { 42 | behavior.setState(BottomSheetBehavior.STATE_COLLAPSED); 43 | } 44 | } 45 | }); 46 | } 47 | 48 | @Override 49 | public void show() { 50 | super.show(); 51 | behavior.setState(BottomSheetBehavior.STATE_EXPANDED); 52 | } 53 | 54 | private void initialize(final View view) { 55 | ViewGroup parent = (ViewGroup) view.getParent(); 56 | CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) parent.getLayoutParams(); 57 | behavior = (BottomSheetBehavior) params.getBehavior(); 58 | if (behavior == null) { 59 | return; 60 | } 61 | behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() { 62 | @Override 63 | public void onStateChanged(@NonNull View bottomSheet, int newState) { 64 | if (newState == BottomSheetBehavior.STATE_HIDDEN) { 65 | dismiss(); 66 | behavior.setState(BottomSheetBehavior.STATE_COLLAPSED); 67 | } 68 | } 69 | 70 | @Override 71 | public void onSlide(@NonNull View bottomSheet, float slideOffset) { 72 | } 73 | }); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/apple/keyboarddemo/topic/BottomSheetBar.java: -------------------------------------------------------------------------------- 1 | package com.example.apple.keyboarddemo.topic; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.content.DialogInterface; 6 | import android.content.Intent; 7 | import android.text.Editable; 8 | import android.text.TextUtils; 9 | import android.text.TextWatcher; 10 | import android.view.LayoutInflater; 11 | import android.view.MotionEvent; 12 | import android.view.View; 13 | import android.view.inputmethod.InputMethodManager; 14 | import android.widget.Button; 15 | import android.widget.CheckBox; 16 | import android.widget.EditText; 17 | import android.widget.FrameLayout; 18 | import android.widget.ImageButton; 19 | 20 | import com.example.apple.keyboarddemo.R; 21 | 22 | /** 23 | * @author crazyZhangxl on 2018/10/25. 24 | * Describe: 25 | */ 26 | public class BottomSheetBar { 27 | 28 | private View mRootView; 29 | private EditText mEditText; 30 | private Context mContext; 31 | private Button mBtnCommit; 32 | private BottomDialog mDialog; 33 | private FrameLayout mFrameLayout; 34 | 35 | 36 | private BottomSheetBar(Context context) { 37 | this.mContext = context; 38 | } 39 | 40 | @SuppressLint("InflateParams") 41 | public static BottomSheetBar delegation(Context context) { 42 | BottomSheetBar bar = new BottomSheetBar(context); 43 | bar.mRootView = LayoutInflater.from(context).inflate(R.layout.layout_bottom_sheet_comment_bar, null, false); 44 | bar.initView(); 45 | return bar; 46 | } 47 | 48 | @SuppressLint("ClickableViewAccessibility") 49 | private void initView() { 50 | mFrameLayout = (FrameLayout) mRootView.findViewById(R.id.fl_face); 51 | mEditText = (EditText) mRootView.findViewById(R.id.et_comment); 52 | 53 | mBtnCommit = (Button) mRootView.findViewById(R.id.btn_comment); 54 | mBtnCommit.setEnabled(false); 55 | 56 | mDialog = new BottomDialog(mContext, R.style.BottomSheetEdit,false); 57 | mDialog.setContentView(mRootView); 58 | 59 | mDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { 60 | @Override 61 | public void onDismiss(DialogInterface dialog) { 62 | closeKeyboard(mEditText); 63 | mFrameLayout.setVisibility(View.GONE); 64 | } 65 | }); 66 | 67 | mEditText.addTextChangedListener(new TextWatcher() { 68 | @Override 69 | public void beforeTextChanged(CharSequence s, int start, int count, int after) { 70 | 71 | } 72 | 73 | @Override 74 | public void onTextChanged(CharSequence s, int start, int before, int count) { 75 | 76 | } 77 | 78 | @Override 79 | public void afterTextChanged(Editable s) { 80 | mBtnCommit.setEnabled(s.length() > 0); 81 | } 82 | }); 83 | 84 | } 85 | 86 | public void showEmoji() { 87 | 88 | mEditText.setOnClickListener(new View.OnClickListener() { 89 | @Override 90 | public void onClick(View v) { 91 | mFrameLayout.setVisibility(View.GONE); 92 | } 93 | }); 94 | } 95 | 96 | public void show(String hint) { 97 | mDialog.show(); 98 | if (!"添加评论".equals(hint)) { 99 | mEditText.setHint(hint + " "); 100 | } 101 | mRootView.postDelayed(new Runnable() { 102 | @Override 103 | public void run() { 104 | showSoftKeyboard(mEditText); 105 | } 106 | }, 50); 107 | } 108 | 109 | public void dismiss() { 110 | closeKeyboard(mEditText); 111 | mDialog.dismiss(); 112 | } 113 | 114 | 115 | 116 | 117 | public String getCommentText() { 118 | String str = mEditText.getText().toString(); 119 | return TextUtils.isEmpty(str) ? "" : str.trim(); 120 | } 121 | 122 | public Button getBtnCommit() { 123 | return mBtnCommit; 124 | } 125 | 126 | 127 | 128 | 129 | private void closeKeyboard(EditText view) { 130 | view.clearFocus(); 131 | InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); 132 | imm.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.RESULT_UNCHANGED_SHOWN); 133 | } 134 | 135 | private void showSoftKeyboard(View view) { 136 | if (view == null) { 137 | return; 138 | } 139 | view.setFocusable(true); 140 | view.setFocusableInTouchMode(true); 141 | if (!view.isFocused()) { 142 | view.requestFocus(); 143 | } 144 | 145 | InputMethodManager inputMethodManager = (InputMethodManager) view.getContext() 146 | .getSystemService(Context.INPUT_METHOD_SERVICE); 147 | inputMethodManager.showSoftInput(view, 0); 148 | } 149 | 150 | } 151 | 152 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/apple/keyboarddemo/topic/RichEditText.java: -------------------------------------------------------------------------------- 1 | package com.example.apple.keyboarddemo.topic; 2 | 3 | import android.content.ClipData; 4 | import android.content.ClipboardManager; 5 | import android.content.Context; 6 | import android.os.Parcel; 7 | import android.os.Parcelable; 8 | import android.support.annotation.NonNull; 9 | import android.support.v7.widget.AppCompatEditText; 10 | import android.text.Editable; 11 | import android.text.Selection; 12 | import android.text.Spannable; 13 | import android.text.SpannableString; 14 | import android.text.Spanned; 15 | import android.text.TextPaint; 16 | import android.text.TextUtils; 17 | import android.text.TextWatcher; 18 | import android.text.style.ForegroundColorSpan; 19 | import android.util.AttributeSet; 20 | import android.view.KeyEvent; 21 | import android.view.inputmethod.EditorInfo; 22 | import android.view.inputmethod.InputConnection; 23 | import android.view.inputmethod.InputConnectionWrapper; 24 | 25 | 26 | import java.util.logging.Logger; 27 | import java.util.regex.Matcher; 28 | import java.util.regex.Pattern; 29 | 30 | 31 | /** 32 | * 一个简单的富文本编辑器 33 | * 实现了@(AT)和##的Tag匹配功能, 34 | * 具有Tag删除判断,和光标定位判断;预防用户胡乱篡改 35 | * 36 | * @author qiujuer Email:qiujuer@live.cn 37 | * @version 1.0.0 38 | */ 39 | @SuppressWarnings("all") 40 | public class RichEditText extends AppCompatEditText { 41 | public static final String MATCH_MENTION = "@([^@^\\s^:^,^;^','^';'^>^<]{1,})";//@([^@^\\s^:]{1,})([\\s\\:\\,\\;]{0,1})");//@.+?[\\s:] 42 | public static final String MATCH_TOPIC = "#.+?#"; 43 | public static boolean DEBUG = false; 44 | private static final String TAG = RichEditText.class.getName(); 45 | private final RichEditText.TagSpanTextWatcher mTagSpanTextWatcher = new RichEditText.TagSpanTextWatcher(); 46 | private RichEditText.OnKeyArrivedListener mOnKeyArrivedListener; 47 | 48 | public RichEditText(Context context) { 49 | super(context); 50 | init(); 51 | } 52 | 53 | public RichEditText(Context context, AttributeSet attrs) { 54 | super(context, attrs); 55 | init(); 56 | } 57 | 58 | public RichEditText(Context context, AttributeSet attrs, int defStyleAttr) { 59 | super(context, attrs, defStyleAttr); 60 | init(); 61 | } 62 | 63 | private void init() { 64 | addTextChangedListener(mTagSpanTextWatcher); 65 | } 66 | 67 | @Override 68 | public InputConnection onCreateInputConnection(EditorInfo outAttrs) { 69 | return new RichEditText.ZanyInputConnection(super.onCreateInputConnection(outAttrs), true); 70 | } 71 | 72 | @Override 73 | public void setText(CharSequence text, BufferType type) { 74 | Spannable spannable = new SpannableString(text); 75 | spannable = matchMention(spannable); 76 | spannable = matchTopic(spannable); 77 | super.setText(spannable, type); 78 | } 79 | 80 | @Override 81 | protected void onSelectionChanged(int selStart, int selEnd) { 82 | log("onSelectionChanged:" + selStart + " " + selEnd); 83 | Editable message = getText(); 84 | 85 | if (selStart == selEnd) { 86 | RichEditText.TagSpan[] list = message.getSpans(selStart - 1, selStart, RichEditText.TagSpan.class); 87 | if (list.length > 0) { 88 | // Get first tag 89 | RichEditText.TagSpan span = list[0]; 90 | int spanStart = message.getSpanStart(span); 91 | int spanEnd = message.getSpanEnd(span); 92 | log("onSelectionChanged#Yes:" + spanStart + " " + spanEnd); 93 | // Check index 94 | if (Math.abs(selStart - spanStart) > Math.abs(selStart - spanEnd)) { 95 | Selection.setSelection(message, spanEnd); 96 | replaceCacheTagSpan(message, span, false); 97 | return; 98 | } else { 99 | Selection.setSelection(message, spanStart); 100 | } 101 | } 102 | } else { 103 | RichEditText.TagSpan[] list = message.getSpans(selStart, selEnd, RichEditText.TagSpan.class); 104 | if (list.length == 0) 105 | return; 106 | int start = selStart; 107 | int end = selEnd; 108 | for (RichEditText.TagSpan span : list) { 109 | int spanStart = message.getSpanStart(span); 110 | int spanEnd = message.getSpanEnd(span); 111 | 112 | if (spanStart < start) 113 | start = spanStart; 114 | 115 | if (spanEnd > end) 116 | end = spanEnd; 117 | } 118 | if (start != selStart || end != selEnd) { 119 | Selection.setSelection(message, start, end); 120 | log("onSelectionChanged#No:" + start + " " + end); 121 | } 122 | } 123 | 124 | replaceCacheTagSpan(message, null, false); 125 | } 126 | 127 | @Override 128 | public boolean onTextContextMenuItem(int id) { 129 | // Handle the paste option 130 | if (id == android.R.id.paste) { 131 | // Handle to the clipboard service. 132 | ClipboardManager clipboard = (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE); 133 | // Handle the data. 134 | if (clipboard.hasPrimaryClip()) { 135 | ClipData.Item item = clipboard.getPrimaryClip().getItemAt(0); 136 | if (item != null) { 137 | // Gets the clipboard date to string and do trim 138 | String paste = item.coerceToText(getContext()).toString().trim(); 139 | // Check need space 140 | if (mTagSpanTextWatcher != null && mTagSpanTextWatcher.checkCommit(paste)) 141 | paste = " " + paste; 142 | // Clear add span 143 | Spannable spannablePaste = new SpannableString(paste); 144 | spannablePaste = matchMention(spannablePaste); 145 | spannablePaste = matchTopic(spannablePaste); 146 | getText().replace(getSelectionStart(), getSelectionEnd(), spannablePaste); 147 | return true; 148 | } 149 | } 150 | } 151 | // Call super 152 | return super.onTextContextMenuItem(id); 153 | } 154 | 155 | public void setOnKeyArrivedListener(RichEditText.OnKeyArrivedListener listener) { 156 | mOnKeyArrivedListener = listener; 157 | } 158 | 159 | protected boolean callToMention() { 160 | RichEditText.OnKeyArrivedListener listener = mOnKeyArrivedListener; 161 | return listener == null || listener.onMentionKeyArrived(this); 162 | } 163 | 164 | protected boolean callToTopic() { 165 | RichEditText.OnKeyArrivedListener listener = mOnKeyArrivedListener; 166 | return listener == null || listener.onTopicKeyArrived(this); 167 | } 168 | 169 | private void replaceCacheTagSpan(Editable message, RichEditText.TagSpan span, boolean targetDelState) { 170 | if (mTagSpanTextWatcher != null) { 171 | mTagSpanTextWatcher.replaceSpan(message, span, targetDelState); 172 | } 173 | } 174 | 175 | private String filterDirty(String str) { 176 | return str.replace("#", "").replace("@", "").replace(" ", ""); 177 | } 178 | 179 | private void replaceLastChar(@NonNull String chr, SpannableString spannable) { 180 | Editable msg = getText(); 181 | int selStart = getSelectionStart(); 182 | int selEnd = getSelectionEnd(); 183 | 184 | int selStartBefore = selStart - 1; 185 | if (selStart == selEnd && selStart > 0 186 | && chr.equals(msg.subSequence(selStartBefore, selEnd).toString()) 187 | && msg.getSpans(selStartBefore, selEnd, RichEditText.TagSpan.class).length == 0) { 188 | selStart = selStartBefore; 189 | } 190 | 191 | msg.replace(selStart >= 0 ? selStart : 0, selEnd >= 0 ? selEnd : 0, spannable); 192 | } 193 | 194 | /** 195 | * 添加提到字符串 196 | * 197 | * @param mentions 提及的人,不含@ 198 | */ 199 | @SuppressWarnings("unused") 200 | public void appendMention(String... mentions) { 201 | if (mentions == null || mentions.length == 0) 202 | return; 203 | 204 | String mentionStr = ""; 205 | 206 | for (String mention : mentions) { 207 | if (mention == null || TextUtils.isEmpty(mention = mention.trim()) 208 | || TextUtils.isEmpty(mention = filterDirty(mention))) 209 | continue; 210 | mentionStr += String.format("@%s ", mention); 211 | } 212 | if (TextUtils.isEmpty(mentionStr)) 213 | return; 214 | 215 | SpannableString spannable = new SpannableString(mentionStr); 216 | RichEditText.matchMention(spannable); 217 | 218 | replaceLastChar("@", spannable); 219 | } 220 | 221 | /** 222 | * 添加话题字符串 223 | * 224 | * @param topics 话题,不含# 225 | */ 226 | @SuppressWarnings("unused") 227 | public void appendTopic(String... topics) { 228 | if (topics == null || topics.length == 0) { 229 | return; 230 | } 231 | 232 | String topicStr = ""; 233 | 234 | for (String topic : topics) { 235 | if (topic == null || TextUtils.isEmpty(topic = topic.trim()) 236 | || TextUtils.isEmpty(topic = filterDirty(topic))) { 237 | continue; 238 | } 239 | topicStr += String.format("#%s# ", topic); 240 | } 241 | if (TextUtils.isEmpty(topicStr)) { 242 | return; 243 | } 244 | 245 | SpannableString spannable = new SpannableString(topicStr); 246 | RichEditText.matchTopic(spannable); 247 | 248 | replaceLastChar("#", spannable); 249 | } 250 | 251 | 252 | private class TagSpanTextWatcher implements TextWatcher { 253 | private RichEditText.TagSpan willDelSpan; 254 | 255 | void replaceSpan(Editable message, RichEditText.TagSpan span, boolean targetDelState) { 256 | if (span != null) { 257 | span.changeRemoveState(targetDelState, message); 258 | } 259 | 260 | if (willDelSpan != span) { 261 | // When different 262 | RichEditText.TagSpan cacheSpan = willDelSpan; 263 | if (cacheSpan != null) { 264 | cacheSpan.changeRemoveState(false, message); 265 | } 266 | willDelSpan = span; 267 | } 268 | } 269 | 270 | boolean checkKeyDel() { 271 | int selStart = getSelectionStart(); 272 | int selEnd = getSelectionEnd(); 273 | Editable message = getText(); 274 | log("TagSpanTextWatcher#checkKeyDel:" + selStart + " " + selEnd); 275 | if (selStart == selEnd) { 276 | int start = selStart - 1; 277 | int count = 1; 278 | 279 | start = start < 0 ? 0 : start; 280 | 281 | int end = start + count; 282 | RichEditText.TagSpan[] list = message.getSpans(start, end, RichEditText.TagSpan.class); 283 | 284 | if (list.length > 0) { 285 | // Only get first 286 | final RichEditText.TagSpan span = list[0]; 287 | final RichEditText.TagSpan cacheSpan = willDelSpan; 288 | 289 | if (span == cacheSpan) { 290 | if (span.willRemove) 291 | return true; 292 | else { 293 | span.changeRemoveState(true, message); 294 | return false; 295 | } 296 | } 297 | } 298 | } 299 | // Replace cache tag to null 300 | replaceSpan(message, null, false); 301 | return true; 302 | } 303 | 304 | boolean checkCommit(CharSequence s) { 305 | if (willDelSpan != null) { 306 | willDelSpan.willRemove = false; 307 | willDelSpan = null; 308 | return s != null && s.length() > 0 && !" ".equals(s.subSequence(0, 1)); 309 | } 310 | return false; 311 | } 312 | 313 | @Override 314 | public void beforeTextChanged(CharSequence s, int start, int count, int after) { 315 | 316 | } 317 | 318 | @Override 319 | public void onTextChanged(CharSequence s, int start, int before, int count) { 320 | 321 | } 322 | 323 | @Override 324 | public void afterTextChanged(Editable s) { 325 | final RichEditText.TagSpan span = willDelSpan; 326 | log("TagSpanTextWatcher#willRemove#span:" + (span == null ? "null" : span.toString())); 327 | if (span != null && span.willRemove) { 328 | int start = s.getSpanStart(span); 329 | int end = s.getSpanEnd(span); 330 | 331 | // Remove the span 332 | s.removeSpan(span); 333 | 334 | // Remove the remaining emoticon text. 335 | if (start != end) { 336 | s.delete(start, end); 337 | } 338 | } 339 | } 340 | } 341 | 342 | public interface OnKeyArrivedListener { 343 | boolean onMentionKeyArrived(RichEditText editText); 344 | 345 | boolean onTopicKeyArrived(RichEditText text); 346 | } 347 | 348 | public static Spannable matchMention(Spannable spannable) { 349 | String text = spannable.toString(); 350 | 351 | Pattern pattern = Pattern.compile(MATCH_MENTION); 352 | Matcher matcher = pattern.matcher(text); 353 | 354 | while (matcher.find()) { 355 | String str = matcher.group(); 356 | int matcherStart = matcher.start(); 357 | int matcherEnd = matcher.end(); 358 | spannable.setSpan(new RichEditText.TagSpan(str), matcherStart, matcherEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 359 | log("matchMention:" + str + " " + matcherStart + " " + matcherEnd); 360 | } 361 | 362 | return spannable; 363 | } 364 | 365 | public static Spannable matchTopic(Spannable spannable) { 366 | String text = spannable.toString(); 367 | 368 | Pattern pattern = Pattern.compile(MATCH_TOPIC); 369 | Matcher matcher = pattern.matcher(text); 370 | 371 | while (matcher.find()) { 372 | String str = matcher.group(); 373 | int matcherStart = matcher.start(); 374 | int matcherEnd = matcher.end(); 375 | spannable.setSpan(new RichEditText.TagSpan(str), matcherStart, matcherEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 376 | log("matchTopic:" + str + " " + matcherStart + " " + matcherEnd); 377 | } 378 | 379 | return spannable; 380 | } 381 | 382 | private static void log(String msg) { 383 | } 384 | 385 | @SuppressWarnings("WeakerAccess") 386 | public static class TagSpan extends ForegroundColorSpan implements Parcelable { 387 | private String value; 388 | public boolean willRemove; 389 | 390 | public TagSpan(String value) { 391 | super(0xFF24cf5f); 392 | this.value = value; 393 | } 394 | 395 | public TagSpan(Parcel src) { 396 | super(src); 397 | value = src.readString(); 398 | } 399 | 400 | @Override 401 | public int describeContents() { 402 | return 0; 403 | } 404 | 405 | public static final Creator CREATOR = new Creator() { 406 | @Override 407 | public RichEditText.TagSpan createFromParcel(Parcel in) { 408 | return new RichEditText.TagSpan(in); 409 | } 410 | 411 | @Override 412 | public RichEditText.TagSpan[] newArray(int size) { 413 | return new RichEditText.TagSpan[size]; 414 | } 415 | }; 416 | 417 | @Override 418 | public void updateDrawState(TextPaint ds) { 419 | //log("TagSpan:updateDrawState:" + isPreDeleteState); 420 | ds.setFakeBoldText(true); 421 | if (willRemove) { 422 | ds.setColor(0xFFFFFFFF); 423 | ds.bgColor = 0xFF24cf5f; 424 | } else { 425 | super.updateDrawState(ds); 426 | } 427 | } 428 | 429 | void changeRemoveState(boolean willRemove, Editable message) { 430 | if (this.willRemove == willRemove) { 431 | return; 432 | } 433 | this.willRemove = willRemove; 434 | int cacheSpanStart = message.getSpanStart(this); 435 | int cacheSpanEnd = message.getSpanEnd(this); 436 | if (cacheSpanStart >= 0 && cacheSpanEnd >= cacheSpanStart) { 437 | message.setSpan(this, cacheSpanStart, cacheSpanEnd, 438 | Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 439 | } 440 | } 441 | 442 | public String getValue() { 443 | return value; 444 | } 445 | 446 | @Override 447 | public void writeToParcel(Parcel dest, int flags) { 448 | super.writeToParcel(dest, flags); 449 | dest.writeString(value); 450 | } 451 | 452 | @Override 453 | public String toString() { 454 | return "TagSpan{" + 455 | "value='" + value + '\'' + 456 | ", willRemove=" + willRemove + 457 | '}'; 458 | } 459 | } 460 | 461 | 462 | private class ZanyInputConnection extends InputConnectionWrapper { 463 | 464 | ZanyInputConnection(InputConnection target, boolean mutable) { 465 | super(target, mutable); 466 | } 467 | 468 | @Override 469 | public boolean sendKeyEvent(KeyEvent event) { 470 | if (event.getAction() == KeyEvent.ACTION_DOWN 471 | && event.getKeyCode() == KeyEvent.KEYCODE_DEL) { 472 | if (!RichEditText.this.mTagSpanTextWatcher.checkKeyDel()) { 473 | return false; 474 | } 475 | } 476 | return super.sendKeyEvent(event); 477 | } 478 | 479 | @Override 480 | public boolean deleteSurroundingText(int beforeLength, int afterLength) { 481 | // magic: in latest Android, deleteSurroundingText(1, 0) will be called for backspace 482 | if (beforeLength == 1 && afterLength == 0) { 483 | // backspace 484 | return sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)) 485 | && sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL)); 486 | } 487 | 488 | return super.deleteSurroundingText(beforeLength, afterLength); 489 | } 490 | 491 | @Override 492 | public boolean commitText(CharSequence text, int newCursorPosition) { 493 | return super.commitText(text, newCursorPosition); 494 | } 495 | 496 | @Override 497 | public boolean setComposingText(CharSequence text, int newCursorPosition) { 498 | return super.setComposingText(text, newCursorPosition); 499 | } 500 | } 501 | } 502 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/apple/keyboarddemo/topic/TopicActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.apple.keyboarddemo.topic; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.widget.FrameLayout; 8 | import android.widget.LinearLayout; 9 | import android.widget.TextView; 10 | 11 | import com.example.apple.keyboarddemo.R; 12 | 13 | /** 14 | * @author crazyZhangxl on 2018-10-25 9:52:10. 15 | * Describe: 16 | */ 17 | 18 | public class TopicActivity extends AppCompatActivity { 19 | 20 | private LinearLayout mLlComment; 21 | private FrameLayout mFmContainer; 22 | private TextView mTextView; 23 | private BottomSheetBar mBottomSheetBar; 24 | 25 | @Override 26 | protected void onCreate(Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | setContentView(R.layout.activity_topic); 29 | initViews(); 30 | initListener(); 31 | } 32 | 33 | private void initListener() { 34 | mTextView.setOnClickListener(new View.OnClickListener() { 35 | @Override 36 | public void onClick(View v) { 37 | mBottomSheetBar.show(mTextView.getHint().toString()); 38 | } 39 | }); 40 | } 41 | 42 | private void initViews() { 43 | mLlComment = findViewById(R.id.ll_comment); 44 | mFmContainer = findViewById(R.id.lay_container); 45 | mTextView = findViewById(R.id.tv_comment); 46 | mBottomSheetBar = BottomSheetBar.delegation(this); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/apple/todo.txt: -------------------------------------------------------------------------------- 1 | todo 分析下差异,并思考同城的做法 -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_border_color_black.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_comment.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_splash.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyzhangxl/KeyBoardDemo/d7c1bd3eb087e3bb542e29b0686c89f9f28b8843/app/src/main/res/drawable/bg_splash.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_bg_edit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_bg_edit_active.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_bg_edit_normal.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_selector_checkbox.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/iconmbile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyzhangxl/KeyBoardDemo/d7c1bd3eb087e3bb542e29b0686c89f9f28b8843/app/src/main/res/drawable/iconmbile.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/keyboard_btn_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/keyboard_btn_normal.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyzhangxl/KeyBoardDemo/d7c1bd3eb087e3bb542e29b0686c89f9f28b8843/app/src/main/res/drawable/keyboard_btn_normal.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/keyboard_btn_normal_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/keyboard_btn_pressed.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyzhangxl/KeyBoardDemo/d7c1bd3eb087e3bb542e29b0686c89f9f28b8843/app/src/main/res/drawable/keyboard_btn_pressed.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/keyboard_cofirm_btn_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/keyboard_confirm_btn.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyzhangxl/KeyBoardDemo/d7c1bd3eb087e3bb542e29b0686c89f9f28b8843/app/src/main/res/drawable/keyboard_confirm_btn.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/keyboard_confirm_btn_pressed.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyzhangxl/KeyBoardDemo/d7c1bd3eb087e3bb542e29b0686c89f9f28b8843/app/src/main/res/drawable/keyboard_confirm_btn_pressed.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/keyboard_delete_btn.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyzhangxl/KeyBoardDemo/d7c1bd3eb087e3bb542e29b0686c89f9f28b8843/app/src/main/res/drawable/keyboard_delete_btn.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/keyboard_delete_btn_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/keyboard_delete_btn_pressed.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyzhangxl/KeyBoardDemo/d7c1bd3eb087e3bb542e29b0686c89f9f28b8843/app/src/main/res/drawable/keyboard_delete_btn_pressed.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/keyboard_delete_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyzhangxl/KeyBoardDemo/d7c1bd3eb087e3bb542e29b0686c89f9f28b8843/app/src/main/res/drawable/keyboard_delete_icon.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/keyboard_fold_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crazyzhangxl/KeyBoardDemo/d7c1bd3eb087e3bb542e29b0686c89f9f28b8843/app/src/main/res/drawable/keyboard_fold_icon.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_edit_focus.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_bottom_gray.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_bottom_green.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_session_btn_send.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_session_btn_voice_normal.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_collapse.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 15 | 21 | 28 | 29 | 34 | 40 | 41 | 45 | 46 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_keyboard_number.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 14 | 17 | 28 | 29 | 30 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_register.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 15 | 19 | 27 | 28 | 32 | 44 | 52 | 53 | 67 | 68 | 75 | 83 | 91 | 92 | 107 | 108 | 120 | 121 | 122 | 129 | 130 | 139 | 140 | 148 | 149 | 150 | 151 |