error
is null
, the error message and icon
112 | * will be cleared.
113 | */
114 | public void setError(CharSequence error) {
115 | if(DEBUG) Log.d(TAG, ".setError(error)...");
116 | if (error == null) {
117 | setError(null, null, true, true);
118 | } else {
119 | /*
120 | Drawable dr = getContext().getResources().getDrawable(R.drawable.indicator_input_error);
121 |
122 | dr.setBounds(0, 0, dr.getIntrinsicWidth(), dr.getIntrinsicHeight());
123 | setError(error, dr);
124 | */
125 | setError(error, null, true, true);
126 | }
127 | }
128 |
129 | public void setError(CharSequence error, boolean showError) {
130 | setError(error, null, showError, true);
131 | }
132 |
133 | public void setError(CharSequence error, Drawable icon) {
134 | setError(error, icon, true, true);
135 | }
136 |
137 | public void setError(CharSequence error, Drawable icon, boolean showError) {
138 | setError(error, icon, showError, true);
139 | }
140 |
141 | public void setError(CharSequence error, Drawable icon, boolean showError, boolean showCompoundDrawableOnRight) {
142 | if(DEBUG) Log.d(TAG, ".setError(error, icon, showError, showCompoundDrawableOnRight)...");
143 | if(icon != null) {
144 | if(DEBUG) Log.d(TAG, "...icon is not null...");
145 | icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
146 | }
147 | error = TextUtils.stringOrSpannedString(error);
148 | mErrorWasChanged = true;
149 |
150 | mError = error;
151 | mErrorWasChanged = true;
152 |
153 | final Drawables dr = mDrawables;
154 | if(mView instanceof TextView && error != null) {
155 | if (true || dr != null) {
156 | if(showCompoundDrawableOnRight) {
157 | if(DEBUG) Log.d(TAG, "...showing CompoundDrawable on right)...");
158 | //((TextView) mView).setCompoundDrawables(dr.mDrawableLeft, dr.mDrawableTop, icon, dr.mDrawableBottom);
159 | ((TextView) mView).setCompoundDrawables(null, null, icon, null);
160 | } else {
161 | //((TextView) mView).setCompoundDrawables(icon, dr.mDrawableTop, dr.mDrawableRight, dr.mDrawableBottom);
162 | ((TextView) mView).setCompoundDrawables(icon, null, null, null);
163 | }
164 | }
165 | }
166 |
167 | if (error == null) {
168 | if (mPopup != null) {
169 | if (mPopup.isShowing()) {
170 | mPopup.dismiss();
171 | }
172 | if(mView instanceof TextView) {
173 | ((TextView) mView).setCompoundDrawables(null, null, null, null);
174 | }
175 | mPopup = null;
176 | }
177 | } else if(showError) {
178 | //LD - EditTexts use isFocused to show only the focused one, other Views may not be focusable
179 | //if (isFocused()) {
180 | showError();
181 | //}
182 | }
183 | }
184 |
185 | public void showError() {
186 | if(DEBUG) Log.d(TAG, ".showError()...");
187 | if (mView.getWindowToken() == null) {
188 | mShowErrorAfterAttach = true;
189 | return;
190 | }
191 |
192 | if (mPopup == null) {
193 | LayoutInflater inflater = LayoutInflater.from(mView.getContext());
194 | final TextView err = (TextView) inflater.inflate(R.layout.textview_hint, null);
195 | err.setText(mError);
196 |
197 | final float scale = mContext.getResources().getDisplayMetrics().density;
198 | mPopup = new ErrorPopup(mContext, err, (int) (200 * scale + 0.5f), (int) (50 * scale + 0.5f));
199 | mPopup.setFocusable(false);
200 | //LD - non EditTexts may not require this:
201 | // The user is entering text, so the input method is needed. We
202 | // don't want the popup to be displayed on top of it.
203 | mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
204 | }
205 |
206 | if(DEBUG) Log.d(TAG, "...error: "+mError);
207 | TextView tv = (TextView) mPopup.getContentView();
208 | //tv.setPadding(mErrorPopupPaddingLeft, mErrorPopupPaddingTop, mErrorPopupPaddingRight, mErrorPopupPaddingBottom);
209 | chooseSize(mPopup, mError, tv);
210 | tv.setText(mError);
211 |
212 | mPopup.showAsDropDown(mView, getErrorX(), getErrorY());
213 | mPopup.fixDirection(mPopup.isAboveAnchor());
214 | }
215 |
216 | public void hideError() {
217 | if (mPopup != null) {
218 | if (mPopup.isShowing()) {
219 | mPopup.dismiss();
220 | }
221 | }
222 |
223 | mShowErrorAfterAttach = false;
224 | }
225 |
226 | private void chooseSize(PopupWindow pop, CharSequence text, TextView tv) {
227 | int wid = tv.getPaddingLeft() + tv.getPaddingRight();
228 | int ht = tv.getPaddingTop() + tv.getPaddingBottom();
229 |
230 | //com.android.internal.R.dimen.textview_error_popup_default_width introduced after Gingerbread, only has one variant (240dip)
231 | int defaultWidthInPixels = mContext.getResources().getDimensionPixelSize(R.dimen.textview_error_popup_default_width);
232 | Layout l = new StaticLayout(text, tv.getPaint(), defaultWidthInPixels, Layout.Alignment.ALIGN_NORMAL, 1, 0, true);
233 |
234 | float max = 0;
235 | for (int i = 0; i < l.getLineCount(); i++) {
236 | max = Math.max(max, l.getLineWidth(i));
237 | }
238 |
239 | if(DEBUG) Log.d(TAG, "max: "+max+", height: "+l.getHeight());
240 |
241 | /*
242 | * Now set the popup size to be big enough for the text plus the border.
243 | */
244 | pop.setWidth(wid + (int) Math.ceil(max));
245 | pop.setHeight(ht + l.getHeight()); //TODO: buggy (the 2 shouldnt need to be there)
246 | }
247 |
248 | /**
249 | * Returns the Y offset to make the pointy top of the error point
250 | * at the middle of the error icon.
251 | */
252 | private int getErrorX() {
253 | /*
254 | * The "25" is the distance between the point and the right edge
255 | * of the background
256 | */
257 |
258 | final Drawables dr = mDrawables;
259 | return mView.getWidth() - mPopup.getWidth();// - getPaddingRight() - (dr != null ? dr.mDrawableSizeRight : 0) / 2 + 0;
260 | }
261 |
262 | /**
263 | * Returns the Y offset to make the pointy top of the error point
264 | * at the bottom of the error icon.
265 | */
266 | private int getErrorY() {
267 | /*
268 | * Compound, not extended, because the icon is not clipped
269 | * if the text height is smaller.
270 | */
271 | int vspace = mBottom - mTop -
272 | getCompoundPaddingBottom() - getCompoundPaddingTop();
273 |
274 | final Drawables dr = mDrawables;
275 | int icontop = getCompoundPaddingTop()
276 | + (vspace - (dr != null ? dr.mDrawableHeightRight : 0)) / 2;
277 |
278 | /*
279 | * The "2" is the distance between the point and the top edge
280 | * of the background.
281 | */
282 | //return icontop + (dr != null ? dr.mDrawableHeightRight : 0) - getHeight() - 2;
283 | return 0 - mView.getHeight()/2;
284 | }
285 |
286 | /**
287 | * Returns the top padding of the view, plus space for the top
288 | * Drawable if any.
289 | */
290 | public int getCompoundPaddingTop() {
291 | final Drawables dr = mDrawables;
292 | if (dr == null || dr.mDrawableTop == null) {
293 | return mPaddingTop;
294 | } else {
295 | return mPaddingTop + dr.mDrawablePadding + dr.mDrawableSizeTop;
296 | }
297 | }
298 |
299 | /**
300 | * Returns the bottom padding of the view, plus space for the bottom
301 | * Drawable if any.
302 | */
303 | public int getCompoundPaddingBottom() {
304 | final Drawables dr = mDrawables;
305 | if (dr == null || dr.mDrawableBottom == null) {
306 | return mPaddingBottom;
307 | } else {
308 | return mPaddingBottom + dr.mDrawablePadding + dr.mDrawableSizeBottom;
309 | }
310 | }
311 |
312 | /**
313 | * Returns the left padding of the view, plus space for the left
314 | * Drawable if any.
315 | */
316 | public int getCompoundPaddingLeft() {
317 | final Drawables dr = mDrawables;
318 | if (dr == null || dr.mDrawableLeft == null) {
319 | return mPaddingLeft;
320 | } else {
321 | return mPaddingLeft + dr.mDrawablePadding + dr.mDrawableSizeLeft;
322 | }
323 | }
324 |
325 | /**
326 | * Returns the right padding of the view, plus space for the right
327 | * Drawable if any.
328 | */
329 | public int getCompoundPaddingRight() {
330 | final Drawables dr = mDrawables;
331 | if (dr == null || dr.mDrawableRight == null) {
332 | return mPaddingRight;
333 | } else {
334 | return mPaddingRight + dr.mDrawablePadding + dr.mDrawableSizeRight;
335 | }
336 | }
337 |
338 | /**
339 | * Sets the Drawables (if any) to appear to the left of, above,
340 | * to the right of, and below the text. Use null if you do not
341 | * want a Drawable there. The Drawables must already have had
342 | * {@link Drawable#setBounds} called.
343 | *
344 | * @attr ref android.R.styleable#TextView_drawableLeft
345 | * @attr ref android.R.styleable#TextView_drawableTop
346 | * @attr ref android.R.styleable#TextView_drawableRight
347 | * @attr ref android.R.styleable#TextView_drawableBottom
348 | */
349 | public void setCompoundDrawables(Drawable left, Drawable top,
350 | Drawable right, Drawable bottom) {
351 | Drawables dr = mDrawables;
352 |
353 | final boolean drawables = left != null || top != null
354 | || right != null || bottom != null;
355 |
356 | if (!drawables) {
357 | // Clearing drawables... can we free the data structure?
358 | if (dr != null) {
359 | if (dr.mDrawablePadding == 0) {
360 | mDrawables = null;
361 | } else {
362 | // We need to retain the last set padding, so just clear
363 | // out all of the fields in the existing structure.
364 | dr.mDrawableLeft = null;
365 | dr.mDrawableTop = null;
366 | dr.mDrawableRight = null;
367 | dr.mDrawableBottom = null;
368 | dr.mDrawableSizeLeft = dr.mDrawableHeightLeft = 0;
369 | dr.mDrawableSizeRight = dr.mDrawableHeightRight = 0;
370 | dr.mDrawableSizeTop = dr.mDrawableWidthTop = 0;
371 | dr.mDrawableSizeBottom = dr.mDrawableWidthBottom = 0;
372 | }
373 | }
374 | } else {
375 | if (dr == null) {
376 | mDrawables = dr = new Drawables();
377 | }
378 |
379 | dr.mDrawableLeft = left;
380 | dr.mDrawableTop = top;
381 | dr.mDrawableRight = right;
382 | dr.mDrawableBottom = bottom;
383 |
384 | final Rect compoundRect = dr.mCompoundRect;
385 | int[] state = null;
386 |
387 | state = mView.getDrawableState();
388 |
389 | if (left != null) {
390 | left.setState(state);
391 | left.copyBounds(compoundRect);
392 | dr.mDrawableSizeLeft = compoundRect.width();
393 | dr.mDrawableHeightLeft = compoundRect.height();
394 | } else {
395 | dr.mDrawableSizeLeft = dr.mDrawableHeightLeft = 0;
396 | }
397 |
398 | if (right != null) {
399 | right.setState(state);
400 | right.copyBounds(compoundRect);
401 | dr.mDrawableSizeRight = compoundRect.width();
402 | dr.mDrawableHeightRight = compoundRect.height();
403 | } else {
404 | dr.mDrawableSizeRight = dr.mDrawableHeightRight = 0;
405 | }
406 |
407 | if (top != null) {
408 | top.setState(state);
409 | top.copyBounds(compoundRect);
410 | dr.mDrawableSizeTop = compoundRect.height();
411 | dr.mDrawableWidthTop = compoundRect.width();
412 | } else {
413 | dr.mDrawableSizeTop = dr.mDrawableWidthTop = 0;
414 | }
415 |
416 | if (bottom != null) {
417 | bottom.setState(state);
418 | bottom.copyBounds(compoundRect);
419 | dr.mDrawableSizeBottom = compoundRect.height();
420 | dr.mDrawableWidthBottom = compoundRect.width();
421 | } else {
422 | dr.mDrawableSizeBottom = dr.mDrawableWidthBottom = 0;
423 | }
424 | }
425 |
426 | mView.invalidate();
427 | mView.requestLayout();
428 | }
429 |
430 | public void hideErrorIfUnchanged() {
431 | if (mError != null && !mErrorWasChanged) {
432 | setError(null, null);
433 | }
434 | }
435 |
436 | /**
437 | * Resets the mErrorWasChanged flag, so that future calls to {@link #setError(CharSequence)}
438 | * can be recorded.
439 | * @hide
440 | */
441 | public void resetErrorChangedFlag() {
442 | /*
443 | * Keep track of what the error was before doing the input
444 | * so that if an input filter changed the error, we leave
445 | * that error showing. Otherwise, we take down whatever
446 | * error was showing when the user types something.
447 | */
448 | mErrorWasChanged = false;
449 | }
450 |
451 | /*
452 | * INNER CLASSES
453 | */
454 |
455 | /**
456 | * Ripped from android.Widget.TextView.
457 | * Modified to utilise end-developer-App's local resources.
458 | *
459 | */
460 | private static class ErrorPopup extends PopupWindow {
461 | private boolean mAbove = false;
462 | private TextView mView;
463 | private int mPopupInlineErrorBackgroundId = 0;
464 | private int mPopupInlineErrorAboveBackgroundId = 0;
465 |
466 | ErrorPopup(Context mContext, TextView v, int width, int height) {
467 | super(v, width, height);
468 | mView = v;
469 | // Make sure the TextView has a background set as it will be used the first time it is
470 | // shown and positioned. Initialised with below background, which should have
471 | // dimensions identical to the above version for this to work (and is more likely).
472 | //following is a tweak on the ICS take...
473 | TypedArray array = mContext.obtainStyledAttributes(R.styleable.Theme);
474 | mPopupInlineErrorBackgroundId = array.getResourceId(R.styleable.Theme_errorMessageBackground, 0);
475 | mPopupInlineErrorAboveBackgroundId = array.getResourceId(R.styleable.Theme_errorMessageAboveBackground, 0);
476 | //if(DEBUG) Log.d(TAG, "popupInlineErrorBackgroundId: "+mPopupInlineErrorBackgroundId);
477 | //if(DEBUG) Log.d(TAG, "popupInlineErrorAboveBackgroundId: "+mPopupInlineErrorAboveBackgroundId);
478 | mView.setBackgroundResource(mPopupInlineErrorBackgroundId);
479 |
480 | }
481 |
482 | void fixDirection(boolean above) {
483 | mAbove = above;
484 |
485 | if(above) {
486 | mView.setBackgroundResource(mPopupInlineErrorAboveBackgroundId);
487 | } else {
488 | mView.setBackgroundResource(mPopupInlineErrorBackgroundId);
489 | }
490 | }
491 |
492 | @Override
493 | public void update(int x, int y, int w, int h, boolean force) {
494 | super.update(x, y, w, h, force);
495 |
496 | boolean above = isAboveAnchor();
497 | if(above != mAbove) {
498 | fixDirection(above);
499 | }
500 | }
501 | }
502 | }
503 |
--------------------------------------------------------------------------------
/android-formidable-validation/src/com/coreform/open/android/formidablevalidation/SimpleDependencyValidator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2006 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.coreform.open.android.formidablevalidation;
18 |
19 | import java.util.List;
20 | import java.util.regex.Pattern;
21 |
22 | import android.util.Log;
23 | import android.widget.EditText;
24 |
25 | public class SimpleDependencyValidator extends AbstractDependencyValidator {
26 | private static final boolean DEBUG = true;
27 | private static final String TAG = "SimpleDependencyValidator";
28 |
29 | private Object mSource;
30 | private int mSourceResID;
31 | private String mCruxFieldKey; //the key in ValidationManager's ValueValidatorsMap that corresponds with the Dependent Field
32 | private Object mCruxFieldSource;
33 | private int mCruxFieldResID;
34 | private boolean mCruxFieldRequiredToExist;
35 | private boolean mCruxFieldRequiredToBeValid;
36 | private List393 | * For backwards compatibility, we're constructing an event from scratch 394 | * using the appropriate event type. If your application only targets SDK 395 | * 16+, you can just call View.announceForAccessibility(CharSequence). 396 | *
397 | * 398 | * Adapted from https://http://eyes-free.googlecode.com/files/accessibility_codelab_demos_v2_src.zip 399 | * 400 | * @param text The text to announce. 401 | */ 402 | public static void announceForAccessibilityCompat(CharSequence text) { 403 | if (!mAccessibilityManager.isEnabled()) { 404 | return; 405 | } 406 | 407 | // Prior to SDK 16, announcements could only be made through FOCUSED 408 | // events. Jelly Bean (SDK 16) added support for speaking text verbatim 409 | // using the ANNOUNCEMENT event type. 410 | final int eventType; 411 | if (Build.VERSION.SDK_INT < 16) { 412 | eventType = AccessibilityEvent.TYPE_VIEW_FOCUSED; 413 | } else { 414 | eventType = AccessibilityEventCompat.TYPE_ANNOUNCEMENT; 415 | } 416 | 417 | // Construct an accessibility event with the minimum recommended 418 | // attributes. An event without a class name or package may be dropped. 419 | final AccessibilityEvent event = AccessibilityEvent.obtain(eventType); 420 | event.getText().add(text); 421 | event.setClassName(SetErrorHandler.class.getName()); 422 | event.setPackageName(mContext.getPackageName()); 423 | 424 | // Sends the event directly through the accessibility manager. If your 425 | // application only targets SDK 14+, you should just call 426 | // getParent().requestSendAccessibilityEvent(this, event); 427 | mAccessibilityManager.sendAccessibilityEvent(event); 428 | } 429 | 430 | /* 431 | * INNER CLASSES 432 | */ 433 | 434 | private static class AnnounceForAccessibilityRunnable implements Runnable { 435 | private final CharSequence mText; 436 | 437 | public AnnounceForAccessibilityRunnable(CharSequence text) { 438 | mText = text; 439 | } 440 | @Override 441 | public void run() { 442 | announceForAccessibilityCompat(mText); 443 | } 444 | 445 | } 446 | } 447 | -------------------------------------------------------------------------------- /android-formidable-validation/src/com/coreform/open/android/formidablevalidation/ValidationResult.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.coreform.open.android.formidablevalidation; 18 | 19 | /** 20 | * Validation result class 21 | * value holder. 22 | * this class contains true/false (validation status) 23 | * and a message. 24 | * 25 | * based off: http://dekwant.eu/2010/10/04/android-form-field-validation/ 26 | * 27 | * customised and enhanced by: 28 | * @author Linden Darling (contact@coreform.com.au) 29 | * 30 | */ 31 | public class ValidationResult { 32 | private static final boolean DEBUG = true; 33 | private static final String TAG = "ValidationResult"; 34 | 35 | private boolean mValid = false; 36 | private String mMessage = ""; 37 | 38 | public ValidationResult(boolean ok, String message) { 39 | mValid = ok; 40 | mMessage = message; 41 | } 42 | 43 | public boolean isValid() { 44 | return mValid; 45 | } 46 | 47 | public String getMessage() { 48 | return mMessage; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /android-formidable-validation/src/com/coreform/open/android/formidablevalidation/ValueValidationResult.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.coreform.open.android.formidablevalidation; 18 | 19 | /** 20 | * ValueValidationResult class 21 | * value holder. 22 | * this class contains true/false (validation status) 23 | * and a message. 24 | * 25 | * based off: http://dekwant.eu/2010/10/04/android-form-field-validation/ 26 | * 27 | * customised and enhanced by: 28 | * @author Linden Darling (contact@coreform.com.au) 29 | * 30 | */ 31 | public class ValueValidationResult { 32 | private static final boolean DEBUG = true; 33 | private static final String TAG = "ValueValidationResult"; 34 | 35 | private Object mSource; //clunky way of passing the source from Validator through to end-handler to be used for, say, .setError() 36 | private boolean mActive = false; //true indicates this field is activated (checked, populated, etc), usually this is true when mValueValid is true, indicating dependent fields need to also be valid 37 | private boolean mValid = false; //high level validity, 38 | private String mMessage = ""; 39 | 40 | public ValueValidationResult(boolean ok, String message) { 41 | mValid = ok; 42 | mMessage = message; 43 | } 44 | 45 | public ValueValidationResult(Object source, boolean ok, String message) { 46 | mSource = source; 47 | mValid = ok; 48 | mMessage = message; 49 | } 50 | 51 | public ValueValidationResult(Object source, boolean ok) { 52 | mSource = source; 53 | mValid = ok; 54 | } 55 | 56 | public boolean isValid() { 57 | return mValid; 58 | } 59 | 60 | public String getMessage() { 61 | return mMessage; 62 | } 63 | 64 | public Object getSource() { 65 | return mSource; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /android-formidable-validation/src/com/coreform/open/android/formidablevalidation/ValueValidatorInterface.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.coreform.open.android.formidablevalidation; 18 | 19 | /** 20 | * Generic interface for validation of 21 | * Android input fields 22 | * 23 | * based off: http://dekwant.eu/2010/10/04/android-form-field-validation/ 24 | * @author http://nl.linkedin.com/in/marcdekwant 25 | * 26 | */ 27 | public interface ValueValidatorInterface { 28 | 29 | /** 30 | * @return true if enabled 31 | */ 32 | boolean isEnabled(); 33 | 34 | /** 35 | * @return true if required 36 | */ 37 | boolean isRequired(); 38 | 39 | /** 40 | * Message to be displayed when the required 41 | * validation is not met. 42 | * @param message the error message 43 | */ 44 | void setRequiredMessage(String message); 45 | 46 | void setEnabled(boolean enabled); 47 | 48 | void setRequired(boolean required); 49 | 50 | /** 51 | * Set the the source object 52 | * that is under validation. The actual 53 | * implementation of the validator is 54 | * responsible for the correctness of the 55 | * Object. 56 | * 57 | * @return the source object 58 | */ 59 | void setSource(Object source); 60 | 61 | /** 62 | * Resource ID of source object that is under validation. 63 | * @param the source object's Resource ID 64 | */ 65 | void setSourceResID(int sourceResID); 66 | 67 | /** 68 | * This method return the source object 69 | * that is under validation. The actual 70 | * implementation of the validator is 71 | * responsible for the correctness of the 72 | * Object. 73 | * 74 | * @return the source object 75 | */ 76 | Object getSource(); 77 | 78 | /** 79 | * Returns the resource ID of source object that is under validation. 80 | * @return the source object's Resource ID 81 | */ 82 | int getSourceResID(); 83 | 84 | /** 85 | * Returns the expression used to validate the source's value. 86 | * Return some default message if the implementing class does not have a String expression. 87 | * @return the validation expression 88 | */ 89 | String getExpression(); 90 | 91 | /** 92 | * This method is called when an input field is to be validated 93 | * using the validator 94 | * 95 | * @return an validation result object 96 | */ 97 | ValueValidationResult validateValue(); 98 | 99 | /** 100 | * Set a message that will be displayed when 101 | * the validation requirements are NOT met. 102 | * 103 | * @param message the fault message to be displayed 104 | */ 105 | void setFaultMessage(String message); 106 | 107 | } 108 | -------------------------------------------------------------------------------- /android-formidable-validation/src/com/coreform/open/android/formidablevalidation/example/AddressActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.coreform.open.android.formidablevalidation.example; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | import com.coreform.open.android.formidablevalidation.CheckBoxCheckedDependencyValidator; 23 | import com.coreform.open.android.formidablevalidation.CheckBoxRequiredValueValidator; 24 | import com.coreform.open.android.formidablevalidation.R; 25 | import com.coreform.open.android.formidablevalidation.RegExpressionValueValidator; 26 | import com.coreform.open.android.formidablevalidation.SetErrorAbleButton; 27 | import com.coreform.open.android.formidablevalidation.SetErrorAbleCheckBox; 28 | import com.coreform.open.android.formidablevalidation.SetErrorAbleEditText; 29 | import com.coreform.open.android.formidablevalidation.SetErrorAbleSpinner; 30 | import com.coreform.open.android.formidablevalidation.SpinnerRequiredValueValidator; 31 | import com.coreform.open.android.formidablevalidation.ValidationManager; 32 | 33 | import android.app.Activity; 34 | import android.content.Context; 35 | import android.content.Intent; 36 | import android.os.Build; 37 | import android.os.Bundle; 38 | import android.view.View; 39 | import android.view.View.OnClickListener; 40 | import android.view.ViewGroup; 41 | import android.widget.ArrayAdapter; 42 | import android.widget.Button; 43 | import android.widget.CheckBox; 44 | import android.widget.EditText; 45 | import android.widget.LinearLayout; 46 | import android.widget.ScrollView; 47 | import android.widget.TextView; 48 | 49 | public class AddressActivity extends Activity { 50 | private static final boolean DEBUG = true; 51 | private static final String TAG = "AddressActivity"; 52 | 53 | private static final int REQUEST_COLOURPICKER1 = 101; 54 | private static final int REQUEST_COLOURPICKER2 = 102; 55 | 56 | private ValidationManager mValidationManager; 57 | 58 | private ScrollView mContentScrollView; 59 | private CheckBox mUnderstoodCheckBox; 60 | private EditText mAddressLine1EditText; 61 | private EditText mAddressLine2EditText; 62 | private EditText mCityEditText; 63 | private EditText mProvinceEditText; 64 | private SetErrorAbleSpinner mCountrySpinner; 65 | private EditText mPhoneEditText; 66 | private EditText mEmailEditText; 67 | private CheckBox mSignupNewsletterCheckBox; 68 | private Button mFavouriteColourButton; 69 | private SetErrorAbleButton mExampleSetErrorAbleButton; 70 | private Button mClearFormButton; 71 | private Button mValidateFormButton; 72 | private SetErrorAbleEditText mExampleSetErrorAbleEditText; 73 | 74 | @Override 75 | public void onCreate(Bundle savedInstanceState) { 76 | super.onCreate(savedInstanceState); 77 | 78 | if(Build.VERSION.SDK_INT > 10) { 79 | setTheme(R.style.Theme_Holo); 80 | } else { 81 | setTheme(R.style.Theme); 82 | } 83 | 84 | setContentView(R.layout.screen_form_address); 85 | 86 | mContentScrollView = (ScrollView) findViewById(R.id.contentScrollView); 87 | mUnderstoodCheckBox = (SetErrorAbleCheckBox) findViewById(R.id.field00CheckBox); 88 | mAddressLine1EditText = (EditText) findViewById(R.id.field01EditText); 89 | mAddressLine2EditText = (EditText) findViewById(R.id.field02EditText); 90 | mCityEditText = (EditText) findViewById(R.id.field03EditText); 91 | mProvinceEditText = (EditText) findViewById(R.id.field04EditText); 92 | mCountrySpinner = (SetErrorAbleSpinner) findViewById(R.id.field05Spinner); 93 | mPhoneEditText = (EditText) findViewById(R.id.field06EditText); 94 | mEmailEditText = (EditText) findViewById(R.id.field07EditText); 95 | mSignupNewsletterCheckBox = (CheckBox) findViewById(R.id.field08CheckBox); 96 | mFavouriteColourButton = (Button) findViewById(R.id.field09Button); 97 | mExampleSetErrorAbleButton = (SetErrorAbleButton) findViewById(R.id.field09bButton); 98 | mClearFormButton = (Button) findViewById(R.id.clearFormButton); 99 | mValidateFormButton = (Button) findViewById(R.id.validateFormButton); 100 | mExampleSetErrorAbleEditText = (SetErrorAbleEditText) findViewById(R.id.field10EditText); 101 | 102 | mFavouriteColourButton.setOnClickListener(new FavouriteColourButtonOnClickListener(REQUEST_COLOURPICKER1)); 103 | mExampleSetErrorAbleButton.setOnClickListener(new FavouriteColourButtonOnClickListener(REQUEST_COLOURPICKER2)); 104 | mValidateFormButton.setOnClickListener(new ValidateFormButtonOnClickListener()); 105 | 106 | String[] itemTextsArray = getResources().getStringArray(R.array.countries_array); 107 | List