├── .gitignore
├── .idea
    ├── .name
    ├── compiler.xml
    ├── copyright
    │   └── profiles_settings.xml
    ├── encodings.xml
    ├── gradle.xml
    ├── misc.xml
    ├── modules.xml
    └── runConfigurations.xml
├── README.md
├── app
    ├── .gitignore
    ├── app-release.apk
    ├── build.gradle
    ├── proguard-rules.pro
    └── src
    │   ├── androidTest
    │       └── java
    │       │   └── com
    │       │       └── igeek
    │       │           └── safesoftboard
    │       │               └── ApplicationTest.java
    │   ├── main
    │       ├── AndroidManifest.xml
    │       ├── java
    │       │   ├── com
    │       │   │   └── igeek
    │       │   │   │   └── safesoftboard
    │       │   │   │       ├── ISoftKeyBoard.java
    │       │   │   │       ├── ISoftKeyEvent.java
    │       │   │   │       ├── MainActivity.java
    │       │   │   │       ├── SafeEdit.java
    │       │   │   │       ├── SoftKey.java
    │       │   │   │       ├── SoftKeyAzLayView.java
    │       │   │   │       ├── SoftKeyBoard.java
    │       │   │   │       ├── SoftKeyNumLayView.java
    │       │   │   │       ├── SoftKeyPunctLayView.java
    │       │   │   │       ├── SoftKeyStatusListener.java
    │       │   │   │       └── SoftKeyView.java
    │       │   └── utils
    │       │   │   ├── DensityUtils.java
    │       │   │   └── ScreenUtils.java
    │       └── res
    │       │   ├── drawable-hdpi
    │       │       ├── ic_launcher.png
    │       │       ├── ic_softb_close.png
    │       │       ├── ic_softboard.png
    │       │       └── ic_softkey_delete.png
    │       │   ├── drawable-xhdpi
    │       │       ├── ic_launcher.png
    │       │       ├── ic_softb_close.png
    │       │       ├── ic_softboard.png
    │       │       └── ic_softkey_delete.png
    │       │   ├── drawable-xxhdpi
    │       │       ├── ic_launcher.png
    │       │       ├── ic_softb_close.png
    │       │       ├── ic_softboard.png
    │       │       └── ic_softkey_delete.png
    │       │   ├── drawable
    │       │       ├── bg_radio.xml
    │       │       ├── bg_stroke_gray.xml
    │       │       ├── bg_stroke_gray_gray.xml
    │       │       └── vertical_line.xml
    │       │   ├── layout
    │       │       ├── activity_main.xml
    │       │       ├── content_main.xml
    │       │       └── layout_keyboard.xml
    │       │   ├── menu
    │       │       └── menu_main.xml
    │       │   ├── mipmap-hdpi
    │       │       └── ic_launcher.png
    │       │   ├── mipmap-mdpi
    │       │       └── ic_launcher.png
    │       │   ├── mipmap-xhdpi
    │       │       └── ic_launcher.png
    │       │   ├── mipmap-xxhdpi
    │       │       └── ic_launcher.png
    │       │   ├── mipmap-xxxhdpi
    │       │       └── ic_launcher.png
    │       │   ├── values-v21
    │       │       └── styles.xml
    │       │   ├── values-w820dp
    │       │       └── dimens.xml
    │       │   └── values
    │       │       ├── attrs.xml
    │       │       ├── colors.xml
    │       │       ├── dimens.xml
    │       │       ├── strings.xml
    │       │       └── styles.xml
    │   └── test
    │       └── java
    │           └── com
    │               └── igeek
    │                   └── safesoftboard
    │                       └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
    └── wrapper
    │   ├── gradle-wrapper.jar
    │   └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── pics
    └── customsoftkeyboard.gif
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | 
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | SafeSoftBoard
--------------------------------------------------------------------------------
/.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 |     
23 |   
24 | 
--------------------------------------------------------------------------------
/.idea/misc.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 |     $USER_HOME$/.subversion
48 |   
49 |   
50 |     
51 |       
52 |         
53 |           Android API 22 Platform
54 |           
55 |             
56 |
57 |                 
58 |               
59 |             
60 |           
61 |         
62 |       
63 |     
64 |   
65 | 
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 | 
2 | 
3 |   
4 |     
5 |       
6 |       
7 |     
8 |   
9 | 
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 |   
 4 |     
 5 |       
 6 |         
 7 |         
 8 |         
 9 |       
10 |     
11 |   
12 | 
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
 1 | # SafeSoftBoard
 2 | 自定义数字,字母,符号的软键盘 继承View绘制。字符布局随机排版
 3 | 
 4 | ####效果图如下
 5 | 
 6 | 7 | 
 8 | 
 9 | ####XML 说明
10 | 	
15 | 
16 |     
20 | 
21 |     
29 | 
30 | 	
31 | 
32 | ####MainActivity 说明
33 | 	public class MainActivity extends Activity{
34 | 
35 | 		@Override
36 | 		protected void onCreate(Bundle savedInstanceState) {
37 | 			super.onCreate(savedInstanceState);
38 | 			setContentView(R.layout.activity_main);
39 | 		}
40 | 	}
41 | 
42 | 
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | 
--------------------------------------------------------------------------------
/app/app-release.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/app-release.apk
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: 'com.android.application'
 2 | 
 3 | android {
 4 |     compileSdkVersion 23
 5 |     buildToolsVersion "23.0.2"
 6 | 
 7 |     defaultConfig {
 8 |         applicationId "com.igeek.safesoftboard"
 9 |         minSdkVersion 15
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.3.0'
26 |     compile 'com.android.support:design:23.3.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 /Users/Allen1/Library/Android/sdk/tools/proguard/proguard-android.txt
 4 | # You can edit the include path and order by changing the proguardFiles
 5 | # directive in build.gradle.
 6 | #
 7 | # For more details, see
 8 | #   http://developer.android.com/guide/developing/tools/proguard.html
 9 | 
10 | # Add any project specific keep options here:
11 | 
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | #   public *;
17 | #}
18 | 
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/igeek/safesoftboard/ApplicationTest.java:
--------------------------------------------------------------------------------
 1 | package com.igeek.safesoftboard;
 2 | 
 3 | import android.app.Application;
 4 | import android.test.ApplicationTestCase;
 5 | 
 6 | /**
 7 |  * Testing Fundamentals
 8 |  */
 9 | public class ApplicationTest extends ApplicationTestCase {
10 |     public ApplicationTest() {
11 |         super(Application.class);
12 |     }
13 | }
--------------------------------------------------------------------------------
/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/igeek/safesoftboard/ISoftKeyBoard.java:
--------------------------------------------------------------------------------
 1 | package com.igeek.safesoftboard;
 2 | 
 3 | import android.graphics.Canvas;
 4 | import android.view.View;
 5 | 
 6 | public interface ISoftKeyBoard extends View.OnTouchListener,ISoftKeyEvent{
 7 | 
 8 | 	/**
 9 | 	 * 初始化关键的字符数组
10 | 	 * @return
11 | 	 */
12 | 	public SoftKey[] initSoftKeys();
13 | 
14 | 	/**
15 | 	 * 数组重新随机排列
16 | 	 * @param softKeys 软键盘中的关键字符数组
17 | 	 * @return
18 | 	 */
19 | 	public SoftKey[] makeSoftKeysRandom(SoftKey[] softKeys);
20 | 	/**
21 | 	 * 初始化字符数组的绘画位置
22 | 	 * @param softKeys 软键盘中的关键字符数组
23 | 	 * @return
24 | 	 */
25 | 	public SoftKey[] measureSoftKeysPos(SoftKey[] softKeys);
26 | 	/**
27 | 	 *
28 | 	 * 计算每个softkey的宽度
29 | 	 * @param keyBoardwidth 软键盘的宽度
30 | 	 * @return
31 | 	 */
32 | 	public int measureBlockWidth(int keyBoardwidth);
33 | 	/**
34 | 	 * 计算每个softkey的高度
35 | 	 * @param keyBoardHeight 软键盘的高度
36 | 	 * @return
37 | 	 */
38 | 	public int measureBlockHeight(int keyBoardHeight);
39 | 	/**
40 | 	 * 绘制字符数组
41 | 	 * @param canvas
42 | 	 * @param softKeys
43 | 	 */
44 | 	public void drawSoftKeysPos(Canvas canvas,SoftKey[] softKeys);
45 | 
46 | 	/**
47 | 	 * 绘制按钮
48 | 	 * @param canvas
49 | 	 * @param softkey
50 | 	 */
51 | 	public void drawSoftKey(Canvas canvas,SoftKey softkey);
52 | 
53 | 	/**
54 | 	 * 获取用户手指正在触摸的sofkey
55 | 	 * @param eventX 手指所在当前视图的X坐标
56 | 	 * @param eventY 手指所在当前视图的Y坐标
57 | 	 * @return
58 | 	 */
59 | 	public SoftKey obtainTouchSoftKey(int eventX, int eventY);
60 | 	/**
61 | 	 * 重置所有按钮的状态
62 | 	 */
63 | 	public void resetSoftKeysState();
64 | }
65 | 
--------------------------------------------------------------------------------
/app/src/main/java/com/igeek/safesoftboard/ISoftKeyEvent.java:
--------------------------------------------------------------------------------
 1 | package com.igeek.safesoftboard;
 2 | 
 3 | public interface ISoftKeyEvent {
 4 | 	/**
 5 | 	 * 更新手指在视图上按钮的状态
 6 | 	 * @param eventX 手指所在当前视图的X坐标
 7 | 	 * @param eventY 手指所在当前视图的Y坐标
 8 | 	 * @param action 事件的动作  -down,move
 9 | 	 * @return true -表示需要刷新视图,反之无需刷新
10 | 	 */
11 | 	public boolean handleKeyTouching(int eventX, int eventY,int action);
12 | 	/**
13 | 	 * 是否拦截用户手指的抬起事件(action_up)
14 | 	 * @param eventX 手指所在当前视图的X坐标
15 | 	 * @param eventY 手指所在当前视图的Y坐标
16 | 	 * @param action 事件的动作  -up
17 | 	 */
18 | 	public boolean handleTouchUp(int eventX, int eventY,int action);
19 | 	/**
20 | 	 * 通知长按删除事件
21 | 	 */
22 | 	public void performQuickDelete();
23 | 	/**
24 | 	 * 取消长按删除事件
25 | 	 */
26 | 	public void cancelQuickDelete();
27 | 	
28 | }
29 | 
--------------------------------------------------------------------------------
/app/src/main/java/com/igeek/safesoftboard/MainActivity.java:
--------------------------------------------------------------------------------
 1 | package com.igeek.safesoftboard;
 2 | 
 3 | import android.app.Activity;
 4 | import android.os.Bundle;
 5 | 
 6 | public class MainActivity extends Activity{
 7 | 
 8 | 	@Override
 9 | 	protected void onCreate(Bundle savedInstanceState) {
10 | 		super.onCreate(savedInstanceState);
11 | 		setContentView(R.layout.activity_main);
12 | 	}
13 | }
14 | 
--------------------------------------------------------------------------------
/app/src/main/java/com/igeek/safesoftboard/SafeEdit.java:
--------------------------------------------------------------------------------
 1 | package com.igeek.safesoftboard;
 2 | 
 3 | import android.annotation.SuppressLint;
 4 | import android.content.Context;
 5 | import android.util.AttributeSet;
 6 | import android.view.MotionEvent;
 7 | import android.widget.EditText;
 8 | import android.widget.PopupWindow.OnDismissListener;
 9 | 
10 | public class SafeEdit extends EditText implements OnDismissListener{
11 | 
12 | 	private SoftKeyBoard softKeyBoard;
13 | 
14 | 	public SafeEdit(Context context) {
15 | 		super(context);
16 | 		initSafeEdit(context);
17 | 	}
18 | 
19 | 	public SafeEdit(Context context, AttributeSet attrs) {
20 | 		super(context, attrs);
21 | 		initSafeEdit(context);
22 | 	}
23 | 
24 | 	public SafeEdit(Context context, AttributeSet attrs, int defStyleAttr) {
25 | 		super(context, attrs, defStyleAttr);
26 | 		initSafeEdit(context);
27 | 	}
28 | 	
29 | 	public void initSafeEdit(Context context){
30 | 		//setOnFocusChangeListener(this);
31 | 	}
32 | 
33 | 	
34 | 	@SuppressLint("ClickableViewAccessibility")
35 | 	@Override
36 | 	public boolean onTouchEvent(MotionEvent event) {
37 | 		// TODO Auto-generated method stub
38 | 		if(event.getAction()==MotionEvent.ACTION_UP){
39 | 			if (softKeyBoard == null) {
40 | 				softKeyBoard=new SoftKeyBoard(getContext());
41 | 				softKeyBoard.setEdit(this);
42 | 				softKeyBoard.setOnDismissListener(this);
43 | 				softKeyBoard.show();
44 | 			}
45 | 		}
46 | 		return true;
47 | 	}
48 | 
49 | 	@Override
50 | 	public void onDismiss() {
51 | 		softKeyBoard.recycle();
52 | 		softKeyBoard=null;
53 | 	}
54 | }
55 | 
--------------------------------------------------------------------------------
/app/src/main/java/com/igeek/safesoftboard/SoftKey.java:
--------------------------------------------------------------------------------
  1 | package com.igeek.safesoftboard;
  2 | 
  3 | import java.io.Serializable;
  4 | 
  5 | 
  6 | public class SoftKey implements Serializable {
  7 | 
  8 | 	/**
  9 | 	 *
 10 | 	 */
 11 | 	private static final long serialVersionUID = 1L;
 12 | 	/**
 13 | 	 * X坐标
 14 | 	 */
 15 | 	private int x;
 16 | 	/**
 17 | 	 * y坐标
 18 | 	 */
 19 | 	private int y;
 20 | 	/**
 21 | 	 * 图标
 22 | 	 */
 23 | 	private int icon;
 24 | 	/**
 25 | 	 * 按钮的宽度
 26 | 	 */
 27 | 	private int width;
 28 | 	/**
 29 | 	 * 按钮的高度
 30 | 	 */
 31 | 	private int height;
 32 | 	/**
 33 | 	 * 按钮的文本
 34 | 	 */
 35 | 	private String text;
 36 | 	/**
 37 | 	 * 是否被按下选中
 38 | 	 */
 39 | 	private boolean isPreessed;
 40 | 	
 41 | 	private KeyType keyType=KeyType.TEXT;
 42 | 	
 43 | 	public static enum KeyType{
 44 | 		TEXT,ICON,TEXT_ICON;
 45 | 	}
 46 | 	
 47 | 	public SoftKey() {
 48 | 		super();
 49 | 	}
 50 | 
 51 | 	public int getX() {
 52 | 		return x;
 53 | 	}
 54 | 
 55 | 	public void setX(int x) {
 56 | 		this.x = x;
 57 | 	}
 58 | 
 59 | 	public int getY() {
 60 | 		return y;
 61 | 	}
 62 | 
 63 | 	public void setY(int y) {
 64 | 		this.y = y;
 65 | 	}
 66 | 	
 67 | 	public int getIcon() {
 68 | 		return icon;
 69 | 	}
 70 | 
 71 | 	public void setIcon(int icon) {
 72 | 		this.icon = icon;
 73 | 	}
 74 | 
 75 | 	public int getWidth() {
 76 | 		return width;
 77 | 	}
 78 | 
 79 | 	public void setWidth(int width) {
 80 | 		this.width = width;
 81 | 	}
 82 | 
 83 | 	public int getHeight() {
 84 | 		return height;
 85 | 	}
 86 | 
 87 | 	public void setHeight(int height) {
 88 | 		this.height = height;
 89 | 	}
 90 | 
 91 | 	public String getText() {
 92 | 		return text;
 93 | 	}
 94 | 
 95 | 	public void setText(String text) {
 96 | 		this.text = text;
 97 | 	}
 98 | 	
 99 | 	public KeyType getKeyType() {
100 | 		return keyType;
101 | 	}
102 | 
103 | 	public void setKeyType(KeyType keyType) {
104 | 		this.keyType = keyType;
105 | 	}
106 | 
107 | 	public boolean isPreessed() {
108 | 		return isPreessed;
109 | 	}
110 | 
111 | 	public void setPreessed(boolean isPreessed) {
112 | 		this.isPreessed = isPreessed;
113 | 	}
114 | 	
115 | 	public boolean updatePressed(int eventX, int eventY){
116 | 		 boolean isPress=this.isPreessed;
117 | 		 this.isPreessed=inRange(eventX,eventY);
118 | 		 return isPress!=this.isPreessed;
119 | 	}
120 | 
121 | 	public boolean equa(SoftKey btn) {
122 | 		if (x == btn.getX() && y == btn.getY()) {
123 | 			return true;
124 | 		} else {
125 | 			return false;
126 | 		}
127 | 	}
128 | 
129 | 	public boolean inRange(int eventX, int eventY) {
130 | 		boolean inXRange = (eventX > x - width / 2)
131 | 				&& (eventX < x + width / 2);
132 | 		boolean inYRange = (eventY > y - height / 2)
133 | 				&& (eventY < y + height / 2);
134 | 		if (inXRange && inYRange) {
135 | 			return true;
136 | 		} else {
137 | 			return false;
138 | 		}
139 | 	}
140 | 
141 | }
142 | 
--------------------------------------------------------------------------------
/app/src/main/java/com/igeek/safesoftboard/SoftKeyAzLayView.java:
--------------------------------------------------------------------------------
  1 | package com.igeek.safesoftboard;
  2 | 
  3 | import android.annotation.SuppressLint;
  4 | import android.content.Context;
  5 | import android.graphics.Canvas;
  6 | import android.util.AttributeSet;
  7 | 
  8 | import com.igeek.safesoftboard.SoftKey.KeyType;
  9 | 
 10 | /**
 11 |  * 字母键盘
 12 |  */
 13 | public class SoftKeyAzLayView extends SoftKeyView{
 14 | 
 15 | 
 16 | 	/**
 17 | 	 * 数字键盘的分布4行 -10列-9列-9列(包含2个其他的按钮)
 18 | 	 */
 19 | 	private int OneCol=10;
 20 | 	private int twoCol=9;
 21 | 	private int row=4;
 22 | 	private SoftKey capsLockBtn;
 23 | 	private SoftKey [] punctKeys;
 24 | 	
 25 | 
 26 | 	public SoftKeyAzLayView(Context context) {
 27 | 		this(context, null);
 28 | 	}
 29 | 
 30 | 	public SoftKeyAzLayView(Context context, AttributeSet attrs) {
 31 | 		this(context, attrs, 0);
 32 | 	}
 33 | 
 34 | 	public SoftKeyAzLayView(Context context, AttributeSet attrs,
 35 | 			int defStyleAttr) {
 36 | 		super(context, attrs, defStyleAttr);
 37 | 	}
 38 | 	
 39 | 	@Override
 40 | 	public SoftKey[] initSoftKeys() {
 41 | 		SoftKey [] result=new SoftKey[26];
 42 | 		char cha='a';
 43 | 		for(int index=0;indexdecorViewHeight="+decorViewHeight);
244 | 				TranslateAnimation translate=new TranslateAnimation(0, 0, 0, softKeyHeight);
245 | 				translate.setDuration(200);
246 | 				translate.setFillAfter(true);
247 | 				decorView.startAnimation(translate);
248 | 			}else{
249 | 				Log.i(TAG, "updateViewDraw-->decorViewHeight="+decorViewHeight);
250 | 				TranslateAnimation translate=new TranslateAnimation(0, 0, -softKeyHeight, 0);
251 | 				translate.setDuration(200);
252 | 				translate.setFillAfter(true);
253 | 				decorView.startAnimation(translate);
254 | 			}
255 | 		}
256 | 		
257 | 	};
258 | 	
259 | 	@Override
260 | 	public void onPressed(SoftKey softKey) {
261 | 		if(edit!=null){
262 | 			inputStr.append(softKey.getText());
263 | 			edit.setText(inputStr.toString());
264 | 			edit.setSelection(inputStr.length());
265 | 		}
266 | 	}
267 | 
268 | 	@Override
269 | 	public void onDeleted() {
270 | 		if(edit!=null&&(!TextUtils.isEmpty(inputStr.toString()))){
271 | 			edit.setText(inputStr.deleteCharAt(inputStr.length()-1));
272 | 			edit.setSelection(inputStr.length());
273 | 		}
274 | 	}
275 | 
276 | 	@Override
277 | 	public void onConfirm() {
278 | 		close();
279 | 	}
280 | 	
281 | 	public void setEdit(EditText edit) {
282 | 		this.edit = edit;
283 | 	}
284 | 
285 | 	public void setViewMode(int viewMode) {
286 | 		if(viewMode!=this.viewMode){
287 | 			this.viewMode = viewMode;
288 | 			updateViewByMode(viewMode);
289 | 		}
290 | 	}
291 | 
292 | 	public boolean isPendding() {
293 | 		return isPendding;
294 | 	}
295 | 
296 | 	public void setPendding(boolean isPendding) {
297 | 		this.isPendding = isPendding;
298 | 	}
299 | 	
300 | }
301 | 
--------------------------------------------------------------------------------
/app/src/main/java/com/igeek/safesoftboard/SoftKeyNumLayView.java:
--------------------------------------------------------------------------------
  1 | package com.igeek.safesoftboard;
  2 | 
  3 | import android.content.Context;
  4 | import android.graphics.Canvas;
  5 | import android.graphics.Color;
  6 | import android.util.AttributeSet;
  7 | 
  8 | import com.igeek.safesoftboard.SoftKey.KeyType;
  9 | 
 10 | /**
 11 |  * 数字键盘布局
 12 |  */
 13 | public class SoftKeyNumLayView extends SoftKeyView {
 14 | 
 15 | 	/**
 16 | 	 * 数字键盘的分布4行3列
 17 | 	 */
 18 | 	private int row = 4;
 19 | 	private int col = 3;
 20 | 
 21 | 
 22 | 	public SoftKeyNumLayView(Context context) {
 23 | 		this(context, null);
 24 | 	}
 25 | 
 26 | 	public SoftKeyNumLayView(Context context, AttributeSet attrs) {
 27 | 		this(context, attrs,0);
 28 | 	}
 29 | 
 30 | 	public SoftKeyNumLayView(Context context, AttributeSet attrs, int defStyleAttr) {
 31 | 		super(context, attrs, defStyleAttr);
 32 | 	}
 33 | 
 34 | 	@Override
 35 | 	public SoftKey[] initSoftKeys() {
 36 | 		SoftKey[] result = new SoftKey[10];
 37 | 		for (int i = 0; i < result.length; i++) {
 38 | 			SoftKey btn = new SoftKey();
 39 | 			btn.setText(String.valueOf(i));
 40 | 			result[i] = btn;
 41 | 		}
 42 | 		return result;
 43 | 	}
 44 | 
 45 | 	@Override
 46 | 	public SoftKey[] measureSoftKeysPos(SoftKey[] softKeys) {
 47 | 		for (int i = 0; i < softKeys.length; i++) {
 48 | 			softKeys[i].setX(blockWidth / 2 + (i % col) * blockWidth);
 49 | 			softKeys[i].setY(blockHeight / 2 + (i / col % row) * blockHeight);
 50 | 			softKeys[i].setWidth(blockWidth);
 51 | 			softKeys[i].setHeight(blockHeight);
 52 | 		}
 53 | 		return softKeys;
 54 | 	}
 55 | 
 56 | 	@Override
 57 | 	public int measureBlockWidth(int keyBoardwidth) {
 58 | 		return keyBoardwidth/col;
 59 | 	}
 60 | 
 61 | 	@Override
 62 | 	public int measureBlockHeight(int keyBoardHeight) {
 63 | 		return keyBoardHeight/row;
 64 | 	}
 65 | 
 66 | 	@Override
 67 | 	public void drawSoftKeysPos(Canvas canvas, SoftKey[] softKeys) {
 68 | 		if (softKeys == null) {
 69 | 			return ;
 70 | 		}
 71 | 
 72 | 		canvas.drawColor(Color.WHITE);
 73 | 		//画垂直分割线
 74 | 		for (int index = 0; index < col; index++) {
 75 | 			canvas.drawLine((index + 1) * blockWidth, 0, (index + 1)* blockWidth, getHeight(), keyBorderPaint);
 76 | 		}
 77 | 
 78 | 		//画水平分割线
 79 | 		for (int index = 0; index < row; index++) {
 80 | 			canvas.drawLine(0, index * blockHeight, getWidth(),index * blockHeight, keyBorderPaint);
 81 | 		}
 82 | 
 83 | 		//画软键盘的9个数字按钮
 84 | 		for (int index = 0; index < softKeys.length-1; index++) {
 85 | 			drawSoftKey(canvas, softKeys[index]);
 86 | 		}
 87 | 
 88 | 		//创建软键盘的删除按钮
 89 | 		if(delBtn==null){
 90 | 			delBtn=new SoftKey();
 91 | 			delBtn.setKeyType(KeyType.ICON);
 92 | 			delBtn.setIcon(R.drawable.ic_softkey_delete);
 93 | 			delBtn.setHeight(blockHeight);
 94 | 			delBtn.setWidth(blockWidth);
 95 | 			delBtn.setX(softKeys[softKeys.length-1].getX());
 96 | 			delBtn.setY(softKeys[softKeys.length-1].getY());
 97 | 			softKeys[softKeys.length-1].setX(blockWidth / 2 + ((col-2)% col) * blockWidth);
 98 | 			softKeys[softKeys.length-1].setY(blockHeight / 2 + ((row-1) % row) * blockHeight);
 99 | 		}
100 | 
101 | 		//画软键盘的删除按钮
102 | 		drawSoftKey(canvas,delBtn);
103 | 
104 | 		//画第10个数字按钮
105 | 		drawSoftKey(canvas,softKeys[softKeys.length-1]);
106 | 
107 | 		if(confirmBtn==null){
108 | 			confirmBtn=new SoftKey();
109 | 			confirmBtn.setText("确定");
110 | 			confirmBtn.setHeight(blockHeight);
111 | 			confirmBtn.setWidth(blockWidth);
112 | 			confirmBtn.setX(blockWidth / 2 + ((col-1)% col) * blockWidth);
113 | 			confirmBtn.setY(blockHeight / 2 + ((row-1) % row) * blockHeight);
114 | 		}
115 | 
116 | 		drawSoftKey(canvas,confirmBtn);
117 | 
118 | 	}
119 | }
120 | 
--------------------------------------------------------------------------------
/app/src/main/java/com/igeek/safesoftboard/SoftKeyPunctLayView.java:
--------------------------------------------------------------------------------
  1 | package com.igeek.safesoftboard;
  2 | 
  3 | import android.content.Context;
  4 | import android.graphics.Canvas;
  5 | import android.util.AttributeSet;
  6 | 
  7 | import com.igeek.safesoftboard.SoftKey.KeyType;
  8 | /**
  9 |  * 标点符号视图
 10 |  */
 11 | public class SoftKeyPunctLayView extends SoftKeyView {
 12 | 
 13 | 	private int col=8;
 14 | 	private int row=4;
 15 | 	
 16 | 	public SoftKeyPunctLayView(Context context) {
 17 | 		super(context);
 18 | 		// TODO Auto-generated constructor stub
 19 | 	}
 20 | 
 21 | 	public SoftKeyPunctLayView(Context context, AttributeSet attrs) {
 22 | 		super(context, attrs);
 23 | 		// TODO Auto-generated constructor stub
 24 | 	}
 25 | 
 26 | 	public SoftKeyPunctLayView(Context context, AttributeSet attrs,
 27 | 			int defStyleAttr) {
 28 | 		super(context, attrs, defStyleAttr);
 29 | 		// TODO Auto-generated constructor stub
 30 | 	}
 31 | 
 32 | 	@Override
 33 | 	public SoftKey[] initSoftKeys() {
 34 | 		// TODO Auto-generated method stub
 35 | 		//提取了<@#*./>到字母布局中
 36 | 		String mSignArray="~!<>?`-=[]\\;',$%^&()_+{}|:\"";
 37 | 		SoftKey [] softKeys=new SoftKey[mSignArray.length()];
 38 | 		for(int index=0;index 0; i--) {
227 | 			w = rand.nextInt(i);
228 | 			String number = softKeys[i].getText();
229 | 			softKeys[i].setText(softKeys[w].getText());
230 | 			softKeys[w].setText(number);
231 | 		}
232 | 		return softKeys;
233 | 	}
234 | 
235 | 	@Override
236 | 	public void drawSoftKey(Canvas canvas, SoftKey softkey) {
237 | 		// TODO Auto-generated method stub
238 | 		switch (softkey.getKeyType()) {
239 | 		case TEXT:
240 | 			drawTextSoftKey(canvas, softkey);
241 | 			break;
242 | 		case ICON:
243 | 			drawIconSoftKey(canvas, softkey);
244 | 			break;
245 | 		case TEXT_ICON:
246 | 			drawIconSoftKey(canvas, softkey);
247 | 			break;
248 | 		}
249 | 		if(softkey.isPreessed()){
250 | 			drawSoftKeyPressBg(canvas, softkey);
251 | 		}
252 | 	}
253 | 	
254 | 	/**
255 | 	 * �����ı��İ�ť
256 | 	 * @param canvas
257 | 	 * @param softkey
258 | 	 */
259 | 	public void drawTextSoftKey(Canvas canvas,SoftKey softkey){
260 | 		Rect bounds = new Rect();
261 | 		keyTextPaint.getTextBounds(softkey.getText(), 0, softkey.getText().length(), bounds);
262 | 		int startX = softkey.getX() - bounds.width() / 2;
263 | 		int startY = softkey.getY() + bounds.height() / 2;
264 | 		canvas.drawText(softkey.getText(), startX, startY, keyTextPaint);
265 | 	}
266 | 	/**
267 | 	 * ����ͼ��İ�ť
268 | 	 * @param canvas
269 | 	 * @param softkey
270 | 	 */
271 | 	public void drawIconSoftKey(Canvas canvas,SoftKey softkey){
272 | 		Options opts=new Options();
273 | 		BitmapFactory.decodeResource(getContext().getResources(), softkey.getIcon(),opts);
274 | 		opts.inJustDecodeBounds=true;
275 | 		int minWH=Math.min(softkey.getHeight(), softkey.getWidth());
276 | 		int maxBP=Math.max(opts.outHeight, opts.outWidth);
277 | 		if(maxBP>minWH){
278 | 			opts.inSampleSize=minWH/maxBP;
279 | 		}else{
280 | 			opts.inSampleSize=maxBP/minWH;
281 | 		}
282 | 		opts.inJustDecodeBounds=false;
283 | 		Bitmap newBit=BitmapFactory.decodeResource(getContext().getResources(), softkey.getIcon(),opts);
284 | 		canvas.drawBitmap(newBit, softkey.getX()-newBit.getWidth()/2, softkey.getY()-newBit.getHeight()/2, null);
285 | 		newBit.recycle();
286 | 	}
287 | 	
288 | 	/**
289 | 	 * @param canvas
290 | 	 * @param softkey
291 | 	 */
292 | 	public void drawSoftKeyPressBg(Canvas canvas, SoftKey softkey) {
293 | 		int left = softkey.getX() - softkey.getWidth() / 2;
294 | 		int top = softkey.getY() - softkey.getHeight() / 2;
295 | 		int right = softkey.getX() + softkey.getWidth() / 2;
296 | 		int bottom = softkey.getY() + softkey.getHeight() / 2;
297 | 		canvas.drawRect(left, top, right, bottom, keyPressedBgPaint);
298 | 	}
299 | 
300 | 	@Override
301 | 	public boolean handleKeyTouching(int eventX, int eventY, int action) {
302 | 		boolean isrefresh = false;
303 | 
304 | 		if (softKeys == null) {
305 | 			return false;
306 | 		}
307 | 
308 | 		if (delBtn.inRange(eventX, eventY) && action == MotionEvent.ACTION_DOWN) {
309 | 			performQuickDelete();
310 | 		}
311 | 
312 | 		if (!delBtn.inRange(eventX, eventY)&& action == MotionEvent.ACTION_MOVE) {
313 | 			cancelQuickDelete();
314 | 		}
315 | 
316 | 		delBtn.updatePressed(eventX, eventY);
317 | 		confirmBtn.updatePressed(eventX, eventY);
318 | 
319 | 		isrefresh = (delBtn.isPreessed() || confirmBtn.isPreessed());
320 | 
321 | 		for (int index = 0; index < softKeys.length; index++) {
322 | 			if (isrefresh) {
323 | 				softKeys[index].setPreessed(false);
324 | 			} else {
325 | 				isrefresh = softKeys[index].updatePressed(eventX, eventY);
326 | 			}
327 | 		}
328 | 		return isrefresh;
329 | 	}
330 | 	
331 | 	@Override
332 | 	public boolean handleTouchUp(int eventX, int eventY, int action) {
333 | 		resetSoftKeysState();
334 | 		if (delBtn.inRange(eventX, eventY)) {
335 | 			if (listener != null) {
336 | 				listener.onDeleted();
337 | 			}
338 | 			return true;
339 | 		}
340 | 		if (confirmBtn.inRange(eventX, eventY)) {
341 | 			if (listener != null) {
342 | 				listener.onConfirm();
343 | 			}
344 | 			return true;
345 | 		}
346 | 		SoftKey btn = obtainTouchSoftKey(eventX, eventY);
347 | 		if (btn != null) {
348 | 			if (listener != null) {
349 | 				listener.onPressed(btn);
350 | 			}
351 | 			return true;
352 | 		}
353 | 		return false;
354 | 	}
355 | 	
356 | 	@Override
357 | 	public SoftKey obtainTouchSoftKey(int eventX, int eventY) {
358 | 		if (softKeys == null) {
359 | 			return null;
360 | 		}
361 | 		for (int index = 0; index < softKeys.length; index++) {
362 | 			if (softKeys[index].inRange(eventX, eventY)) {
363 | 				return softKeys[index];
364 | 			}
365 | 		}	
366 | 		return null;
367 | 	}
368 | 
369 | 	@Override
370 | 	public void resetSoftKeysState() {
371 | 		cancelQuickDelete();
372 | 		delBtn.setPreessed(false);
373 | 		confirmBtn.setPreessed(false);
374 | 		for (int index = 0; index < softKeys.length; index++) {
375 | 			softKeys[index].setPreessed(false);
376 | 		}
377 | 	}
378 | 
379 | 	@Override
380 | 	public void performQuickDelete() {
381 | 		pressHandler.sendEmptyMessageDelayed(KeyEvent.FLAG_KEEP_TOUCH_MODE,ViewConfiguration.getLongPressTimeout());
382 | 	}
383 | 
384 | 	@Override
385 | 	public void cancelQuickDelete() {
386 | 		pressHandler.sendEmptyMessage(KeyEvent.FLAG_CANCELED_LONG_PRESS);
387 | 	}
388 | 
389 | 	public Handler pressHandler = new Handler() {
390 | 		public void handleMessage(android.os.Message msg) {
391 | 			switch (msg.what) {
392 | 			case KeyEvent.FLAG_LONG_PRESS:
393 | 				if (listener != null) {
394 | 					listener.onDeleted();
395 | 					pressHandler.sendEmptyMessageDelayed(KeyEvent.FLAG_LONG_PRESS, 100);
396 | 				}
397 | 				break;
398 | 			case KeyEvent.FLAG_KEEP_TOUCH_MODE:
399 | 				pressHandler.sendEmptyMessage(KeyEvent.FLAG_LONG_PRESS);
400 | 				pressHandler.removeMessages(KeyEvent.FLAG_KEEP_TOUCH_MODE);
401 | 				break;
402 | 
403 | 			case KeyEvent.FLAG_CANCELED_LONG_PRESS:
404 | 				pressHandler.removeMessages(KeyEvent.FLAG_KEEP_TOUCH_MODE);
405 | 				pressHandler.removeMessages(KeyEvent.FLAG_LONG_PRESS);
406 | 				break;
407 | 			}
408 | 		};
409 | 	};
410 | 	
411 | 	public void setSoftKeyListener(SoftKeyStatusListener listener) {
412 | 		this.listener = listener;
413 | 	}
414 | 
415 | }
416 | 
--------------------------------------------------------------------------------
/app/src/main/java/utils/DensityUtils.java:
--------------------------------------------------------------------------------
 1 | package utils;
 2 | 
 3 | import android.content.res.Resources;
 4 | import android.util.TypedValue;
 5 | 
 6 | /**
 7 |  * 常用单位转换的辅助类
 8 |  * Created by igeek2014@hotmail.com on 2015/4/16.
 9 |  */
10 | public class DensityUtils {
11 | 
12 |     private DensityUtils() {
13 |         throw new UnsupportedOperationException("单位工具类不能初始化对象");
14 |     }
15 | 
16 |     /**
17 |      * dp转px
18 |      *
19 |      * @param dpVal
20 |      * @return
21 |      */
22 |     public static int dp2px(float dpVal) {
23 |         return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
24 |                 dpVal, Resources.getSystem().getDisplayMetrics());
25 |     }
26 | 
27 |     /**
28 |      * sp转px
29 |      *
30 |      * @param spVal
31 |      * @return
32 |      */
33 |     public static int sp2px(float spVal) {
34 |         return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
35 |                 spVal, Resources.getSystem().getDisplayMetrics());
36 |     }
37 | 
38 |     /**
39 |      * px转dp
40 |      *
41 |      * @param pxVal
42 |      * @return
43 |      */
44 |     public static float px2dp(float pxVal) {
45 |         final float scale = Resources.getSystem().getDisplayMetrics().density;
46 |         return (pxVal / scale);
47 |     }
48 | 
49 |     /**
50 |      * px转sp
51 |      *
52 |      * @param pxVal
53 |      * @return
54 |      */
55 |     public static float px2sp(float pxVal) {
56 |         return (pxVal / Resources.getSystem().getDisplayMetrics().scaledDensity);
57 |     }
58 | 
59 | 
60 | }
61 | 
--------------------------------------------------------------------------------
/app/src/main/java/utils/ScreenUtils.java:
--------------------------------------------------------------------------------
  1 | package utils;
  2 | 
  3 | import android.app.Activity;
  4 | import android.content.Context;
  5 | import android.graphics.Bitmap;
  6 | import android.graphics.Rect;
  7 | import android.util.DisplayMetrics;
  8 | import android.view.View;
  9 | import android.view.WindowManager;
 10 | 
 11 | /**
 12 |  * 屏幕相关的工具类
 13 |  * Created by  igeek2014@hotmail.com on 2015/4/16.
 14 |  */
 15 | public class ScreenUtils {
 16 | 
 17 |     private ScreenUtils() {
 18 |         throw new UnsupportedOperationException("屏幕工具类不能初始化对象");
 19 |     }
 20 | 
 21 |     /**
 22 |      * 获得屏幕高度
 23 |      *
 24 |      * @param context
 25 |      * @return
 26 |      */
 27 |     public static int getScreenWidth(Context context) {
 28 |         WindowManager wm = (WindowManager) context
 29 |                 .getSystemService(Context.WINDOW_SERVICE);
 30 |         DisplayMetrics outMetrics = new DisplayMetrics();
 31 |         wm.getDefaultDisplay().getMetrics(outMetrics);
 32 |         return outMetrics.widthPixels;
 33 |     }
 34 | 
 35 |     /**
 36 |      * 获得屏幕宽度
 37 |      *
 38 |      * @param context
 39 |      * @return
 40 |      */
 41 |     public static int getScreenHeight(Context context) {
 42 |         WindowManager wm = (WindowManager) context
 43 |                 .getSystemService(Context.WINDOW_SERVICE);
 44 |         DisplayMetrics outMetrics = new DisplayMetrics();
 45 |         wm.getDefaultDisplay().getMetrics(outMetrics);
 46 |         return outMetrics.heightPixels;
 47 |     }
 48 | 
 49 |     /**
 50 |      * 获得状态栏的高度
 51 |      *
 52 |      * @param context
 53 |      * @return
 54 |      */
 55 |     public static int getStatusHeight(Context context) {
 56 | 
 57 |         int statusHeight = -1;
 58 |         try {
 59 |             Class> clazz = Class.forName("com.android.internal.R$dimen");
 60 |             Object object = clazz.newInstance();
 61 |             int height = Integer.parseInt(clazz.getField("status_bar_height")
 62 |                     .get(object).toString());
 63 |             statusHeight = context.getResources().getDimensionPixelSize(height);
 64 |         } catch (Exception e) {
 65 |             e.printStackTrace();
 66 |         }
 67 |         return statusHeight;
 68 |     }
 69 | 
 70 |     /**
 71 |      * 获取当前屏幕截图,包含状态栏
 72 |      *
 73 |      * @param activity
 74 |      * @return
 75 |      */
 76 |     public static Bitmap snapShotWithStatusBar(Activity activity) {
 77 |         View view = activity.getWindow().getDecorView();
 78 |         view.setDrawingCacheEnabled(true);
 79 |         view.buildDrawingCache();
 80 |         Bitmap bmp = view.getDrawingCache();
 81 |         int width = getScreenWidth(activity);
 82 |         int height = getScreenHeight(activity);
 83 |         Bitmap bp = null;
 84 |         bp = Bitmap.createBitmap(bmp, 0, 0, width, height);
 85 |         view.destroyDrawingCache();
 86 |         return bp;
 87 | 
 88 |     }
 89 | 
 90 |     /**
 91 |      * 获取当前屏幕截图,不包含状态栏
 92 |      *
 93 |      * @param activity
 94 |      * @return
 95 |      */
 96 |     public static Bitmap snapShotWithoutStatusBar(Activity activity) {
 97 |         View view = activity.getWindow().getDecorView();
 98 |         view.setDrawingCacheEnabled(true);
 99 |         view.buildDrawingCache();
100 |         Bitmap bmp = view.getDrawingCache();
101 |         Rect frame = new Rect();
102 |         activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
103 |         int statusBarHeight = frame.top;
104 | 
105 |         int width = getScreenWidth(activity);
106 |         int height = getScreenHeight(activity);
107 |         Bitmap bp = null;
108 |         bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height
109 |                 - statusBarHeight);
110 |         view.destroyDrawingCache();
111 |         return bp;
112 | 
113 |     }
114 | 
115 |     public static int getXOnScreen(View view){
116 |         int [] location =new int[2];
117 |         view.getLocationOnScreen(location);
118 |         return location[0];
119 |     }
120 | 
121 |     public static int getYOnScreen(View view){
122 |         int [] location =new int[2];
123 |         view.getLocationOnScreen(location);
124 |         return location[1];
125 |     }
126 | 
127 | }
128 | 
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_softb_close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/src/main/res/drawable-hdpi/ic_softb_close.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_softboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/src/main/res/drawable-hdpi/ic_softboard.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_softkey_delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/src/main/res/drawable-hdpi/ic_softkey_delete.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_softb_close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/src/main/res/drawable-xhdpi/ic_softb_close.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_softboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/src/main/res/drawable-xhdpi/ic_softboard.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_softkey_delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/src/main/res/drawable-xhdpi/ic_softkey_delete.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/src/main/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_softb_close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/src/main/res/drawable-xxhdpi/ic_softb_close.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_softboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/src/main/res/drawable-xxhdpi/ic_softboard.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_softkey_delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/src/main/res/drawable-xxhdpi/ic_softkey_delete.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_radio.xml:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 |     
 4 |
 7 | 
 8 | 
 9 | ####XML 说明
10 | 	
15 | 
16 |     
20 | 
21 |     
29 | 
30 | 	
31 | 
32 | ####MainActivity 说明
33 | 	public class MainActivity extends Activity{
34 | 
35 | 		@Override
36 | 		protected void onCreate(Bundle savedInstanceState) {
37 | 			super.onCreate(savedInstanceState);
38 | 			setContentView(R.layout.activity_main);
39 | 		}
40 | 	}
41 | 
42 | 
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | 
--------------------------------------------------------------------------------
/app/app-release.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/app-release.apk
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: 'com.android.application'
 2 | 
 3 | android {
 4 |     compileSdkVersion 23
 5 |     buildToolsVersion "23.0.2"
 6 | 
 7 |     defaultConfig {
 8 |         applicationId "com.igeek.safesoftboard"
 9 |         minSdkVersion 15
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.3.0'
26 |     compile 'com.android.support:design:23.3.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 /Users/Allen1/Library/Android/sdk/tools/proguard/proguard-android.txt
 4 | # You can edit the include path and order by changing the proguardFiles
 5 | # directive in build.gradle.
 6 | #
 7 | # For more details, see
 8 | #   http://developer.android.com/guide/developing/tools/proguard.html
 9 | 
10 | # Add any project specific keep options here:
11 | 
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | #   public *;
17 | #}
18 | 
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/igeek/safesoftboard/ApplicationTest.java:
--------------------------------------------------------------------------------
 1 | package com.igeek.safesoftboard;
 2 | 
 3 | import android.app.Application;
 4 | import android.test.ApplicationTestCase;
 5 | 
 6 | /**
 7 |  * Testing Fundamentals
 8 |  */
 9 | public class ApplicationTest extends ApplicationTestCase {
10 |     public ApplicationTest() {
11 |         super(Application.class);
12 |     }
13 | }
--------------------------------------------------------------------------------
/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/igeek/safesoftboard/ISoftKeyBoard.java:
--------------------------------------------------------------------------------
 1 | package com.igeek.safesoftboard;
 2 | 
 3 | import android.graphics.Canvas;
 4 | import android.view.View;
 5 | 
 6 | public interface ISoftKeyBoard extends View.OnTouchListener,ISoftKeyEvent{
 7 | 
 8 | 	/**
 9 | 	 * 初始化关键的字符数组
10 | 	 * @return
11 | 	 */
12 | 	public SoftKey[] initSoftKeys();
13 | 
14 | 	/**
15 | 	 * 数组重新随机排列
16 | 	 * @param softKeys 软键盘中的关键字符数组
17 | 	 * @return
18 | 	 */
19 | 	public SoftKey[] makeSoftKeysRandom(SoftKey[] softKeys);
20 | 	/**
21 | 	 * 初始化字符数组的绘画位置
22 | 	 * @param softKeys 软键盘中的关键字符数组
23 | 	 * @return
24 | 	 */
25 | 	public SoftKey[] measureSoftKeysPos(SoftKey[] softKeys);
26 | 	/**
27 | 	 *
28 | 	 * 计算每个softkey的宽度
29 | 	 * @param keyBoardwidth 软键盘的宽度
30 | 	 * @return
31 | 	 */
32 | 	public int measureBlockWidth(int keyBoardwidth);
33 | 	/**
34 | 	 * 计算每个softkey的高度
35 | 	 * @param keyBoardHeight 软键盘的高度
36 | 	 * @return
37 | 	 */
38 | 	public int measureBlockHeight(int keyBoardHeight);
39 | 	/**
40 | 	 * 绘制字符数组
41 | 	 * @param canvas
42 | 	 * @param softKeys
43 | 	 */
44 | 	public void drawSoftKeysPos(Canvas canvas,SoftKey[] softKeys);
45 | 
46 | 	/**
47 | 	 * 绘制按钮
48 | 	 * @param canvas
49 | 	 * @param softkey
50 | 	 */
51 | 	public void drawSoftKey(Canvas canvas,SoftKey softkey);
52 | 
53 | 	/**
54 | 	 * 获取用户手指正在触摸的sofkey
55 | 	 * @param eventX 手指所在当前视图的X坐标
56 | 	 * @param eventY 手指所在当前视图的Y坐标
57 | 	 * @return
58 | 	 */
59 | 	public SoftKey obtainTouchSoftKey(int eventX, int eventY);
60 | 	/**
61 | 	 * 重置所有按钮的状态
62 | 	 */
63 | 	public void resetSoftKeysState();
64 | }
65 | 
--------------------------------------------------------------------------------
/app/src/main/java/com/igeek/safesoftboard/ISoftKeyEvent.java:
--------------------------------------------------------------------------------
 1 | package com.igeek.safesoftboard;
 2 | 
 3 | public interface ISoftKeyEvent {
 4 | 	/**
 5 | 	 * 更新手指在视图上按钮的状态
 6 | 	 * @param eventX 手指所在当前视图的X坐标
 7 | 	 * @param eventY 手指所在当前视图的Y坐标
 8 | 	 * @param action 事件的动作  -down,move
 9 | 	 * @return true -表示需要刷新视图,反之无需刷新
10 | 	 */
11 | 	public boolean handleKeyTouching(int eventX, int eventY,int action);
12 | 	/**
13 | 	 * 是否拦截用户手指的抬起事件(action_up)
14 | 	 * @param eventX 手指所在当前视图的X坐标
15 | 	 * @param eventY 手指所在当前视图的Y坐标
16 | 	 * @param action 事件的动作  -up
17 | 	 */
18 | 	public boolean handleTouchUp(int eventX, int eventY,int action);
19 | 	/**
20 | 	 * 通知长按删除事件
21 | 	 */
22 | 	public void performQuickDelete();
23 | 	/**
24 | 	 * 取消长按删除事件
25 | 	 */
26 | 	public void cancelQuickDelete();
27 | 	
28 | }
29 | 
--------------------------------------------------------------------------------
/app/src/main/java/com/igeek/safesoftboard/MainActivity.java:
--------------------------------------------------------------------------------
 1 | package com.igeek.safesoftboard;
 2 | 
 3 | import android.app.Activity;
 4 | import android.os.Bundle;
 5 | 
 6 | public class MainActivity extends Activity{
 7 | 
 8 | 	@Override
 9 | 	protected void onCreate(Bundle savedInstanceState) {
10 | 		super.onCreate(savedInstanceState);
11 | 		setContentView(R.layout.activity_main);
12 | 	}
13 | }
14 | 
--------------------------------------------------------------------------------
/app/src/main/java/com/igeek/safesoftboard/SafeEdit.java:
--------------------------------------------------------------------------------
 1 | package com.igeek.safesoftboard;
 2 | 
 3 | import android.annotation.SuppressLint;
 4 | import android.content.Context;
 5 | import android.util.AttributeSet;
 6 | import android.view.MotionEvent;
 7 | import android.widget.EditText;
 8 | import android.widget.PopupWindow.OnDismissListener;
 9 | 
10 | public class SafeEdit extends EditText implements OnDismissListener{
11 | 
12 | 	private SoftKeyBoard softKeyBoard;
13 | 
14 | 	public SafeEdit(Context context) {
15 | 		super(context);
16 | 		initSafeEdit(context);
17 | 	}
18 | 
19 | 	public SafeEdit(Context context, AttributeSet attrs) {
20 | 		super(context, attrs);
21 | 		initSafeEdit(context);
22 | 	}
23 | 
24 | 	public SafeEdit(Context context, AttributeSet attrs, int defStyleAttr) {
25 | 		super(context, attrs, defStyleAttr);
26 | 		initSafeEdit(context);
27 | 	}
28 | 	
29 | 	public void initSafeEdit(Context context){
30 | 		//setOnFocusChangeListener(this);
31 | 	}
32 | 
33 | 	
34 | 	@SuppressLint("ClickableViewAccessibility")
35 | 	@Override
36 | 	public boolean onTouchEvent(MotionEvent event) {
37 | 		// TODO Auto-generated method stub
38 | 		if(event.getAction()==MotionEvent.ACTION_UP){
39 | 			if (softKeyBoard == null) {
40 | 				softKeyBoard=new SoftKeyBoard(getContext());
41 | 				softKeyBoard.setEdit(this);
42 | 				softKeyBoard.setOnDismissListener(this);
43 | 				softKeyBoard.show();
44 | 			}
45 | 		}
46 | 		return true;
47 | 	}
48 | 
49 | 	@Override
50 | 	public void onDismiss() {
51 | 		softKeyBoard.recycle();
52 | 		softKeyBoard=null;
53 | 	}
54 | }
55 | 
--------------------------------------------------------------------------------
/app/src/main/java/com/igeek/safesoftboard/SoftKey.java:
--------------------------------------------------------------------------------
  1 | package com.igeek.safesoftboard;
  2 | 
  3 | import java.io.Serializable;
  4 | 
  5 | 
  6 | public class SoftKey implements Serializable {
  7 | 
  8 | 	/**
  9 | 	 *
 10 | 	 */
 11 | 	private static final long serialVersionUID = 1L;
 12 | 	/**
 13 | 	 * X坐标
 14 | 	 */
 15 | 	private int x;
 16 | 	/**
 17 | 	 * y坐标
 18 | 	 */
 19 | 	private int y;
 20 | 	/**
 21 | 	 * 图标
 22 | 	 */
 23 | 	private int icon;
 24 | 	/**
 25 | 	 * 按钮的宽度
 26 | 	 */
 27 | 	private int width;
 28 | 	/**
 29 | 	 * 按钮的高度
 30 | 	 */
 31 | 	private int height;
 32 | 	/**
 33 | 	 * 按钮的文本
 34 | 	 */
 35 | 	private String text;
 36 | 	/**
 37 | 	 * 是否被按下选中
 38 | 	 */
 39 | 	private boolean isPreessed;
 40 | 	
 41 | 	private KeyType keyType=KeyType.TEXT;
 42 | 	
 43 | 	public static enum KeyType{
 44 | 		TEXT,ICON,TEXT_ICON;
 45 | 	}
 46 | 	
 47 | 	public SoftKey() {
 48 | 		super();
 49 | 	}
 50 | 
 51 | 	public int getX() {
 52 | 		return x;
 53 | 	}
 54 | 
 55 | 	public void setX(int x) {
 56 | 		this.x = x;
 57 | 	}
 58 | 
 59 | 	public int getY() {
 60 | 		return y;
 61 | 	}
 62 | 
 63 | 	public void setY(int y) {
 64 | 		this.y = y;
 65 | 	}
 66 | 	
 67 | 	public int getIcon() {
 68 | 		return icon;
 69 | 	}
 70 | 
 71 | 	public void setIcon(int icon) {
 72 | 		this.icon = icon;
 73 | 	}
 74 | 
 75 | 	public int getWidth() {
 76 | 		return width;
 77 | 	}
 78 | 
 79 | 	public void setWidth(int width) {
 80 | 		this.width = width;
 81 | 	}
 82 | 
 83 | 	public int getHeight() {
 84 | 		return height;
 85 | 	}
 86 | 
 87 | 	public void setHeight(int height) {
 88 | 		this.height = height;
 89 | 	}
 90 | 
 91 | 	public String getText() {
 92 | 		return text;
 93 | 	}
 94 | 
 95 | 	public void setText(String text) {
 96 | 		this.text = text;
 97 | 	}
 98 | 	
 99 | 	public KeyType getKeyType() {
100 | 		return keyType;
101 | 	}
102 | 
103 | 	public void setKeyType(KeyType keyType) {
104 | 		this.keyType = keyType;
105 | 	}
106 | 
107 | 	public boolean isPreessed() {
108 | 		return isPreessed;
109 | 	}
110 | 
111 | 	public void setPreessed(boolean isPreessed) {
112 | 		this.isPreessed = isPreessed;
113 | 	}
114 | 	
115 | 	public boolean updatePressed(int eventX, int eventY){
116 | 		 boolean isPress=this.isPreessed;
117 | 		 this.isPreessed=inRange(eventX,eventY);
118 | 		 return isPress!=this.isPreessed;
119 | 	}
120 | 
121 | 	public boolean equa(SoftKey btn) {
122 | 		if (x == btn.getX() && y == btn.getY()) {
123 | 			return true;
124 | 		} else {
125 | 			return false;
126 | 		}
127 | 	}
128 | 
129 | 	public boolean inRange(int eventX, int eventY) {
130 | 		boolean inXRange = (eventX > x - width / 2)
131 | 				&& (eventX < x + width / 2);
132 | 		boolean inYRange = (eventY > y - height / 2)
133 | 				&& (eventY < y + height / 2);
134 | 		if (inXRange && inYRange) {
135 | 			return true;
136 | 		} else {
137 | 			return false;
138 | 		}
139 | 	}
140 | 
141 | }
142 | 
--------------------------------------------------------------------------------
/app/src/main/java/com/igeek/safesoftboard/SoftKeyAzLayView.java:
--------------------------------------------------------------------------------
  1 | package com.igeek.safesoftboard;
  2 | 
  3 | import android.annotation.SuppressLint;
  4 | import android.content.Context;
  5 | import android.graphics.Canvas;
  6 | import android.util.AttributeSet;
  7 | 
  8 | import com.igeek.safesoftboard.SoftKey.KeyType;
  9 | 
 10 | /**
 11 |  * 字母键盘
 12 |  */
 13 | public class SoftKeyAzLayView extends SoftKeyView{
 14 | 
 15 | 
 16 | 	/**
 17 | 	 * 数字键盘的分布4行 -10列-9列-9列(包含2个其他的按钮)
 18 | 	 */
 19 | 	private int OneCol=10;
 20 | 	private int twoCol=9;
 21 | 	private int row=4;
 22 | 	private SoftKey capsLockBtn;
 23 | 	private SoftKey [] punctKeys;
 24 | 	
 25 | 
 26 | 	public SoftKeyAzLayView(Context context) {
 27 | 		this(context, null);
 28 | 	}
 29 | 
 30 | 	public SoftKeyAzLayView(Context context, AttributeSet attrs) {
 31 | 		this(context, attrs, 0);
 32 | 	}
 33 | 
 34 | 	public SoftKeyAzLayView(Context context, AttributeSet attrs,
 35 | 			int defStyleAttr) {
 36 | 		super(context, attrs, defStyleAttr);
 37 | 	}
 38 | 	
 39 | 	@Override
 40 | 	public SoftKey[] initSoftKeys() {
 41 | 		SoftKey [] result=new SoftKey[26];
 42 | 		char cha='a';
 43 | 		for(int index=0;indexdecorViewHeight="+decorViewHeight);
244 | 				TranslateAnimation translate=new TranslateAnimation(0, 0, 0, softKeyHeight);
245 | 				translate.setDuration(200);
246 | 				translate.setFillAfter(true);
247 | 				decorView.startAnimation(translate);
248 | 			}else{
249 | 				Log.i(TAG, "updateViewDraw-->decorViewHeight="+decorViewHeight);
250 | 				TranslateAnimation translate=new TranslateAnimation(0, 0, -softKeyHeight, 0);
251 | 				translate.setDuration(200);
252 | 				translate.setFillAfter(true);
253 | 				decorView.startAnimation(translate);
254 | 			}
255 | 		}
256 | 		
257 | 	};
258 | 	
259 | 	@Override
260 | 	public void onPressed(SoftKey softKey) {
261 | 		if(edit!=null){
262 | 			inputStr.append(softKey.getText());
263 | 			edit.setText(inputStr.toString());
264 | 			edit.setSelection(inputStr.length());
265 | 		}
266 | 	}
267 | 
268 | 	@Override
269 | 	public void onDeleted() {
270 | 		if(edit!=null&&(!TextUtils.isEmpty(inputStr.toString()))){
271 | 			edit.setText(inputStr.deleteCharAt(inputStr.length()-1));
272 | 			edit.setSelection(inputStr.length());
273 | 		}
274 | 	}
275 | 
276 | 	@Override
277 | 	public void onConfirm() {
278 | 		close();
279 | 	}
280 | 	
281 | 	public void setEdit(EditText edit) {
282 | 		this.edit = edit;
283 | 	}
284 | 
285 | 	public void setViewMode(int viewMode) {
286 | 		if(viewMode!=this.viewMode){
287 | 			this.viewMode = viewMode;
288 | 			updateViewByMode(viewMode);
289 | 		}
290 | 	}
291 | 
292 | 	public boolean isPendding() {
293 | 		return isPendding;
294 | 	}
295 | 
296 | 	public void setPendding(boolean isPendding) {
297 | 		this.isPendding = isPendding;
298 | 	}
299 | 	
300 | }
301 | 
--------------------------------------------------------------------------------
/app/src/main/java/com/igeek/safesoftboard/SoftKeyNumLayView.java:
--------------------------------------------------------------------------------
  1 | package com.igeek.safesoftboard;
  2 | 
  3 | import android.content.Context;
  4 | import android.graphics.Canvas;
  5 | import android.graphics.Color;
  6 | import android.util.AttributeSet;
  7 | 
  8 | import com.igeek.safesoftboard.SoftKey.KeyType;
  9 | 
 10 | /**
 11 |  * 数字键盘布局
 12 |  */
 13 | public class SoftKeyNumLayView extends SoftKeyView {
 14 | 
 15 | 	/**
 16 | 	 * 数字键盘的分布4行3列
 17 | 	 */
 18 | 	private int row = 4;
 19 | 	private int col = 3;
 20 | 
 21 | 
 22 | 	public SoftKeyNumLayView(Context context) {
 23 | 		this(context, null);
 24 | 	}
 25 | 
 26 | 	public SoftKeyNumLayView(Context context, AttributeSet attrs) {
 27 | 		this(context, attrs,0);
 28 | 	}
 29 | 
 30 | 	public SoftKeyNumLayView(Context context, AttributeSet attrs, int defStyleAttr) {
 31 | 		super(context, attrs, defStyleAttr);
 32 | 	}
 33 | 
 34 | 	@Override
 35 | 	public SoftKey[] initSoftKeys() {
 36 | 		SoftKey[] result = new SoftKey[10];
 37 | 		for (int i = 0; i < result.length; i++) {
 38 | 			SoftKey btn = new SoftKey();
 39 | 			btn.setText(String.valueOf(i));
 40 | 			result[i] = btn;
 41 | 		}
 42 | 		return result;
 43 | 	}
 44 | 
 45 | 	@Override
 46 | 	public SoftKey[] measureSoftKeysPos(SoftKey[] softKeys) {
 47 | 		for (int i = 0; i < softKeys.length; i++) {
 48 | 			softKeys[i].setX(blockWidth / 2 + (i % col) * blockWidth);
 49 | 			softKeys[i].setY(blockHeight / 2 + (i / col % row) * blockHeight);
 50 | 			softKeys[i].setWidth(blockWidth);
 51 | 			softKeys[i].setHeight(blockHeight);
 52 | 		}
 53 | 		return softKeys;
 54 | 	}
 55 | 
 56 | 	@Override
 57 | 	public int measureBlockWidth(int keyBoardwidth) {
 58 | 		return keyBoardwidth/col;
 59 | 	}
 60 | 
 61 | 	@Override
 62 | 	public int measureBlockHeight(int keyBoardHeight) {
 63 | 		return keyBoardHeight/row;
 64 | 	}
 65 | 
 66 | 	@Override
 67 | 	public void drawSoftKeysPos(Canvas canvas, SoftKey[] softKeys) {
 68 | 		if (softKeys == null) {
 69 | 			return ;
 70 | 		}
 71 | 
 72 | 		canvas.drawColor(Color.WHITE);
 73 | 		//画垂直分割线
 74 | 		for (int index = 0; index < col; index++) {
 75 | 			canvas.drawLine((index + 1) * blockWidth, 0, (index + 1)* blockWidth, getHeight(), keyBorderPaint);
 76 | 		}
 77 | 
 78 | 		//画水平分割线
 79 | 		for (int index = 0; index < row; index++) {
 80 | 			canvas.drawLine(0, index * blockHeight, getWidth(),index * blockHeight, keyBorderPaint);
 81 | 		}
 82 | 
 83 | 		//画软键盘的9个数字按钮
 84 | 		for (int index = 0; index < softKeys.length-1; index++) {
 85 | 			drawSoftKey(canvas, softKeys[index]);
 86 | 		}
 87 | 
 88 | 		//创建软键盘的删除按钮
 89 | 		if(delBtn==null){
 90 | 			delBtn=new SoftKey();
 91 | 			delBtn.setKeyType(KeyType.ICON);
 92 | 			delBtn.setIcon(R.drawable.ic_softkey_delete);
 93 | 			delBtn.setHeight(blockHeight);
 94 | 			delBtn.setWidth(blockWidth);
 95 | 			delBtn.setX(softKeys[softKeys.length-1].getX());
 96 | 			delBtn.setY(softKeys[softKeys.length-1].getY());
 97 | 			softKeys[softKeys.length-1].setX(blockWidth / 2 + ((col-2)% col) * blockWidth);
 98 | 			softKeys[softKeys.length-1].setY(blockHeight / 2 + ((row-1) % row) * blockHeight);
 99 | 		}
100 | 
101 | 		//画软键盘的删除按钮
102 | 		drawSoftKey(canvas,delBtn);
103 | 
104 | 		//画第10个数字按钮
105 | 		drawSoftKey(canvas,softKeys[softKeys.length-1]);
106 | 
107 | 		if(confirmBtn==null){
108 | 			confirmBtn=new SoftKey();
109 | 			confirmBtn.setText("确定");
110 | 			confirmBtn.setHeight(blockHeight);
111 | 			confirmBtn.setWidth(blockWidth);
112 | 			confirmBtn.setX(blockWidth / 2 + ((col-1)% col) * blockWidth);
113 | 			confirmBtn.setY(blockHeight / 2 + ((row-1) % row) * blockHeight);
114 | 		}
115 | 
116 | 		drawSoftKey(canvas,confirmBtn);
117 | 
118 | 	}
119 | }
120 | 
--------------------------------------------------------------------------------
/app/src/main/java/com/igeek/safesoftboard/SoftKeyPunctLayView.java:
--------------------------------------------------------------------------------
  1 | package com.igeek.safesoftboard;
  2 | 
  3 | import android.content.Context;
  4 | import android.graphics.Canvas;
  5 | import android.util.AttributeSet;
  6 | 
  7 | import com.igeek.safesoftboard.SoftKey.KeyType;
  8 | /**
  9 |  * 标点符号视图
 10 |  */
 11 | public class SoftKeyPunctLayView extends SoftKeyView {
 12 | 
 13 | 	private int col=8;
 14 | 	private int row=4;
 15 | 	
 16 | 	public SoftKeyPunctLayView(Context context) {
 17 | 		super(context);
 18 | 		// TODO Auto-generated constructor stub
 19 | 	}
 20 | 
 21 | 	public SoftKeyPunctLayView(Context context, AttributeSet attrs) {
 22 | 		super(context, attrs);
 23 | 		// TODO Auto-generated constructor stub
 24 | 	}
 25 | 
 26 | 	public SoftKeyPunctLayView(Context context, AttributeSet attrs,
 27 | 			int defStyleAttr) {
 28 | 		super(context, attrs, defStyleAttr);
 29 | 		// TODO Auto-generated constructor stub
 30 | 	}
 31 | 
 32 | 	@Override
 33 | 	public SoftKey[] initSoftKeys() {
 34 | 		// TODO Auto-generated method stub
 35 | 		//提取了<@#*./>到字母布局中
 36 | 		String mSignArray="~!<>?`-=[]\\;',$%^&()_+{}|:\"";
 37 | 		SoftKey [] softKeys=new SoftKey[mSignArray.length()];
 38 | 		for(int index=0;index 0; i--) {
227 | 			w = rand.nextInt(i);
228 | 			String number = softKeys[i].getText();
229 | 			softKeys[i].setText(softKeys[w].getText());
230 | 			softKeys[w].setText(number);
231 | 		}
232 | 		return softKeys;
233 | 	}
234 | 
235 | 	@Override
236 | 	public void drawSoftKey(Canvas canvas, SoftKey softkey) {
237 | 		// TODO Auto-generated method stub
238 | 		switch (softkey.getKeyType()) {
239 | 		case TEXT:
240 | 			drawTextSoftKey(canvas, softkey);
241 | 			break;
242 | 		case ICON:
243 | 			drawIconSoftKey(canvas, softkey);
244 | 			break;
245 | 		case TEXT_ICON:
246 | 			drawIconSoftKey(canvas, softkey);
247 | 			break;
248 | 		}
249 | 		if(softkey.isPreessed()){
250 | 			drawSoftKeyPressBg(canvas, softkey);
251 | 		}
252 | 	}
253 | 	
254 | 	/**
255 | 	 * �����ı��İ�ť
256 | 	 * @param canvas
257 | 	 * @param softkey
258 | 	 */
259 | 	public void drawTextSoftKey(Canvas canvas,SoftKey softkey){
260 | 		Rect bounds = new Rect();
261 | 		keyTextPaint.getTextBounds(softkey.getText(), 0, softkey.getText().length(), bounds);
262 | 		int startX = softkey.getX() - bounds.width() / 2;
263 | 		int startY = softkey.getY() + bounds.height() / 2;
264 | 		canvas.drawText(softkey.getText(), startX, startY, keyTextPaint);
265 | 	}
266 | 	/**
267 | 	 * ����ͼ��İ�ť
268 | 	 * @param canvas
269 | 	 * @param softkey
270 | 	 */
271 | 	public void drawIconSoftKey(Canvas canvas,SoftKey softkey){
272 | 		Options opts=new Options();
273 | 		BitmapFactory.decodeResource(getContext().getResources(), softkey.getIcon(),opts);
274 | 		opts.inJustDecodeBounds=true;
275 | 		int minWH=Math.min(softkey.getHeight(), softkey.getWidth());
276 | 		int maxBP=Math.max(opts.outHeight, opts.outWidth);
277 | 		if(maxBP>minWH){
278 | 			opts.inSampleSize=minWH/maxBP;
279 | 		}else{
280 | 			opts.inSampleSize=maxBP/minWH;
281 | 		}
282 | 		opts.inJustDecodeBounds=false;
283 | 		Bitmap newBit=BitmapFactory.decodeResource(getContext().getResources(), softkey.getIcon(),opts);
284 | 		canvas.drawBitmap(newBit, softkey.getX()-newBit.getWidth()/2, softkey.getY()-newBit.getHeight()/2, null);
285 | 		newBit.recycle();
286 | 	}
287 | 	
288 | 	/**
289 | 	 * @param canvas
290 | 	 * @param softkey
291 | 	 */
292 | 	public void drawSoftKeyPressBg(Canvas canvas, SoftKey softkey) {
293 | 		int left = softkey.getX() - softkey.getWidth() / 2;
294 | 		int top = softkey.getY() - softkey.getHeight() / 2;
295 | 		int right = softkey.getX() + softkey.getWidth() / 2;
296 | 		int bottom = softkey.getY() + softkey.getHeight() / 2;
297 | 		canvas.drawRect(left, top, right, bottom, keyPressedBgPaint);
298 | 	}
299 | 
300 | 	@Override
301 | 	public boolean handleKeyTouching(int eventX, int eventY, int action) {
302 | 		boolean isrefresh = false;
303 | 
304 | 		if (softKeys == null) {
305 | 			return false;
306 | 		}
307 | 
308 | 		if (delBtn.inRange(eventX, eventY) && action == MotionEvent.ACTION_DOWN) {
309 | 			performQuickDelete();
310 | 		}
311 | 
312 | 		if (!delBtn.inRange(eventX, eventY)&& action == MotionEvent.ACTION_MOVE) {
313 | 			cancelQuickDelete();
314 | 		}
315 | 
316 | 		delBtn.updatePressed(eventX, eventY);
317 | 		confirmBtn.updatePressed(eventX, eventY);
318 | 
319 | 		isrefresh = (delBtn.isPreessed() || confirmBtn.isPreessed());
320 | 
321 | 		for (int index = 0; index < softKeys.length; index++) {
322 | 			if (isrefresh) {
323 | 				softKeys[index].setPreessed(false);
324 | 			} else {
325 | 				isrefresh = softKeys[index].updatePressed(eventX, eventY);
326 | 			}
327 | 		}
328 | 		return isrefresh;
329 | 	}
330 | 	
331 | 	@Override
332 | 	public boolean handleTouchUp(int eventX, int eventY, int action) {
333 | 		resetSoftKeysState();
334 | 		if (delBtn.inRange(eventX, eventY)) {
335 | 			if (listener != null) {
336 | 				listener.onDeleted();
337 | 			}
338 | 			return true;
339 | 		}
340 | 		if (confirmBtn.inRange(eventX, eventY)) {
341 | 			if (listener != null) {
342 | 				listener.onConfirm();
343 | 			}
344 | 			return true;
345 | 		}
346 | 		SoftKey btn = obtainTouchSoftKey(eventX, eventY);
347 | 		if (btn != null) {
348 | 			if (listener != null) {
349 | 				listener.onPressed(btn);
350 | 			}
351 | 			return true;
352 | 		}
353 | 		return false;
354 | 	}
355 | 	
356 | 	@Override
357 | 	public SoftKey obtainTouchSoftKey(int eventX, int eventY) {
358 | 		if (softKeys == null) {
359 | 			return null;
360 | 		}
361 | 		for (int index = 0; index < softKeys.length; index++) {
362 | 			if (softKeys[index].inRange(eventX, eventY)) {
363 | 				return softKeys[index];
364 | 			}
365 | 		}	
366 | 		return null;
367 | 	}
368 | 
369 | 	@Override
370 | 	public void resetSoftKeysState() {
371 | 		cancelQuickDelete();
372 | 		delBtn.setPreessed(false);
373 | 		confirmBtn.setPreessed(false);
374 | 		for (int index = 0; index < softKeys.length; index++) {
375 | 			softKeys[index].setPreessed(false);
376 | 		}
377 | 	}
378 | 
379 | 	@Override
380 | 	public void performQuickDelete() {
381 | 		pressHandler.sendEmptyMessageDelayed(KeyEvent.FLAG_KEEP_TOUCH_MODE,ViewConfiguration.getLongPressTimeout());
382 | 	}
383 | 
384 | 	@Override
385 | 	public void cancelQuickDelete() {
386 | 		pressHandler.sendEmptyMessage(KeyEvent.FLAG_CANCELED_LONG_PRESS);
387 | 	}
388 | 
389 | 	public Handler pressHandler = new Handler() {
390 | 		public void handleMessage(android.os.Message msg) {
391 | 			switch (msg.what) {
392 | 			case KeyEvent.FLAG_LONG_PRESS:
393 | 				if (listener != null) {
394 | 					listener.onDeleted();
395 | 					pressHandler.sendEmptyMessageDelayed(KeyEvent.FLAG_LONG_PRESS, 100);
396 | 				}
397 | 				break;
398 | 			case KeyEvent.FLAG_KEEP_TOUCH_MODE:
399 | 				pressHandler.sendEmptyMessage(KeyEvent.FLAG_LONG_PRESS);
400 | 				pressHandler.removeMessages(KeyEvent.FLAG_KEEP_TOUCH_MODE);
401 | 				break;
402 | 
403 | 			case KeyEvent.FLAG_CANCELED_LONG_PRESS:
404 | 				pressHandler.removeMessages(KeyEvent.FLAG_KEEP_TOUCH_MODE);
405 | 				pressHandler.removeMessages(KeyEvent.FLAG_LONG_PRESS);
406 | 				break;
407 | 			}
408 | 		};
409 | 	};
410 | 	
411 | 	public void setSoftKeyListener(SoftKeyStatusListener listener) {
412 | 		this.listener = listener;
413 | 	}
414 | 
415 | }
416 | 
--------------------------------------------------------------------------------
/app/src/main/java/utils/DensityUtils.java:
--------------------------------------------------------------------------------
 1 | package utils;
 2 | 
 3 | import android.content.res.Resources;
 4 | import android.util.TypedValue;
 5 | 
 6 | /**
 7 |  * 常用单位转换的辅助类
 8 |  * Created by igeek2014@hotmail.com on 2015/4/16.
 9 |  */
10 | public class DensityUtils {
11 | 
12 |     private DensityUtils() {
13 |         throw new UnsupportedOperationException("单位工具类不能初始化对象");
14 |     }
15 | 
16 |     /**
17 |      * dp转px
18 |      *
19 |      * @param dpVal
20 |      * @return
21 |      */
22 |     public static int dp2px(float dpVal) {
23 |         return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
24 |                 dpVal, Resources.getSystem().getDisplayMetrics());
25 |     }
26 | 
27 |     /**
28 |      * sp转px
29 |      *
30 |      * @param spVal
31 |      * @return
32 |      */
33 |     public static int sp2px(float spVal) {
34 |         return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
35 |                 spVal, Resources.getSystem().getDisplayMetrics());
36 |     }
37 | 
38 |     /**
39 |      * px转dp
40 |      *
41 |      * @param pxVal
42 |      * @return
43 |      */
44 |     public static float px2dp(float pxVal) {
45 |         final float scale = Resources.getSystem().getDisplayMetrics().density;
46 |         return (pxVal / scale);
47 |     }
48 | 
49 |     /**
50 |      * px转sp
51 |      *
52 |      * @param pxVal
53 |      * @return
54 |      */
55 |     public static float px2sp(float pxVal) {
56 |         return (pxVal / Resources.getSystem().getDisplayMetrics().scaledDensity);
57 |     }
58 | 
59 | 
60 | }
61 | 
--------------------------------------------------------------------------------
/app/src/main/java/utils/ScreenUtils.java:
--------------------------------------------------------------------------------
  1 | package utils;
  2 | 
  3 | import android.app.Activity;
  4 | import android.content.Context;
  5 | import android.graphics.Bitmap;
  6 | import android.graphics.Rect;
  7 | import android.util.DisplayMetrics;
  8 | import android.view.View;
  9 | import android.view.WindowManager;
 10 | 
 11 | /**
 12 |  * 屏幕相关的工具类
 13 |  * Created by  igeek2014@hotmail.com on 2015/4/16.
 14 |  */
 15 | public class ScreenUtils {
 16 | 
 17 |     private ScreenUtils() {
 18 |         throw new UnsupportedOperationException("屏幕工具类不能初始化对象");
 19 |     }
 20 | 
 21 |     /**
 22 |      * 获得屏幕高度
 23 |      *
 24 |      * @param context
 25 |      * @return
 26 |      */
 27 |     public static int getScreenWidth(Context context) {
 28 |         WindowManager wm = (WindowManager) context
 29 |                 .getSystemService(Context.WINDOW_SERVICE);
 30 |         DisplayMetrics outMetrics = new DisplayMetrics();
 31 |         wm.getDefaultDisplay().getMetrics(outMetrics);
 32 |         return outMetrics.widthPixels;
 33 |     }
 34 | 
 35 |     /**
 36 |      * 获得屏幕宽度
 37 |      *
 38 |      * @param context
 39 |      * @return
 40 |      */
 41 |     public static int getScreenHeight(Context context) {
 42 |         WindowManager wm = (WindowManager) context
 43 |                 .getSystemService(Context.WINDOW_SERVICE);
 44 |         DisplayMetrics outMetrics = new DisplayMetrics();
 45 |         wm.getDefaultDisplay().getMetrics(outMetrics);
 46 |         return outMetrics.heightPixels;
 47 |     }
 48 | 
 49 |     /**
 50 |      * 获得状态栏的高度
 51 |      *
 52 |      * @param context
 53 |      * @return
 54 |      */
 55 |     public static int getStatusHeight(Context context) {
 56 | 
 57 |         int statusHeight = -1;
 58 |         try {
 59 |             Class> clazz = Class.forName("com.android.internal.R$dimen");
 60 |             Object object = clazz.newInstance();
 61 |             int height = Integer.parseInt(clazz.getField("status_bar_height")
 62 |                     .get(object).toString());
 63 |             statusHeight = context.getResources().getDimensionPixelSize(height);
 64 |         } catch (Exception e) {
 65 |             e.printStackTrace();
 66 |         }
 67 |         return statusHeight;
 68 |     }
 69 | 
 70 |     /**
 71 |      * 获取当前屏幕截图,包含状态栏
 72 |      *
 73 |      * @param activity
 74 |      * @return
 75 |      */
 76 |     public static Bitmap snapShotWithStatusBar(Activity activity) {
 77 |         View view = activity.getWindow().getDecorView();
 78 |         view.setDrawingCacheEnabled(true);
 79 |         view.buildDrawingCache();
 80 |         Bitmap bmp = view.getDrawingCache();
 81 |         int width = getScreenWidth(activity);
 82 |         int height = getScreenHeight(activity);
 83 |         Bitmap bp = null;
 84 |         bp = Bitmap.createBitmap(bmp, 0, 0, width, height);
 85 |         view.destroyDrawingCache();
 86 |         return bp;
 87 | 
 88 |     }
 89 | 
 90 |     /**
 91 |      * 获取当前屏幕截图,不包含状态栏
 92 |      *
 93 |      * @param activity
 94 |      * @return
 95 |      */
 96 |     public static Bitmap snapShotWithoutStatusBar(Activity activity) {
 97 |         View view = activity.getWindow().getDecorView();
 98 |         view.setDrawingCacheEnabled(true);
 99 |         view.buildDrawingCache();
100 |         Bitmap bmp = view.getDrawingCache();
101 |         Rect frame = new Rect();
102 |         activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
103 |         int statusBarHeight = frame.top;
104 | 
105 |         int width = getScreenWidth(activity);
106 |         int height = getScreenHeight(activity);
107 |         Bitmap bp = null;
108 |         bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height
109 |                 - statusBarHeight);
110 |         view.destroyDrawingCache();
111 |         return bp;
112 | 
113 |     }
114 | 
115 |     public static int getXOnScreen(View view){
116 |         int [] location =new int[2];
117 |         view.getLocationOnScreen(location);
118 |         return location[0];
119 |     }
120 | 
121 |     public static int getYOnScreen(View view){
122 |         int [] location =new int[2];
123 |         view.getLocationOnScreen(location);
124 |         return location[1];
125 |     }
126 | 
127 | }
128 | 
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_softb_close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/src/main/res/drawable-hdpi/ic_softb_close.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_softboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/src/main/res/drawable-hdpi/ic_softboard.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_softkey_delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/src/main/res/drawable-hdpi/ic_softkey_delete.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_softb_close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/src/main/res/drawable-xhdpi/ic_softb_close.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_softboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/src/main/res/drawable-xhdpi/ic_softboard.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_softkey_delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/src/main/res/drawable-xhdpi/ic_softkey_delete.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/src/main/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_softb_close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/src/main/res/drawable-xxhdpi/ic_softb_close.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_softboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/src/main/res/drawable-xxhdpi/ic_softboard.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_softkey_delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/src/main/res/drawable-xxhdpi/ic_softkey_delete.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_radio.xml:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 |     
 4 |     - 
 5 |         
 6 |             
 7 |             
 8 |         
 9 |     10 |
- 
11 |         
12 |             
13 |             
14 |         
15 |     16 |
- 
17 |         
18 |             
19 |             
20 |         
21 |     22 | 
23 | 
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_stroke_gray.xml:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 |
- 
 4 |         
 5 |             
 6 |             
 7 |         
 8 |     9 |
- 
10 |         
11 |             
12 |             
13 |         
14 |     15 | 
16 | 
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_stroke_gray_gray.xml:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 |
- 
 4 |         
 5 |             
 6 |             
 7 |         
 8 |     9 |
- 
10 |         
11 |             
12 |             
13 |         
14 |     15 | 
16 | 
--------------------------------------------------------------------------------
/app/src/main/res/drawable/vertical_line.xml:
--------------------------------------------------------------------------------
1 | 
2 | 
4 | 
5 |     
6 |     
7 | 
8 | 
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
 1 | 
 6 | 
 7 |     
11 | 
12 |     
20 | 
21 | 
--------------------------------------------------------------------------------
/app/src/main/res/layout/content_main.xml:
--------------------------------------------------------------------------------
 1 | 
 2 | 
15 | 
16 |     
20 | 
21 | 
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_keyboard.xml:
--------------------------------------------------------------------------------
  1 | 
  2 | 
  8 | 
  9 |     
 17 | 
 18 |         
 28 | 
 29 |         
 33 | 
 34 |             
 42 | 
 43 |                 
 54 | 
 55 |                 
 66 | 
 67 |                 
 78 |             
 79 | 
 80 |             
 91 |         
 92 | 
 93 |         
103 |     
104 | 
105 |     
109 | 
110 |         
121 | 
122 |         
133 | 
134 |         
145 |     
146 | 
147 | 
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
 1 | 
10 | 
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 | 
2 |             
8 | 
9 | 
--------------------------------------------------------------------------------
/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 | 
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 | 
2 | 
3 |     #66929292
4 |     #cdcdcd
5 |     #efeff4
6 | 
7 | 
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 | 
2 | 
3 |     
4 |     16dp
5 |     16dp
6 | 
7 | 
8 | 
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 | 
2 | 
3 | 
4 |     customSoftKeyboard
5 |     Hello world!
6 |     Settings
7 | 
8 | 
9 | 
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 |     
 7 |     
14 | 
15 |     
16 |     
19 | 
20 | 
21 | 
--------------------------------------------------------------------------------
/app/src/test/java/com/igeek/safesoftboard/ExampleUnitTest.java:
--------------------------------------------------------------------------------
 1 | package com.igeek.safesoftboard;
 2 | 
 3 | import org.junit.Test;
 4 | 
 5 | import static org.junit.Assert.*;
 6 | 
 7 | /**
 8 |  * To work on unit tests, switch the Test Artifact in the Build Variants view.
 9 |  */
10 | public class ExampleUnitTest {
11 |     @Test
12 |     public void addition_isCorrect() throws Exception {
13 |         assertEquals(4, 2 + 2);
14 |     }
15 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
 2 | 
 3 | buildscript {
 4 |     repositories {
 5 |         jcenter()
 6 |     }
 7 |     dependencies {
 8 |         classpath 'com.android.tools.build:gradle:1.3.0'
 9 |         classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
10 | 
11 |         // NOTE: Do not place your application dependencies here; they belong
12 |         // in the individual module build.gradle files
13 |     }
14 | }
15 | 
16 | allprojects {
17 |     repositories {
18 |         jcenter()
19 |     }
20 | }
21 | 
22 | task clean(type: Delete) {
23 |     delete rootProject.buildDir
24 | }
25 | 
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
 1 | # Project-wide Gradle settings.
 2 | 
 3 | # IDE (e.g. Android Studio) users:
 4 | # Gradle settings configured through the IDE *will override*
 5 | # any settings specified in this file.
 6 | 
 7 | # For more details on how to configure your build environment visit
 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
 9 | 
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 | 
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Oct 21 11:34:03 PDT 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip
7 | 
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
  1 | #!/usr/bin/env bash
  2 | 
  3 | ##############################################################################
  4 | ##
  5 | ##  Gradle start up script for UN*X
  6 | ##
  7 | ##############################################################################
  8 | 
  9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
 10 | DEFAULT_JVM_OPTS=""
 11 | 
 12 | APP_NAME="Gradle"
 13 | APP_BASE_NAME=`basename "$0"`
 14 | 
 15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
 16 | MAX_FD="maximum"
 17 | 
 18 | warn ( ) {
 19 |     echo "$*"
 20 | }
 21 | 
 22 | die ( ) {
 23 |     echo
 24 |     echo "$*"
 25 |     echo
 26 |     exit 1
 27 | }
 28 | 
 29 | # OS specific support (must be 'true' or 'false').
 30 | cygwin=false
 31 | msys=false
 32 | darwin=false
 33 | case "`uname`" in
 34 |   CYGWIN* )
 35 |     cygwin=true
 36 |     ;;
 37 |   Darwin* )
 38 |     darwin=true
 39 |     ;;
 40 |   MINGW* )
 41 |     msys=true
 42 |     ;;
 43 | esac
 44 | 
 45 | # Attempt to set APP_HOME
 46 | # Resolve links: $0 may be a link
 47 | PRG="$0"
 48 | # Need this for relative symlinks.
 49 | while [ -h "$PRG" ] ; do
 50 |     ls=`ls -ld "$PRG"`
 51 |     link=`expr "$ls" : '.*-> \(.*\)$'`
 52 |     if expr "$link" : '/.*' > /dev/null; then
 53 |         PRG="$link"
 54 |     else
 55 |         PRG=`dirname "$PRG"`"/$link"
 56 |     fi
 57 | done
 58 | SAVED="`pwd`"
 59 | cd "`dirname \"$PRG\"`/" >/dev/null
 60 | APP_HOME="`pwd -P`"
 61 | cd "$SAVED" >/dev/null
 62 | 
 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
 64 | 
 65 | # Determine the Java command to use to start the JVM.
 66 | if [ -n "$JAVA_HOME" ] ; then
 67 |     if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
 68 |         # IBM's JDK on AIX uses strange locations for the executables
 69 |         JAVACMD="$JAVA_HOME/jre/sh/java"
 70 |     else
 71 |         JAVACMD="$JAVA_HOME/bin/java"
 72 |     fi
 73 |     if [ ! -x "$JAVACMD" ] ; then
 74 |         die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
 75 | 
 76 | Please set the JAVA_HOME variable in your environment to match the
 77 | location of your Java installation."
 78 |     fi
 79 | else
 80 |     JAVACMD="java"
 81 |     which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
 82 | 
 83 | Please set the JAVA_HOME variable in your environment to match the
 84 | location of your Java installation."
 85 | fi
 86 | 
 87 | # Increase the maximum file descriptors if we can.
 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
 89 |     MAX_FD_LIMIT=`ulimit -H -n`
 90 |     if [ $? -eq 0 ] ; then
 91 |         if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
 92 |             MAX_FD="$MAX_FD_LIMIT"
 93 |         fi
 94 |         ulimit -n $MAX_FD
 95 |         if [ $? -ne 0 ] ; then
 96 |             warn "Could not set maximum file descriptor limit: $MAX_FD"
 97 |         fi
 98 |     else
 99 |         warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 |     fi
101 | fi
102 | 
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 |     GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 | 
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 |     APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 |     CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 |     JAVACMD=`cygpath --unix "$JAVACMD"`
113 | 
114 |     # We build the pattern for arguments to be converted via cygpath
115 |     ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 |     SEP=""
117 |     for dir in $ROOTDIRSRAW ; do
118 |         ROOTDIRS="$ROOTDIRS$SEP$dir"
119 |         SEP="|"
120 |     done
121 |     OURCYGPATTERN="(^($ROOTDIRS))"
122 |     # Add a user-defined pattern to the cygpath arguments
123 |     if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 |         OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 |     fi
126 |     # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 |     i=0
128 |     for arg in "$@" ; do
129 |         CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 |         CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
131 | 
132 |         if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
133 |             eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 |         else
135 |             eval `echo args$i`="\"$arg\""
136 |         fi
137 |         i=$((i+1))
138 |     done
139 |     case $i in
140 |         (0) set -- ;;
141 |         (1) set -- "$args0" ;;
142 |         (2) set -- "$args0" "$args1" ;;
143 |         (3) set -- "$args0" "$args1" "$args2" ;;
144 |         (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 |         (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 |         (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 |         (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 |         (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 |         (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 |     esac
151 | fi
152 | 
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 |     JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 | 
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 | 
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
 1 | @if "%DEBUG%" == "" @echo off
 2 | @rem ##########################################################################
 3 | @rem
 4 | @rem  Gradle startup script for Windows
 5 | @rem
 6 | @rem ##########################################################################
 7 | 
 8 | @rem Set local scope for the variables with windows NT shell
 9 | if "%OS%"=="Windows_NT" setlocal
10 | 
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 | 
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 | 
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 | 
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 | 
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 | 
32 | goto fail
33 | 
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 | 
38 | if exist "%JAVA_EXE%" goto init
39 | 
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 | 
46 | goto fail
47 | 
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 | 
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 | 
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 | 
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 | 
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 | 
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 | 
69 | :execute
70 | @rem Setup the command line
71 | 
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 | 
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 | 
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 | 
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 | 
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 | 
90 | :omega
91 | 
--------------------------------------------------------------------------------
/pics/customsoftkeyboard.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/igeek-YZ/SafeSoftBoard/613b283bafefe3349cf8e953585a0153ca71c6cd/pics/customsoftkeyboard.gif
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 | 
--------------------------------------------------------------------------------