Friday 15 December 2017

HB Blog 150: ScArcGauge View In Android.

ScArcGauge class is a specialized to create an arc gauge.
By default the arc create a closed circle: from 0° to 360°. Note that all angle is usually expressed in degrees and almost methods need to have an delta angle relative to the start angle.
This class extend the ScGauge class.
ScGauge class is studied to be an "helper class" to facilitate the user to create a gauge. The path is generic and must be defined in a inherited class. In this class are exposed many methods to drive the most used properties from the code or directly from the XML. To manage the features will recognized from the class type and its tag so changing, for example, the color of notches you will change the color of all notches tagged. This is useful when you have a custom features configuration that use one more of feature per type. All the custom features added without a defined tag should be managed by the user by himself.
Refer the below link for complete sample code:-

Download Sample Code

Have a look on few code snippets,

//build.gradle
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "com.harshalbenake.gaugeview"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.github.paroca72:sc-gauges:2.5.3'
}

//activity_main.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="162dp"
        android:background="#354051">

        <com.sccomponents.gauges.ScArcGauge
            android:id="@+id/gauge"
            xmlns:sc="http://schemas.android.com/apk/res-auto"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:padding="30dp"
            sc:scc_angle_start="-180"
            sc:scc_angle_sweep="180"
            sc:scc_progress_color="#1eff00"
            sc:scc_progress_size="15dp"
            sc:scc_stroke_color="#ffffff"
            sc:scc_stroke_size="30dp"
            sc:scc_notches="3"
            sc:scc_notches_length="32dp"
            sc:scc_notches_size="6dp"
            sc:scc_notches_color="#354051"
            sc:scc_text_tokens="1000|2000|3000"
            sc:scc_stroke_colors="#EC4949|#00B4FF|#F7AD36"
            sc:scc_stroke_colors_mode="solid"
            sc:scc_text_align="center"
            sc:scc_text_position="middle"
            sc:scc_text_color="#354051"/>

        <ImageView
            android:id="@+id/indicator"
            android:layout_width="64dp"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|center_horizontal"
            android:src="@drawable/indicator"
            android:layout_marginLeft="18dp"
            android:layout_marginBottom="29dp"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="0000"
            android:layout_marginBottom="2dp"
            android:id="@+id/counter"
            android:layout_gravity="bottom|center_horizontal"
            android:textColor="#ffffff"
            android:textSize="20dp"/>

    </FrameLayout>

</LinearLayout>

//MainActivity.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package com.harshalbenake.gaugeview;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.TextView;
import com.sccomponents.gauges.ScArcGauge;
import com.sccomponents.gauges.ScGauge;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Find the components
        final ScArcGauge gauge = (ScArcGauge) this.findViewById(R.id.gauge);
        assert gauge != null;

        final ImageView indicator = (ImageView) this.findViewById(R.id.indicator);
        assert indicator != null;

        final TextView counter = (TextView) this.findViewById(R.id.counter);
        assert counter != null;

        // Set the center pivot for a right rotation
        indicator.setPivotX(30f);
        indicator.setPivotY(30f);

        // As the progress feature by default the last to be draw I must bring the notches feature
        // on top.
        gauge.bringOnTop(ScGauge.NOTCHES_IDENTIFIER);

        // If you set the value from the xml that not produce an event so I will change the
        // value from code.
        gauge.setHighValue(60);

        // Each time I will change the value I must write it inside the counter text.
        gauge.setOnEventListener(new ScGauge.OnEventListener() {
            @Override
            public void onValueChange(float lowValue, float highValue) {
                // Convert the percentage value in an angle
                float angle = gauge.percentageToAngle(highValue);
                indicator.setRotation(angle);

                // Write the value
                int value = (int) ScGauge.percentageToValue(highValue, 0.0f, 3000.0f);
                counter.setText(value + "");
            }
        });
    }
}

Friday 1 December 2017

HB Blog 149: Cross Platform Development.

In computing, cross-platform software (also multi-platform software or platform-independent software) is computer software that is implemented on multiple computing platforms. Cross-platform software may be divided into two types; one requires individual building or compilation for each platform that it supports, and the other one can be directly run on any platform without special preparation. Cross-platform programming is the practice of actively writing software that will work on more than one platform.
There are a number of tools which are available to help facilitate the process of cross-platform programming:
  1.     8th: A cross-platform development language, which utilizes Juce as its GUI layer. The platforms it currently supports are: Android, iOS, Windows, macOS, Linux and Raspberry Pi.
  2.     Anant Computing: A mobile application platform that works in all Indian languages, including their keyboards, which is also supports AppWallet and Native performance inside all operating systems.
  3.     Appcelerator: It helps in building native apps by deploying just a single JavaScript code base. It provides your web content in a native application, ensuring your code is not wrapped around a web container unlike few other such solutions.
  4.     AppearIQ: A framework that supports the workflow of app development and deployment in an enterprise environment. Natively developed containers present hardware features of the mobile devices or tablets through an API to HTML5 code thus facilitating the development of mobile apps that run on different platforms.
  5.     Cairo: A free software library used to provide a vector graphics-based, device-independent API. It is designed to provide primitives for 2-dimensional drawing across a number of different backends. Cairo is written in C and has bindings for many programming languages.
  6.     Cocos2d: An open source toolkit and game engine for developing 2D and simple 3D cross-platform games and applications.
  7.     Delphi: A cross platform IDE, which uses Pascal language for Development. Currently it supports Android, iOS, Windows, macOS.
  8.     Ecere SDK: A cross platform GUI & 2D/3D graphics toolkit and IDE, written in eC and with support for additional languages such as C and Python. Currently it supports Linux, FreeBSD, Windows, Android, macOS and the Web through Emscripten or Binaryen (WebAssembly)
  9.     Eclipse: An open source cross-platform development environment. Implemented in Java with a configurable architecture which supports many tools for software development. Add-ons are available for several languages, including Java and C++.
  10.     FLTK: Another open source cross platform toolkit, but more lightweight because it restricts itself to the GUI.
  11.     fpGUI: An open source widget toolkit that is completely implemented in Object Pascal. It currently supports Linux, Windows and a bit of Windows CE.
  12.     GeneXus: A Windows rapid software development solution for cross-platform application creation and deployment based on knowledge representation and supporting C#, COBOL, Java including Android and BlackBerry smart devices, Objective-C for Apple mobile devices, RPG, Ruby, Visual Basic, and Visual FoxPro.
  13.     GLBasic: A BASIC dialoect and compiler that generates C++ code. It includes cross compilers for many platforms and supports numerous platform (Windows, Mac, Linux, Android,iOS and some exotic handhelds).
  14.     GTK+: An open source widget toolkit for Unix-like systems with X11 and Microsoft Windows.
  15.     Haxe: An open source cross-platform language.
  16.     Juce: An application framework written in C++, used to write native software on numerous systems (Microsoft Windows, POSIX, macOS), with no change to the code.
  17.     Lazarus: A programming environment for the FreePascal Compiler. It supports the creation of self-standing graphical and console applications and runs on Linux, MacOSX, iOS, Android, WinCE, Windows and WEB.
  18.     Max/MSP: A visual programming language that encapsulates platform-independent code with a platform-specific runtime environment into applications for macOS and Windows.
  19.     MechDome: A cross-platform Android runtime. It allows unmodified Android apps to run natively on iOS and macOS
  20.     MonoCross: An open-source model-view-controller design pattern where the model and controller are shared cross-platform but the view is platform-specific.
  21.     Mono: An open-source cross-platform version of Microsoft .NET (a framework for applications and programming languages)
  22.     MoSync: An open-source SDK for mobile platform app development in the C++ family
  23.     Mozilla application framework: An open source platform for building macOS, Windows and Linux applications
  24.     OpenGL: A cross-platform 3D graphics library.
  25.     PhoneGap: It enables software programmers to build applications for mobile devices using CSS3, HTML5, and JavaScript instead of relying on platform-specific APIs like those in Android, iOS, or Windows Phone.
  26.     PureBasic: A proprietary cross-platform language and IDE for building macOS, Windows and Linux applications
  27.     Qt: An application framework and widget toolkit for Unix-like systems with X11, Microsoft Windows, macOS, and other systems—available under both open source and proprietary licenses.
  28.     Simple and Fast Multimedia Library: A multimedia C++ API that provides low and high level access to graphics, input, audio, etc.
  29.     Simple DirectMedia Layer: An open-source cross-platform multimedia library written in C that creates an abstraction over various platforms’ graphics, sound, and input APIs. It runs on many operating systems including Linux, Windows and macOS and is aimed at games and multimedia applications.
  30.     Smartface: A cross platform native app development tool to create mobile applications for Android and iOS, using WYSIWYG design editor with JavaScript code editor.
  31.     Tcl/Tk
  32.     Ultimate++: A C++ cross-platform rapid application development framework focused on programmers productivity. It includes a set of libraries (GUI, SQL, etc..), and an integrated development environment. It supports Windows and Unix-like OS-s. The U++ competes with popular scripting languages while preserving C/C++ runtime characteristics. It has its own integrated development environment, TheIDE, which features BLITZ-build technology to speedup C++ rebuilds up to 4 times.
  33.     Unity: Another cross-platform SDK which uses Unity Engine.
  34.     Unreal: A cross-platform SDK which uses Unreal Engine.
  35.     V-Play Engine: V-Play is a cross-platform development SDK based on the popular Qt framework. V-Play apps and games are created within Qt Creator.
  36.     WaveMaker: A Cross-platform low-code development tool to create responsive web and hybrid mobile (Android & iOS) applications.
  37.     WinDev: Integrated Development Environment for Windows, Linux, .Net and Java (also with support for Internet and Intranet)
  38.     wxWidgets: An open source widget toolkit that is also an application framework.[14] It runs on Unix-like systems with X11, Microsoft Windows and macOS. It permits applications written to use it to run on all of the systems that it supports, if the application does not use any operating system-specific programming in addition to it.
  39.     Xamrin: With a C#-shared codebase, developers can use Xamarin tools to write native Android, iOS, and Windows apps with native user interfaces and share code across multiple platforms, including Windows and macOS. 
  40.     Xojo: A RAD IDE developed by Xojo, Inc. that uses an object-oriented programming language to create desktop, web and iOS apps. Xojo makes native, compiled desktop apps for macOS, Windows, Linux and Raspberry Pi. It creates compiled web apps that can be run as standalone servers or through CGI. And it recently added the ability to create native iOS apps.

Wednesday 15 November 2017

HB Blog 148: Custom Floating Keyboard.

My  previous post regarding HB Blog 147: Explore 50+ Keyboard Applications On Google Play tells that there’s a whole world of keyboards out there, and your default Google/Samsung/HTC keyboard is nowhere near the most useful, most productive, or the prettiest. The keyboard you choose will depend on what you’re using it for: Are you looking for a keyboard with more keys and options?
Refer the below link for complete sample code:-

Download Sample Code

Have a look on few code snippets,
//activity_main.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
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin">

    <EditText
        android:id="@+id/edittext1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="Type here"
        android:inputType="numberDecimal"
        android:selectAllOnFocus="true"
        android:textIsSelectable="true" />

    <com.harshalbenake.floatingkeyboard.views.FloatingKeyboardView
        android:id="@+id/keyboardview"
        android:layout_width="180dp"
        android:layout_height="210dp"
        android:background="@android:color/transparent"
        android:elevation="1dp"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:keyBackground="@drawable/keyback"
        android:keyTextColor="#384850"
        android:shadowRadius="0.0"
        android:visibility="gone" />
</RelativeLayout>

//FloatingKeyboardView.java
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
package com.harshalbenake.floatingkeyboard.views;

import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.CornerPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.KeyboardView;
import android.text.Editable;
import android.text.InputType;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.RelativeLayout;

/**
 * A Floating and Draggable KeyboardView. Several EditText's can register for it.
 */
public class FloatingKeyboardView extends KeyboardView {
    private static final int MOVE_THRESHOLD = 0;
    private static final int TOP_PADDING_DP = 28;
    private static final int HANDLE_COLOR = Color.parseColor("#AAD1D6D9");
    private static final int HANDLE_PRESSED_COLOR = Color.parseColor("#D1D6D9");
    private static final float HANDLE_ROUND_RADIOUS = 20.0f;
    private static final CornerPathEffect HANDLE_CORNER_EFFECT = new CornerPathEffect(HANDLE_ROUND_RADIOUS);
    private static int topPaddingPx;
    private static int width;
    private static Path mHandlePath;
    private static Paint mHandlePaint;
    private static boolean allignBottomCenter =false;

    /**
     * Create a custom keyboardview
     * Note that a keyboard with layout from xml file must be set (see {@link Keyboard} for description.
     * Note that the keyboard layout xml file may include key codes for navigation; see the constants in this class for their values.
     * Note that to enable EditText's to use this custom keyboard, call the {@link #registerEditText(int)}.
     */
    public FloatingKeyboardView(Context context, AttributeSet attrs) {
        super(context, attrs);
        topPaddingPx = (int) convertDpToPixel((float) TOP_PADDING_DP, context);
        this.setOnKeyboardActionListener(mOnKeyboardActionListener);
        // Hide the standard keyboard initially
        ((Activity) getContext()).getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
        this.setOnTouchListener(mKeyboardOntTouchListener);
        this.setPadding(0, (int) convertDpToPixel(TOP_PADDING_DP, context), 0, 0);

        mHandlePaint=new Paint();
        mHandlePaint.setColor(HANDLE_COLOR);
        mHandlePaint.setStyle(Paint.Style.FILL);
        mHandlePaint.setPathEffect(HANDLE_CORNER_EFFECT);

        mHandlePath=new Path();

    }

    public static boolean isAllignBottomCenter() {
        return allignBottomCenter;
    }

    public static void setAllignBottomCenter(boolean allignBottomCenter) {
        FloatingKeyboardView.allignBottomCenter = allignBottomCenter;
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        if (isAllignBottomCenter()) {
            RelativeLayout.LayoutParams relativeLayoutParams = (RelativeLayout.LayoutParams) getLayoutParams();
            relativeLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
            relativeLayoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
            setLayoutParams(relativeLayoutParams);
        }
    }

    @Override
    public void onSizeChanged(int xNew, int yNew, int xOld, int yOld) {
        super.onSizeChanged(xNew, yNew, xOld, yOld);
        width = xNew;
        drawHandle();
    }

    private void drawHandle() {
        mHandlePath.rewind();
        mHandlePath.moveTo(0, topPaddingPx);
        mHandlePath.lineTo(0, topPaddingPx - 25);
        mHandlePath.lineTo(width / 3, topPaddingPx - 25);
        mHandlePath.lineTo(width / 3, 0);
        mHandlePath.lineTo(2 * width / 3, 0);
        mHandlePath.lineTo(2 * width / 3, topPaddingPx - 25);
        mHandlePath.lineTo(width, topPaddingPx - 25);
        mHandlePath.lineTo(width, topPaddingPx);
        // Draw this line twice to fix strange artifact in API21
        mHandlePath.lineTo(width, topPaddingPx);
    }


    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint paint = mHandlePaint;
        Path path = mHandlePath;
        canvas.drawPath(path, paint);

    }

    /**
     * Returns whether the FloatingKeyboardView is visible.
     */
    public boolean isVisible() {
        return this.getVisibility() == View.VISIBLE;
    }

    /**
     * Make the FloatingKeyboardView visible, and hide the system keyboard for view v.
     */
    public void show(View v) {

        this.setVisibility(View.VISIBLE);
        this.setEnabled(true);
        // TODO: Correct Position Keyboard
//        ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) getLayoutParams();
//        params.topMargin = v.getTop() + v.getHeight();
//        params.leftMargin = v.getLeft();
//        setLayoutParams(params);

        if (v != null)
            ((InputMethodManager) getContext().getSystemService(Activity.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(v.getWindowToken(), 0);

    }

    /**
     * Make the FloatingKeyboardView invisible.
     */
    public void hide() {
        this.setVisibility(View.GONE);
        this.setEnabled(false);
    }

    /**
     * Register <var>EditText<var> with resource id <var>resid</var> (on the hosting activity) for using this custom keyboard.
     *
     * @param resid The resource id of the EditText that registers to the custom keyboard.
     */
    public void registerEditText(int resid) {
        // Find the EditText 'resid'
        EditText edittext = (EditText) ((Activity) getContext()).findViewById(resid);
        // Make the custom keyboard appear
        edittext.setOnFocusChangeListener(new OnFocusChangeListener() {
            // NOTE By setting the on focus listener, we can show the custom keyboard when the edit box gets focus, but also hide it when the edit box loses focus
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if (hasFocus) show(v);
                else hide();
            }
        });

        edittext.setOnClickListener(new OnClickListener() {
            // NOTE By setting the on click listener, we can show the custom keyboard again, by tapping on an edit box that already had focus (but that had the keyboard hidden).
            @Override
            public void onClick(View v) {
                show(v);
            }
        });
        // Disable standard keyboard hard way
        // NOTE There is also an easy way: 'edittext.setInputType(InputType.TYPE_NULL)' (but you will not have a cursor, and no 'edittext.setCursorVisible(true)' doesn't work )
        edittext.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                EditText edittext = (EditText) v;
                int inType = edittext.getInputType();       // Backup the input type
                edittext.setInputType(InputType.TYPE_NULL); // Disable standard keyboard
                edittext.onTouchEvent(event);               // Call native handler
                edittext.setInputType(inType);              // Restore input type
                return true; // Consume touch event
            }
        });

    }

    /**
     * TouchListener to handle the drag of keyboard
     */
    private OnTouchListener mKeyboardOntTouchListener = new OnTouchListener() {
        float dx;
        float dy;
        int moveToY;
        int moveToX;
        int distY;
        int distX;
        Rect inScreenCoordinates;
        boolean handleTouched = false;



        @Override
        public boolean onTouch(View view, MotionEvent event) {
            // Use ViewGroup.MarginLayoutParams so as to work inside any layout
            ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
            boolean performClick = false;

            switch (event.getAction()) {
                case MotionEvent.ACTION_MOVE:
                    if (handleTouched) {
                        moveToY = (int) (event.getRawY() - dy);
                        moveToX = (int) (event.getRawX() - dx);
                        distY = moveToY - params.topMargin;
                        distX = moveToX - params.leftMargin;

                        if (Math.abs(distY) > MOVE_THRESHOLD ||
                                Math.abs(distX) > MOVE_THRESHOLD) {
                            // Ignore any distance before threshold reached
                            moveToY = moveToY - Integer.signum(distY) * Math.min(MOVE_THRESHOLD, Math.abs(distY));
                            moveToX = moveToX - Integer.signum(distX) * Math.min(MOVE_THRESHOLD, Math.abs(distX));

                            inScreenCoordinates = keepInScreen(moveToY, moveToX);
                            view.setY(inScreenCoordinates.top);
                            view.setX(inScreenCoordinates.left);
                        }
                        performClick = false;
                    } else {
                        performClick = true;
                    }
                    break;

                case MotionEvent.ACTION_UP:
                    if (handleTouched) {
                        // reset handle color
                        mHandlePaint.setColor(HANDLE_COLOR);
                        mHandlePaint.setStyle(Paint.Style.FILL);
                        invalidate();

                        performClick = false;
                    } else {
                        performClick = true;
                    }

                    break;

                case MotionEvent.ACTION_DOWN:
                    handleTouched = event.getY() <= getPaddingTop(); // Allow move only wher touch on top padding
                    dy = event.getRawY() - view.getY();
                    dx = event.getRawX() - view.getX();

                    //change handle color on tap
                    if (handleTouched) {
                        mHandlePaint.setColor(HANDLE_PRESSED_COLOR);
                        mHandlePaint.setStyle(Paint.Style.FILL);
                        invalidate();
                        performClick = false;
                    } else {
                        performClick = true;
                    }
                    break;
            }
            return !performClick;
        }


    };

    private void moveTo(int y, int x) {
        ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) getLayoutParams();;
//        Rect inScreenCoordinates = keepInScreen(y, x);
        params.topMargin = y;
        params.leftMargin = x;
        setLayoutParams(params);
    }

    /**
     * Position keyboard to specific point. Caution do not move it outside screen.
     * @param x
     * @param y
     */
    public void positionTo(int x, int y) {
        moveTo (y,x);
    }
    /**
     * @param topMargin of desired position
     * @param leftMargin of desired position
     * @return a Rect with corrected positions so the whole view to stay in screen
     */
    private Rect keepInScreen(int topMargin, int leftMargin) {
        int top = topMargin;
        int left = leftMargin;
        measure(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
        int height = getMeasuredHeight();
        int width = getMeasuredWidth();
        //TODO: Try to explain this !!!
        int rightCorrection = ((View) getParent()).getPaddingRight() ;
        int botomCorrection =((View) getParent()).getPaddingBottom() ;
        int leftCorrection = ((View) getParent()).getPaddingLeft();
        int topCorrection =((View) getParent()).getPaddingTop();

        Rect rootBounds = new Rect();
        ((View) getParent()).getHitRect(rootBounds);
        rootBounds.set(rootBounds.left+leftCorrection,rootBounds.top+topCorrection,rootBounds.right-rightCorrection,rootBounds.bottom-botomCorrection);

        if (top <= rootBounds.top)
            top = rootBounds.top;
        else if (top + height > rootBounds.bottom)
            top = rootBounds.bottom - height;

        if (left <= rootBounds.left)
            left = rootBounds.left;
        else if (left + width > rootBounds.right)
            left = rootBounds.right - width;

//            Log.e("x0:"+rootBounds.left+" y0:"+rootBounds.top+" Sx:"+rootBounds.right+" Sy:"+rootBounds.bottom, "INPUT:left:"+leftMargin+" top:"+topMargin+
//                    " OUTPUT:left:"+left+" top:"+top+" right:"+(left + getWidth())+" bottom:"+(top + getHeight()));
        return new Rect(left, top, left + width, top + height);
//        return new Rect(leftMargin, topMargin, leftMargin + width, topMargin + height);
    }

    /**
     * This method converts dp unit to equivalent pixels, depending on device density.
     *
     * @param dp      A value in dp (density independent pixels) unit. Which we need to convert into pixels
     * @param context Context to get resources and device specific display metrics
     * @return A float value to represent px equivalent to dp depending on device density
     */
    private static float convertDpToPixel(float dp, Context context) {
        Resources resources = context.getResources();
        DisplayMetrics metrics = resources.getDisplayMetrics();
        float px = dp * ((float) metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT);
        return px;
    }

    /**
     * The key (code) handler.
     */
    private OnKeyboardActionListener mOnKeyboardActionListener = new OnKeyboardActionListener() {
        public final static int CodeGrab = -10; //
        public final static int CodeDelete = -5; // Keyboard.KEYCODE_DELETE
        public final static int CodeCancel = -3; // Keyboard.KEYCODE_CANCEL
        public final static int CodePrev = 55000;
        public final static int CodeAllLeft = 55001;
        public final static int CodeLeft = 55002;
        public final static int CodeRight = 55003;
        public final static int CodeAllRight = 55004;
        public final static int CodeNext = 55005;
        public final static int CodeClear = 55006;

        public final static int CodeCellUp = 1001;
        public final static int CodeCellDown = 1002;
        public final static int CodeCellLeft = 1003;
        public final static int CodeCellRight = 1004;
        public final static int CodeDecimalpoint = 46;
        public final static int CodeZero = 48;

        @Override
        public void onKey(int primaryCode, int[] keyCodes) {
            // NOTE We can say '<Key android:codes="49,50" ... >' in the xml file; all codes come in keyCodes, the first in this list in primaryCode
            // Get the EditText or extension of EditText and its Editable
            View focusCurrent = ((Activity) getContext()).getWindow().getCurrentFocus();
            if (focusCurrent == null || (focusCurrent.getClass() != EditText.class
                    && focusCurrent.getClass().getSuperclass()!= EditText.class) ) return;
            EditText edittext = (EditText) focusCurrent;
            Editable editable = edittext.getText();
            int start = edittext.getSelectionStart();
            int end = edittext.getSelectionEnd();
            // Apply the key to the edittext
            if (primaryCode == CodeCancel) {
                hide();
            } else if (primaryCode == CodeDelete) {
                if (editable != null && start > 0) {
                    editable.delete(start - 1, start);
                } else if (editable != null && start != end) { // delete selection
                    editable.delete(start, end);
                }
            } else if (primaryCode == CodeClear) {
                if (editable != null) editable.clear();
            } else if (primaryCode == CodeLeft) {
                if (start > 0) edittext.setSelection(start - 1);
            } else if (primaryCode == CodeRight) {
                if (start < edittext.length()) edittext.setSelection(start + 1);
            } else if (primaryCode == CodeAllLeft) {
                edittext.setSelection(0);
            } else if (primaryCode == CodeAllRight) {
                edittext.setSelection(edittext.length());
            } else if (primaryCode == CodePrev) {
                View focusNew = edittext.focusSearch(View.FOCUS_BACKWARD);
                if (focusNew != null) focusNew.requestFocus();
            } else if (primaryCode == CodeNext) {
                View focusNew = edittext.focusSearch(View.FOCUS_FORWARD);
                if (focusNew != null) focusNew.requestFocus();
                else if (primaryCode == CodeCellUp || primaryCode == CodeCellDown || primaryCode == CodeCellLeft || primaryCode == CodeCellRight) {
                    // TODO
                } else if (primaryCode == CodeGrab) {

                }
            } else { // insert character
                ///////////////////////////////////////////////////////////////////////
                ////////////////////////////////////////////////////////////////////
                /////////////////////////////
                if (start != end) {
                    editable.delete(start, end);
                }
                editable.insert(start, Character.toString((char) primaryCode));
            }
        }

        @Override
        public void onPress(int arg0) {
        }

        @Override
        public void onRelease(int primaryCode) {
        }

        @Override
        public void onText(CharSequence text) {
        }

        @Override
        public void swipeDown() {
        }

        @Override
        public void swipeLeft() {
        }

        @Override
        public void swipeRight() {
        }

        @Override
        public void swipeUp() {
        }
    };
}

//MainActivity.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.harshalbenake.floatingkeyboard;

import android.app.Activity;
import android.inputmethodservice.Keyboard;
import android.os.Bundle;

import com.harshalbenake.floatingkeyboard.views.FloatingKeyboardView;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        FloatingKeyboardView mCustomKeyboard = (FloatingKeyboardView) findViewById(R.id.keyboardview);
        mCustomKeyboard.setKeyboard(new Keyboard(this, R.xml.numkbd));
        mCustomKeyboard.setPreviewEnabled(false); // NOTE Do not show the preview balloons
        mCustomKeyboard.registerEditText(R.id.edittext1);
        mCustomKeyboard.setAllignBottomCenter(true);

    }
}