() {
202 | @Override
203 | public int compare(PinyinSegmentation pinyinSegmentation, PinyinSegmentation t1) {
204 | return ((Double) t1.getScore()).compareTo(pinyinSegmentation.getScore());
205 | }
206 | });
207 | int returnSize = 5;
208 | /* if (calculated <=6) {
209 | returnSize = 3;
210 | }
211 | if (calculated <= 9) {
212 | returnSize = 4;
213 | }*/
214 | if (calculated <=5 && calculated+points.size() >=12) {
215 | returnSize = 3;
216 | }
217 | if (calculated <=7 && calculated+points.size() >=12) {
218 | returnSize = 4;
219 | }
220 | if (calculated+points.size() >= 16) {
221 | returnSize = 2;
222 | }
223 |
224 | return ret.subList(0, Math.min(returnSize, ret.size()));
225 | }
226 | }
227 |
--------------------------------------------------------------------------------
/app/src/main/java/com/shiweinan/keyboard/SettingsActivity.java:
--------------------------------------------------------------------------------
1 | package com.shiweinan.keyboard;
2 |
3 | import android.annotation.TargetApi;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.content.res.Configuration;
7 | import android.media.Ringtone;
8 | import android.media.RingtoneManager;
9 | import android.net.Uri;
10 | import android.os.Build;
11 | import android.os.Bundle;
12 | import android.preference.ListPreference;
13 | import android.preference.Preference;
14 | import android.preference.PreferenceActivity;
15 | import android.support.v7.app.ActionBar;
16 | import android.preference.PreferenceFragment;
17 | import android.preference.PreferenceManager;
18 | import android.preference.RingtonePreference;
19 | import android.text.TextUtils;
20 | import android.view.MenuItem;
21 |
22 | import java.util.List;
23 |
24 | /**
25 | * A {@link PreferenceActivity} that presents a set of application settings. On
26 | * handset devices, settings are presented as a single list. On tablets,
27 | * settings are split by category, with category headers shown to the left of
28 | * the list of settings.
29 | *
30 | * See
31 | * Android Design: Settings for design guidelines and the Settings
33 | * API Guide for more information on developing a Settings UI.
34 | */
35 | public class SettingsActivity extends AppCompatPreferenceActivity {
36 |
37 | /**
38 | * A preference value change listener that updates the preference's summary
39 | * to reflect its new value.
40 | */
41 | private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
42 | @Override
43 | public boolean onPreferenceChange(Preference preference, Object value) {
44 | String stringValue = value.toString();
45 |
46 | if (preference instanceof ListPreference) {
47 | // For list preferences, look up the correct display value in
48 | // the preference's 'entries' list.
49 | ListPreference listPreference = (ListPreference) preference;
50 | int index = listPreference.findIndexOfValue(stringValue);
51 |
52 | // Set the summary to reflect the new value.
53 | preference.setSummary(
54 | index >= 0
55 | ? listPreference.getEntries()[index]
56 | : null);
57 |
58 | } else if (preference instanceof RingtonePreference) {
59 | // For ringtone preferences, look up the correct display value
60 | // using RingtoneManager.
61 | if (TextUtils.isEmpty(stringValue)) {
62 | // Empty values correspond to 'silent' (no ringtone).
63 | preference.setSummary(R.string.pref_ringtone_silent);
64 |
65 | } else {
66 | Ringtone ringtone = RingtoneManager.getRingtone(
67 | preference.getContext(), Uri.parse(stringValue));
68 |
69 | if (ringtone == null) {
70 | // Clear the summary if there was a lookup error.
71 | preference.setSummary(null);
72 | } else {
73 | // Set the summary to reflect the new ringtone display
74 | // name.
75 | String name = ringtone.getTitle(preference.getContext());
76 | preference.setSummary(name);
77 | }
78 | }
79 |
80 | } else {
81 | // For all other preferences, set the summary to the value's
82 | // simple string representation.
83 | preference.setSummary(stringValue);
84 | }
85 | return true;
86 | }
87 | };
88 |
89 | /**
90 | * Helper method to determine if the device has an extra-large screen. For
91 | * example, 10" tablets are extra-large.
92 | */
93 | private static boolean isXLargeTablet(Context context) {
94 | return (context.getResources().getConfiguration().screenLayout
95 | & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
96 | }
97 |
98 | /**
99 | * Binds a preference's summary to its value. More specifically, when the
100 | * preference's value is changed, its summary (line of text below the
101 | * preference title) is updated to reflect the value. The summary is also
102 | * immediately updated upon calling this method. The exact display format is
103 | * dependent on the type of preference.
104 | *
105 | * @see #sBindPreferenceSummaryToValueListener
106 | */
107 | private static void bindPreferenceSummaryToValue(Preference preference) {
108 | // Set the listener to watch for value changes.
109 | preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
110 |
111 | // Trigger the listener immediately with the preference's
112 | // current value.
113 | sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
114 | PreferenceManager
115 | .getDefaultSharedPreferences(preference.getContext())
116 | .getString(preference.getKey(), ""));
117 | }
118 |
119 | @Override
120 | protected void onCreate(Bundle savedInstanceState) {
121 | super.onCreate(savedInstanceState);
122 | setupActionBar();
123 | }
124 |
125 | /**
126 | * Set up the {@link android.app.ActionBar}, if the API is available.
127 | */
128 | private void setupActionBar() {
129 | ActionBar actionBar = getSupportActionBar();
130 | if (actionBar != null) {
131 | // Show the Up button in the action bar.
132 | actionBar.setDisplayHomeAsUpEnabled(true);
133 | }
134 | }
135 |
136 | /**
137 | * {@inheritDoc}
138 | */
139 | @Override
140 | public boolean onIsMultiPane() {
141 | return isXLargeTablet(this);
142 | }
143 |
144 | /**
145 | * {@inheritDoc}
146 | */
147 | @Override
148 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
149 | public void onBuildHeaders(List target) {
150 | loadHeadersFromResource(R.xml.pref_headers, target);
151 | }
152 |
153 | /**
154 | * This method stops fragment injection in malicious applications.
155 | * Make sure to deny any unknown fragments here.
156 | */
157 | protected boolean isValidFragment(String fragmentName) {
158 | return PreferenceFragment.class.getName().equals(fragmentName)
159 | || GeneralPreferenceFragment.class.getName().equals(fragmentName)
160 | || DataSyncPreferenceFragment.class.getName().equals(fragmentName)
161 | || NotificationPreferenceFragment.class.getName().equals(fragmentName);
162 | }
163 |
164 | /**
165 | * This fragment shows general preferences only. It is used when the
166 | * activity is showing a two-pane settings UI.
167 | */
168 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
169 | public static class GeneralPreferenceFragment extends PreferenceFragment {
170 | @Override
171 | public void onCreate(Bundle savedInstanceState) {
172 | super.onCreate(savedInstanceState);
173 | addPreferencesFromResource(R.xml.pref_general);
174 | setHasOptionsMenu(true);
175 |
176 | // Bind the summaries of EditText/List/Dialog/Ringtone preferences
177 | // to their values. When their values change, their summaries are
178 | // updated to reflect the new value, per the Android Design
179 | // guidelines.
180 | bindPreferenceSummaryToValue(findPreference("example_text"));
181 | bindPreferenceSummaryToValue(findPreference("example_list"));
182 | }
183 |
184 | @Override
185 | public boolean onOptionsItemSelected(MenuItem item) {
186 | int id = item.getItemId();
187 | if (id == android.R.id.home) {
188 | startActivity(new Intent(getActivity(), SettingsActivity.class));
189 | return true;
190 | }
191 | return super.onOptionsItemSelected(item);
192 | }
193 | }
194 |
195 | /**
196 | * This fragment shows notification preferences only. It is used when the
197 | * activity is showing a two-pane settings UI.
198 | */
199 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
200 | public static class NotificationPreferenceFragment extends PreferenceFragment {
201 | @Override
202 | public void onCreate(Bundle savedInstanceState) {
203 | super.onCreate(savedInstanceState);
204 | addPreferencesFromResource(R.xml.pref_notification);
205 | setHasOptionsMenu(true);
206 |
207 | // Bind the summaries of EditText/List/Dialog/Ringtone preferences
208 | // to their values. When their values change, their summaries are
209 | // updated to reflect the new value, per the Android Design
210 | // guidelines.
211 | bindPreferenceSummaryToValue(findPreference("notifications_new_message_ringtone"));
212 | }
213 |
214 | @Override
215 | public boolean onOptionsItemSelected(MenuItem item) {
216 | int id = item.getItemId();
217 | if (id == android.R.id.home) {
218 | startActivity(new Intent(getActivity(), SettingsActivity.class));
219 | return true;
220 | }
221 | return super.onOptionsItemSelected(item);
222 | }
223 | }
224 |
225 | /**
226 | * This fragment shows data and sync preferences only. It is used when the
227 | * activity is showing a two-pane settings UI.
228 | */
229 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
230 | public static class DataSyncPreferenceFragment extends PreferenceFragment {
231 | @Override
232 | public void onCreate(Bundle savedInstanceState) {
233 | super.onCreate(savedInstanceState);
234 | addPreferencesFromResource(R.xml.pref_data_sync);
235 | setHasOptionsMenu(true);
236 |
237 | // Bind the summaries of EditText/List/Dialog/Ringtone preferences
238 | // to their values. When their values change, their summaries are
239 | // updated to reflect the new value, per the Android Design
240 | // guidelines.
241 | bindPreferenceSummaryToValue(findPreference("sync_frequency"));
242 | }
243 |
244 | @Override
245 | public boolean onOptionsItemSelected(MenuItem item) {
246 | int id = item.getItemId();
247 | if (id == android.R.id.home) {
248 | startActivity(new Intent(getActivity(), SettingsActivity.class));
249 | return true;
250 | }
251 | return super.onOptionsItemSelected(item);
252 | }
253 | }
254 | }
255 |
--------------------------------------------------------------------------------
/app/src/main/java/com/shiweinan/keyboard/TcpSocketServer.java:
--------------------------------------------------------------------------------
1 | package com.shiweinan.keyboard;
2 |
3 |
4 | import android.util.Log;
5 |
6 | import java.io.BufferedInputStream;
7 | import java.io.BufferedOutputStream;
8 | import java.io.IOException;
9 | import java.net.ServerSocket;
10 | import java.net.Socket;
11 | import java.nio.Buffer;
12 | import java.nio.ByteBuffer;
13 | import java.nio.ByteOrder;
14 | import java.nio.channels.Pipe;
15 | import java.nio.charset.StandardCharsets;
16 | import java.util.Arrays;
17 |
18 | class TcpSocketServer {
19 | static void startListen() {
20 |
21 | new Thread(new Runnable() {
22 | @Override
23 | public void run() {
24 | ServerSocket tcpServer = null;
25 | boolean succFlag = false;
26 | try {
27 | tcpServer = new ServerSocket(Constants.listenPort, 100);
28 | succFlag = true;
29 | }
30 | catch (IOException e) {
31 | Log.e(Constants.errorTag, "Tcp server fail to bind, " + e.getMessage());
32 | }
33 | if (succFlag) {
34 | while (true) {
35 | BufferedInputStream tcpInputStream;
36 | BufferedOutputStream tcpOutputStream;
37 | try {
38 | Socket tcpSocket = tcpServer.accept();
39 | tcpInputStream = new BufferedInputStream(tcpSocket.getInputStream());
40 | tcpOutputStream = new BufferedOutputStream(tcpSocket.getOutputStream());
41 | } catch (IOException e1) {
42 | Log.e(Constants.errorTag, "Fail to accept a connect, " + e1.getMessage());
43 | continue;
44 | }
45 | try {
46 | warmup(tcpInputStream, tcpOutputStream);
47 | }
48 | catch (IOException e3) {
49 | Log.e(Constants.errorTag, "Fail to handshake the tcp connection, " + e3.getMessage());
50 | continue;
51 | }
52 | while (true) {
53 | try {
54 | NetMsgStruct msgStruct = readMsg(tcpInputStream);
55 | if (msgStruct.msgType == 101) {
56 | recvCandidateWords(msgStruct.msgLen, msgStruct.msg);
57 | }
58 | else if(msgStruct.msgType == 102) {
59 | recvDownSen(msgStruct.msgLen, msgStruct.msg);
60 | }
61 | else if (msgStruct.msgType == 103) {
62 | recvUpSen(msgStruct.msgLen, msgStruct.msg);
63 | }
64 | else if (msgStruct.msgType == 106) {
65 | recvHighlightIndex(msgStruct.msgLen, msgStruct.msg);
66 | }
67 | else if (msgStruct.msgType == 107) {
68 | // commit one word
69 | recvCommitWord(msgStruct.msgLen, msgStruct.msg);
70 | // Log.d(Constants.debugTag, "commit word: " + )
71 | }
72 | else if (msgStruct.msgType == 108) {
73 | recvCharsDeleted(msgStruct.msgLen, msgStruct.msg);
74 | }
75 | }
76 | catch (IOException e2) {
77 | Log.e(Constants.errorTag, "Fail to receive msg " + e2.getMessage());
78 | break;
79 | }
80 |
81 | }
82 | // testRecv(tcpInputStream);
83 | // testSend(tcpOutputStream);
84 |
85 | }
86 | }
87 | }
88 | }).start();
89 |
90 |
91 | }
92 |
93 | private static void recvHighlightIndex(int msgLen, byte[] indexMsg) {
94 | assert(msgLen == 4);
95 | assert(indexMsg.length == 4);
96 | ByteBuffer byteBuffer = ByteBuffer.wrap(indexMsg);
97 | byteBuffer.order(ByteOrder.BIG_ENDIAN);
98 | int index = byteBuffer.getInt();
99 | ByteBuffer otherBuffer = ByteBuffer.wrap(indexMsg);
100 | otherBuffer.order(ByteOrder.LITTLE_ENDIAN);
101 | int otherOrderIndex = otherBuffer.getInt();
102 | Log.d(Constants.debugTag, "set highlight index: " + index + " other-order: " + otherOrderIndex);
103 | IMEService.setHighlightWord(index);
104 | // MainActivity.setHighlightWord(index);
105 | }
106 |
107 | private static void recvCharsDeleted(int msgLen, byte[] msg) {
108 | assert(msgLen == 4);
109 | ByteBuffer byteBuffer = ByteBuffer.wrap(msg);
110 | byteBuffer.order(ByteOrder.BIG_ENDIAN);
111 | int deletedCharNum = byteBuffer.getInt();
112 | IMEService.deleteInputChars(deletedCharNum);
113 | // IMEService.setHighlightWord(index);
114 | }
115 |
116 | private static void recvCommitWord(int msgLen, byte[] msgData) {
117 | assert(msgLen < Constants.MAX_NET_WORD_LEN);
118 | String word = new String(msgData, StandardCharsets.UTF_8);
119 | IMEService.addCommitWord(word);
120 | // MainActivity.addCommitWord(word);;
121 | }
122 |
123 |
124 |
125 | private static void recvCandidateWords(int msgLen, byte[] wordsData) {
126 | assert(msgLen == Constants.MAX_NET_WORD_LEN * 5);
127 | String[] strArr = new String[5];
128 | for (int i = 0; i < 5; ++i) {
129 | byte[] tempBytes = Arrays.copyOfRange(wordsData, i * Constants.MAX_NET_WORD_LEN, (i+1) * Constants.MAX_NET_WORD_LEN);
130 | int tempWordLen = 0;
131 | for (int j = 0; j < Constants.MAX_NET_WORD_LEN; ++j) {
132 | if (tempBytes[j] == 0) {
133 | tempWordLen = j;
134 | break;
135 | }
136 | }
137 | byte[] wordBytes = Arrays.copyOf(tempBytes, tempWordLen);
138 | strArr[i] = new String(wordBytes, StandardCharsets.UTF_8);
139 | }
140 | IMEService.updateHintWords(strArr);
141 | // MainActivity.updateHintWords(strArr);
142 | }
143 |
144 | private static void recvDownSen(int msgLen, byte[] msg) {
145 | assert(msgLen <= Constants.MAX_NET_SEN_LEN);
146 | String downSen = new String(msg, StandardCharsets.UTF_8);
147 | // MainActivity.updateDownSentence(downSen);
148 | }
149 |
150 | private static void recvUpSen(int msgLen, byte[] msg) {
151 | assert(msgLen <= Constants.MAX_NET_SEN_LEN);
152 | String upSen = new String(msg, StandardCharsets.UTF_8);
153 | // MainActivity.updateUpSentence(upSen);
154 | }
155 |
156 | private static void warmup(BufferedInputStream inputStream, BufferedOutputStream outputStream) throws IOException {
157 | Log.d(Constants.debugTag, "Begin host tcp warmup");
158 | int x = readMsgInt(inputStream);
159 | assert(x == 101);
160 | x = 102;
161 | writeMsgInt(outputStream, 105, x);
162 | Log.d(Constants.debugTag, "After host tcp warmup");
163 | }
164 |
165 | static class NetMsgStruct{
166 | public int msgLen;
167 | public int msgType;
168 | byte[] msg;
169 | };
170 |
171 | private static NetMsgStruct readMsg(BufferedInputStream inputStream) throws IOException {
172 | int packetLen = readBeginLength(inputStream);
173 | int msgType = readBeginLength(inputStream);
174 | Log.d(Constants.debugTag, "readMsg packetLen: " + packetLen);
175 | int msgLen = packetLen - 4;
176 | NetMsgStruct retStruct = new NetMsgStruct();
177 | retStruct.msg = new byte[msgLen];
178 | try {
179 | if (msgLen == 4) {
180 | for (int i = 0; i < 4; ++i) {
181 | retStruct.msg[i] = 0;
182 | }
183 | }
184 | int readLen = inputStream.read(retStruct.msg, 0, msgLen);
185 | assert(readLen == msgLen);
186 | }
187 | catch (IOException e) {
188 | Log.e(Constants.errorTag, "Fail to readBytes, " + e.getMessage());
189 | throw e;
190 | }
191 |
192 | retStruct.msgLen = msgLen;
193 | retStruct.msgType = msgType;
194 | Log.d(Constants.debugTag, "readMsg, msgLen: " + msgLen + " msgType " + msgType);
195 | if (msgType == 106) {
196 | int[] tempArray = new int[4];
197 | for(int i = 0; i < 4; ++i) {
198 | tempArray[i] = retStruct.msg[i];
199 | }
200 | Log.d(Constants.debugTag, " raw index data: " + tempArray[0] + " " + tempArray[1] + " " + tempArray[2] + " " + tempArray[3]);
201 | }
202 | return retStruct;
203 | }
204 |
205 | private static void writeMsg(BufferedOutputStream outputStream, int msgLen, int msgType, byte[] data) {
206 | int sendLen = msgLen + 4;
207 | writeBeginLength(sendLen, outputStream);
208 | writeBeginLength(msgType, outputStream);
209 | try {
210 | outputStream.write(data);
211 | outputStream.flush();
212 | }
213 | catch (IOException e) {
214 | Log.e(Constants.errorTag, "Fail to write bytes to tcp, " + e.getMessage());
215 | }
216 | }
217 |
218 | private static void testRecv(BufferedInputStream inputStream) throws IOException{
219 | Log.i(Constants.infoTag, "Prepare to recv");
220 | int x = readInt(inputStream);
221 | Log.i(Constants.infoTag, "Recv " + x + " from client");
222 | }
223 |
224 | private static void testSend(BufferedOutputStream outputStream) {
225 | int x = 102;
226 | Log.i(Constants.infoTag, "Prepare to send " + x);
227 | writeInt(x, outputStream);
228 | Log.i(Constants.infoTag, "Sent " + x);
229 | }
230 |
231 | private static int readBeginLength(BufferedInputStream inputStream) throws IOException {
232 | byte[] dataByte = new byte[4];
233 | try {
234 | int realLen = inputStream.read(dataByte, 0, 4);
235 | if(realLen < 4) {
236 | Log.e(Constants.errorTag, "read realLen < 4, realLen = " + realLen);
237 | throw new IOException("read realLen < 4, realLen = " + realLen);
238 | }
239 | } catch(IOException e) {
240 | Log.e(Constants.errorTag, "Fail to read begin length");
241 | Log.e(Constants.errorTag, e.getMessage(), e);
242 | throw e;
243 | }
244 | ByteBuffer byteBuffer = ByteBuffer.wrap(dataByte);
245 | byteBuffer.order(ByteOrder.nativeOrder());
246 | return byteBuffer.getInt();
247 | }
248 |
249 | private static int readInt(BufferedInputStream inputStream) throws IOException {
250 | int beginLen = readBeginLength(inputStream);
251 | if(beginLen != 4) {
252 | Log.e(Constants.errorTag, "read begin len for int not equals 4");
253 | return -1;
254 | }
255 | return readBeginLength(inputStream);
256 | }
257 |
258 | private static int readMsgInt(BufferedInputStream inputStream) throws IOException {
259 | NetMsgStruct msgStruct = readMsg(inputStream);
260 | assert(msgStruct.msgLen == 4);
261 | ByteBuffer byteBuffer = ByteBuffer.wrap(msgStruct.msg);
262 | byteBuffer.order(ByteOrder.nativeOrder());
263 | return byteBuffer.getInt();
264 | }
265 |
266 | private static void writeMsgInt(BufferedOutputStream outputStream, int msgType, int intData) {
267 | writeBeginLength(8, outputStream);
268 | writeBeginLength(msgType, outputStream);
269 | writeBeginLength(intData, outputStream);
270 | }
271 |
272 | private static void writeBeginLength(int len, BufferedOutputStream outputStream) {
273 | ByteBuffer byteBuffer = ByteBuffer.allocate(4);
274 | byteBuffer.order(ByteOrder.nativeOrder());
275 | byteBuffer.putInt(len);
276 | try {
277 | outputStream.write(byteBuffer.array());
278 | outputStream.flush();
279 | } catch (IOException e) {
280 | Log.e(Constants.errorTag, "Fail to write begin length");
281 | Log.e(Constants.errorTag, e.getMessage(), e);
282 | }
283 | }
284 |
285 | private static void writeInt(int intData, BufferedOutputStream outputStream) {
286 | writeBeginLength(4, outputStream);
287 | writeBeginLength(intData, outputStream);
288 | }
289 | }
290 |
--------------------------------------------------------------------------------
/app/src/main/assets/pinyinMap.txt:
--------------------------------------------------------------------------------
1 | 0 a -5.5073080928575315
2 | 1 ai -5.839808124678592
3 | 2 an -5.945603589348929
4 | 3 ang -6.414126361460422
5 | 4 ao -6.26298998335994
6 | 5 ba -5.68867174657811
7 | 6 bai -6.02117177839917
8 | 7 ban -5.900262675918785
9 | 8 bang -6.096739967449411
10 | 9 bao -5.900262675918785
11 | 10 bei -5.915376313728832
12 | 11 ben -6.1118536052594585
13 | 12 beng -6.671058204231241
14 | 13 bi -5.900262675918785
15 | 14 bian -6.066512691829314
16 | 15 biao -6.217649069929796
17 | 16 bie -5.990944502779073
18 | 17 bin -6.459467274890567
19 | 18 bing -6.232762707739844
20 | 19 bo -6.187421794309699
21 | 20 bu -5.461967179427387
22 | 21 ca -6.429239999270471
23 | 22 cai -5.945603589348929
24 | 23 can -6.293217258980037
25 | 24 cang -6.565262739560905
26 | 25 cao -6.26298998335994
27 | 26 ce -6.368785448030278
28 | 27 cen -6.973330960432206
29 | 28 ceng -6.535035463940808
30 | 29 cha -6.081626329639363
31 | 30 chai -6.5803763773709525
32 | 31 chan -6.444353637080519
33 | 32 chang -6.066512691829314
34 | 33 chao -6.142080880879555
35 | 34 che -6.051399054019266
36 | 35 chen -6.217649069929796
37 | 36 cheng -6.051399054019266
38 | 37 chi -5.7793535734383985
39 | 38 chong -6.202535432119748
40 | 39 chou -6.26298998335994
41 | 40 chu -5.854921762488639
42 | 41 chua -7.169808251962832
43 | 42 chuai -7.01867187386235
44 | 43 chuan -6.142080880879555
45 | 44 chuang -6.26298998335994
46 | 45 chui -6.489694550510664
47 | 46 chun -6.3083308967900855
48 | 47 chuo -6.837308220141772
49 | 48 ci -6.066512691829314
50 | 49 cong -6.232762707739844
51 | 50 cou -6.68617184204129
52 | 51 cu -6.519921826130759
53 | 52 cuan -6.973330960432206
54 | 53 cui -6.444353637080519
55 | 54 cun -6.338558172410181
56 | 55 cuo -6.142080880879555
57 | 56 da -5.703785384388158
58 | 57 dai -5.960717227158977
59 | 58 dan -5.93048995153888
60 | 59 dang -6.1118536052594585
61 | 60 dao -5.718899022198206
62 | 61 de -5.5073080928575315
63 | 62 dei -6.383899085840326
64 | 63 den -6.776853668901579
65 | 64 deng -5.945603589348929
66 | 65 di -5.870035400298688
67 | 66 dia -6.776853668901579
68 | 67 dian -5.749126297818302
69 | 68 diao -6.217649069929796
70 | 69 die -6.474580912700615
71 | 70 ding -6.081626329639363
72 | 71 diu -6.459467274890567
73 | 72 dong -5.960717227158977
74 | 73 dou -5.764239935628351
75 | 74 du -6.02117177839917
76 | 75 duan -6.157194518689603
77 | 76 dui -5.915376313728832
78 | 77 dun -6.459467274890567
79 | 78 duo -5.839808124678592
80 | 79 e -5.794467211248447
81 | 80 ei -6.444353637080519
82 | 81 en -5.718899022198206
83 | 82 eng -7.109353700722639
84 | 83 er -5.885149038108736
85 | 84 fa -5.870035400298688
86 | 85 fan -5.93048995153888
87 | 86 fang -5.960717227158977
88 | 87 fei -6.081626329639363
89 | 88 fen -6.081626329639363
90 | 89 feng -6.142080880879555
91 | 90 fiao -7.472081008163795
92 | 91 fo -6.68617184204129
93 | 92 fou -6.595490015181
94 | 93 fu -5.915376313728832
95 | 94 ga -6.278103621169989
96 | 95 gai -6.066512691829314
97 | 96 gan -5.809580849058495
98 | 97 gang -5.990944502779073
99 | 98 gao -5.945603589348929
100 | 99 ge -5.718899022198206
101 | 100 gei -5.839808124678592
102 | 101 gen -5.9758308649690255
103 | 102 geng -6.2478763455498925
104 | 103 gong -5.9758308649690255
105 | 104 gou -6.142080880879555
106 | 105 gu -6.051399054019266
107 | 106 gua -6.26298998335994
108 | 107 guai -6.172308156499652
109 | 108 guan -6.006058140589121
110 | 109 guang -6.157194518689603
111 | 110 gui -6.142080880879555
112 | 111 gun -6.414126361460422
113 | 112 guo -5.794467211248447
114 | 113 ha -5.794467211248447
115 | 114 hai -5.673558108768061
116 | 115 han -6.157194518689603
117 | 116 hang -6.323444534600133
118 | 117 hao -5.59798991971782
119 | 118 he -5.703785384388158
120 | 119 hei -6.051399054019266
121 | 120 hen -5.870035400298688
122 | 121 heng -6.323444534600133
123 | 122 hong -6.217649069929796
124 | 123 hou -5.960717227158977
125 | 124 hu -6.051399054019266
126 | 125 hua -5.854921762488639
127 | 126 huai -6.217649069929796
128 | 127 huan -6.02117177839917
129 | 128 huang -6.232762707739844
130 | 129 hui -5.643330833147965
131 | 130 hun -6.232762707739844
132 | 131 huo -5.990944502779073
133 | 132 ji -5.658444470958013
134 | 133 jia -5.764239935628351
135 | 134 jian -5.854921762488639
136 | 135 jiang -6.066512691829314
137 | 136 jiao -5.870035400298688
138 | 137 jie -5.794467211248447
139 | 138 jin -5.7793535734383985
140 | 139 jing -5.9758308649690255
141 | 140 jiong -6.746626393281482
142 | 141 jiu -5.613103557527869
143 | 142 ju -6.02117177839917
144 | 143 juan -6.489694550510664
145 | 144 jue -6.006058140589121
146 | 145 jun -6.323444534600133
147 | 146 ka -6.217649069929796
148 | 147 kai -5.93048995153888
149 | 148 kan -5.7793535734383985
150 | 149 kang -6.474580912700615
151 | 150 kao -6.066512691829314
152 | 151 ke -5.7793535734383985
153 | 152 kei -7.487194645973844
154 | 153 ken -6.217649069929796
155 | 154 keng -6.610603652991049
156 | 155 kong -6.217649069929796
157 | 156 kou -6.217649069929796
158 | 157 ku -6.157194518689603
159 | 158 kua -6.550149101750856
160 | 159 kuai -5.9758308649690255
161 | 160 kuan -6.429239999270471
162 | 161 kuang -6.459467274890567
163 | 162 kui -6.519921826130759
164 | 163 kun -6.26298998335994
165 | 164 kuo -6.776853668901579
166 | 165 la -5.870035400298688
167 | 166 lai -5.794467211248447
168 | 167 lan -6.202535432119748
169 | 168 lang -6.368785448030278
170 | 169 lao -5.854921762488639
171 | 170 le -5.643330833147965
172 | 171 lei -6.081626329639363
173 | 172 leng -6.232762707739844
174 | 173 li -5.749126297818302
175 | 174 lia -6.35367181022023
176 | 175 lian -6.02117177839917
177 | 176 liang -5.990944502779073
178 | 177 liao -6.036285416209218
179 | 178 lie -6.383899085840326
180 | 179 lin -6.2478763455498925
181 | 180 ling -6.157194518689603
182 | 181 liu -5.990944502779073
183 | 182 lo -6.1118536052594585
184 | 183 long -6.293217258980037
185 | 184 lou -6.217649069929796
186 | 185 lu -6.02117177839917
187 | 186 luan -6.368785448030278
188 | 187 lue -6.761740031091531
189 | 188 lun -6.368785448030278
190 | 189 luo -6.202535432119748
191 | 190 lv -6.278103621169989
192 | 191 ma -5.68867174657811
193 | 192 mai -5.93048995153888
194 | 193 man -6.096739967449411
195 | 194 mang -6.096739967449411
196 | 195 mao -6.1118536052594585
197 | 196 me -5.824694486868543
198 | 197 mei -5.628217195337917
199 | 198 men -5.960717227158977
200 | 199 meng -6.232762707739844
201 | 200 mi -6.096739967449411
202 | 201 mian -6.1118536052594585
203 | 202 miao -6.459467274890567
204 | 203 mie -6.323444534600133
205 | 204 min -6.399012723650374
206 | 205 ming -5.915376313728832
207 | 206 miu -7.154694614152784
208 | 207 mo -6.081626329639363
209 | 208 mou -6.519921826130759
210 | 209 mu -6.1118536052594585
211 | 210 na -5.59798991971782
212 | 211 nai -6.278103621169989
213 | 212 nan -5.93048995153888
214 | 213 nang -6.746626393281482
215 | 214 nao -6.217649069929796
216 | 215 ne -5.824694486868543
217 | 216 nei -6.293217258980037
218 | 217 nen -6.595490015181
219 | 218 neng -5.93048995153888
220 | 219 ni -5.431739903807291
221 | 220 nian -6.051399054019266
222 | 221 niang -6.459467274890567
223 | 222 niao -6.444353637080519
224 | 223 nie -6.519921826130759
225 | 224 nin -6.232762707739844
226 | 225 ning -6.459467274890567
227 | 226 niu -6.232762707739844
228 | 227 nong -6.202535432119748
229 | 228 nou -7.547649197214036
230 | 229 nu -6.338558172410181
231 | 230 nuan -6.474580912700615
232 | 231 nue -6.807080944521675
233 | 232 nun -7.562762835024085
234 | 233 nuo -6.610603652991049
235 | 234 nv -6.02117177839917
236 | 235 o -5.68867174657811
237 | 236 ou -6.35367181022023
238 | 237 pa -6.157194518689603
239 | 238 pai -6.157194518689603
240 | 239 pan -6.399012723650374
241 | 240 pang -6.338558172410181
242 | 241 pao -6.202535432119748
243 | 242 pei -6.126967243069507
244 | 243 pen -6.6408309286111455
245 | 244 peng -6.202535432119748
246 | 245 pi -6.157194518689603
247 | 246 pian -6.202535432119748
248 | 247 piao -6.293217258980037
249 | 248 pie -6.958217322622157
250 | 249 pin -6.338558172410181
251 | 250 ping -6.142080880879555
252 | 251 po -6.202535432119748
253 | 252 pou -7.109353700722639
254 | 253 pu -6.3083308967900855
255 | 254 qi -5.7793535734383985
256 | 255 qia -6.701285479851338
257 | 256 qian -5.93048995153888
258 | 257 qiang -6.26298998335994
259 | 258 qiao -6.323444534600133
260 | 259 qie -6.2478763455498925
261 | 260 qin -6.051399054019266
262 | 261 qing -5.945603589348929
263 | 262 qiong -6.625717290801097
264 | 263 qiu -6.172308156499652
265 | 264 qu -5.718899022198206
266 | 265 quan -6.157194518689603
267 | 266 que -6.2478763455498925
268 | 267 qun -6.399012723650374
269 | 268 ran -6.142080880879555
270 | 269 rang -6.081626329639363
271 | 270 rao -6.5803763773709525
272 | 271 re -6.278103621169989
273 | 272 ren -5.809580849058495
274 | 273 reng -6.671058204231241
275 | 274 ri -6.142080880879555
276 | 275 rong -6.35367181022023
277 | 276 rou -6.368785448030278
278 | 277 ru -6.081626329639363
279 | 278 rua -7.608103748454229
280 | 279 ruan -6.504808188320712
281 | 280 rui -6.550149101750856
282 | 281 run -6.731512755471434
283 | 282 ruo -6.565262739560905
284 | 283 sa -6.217649069929796
285 | 284 sai -6.429239999270471
286 | 285 san -6.051399054019266
287 | 286 sang -6.550149101750856
288 | 287 sao -6.383899085840326
289 | 288 se -6.26298998335994
290 | 289 sen -6.671058204231241
291 | 290 seng -7.033785511672398
292 | 291 sha -5.945603589348929
293 | 292 shai -6.565262739560905
294 | 293 shan -6.172308156499652
295 | 294 shang -5.794467211248447
296 | 295 shao -6.096739967449411
297 | 296 she -6.187421794309699
298 | 297 shei -6.368785448030278
299 | 298 shen -5.824694486868543
300 | 299 sheng -5.960717227158977
301 | 300 shi -5.5073080928575315
302 | 301 shou -5.854921762488639
303 | 302 shu -5.960717227158977
304 | 303 shua -6.278103621169989
305 | 304 shuai -6.323444534600133
306 | 305 shuan -6.897762771381965
307 | 306 shuang -6.26298998335994
308 | 307 shui -5.7793535734383985
309 | 308 shun -6.338558172410181
310 | 309 shuo -5.764239935628351
311 | 310 si -5.870035400298688
312 | 311 song -6.172308156499652
313 | 312 sou -6.504808188320712
314 | 313 su -6.1118536052594585
315 | 314 suan -6.096739967449411
316 | 315 sui -6.157194518689603
317 | 316 sun -6.429239999270471
318 | 317 suo -6.096739967449411
319 | 318 ta -5.794467211248447
320 | 319 tai -5.945603589348929
321 | 320 tan -6.2478763455498925
322 | 321 tang -6.187421794309699
323 | 322 tao -6.172308156499652
324 | 323 te -6.26298998335994
325 | 324 tei -7.0488991494824464
326 | 325 teng -6.323444534600133
327 | 326 ti -6.02117177839917
328 | 327 tian -5.915376313728832
329 | 328 tiao -6.202535432119748
330 | 329 tie -6.368785448030278
331 | 330 ting -5.9758308649690255
332 | 331 tong -6.006058140589121
333 | 332 tou -6.066512691829314
334 | 333 tu -6.096739967449411
335 | 334 tuan -6.489694550510664
336 | 335 tui -6.278103621169989
337 | 336 tun -6.701285479851338
338 | 337 tuo -6.35367181022023
339 | 338 wa -6.1118536052594585
340 | 339 wai -6.142080880879555
341 | 340 wan -5.734012660008254
342 | 341 wang -5.945603589348929
343 | 342 wei -5.824694486868543
344 | 343 wen -5.885149038108736
345 | 344 weng -6.943103684812109
346 | 345 wo -5.477080817237435
347 | 346 wu -5.794467211248447
348 | 347 xi -5.749126297818302
349 | 348 xia -5.794467211248447
350 | 349 xian -5.824694486868543
351 | 350 xiang -5.7793535734383985
352 | 351 xiao -5.809580849058495
353 | 352 xie -5.93048995153888
354 | 353 xin -5.809580849058495
355 | 354 xing -5.885149038108736
356 | 355 xiong -6.323444534600133
357 | 356 xiu -6.066512691829314
358 | 357 xu -6.066512691829314
359 | 358 xuan -6.278103621169989
360 | 359 xue -5.960717227158977
361 | 360 xun -6.3083308967900855
362 | 361 ya -5.885149038108736
363 | 362 yan -5.990944502779073
364 | 363 yang -5.9758308649690255
365 | 364 yao -5.718899022198206
366 | 365 ye -5.718899022198206
367 | 366 yi -5.522421730667579
368 | 367 yin -6.006058140589121
369 | 368 ying -5.990944502779073
370 | 369 yo -6.3083308967900855
371 | 370 yong -5.9758308649690255
372 | 371 you -5.59798991971782
373 | 372 yu -5.885149038108736
374 | 373 yuan -5.945603589348929
375 | 374 yue -6.006058140589121
376 | 375 yun -6.081626329639363
377 | 376 za -6.081626329639363
378 | 377 zai -5.628217195337917
379 | 378 zan -6.202535432119748
380 | 379 zang -6.6408309286111455
381 | 380 zao -5.915376313728832
382 | 381 ze -6.383899085840326
383 | 382 zei -6.731512755471434
384 | 383 zen -5.93048995153888
385 | 384 zeng -6.565262739560905
386 | 385 zha -6.459467274890567
387 | 386 zhai -6.535035463940808
388 | 387 zhan -6.202535432119748
389 | 388 zhang -6.036285416209218
390 | 389 zhao -5.870035400298688
391 | 390 zhe -5.68867174657811
392 | 391 zhei -6.807080944521675
393 | 392 zhen -5.885149038108736
394 | 393 zheng -6.02117177839917
395 | 394 zhi -5.718899022198206
396 | 395 zhong -5.93048995153888
397 | 396 zhou -6.081626329639363
398 | 397 zhu -5.900262675918785
399 | 398 zhua -6.474580912700615
400 | 399 zhuai -6.943103684812109
401 | 400 zhuan -6.172308156499652
402 | 401 zhuang -6.187421794309699
403 | 402 zhui -6.459467274890567
404 | 403 zhun -6.202535432119748
405 | 404 zhuo -6.35367181022023
406 | 405 zi -5.794467211248447
407 | 406 zong -6.187421794309699
408 | 407 zou -6.066512691829314
409 | 408 zu -6.232762707739844
410 | 409 zuan -6.671058204231241
411 | 410 zui -5.990944502779073
412 | 411 zun -6.655944566421193
413 | 412 zuo -5.794467211248447
--------------------------------------------------------------------------------
/app/src/main/java/com/shiweinan/keyboard/IMEService.java:
--------------------------------------------------------------------------------
1 | package com.shiweinan.keyboard;
2 |
3 | import android.inputmethodservice.InputMethodService;
4 | import android.inputmethodservice.Keyboard;
5 | import android.inputmethodservice.KeyboardView;
6 | import android.os.Handler;
7 | import android.os.Looper;
8 | import android.util.Log;
9 | import android.view.KeyEvent;
10 | import android.view.MotionEvent;
11 | import android.view.View;
12 | import android.view.inputmethod.EditorInfo;
13 | import android.view.inputmethod.InputConnection;
14 | import android.view.inputmethod.InputMethodManager;
15 | import android.widget.TextView;
16 |
17 | import java.util.ArrayList;
18 | import java.util.Arrays;
19 | import java.util.HashMap;
20 | import java.util.List;
21 | import java.util.concurrent.Executor;
22 | import java.util.concurrent.Executors;
23 | import java.util.concurrent.ScheduledExecutorService;
24 | import java.util.concurrent.TimeUnit;
25 |
26 | import static android.graphics.Color.BLACK;
27 | import static android.graphics.Color.GRAY;
28 | import static android.graphics.Color.WHITE;
29 |
30 | public class IMEService extends InputMethodService implements KeyboardView.OnKeyboardActionListener {
31 | private StoneKeyboardView mKeyboardView;
32 | private Keyboard mKeyboard;
33 |
34 | private CandidatesContainer mCandidateContainer;
35 | private StringBuilder m_composeString = new StringBuilder(); // 保存写作串
36 | ArrayList pinyinList = new ArrayList();
37 |
38 | private List touchPoints = new ArrayList<>();
39 | private PredictAlgorithm predictAlgorithm;
40 | private TouchModel touchModel;
41 |
42 | static private IMEService _instance;
43 |
44 | static IMEService getInstance() {
45 | return _instance;
46 | }
47 |
48 | @Override
49 | public View onCreateCandidatesView(){
50 | _instance = this;
51 | Log.d(this.getClass().toString(), "onCreateCandidatesView: ");
52 | //mCandidateContainer = new CandidateView(this);
53 | mCandidateContainer = new CandidatesContainer(this);
54 | //mCandidateContainer = new CandidateView(this);
55 | return mCandidateContainer;
56 | }
57 | @Override
58 | public void onStartInput(EditorInfo editorInfo, boolean restarting){
59 | super.onStartInput(editorInfo, restarting);
60 | Log.d(this.getClass().toString(), "onStartInput: ");
61 | m_composeString.setLength(0);
62 | }
63 |
64 | @Override
65 | public View onCreateInputView() {
66 | _instance = this;
67 | //mKeyboardView = (KeyboardView)getLayoutInflater().inflate(R.layout.keyboard,null);
68 | mKeyboardView = new StoneKeyboardView(getApplicationContext(), null, this);
69 | mKeyboard = new Keyboard(this, R.xml.qwerty);
70 | mKeyboardView.setKeyboard(mKeyboard);
71 | mKeyboardView.setOnKeyboardActionListener(this);
72 | mKeyboardView.setPreviewEnabled(false);
73 | ///initialization
74 | if (touchModel == null) {
75 | touchModel = new TouchModel(this);
76 | }
77 | if (predictAlgorithm == null) {
78 | predictAlgorithm = new PredictAlgorithm(this, touchModel);
79 | }
80 | return mKeyboardView;
81 | }
82 | //temporary
83 | private char getRawInput(double x, double y) {
84 | for (Keyboard.Key key:mKeyboardView.getKeyboard().getKeys()) {
85 | if (key.isInside((int)(Math.round(x)), (int)(Math.round(y)))) {
86 | return key.label.charAt(0);
87 | }
88 | }
89 | return ' ';
90 | }
91 |
92 | public static void setHighlightWord(final int index) {
93 | Handler mainHandler = new Handler(Looper.getMainLooper());
94 | mainHandler.post(new Runnable() {
95 | @Override
96 | public void run() {
97 | if (index >= 0 && index <= 4) {
98 | getInstance().mCandidateContainer.setHighlightCandidate(index);
99 | }
100 | }
101 | });
102 | }
103 |
104 | public static void updateHintWords(final String[] hintWords) {
105 | Handler mainHandler = new Handler(Looper.getMainLooper());
106 | mainHandler.post(new Runnable() {
107 | @Override
108 | public void run() {
109 | IMEService instance = getInstance();
110 | instance.pinyinList.clear();
111 | instance.pinyinList.addAll(Arrays.asList(hintWords));
112 | instance.mCandidateContainer.setSuggestions(instance.pinyinList);
113 | instance.setCandidatesViewShown(true);
114 | }
115 | });
116 |
117 | }
118 |
119 | public static void addCommitWord(final String word) {
120 | Handler mainHandler = new Handler(Looper.getMainLooper());
121 | mainHandler.post(new Runnable() {
122 | @Override
123 | public void run() {
124 | IMEService instance = getInstance();
125 | instance.getCurrentInputConnection().commitText(word + " ", 1);
126 | }
127 | });
128 | }
129 |
130 | public static void deleteInputChars(final int charNum) {
131 | Handler mainHandler = new Handler(Looper.getMainLooper());
132 | mainHandler.post(new Runnable() {
133 | @Override
134 | public void run() {
135 | IMEService instance = getInstance();
136 | instance.getCurrentInputConnection().deleteSurroundingText(charNum, 0);
137 | }
138 | });
139 | }
140 |
141 |
142 | private void updateCandidates() {
143 | String ret = "";
144 | List seg = predictAlgorithm.predict(touchPoints);
145 |
146 |
147 | for (int i=0; i 0) {
164 | touchPoints.remove(touchPoints.size() - 1);
165 | updateCandidates();
166 | } else {
167 | getCurrentInputConnection().deleteSurroundingText(1, 0);
168 | }
169 | if (Settings.getShowTouchPoints()) {
170 | mKeyboardView.clearDrawPoints();
171 | }
172 | }
173 | private void enter() {
174 | if (touchPoints.size() > 0) {
175 | getCurrentInputConnection().finishComposingText();
176 |
177 | if (Settings.getShowPinyinSegmentation()) {
178 |
179 | List pyseg = predictAlgorithm.getPinyinSegment(touchPoints, 0);
180 | //System.out.println("===========" + seg.size());
181 | getCurrentInputConnection().commitText("\n", 1);
182 | for (PinyinSegmentation s : pyseg) {
183 | getCurrentInputConnection().commitText(s.getSegments() + " ", 1);
184 | //s.showSegments();
185 | }
186 | // List ret = new ArrayList<>();
187 | // for (PinyinSegmentation s : seg.subList(0, Math.min(5, seg.size()))) {
188 | // ret.add(s.getSegments());
189 | // }
190 | }
191 |
192 | touchPoints.clear();
193 | updateCandidates();
194 |
195 | } else {
196 | getCurrentInputConnection().sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER));
197 | }
198 | }
199 | private void space() {
200 | if (touchPoints.size() > 0) {
201 | if (pinyinList.size() > 0) {
202 | getCurrentInputConnection().commitText(pinyinList.get(0) + " ", 1);
203 | }
204 | touchPoints.clear();
205 | } else {
206 | getCurrentInputConnection().commitText(" ", 1);
207 | }
208 | updateCandidates();
209 | }
210 | public void select(String str) {
211 | getCurrentInputConnection().commitText(str, 1);
212 | touchPoints.clear();
213 | updateCandidates();
214 | }
215 |
216 | public List getKeys() {
217 | return mKeyboard.getKeys();
218 | }
219 | public int getKeyboardHeight() {
220 | return mKeyboardView.getMeasuredHeight();
221 | }
222 |
223 | HashMap schedulers = new HashMap<>();
224 |
225 |
226 |
227 | public boolean onTouchEvent(final MotionEvent me) {
228 | //System.out.println("height!!!" + mKeyboardView.getMeasuredHeight());
229 | int actionId = me.getActionIndex();
230 | final float x = me.getX(actionId);
231 | final float y = me.getY(actionId);
232 | switch (me.getAction() & MotionEvent.ACTION_MASK) {
233 | case MotionEvent.ACTION_DOWN:
234 | case MotionEvent.ACTION_POINTER_DOWN:
235 | /*if (schedulers.get(actionId) != null) {
236 | schedulers.get(actionId).shutdownNow();
237 | schedulers.put(actionId, null);
238 | } else {
239 | ScheduledExecutorService s = Executors.newSingleThreadScheduledExecutor();
240 | s.scheduleWithFixedDelay(new Runnable() {
241 | @Override
242 | public void run() {
243 | touchDown(x, y);
244 | }
245 | }, 0, 100, TimeUnit.MILLISECONDS);
246 |
247 | schedulers.put(actionId, s);
248 | }*/
249 | touchDown(x, y);
250 | break;
251 |
252 | case MotionEvent.ACTION_UP:
253 | case MotionEvent.ACTION_POINTER_UP:
254 | if (schedulers.get(actionId) != null) {
255 | schedulers.get(actionId).shutdownNow();
256 | schedulers.put(actionId, null);
257 | }
258 | // x = me.getX(action);
259 | // y = me.getY(action);
260 | // for (Keyboard.Key key:keys) {
261 | // if (key.isInside(Math.round(x), Math.round(y))) {
262 | // key.onReleased(true);
263 | // //getCurrentInputConnection().commitText(key.label, 1);
264 | // break;
265 | // }
266 | // }
267 | break;
268 | default:
269 | break;
270 | }
271 | return true;
272 | }
273 | private void touchDown(float x, float y) {
274 | boolean isFunction = false;
275 | //touchPoints.add(new TouchPoint(x, y));
276 | //updateCandidates();
277 | //setCandidatesViewShown(true);
278 | List keys = mKeyboardView.getKeyboard().getKeys();
279 | for (Keyboard.Key key:keys) {
280 | if (key.isInside(Math.round(x), Math.round(y))) {
281 | if (key.codes[0] == Keyboard.KEYCODE_MODE_CHANGE) {
282 | //InputMethodManager ime = (InputMethodManager) getApplicationContext().getSystemService(INPUT_METHOD_SERVICE);
283 | //ime.showInputMethodPicker();
284 | //isFunction = true;
285 | return;
286 | } else if (key.codes[0] == -5) { // delete
287 | //delete();
288 | //leave system handle it, for repeatable function
289 | return;
290 | } else if (key.codes[0] == Keyboard.KEYCODE_DONE) {
291 | enter();
292 | isFunction = true;
293 | } else if (key.codes[0] == 32) { //space
294 | space();
295 | isFunction = true;
296 | }
297 | break;
298 | }
299 | }
300 | if (!isFunction) {
301 | touchPoints.add(new TouchPoint(x, y));
302 | updateCandidates();
303 | }
304 | }
305 | private void touchDown(MotionEvent me) {
306 | boolean isFunction = false;
307 | int action = me.getActionIndex();
308 | float x = me.getX(action);
309 | float y = me.getY(action);
310 | System.out.println("pos::::" + x + "," + y);
311 | //touchPoints.add(new TouchPoint(x, y));
312 | //updateCandidates();
313 | //setCandidatesViewShown(true);
314 | List keys = mKeyboardView.getKeyboard().getKeys();
315 | for (Keyboard.Key key:keys) {
316 | if (key.isInside(Math.round(x), Math.round(y))) {
317 | if (key.label.equals("?")) {
318 | InputMethodManager ime = (InputMethodManager) getApplicationContext().getSystemService(INPUT_METHOD_SERVICE);
319 | ime.showInputMethodPicker();
320 | isFunction = true;
321 | } else if (key.label.equals("DEL")) {
322 | delete();
323 | isFunction = true;
324 | } else if (key.codes[0] == Keyboard.KEYCODE_DONE) {
325 | enter();
326 | isFunction = true;
327 | } else if (key.label.equals(" ")) {
328 | space();
329 | isFunction = true;
330 | } else {
331 | //getCurrentInputConnection().commitText(key.label, 1);
332 | isFunction = false;
333 | }
334 | break;
335 | }
336 | }
337 | if (!isFunction) {
338 | touchPoints.add(new TouchPoint(x, y));
339 | updateCandidates();
340 | }
341 | }
342 |
343 |
344 | @Override
345 | public void onKey(int primaryCode, int[] keyCodes) {
346 | InputConnection ic = getCurrentInputConnection();
347 | switch (primaryCode) {
348 | case Keyboard.KEYCODE_DELETE:
349 | //ic.deleteSurroundingText(1, 0);
350 | delete();
351 | break;
352 | case Keyboard.KEYCODE_DONE:
353 | //ic.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER));
354 | enter();
355 | break;
356 | case Keyboard.KEYCODE_MODE_CHANGE:
357 | InputMethodManager ime = (InputMethodManager) getApplicationContext().getSystemService(INPUT_METHOD_SERVICE);
358 | ime.showInputMethodPicker();
359 | break;
360 | default:
361 | /*char code = (char)primaryCode;
362 | if(code == ' '){ // 如果收到的是空格
363 | if(m_composeString.length() > 0) { // 如果有写作串,则将首个候选提交上屏
364 | ic.commitText(m_composeString, m_composeString.length());
365 | m_composeString.setLength(0);
366 | }else{ // 如果没有写作串,则直接将空格上屏
367 | ic.commitText(" ", 1);
368 | }
369 | //setCandidatesViewShown(false);
370 | }else { // 否则,将字符计入写作串
371 | m_composeString.append(code);
372 | ic.setComposingText(m_composeString, 1);
373 | if(mCandidateContainer != null){
374 | ArrayList list = new ArrayList();
375 | list.add(m_composeString.toString());
376 | list.add(m_composeString.toString());
377 | list.add(m_composeString.toString());
378 | mCandidateContainer.setSuggestions(list);
379 | setCandidatesViewShown(true);
380 | }
381 | }*/
382 | }
383 | }
384 |
385 | @Override
386 | public void onPress(int primaryCode) {
387 | }
388 | @Override
389 | public void onRelease(int primaryCode) {
390 | }
391 | @Override
392 | public void onText(CharSequence text) {
393 | }
394 | @Override
395 | public void swipeDown() {
396 | }
397 | @Override
398 | public void swipeLeft() {
399 | }
400 | @Override
401 | public void swipeRight() {
402 | }
403 | @Override
404 | public void swipeUp() {
405 | }
406 |
407 | }
408 |
--------------------------------------------------------------------------------