Skip to content

Latest commit

 

History

History
613 lines (460 loc) · 20.8 KB

Customized Keyboard Features.md

File metadata and controls

613 lines (460 loc) · 20.8 KB

Catalogue


1. Add built-in Dictionary

1.Add the built-in dictionary and configuration files under the assets directory. Please contact zengine@nlptech.com for dictionary and configuration files.
2.Add the following code into build.gradle file:

build.gradle

aaptOptions{
    noCompress 'xz'
}

2. Theme Setting

Add themes by calling Agent.getInstance().addExternalThemes(context, infos).
Delete themes by calling Agent.getInstance().deleteExternalThemes(context, infos). Get new themes by calling Agent.getInstance().getExternalThemes(context). Apply themes by calling Agent.getInstance().loadTheme(context,externalId).

For example, add a theme like this:
ExampleApplication.java:

public class ExampleApplication extends Application {
        @Override
        public void onCreate() {
                super.onCreate();
                … … … … …
                addExternalTheme();
                Agent.getInstance().loadTheme(this,"my external theme id");
                … … … … …
        }  

    private void addExternalTheme() {
        Drawable keyboardBackgroundDrawable = ContextCompat.getDrawable(this, R.drawable.test_theme_keyboard_bg);

        StateListDrawable keyBackgroundDrawable = new StateListDrawable();
        keyBackgroundDrawable.addState(new int[]{android.R.attr.state_pressed}, ContextCompat.getDrawable(this, R.drawable.test_theme_key_press));
        keyBackgroundDrawable.addState(new int[]{}, ContextCompat.getDrawable(this, R.drawable.test_theme_key_normal));

        StateListDrawable functionKeyBackgroundDrawable = new StateListDrawable();
        functionKeyBackgroundDrawable.addState(new int[]{android.R.attr.state_pressed}, ContextCompat.getDrawable(this, R.drawable.test_theme_function_key_press));
        functionKeyBackgroundDrawable.addState(new int[]{}, ContextCompat.getDrawable(this, R.drawable.test_theme_function_key_normal));

        StateListDrawable spacebarBackgroundDrawable = new StateListDrawable();
        spacebarBackgroundDrawable.addState(new int[]{android.R.attr.state_pressed}, ContextCompat.getDrawable(this, R.drawable.test_theme_space_key_press));
        spacebarBackgroundDrawable.addState(new int[]{}, ContextCompat.getDrawable(this, R.drawable.test_theme_space_key_normal));

        ExternalThemeInfo externalThemeInfo = new ExternalThemeInfo.Builder("my external theme id", "Test Theme")
                .setKeyboardBackground(keyboardBackgroundDrawable)
                .setKeyBackground(keyBackgroundDrawable)
                .setFunctionKeyBackground(functionKeyBackgroundDrawable)
                .setSpacebarBackground(spacebarBackgroundDrawable)
                .setKeyLetterSizeRatio(0.4f)
                .setKeyTextColor(Color.RED)
                .setKeyHintLetterColor(Color.BLUE)
                .setFunctionKeyTextColor(Color.YELLOW)
                .setGestureTrailColor(Color.BLACK)
                .build();
        Agent.getInstance().addExternalThemes(this, externalThemeInfo);
    }
… … … … …

3. Custom EmojiView

If you wants to implement your own EmojiView rather than using the default EmojiView provided by SDK, you may implement custom EmojiView in onDisplayEmojiKeyboard() and return True at the same time.

4. Custom NeutralStrip and SuggestionStripView

NeutralStrip, SuggestionStripView, ChineseSuggestStripView and ChineseComposingTextView could be customized after LatinIME extends ZengineInputMethodService.

NeutralStrip

NeutralStrip,such as toolbar, will appear when SuggestStripView is gone.

For example:

input_view.xml:

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    style="?attr/inputViewStyle">

    <FrameLayout
        android:id="@+id/kb_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"/>

    // Add a custom Neutral Strip
    <RelativeLayout
        android:id="@+id/customized_strip"
        android:layout_width="match_parent"
        android:layout_height="@dimen/config_suggestions_strip_height"
        android:layout_alignTop="@id/kb_container"
        android:layoutDirection="ltr"
        android:background="@android:color/black">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:textStyle="bold"
            android:text="Customized Strip"
            android:textColor="@android:color/white"/>

    </RelativeLayout>

</RelativeLayout>

LatinIME.java:

    // Control customized NeutralStip by overriding onHideCustomizedNeutralStripView() / onShowCustomizedNeutralStripView()
    @Override
    public void onHideCustomizedNeutralStripView() {
        // Hide custom NeutralStrip
        mCustomizedStrip.setVisibility(View.GONE);
    }

    @Override
    public void onShowCustomizedNeutralStripView() {
        // Show custom NeutralStrip
        mCustomizedStrip.setVisibility(View.VISIBLE);
    }

SuggestionStripView

Zengine provides default SuggestionStripView and its operations.

And also you could customize SuggestStripView by extending com.nlptech.keyboardview.suggestions.SuggestionStripView.
Please implement functions down below if you would like to customize.

setSuggestionStripViewListener() :

This method will ba called by ZengineInputMethodService.class. You need to update the SuggestionStripViewListener and make sure the method pickSuggestionManually() will be called when a word is chosen from the SuggestionStripView.

setSuggestions() :

Update and display suggestion words.

Example :

CustomizedSuggestStripView.java:

public class CustomizedSuggestStripView extends SuggestionStripView {
    … … … …
    @Override
    public void setSuggestionStripViewListener(final SuggestionStripViewListener listener, final View inputView) {
        //TODO something
        mSuggestionStripViewListener = listener 
        // Call this in a proper position
        // mSuggestionStripViewListener.pickSuggestionManually(index);
    }
    … … … …
    @Override
    public void setSuggestions(final SuggestedWords suggestedWords, final boolean isRtlLanguage) {
        //TODO something
    }
    … … … …
}

LatinIME.java:

    //Pass customized SuggestionStripView by overriding getSuggestionView() of LatinIME.java
    @Override
    public SuggestionStripView getSuggestionView() {
        // Return the custom keyboard suggestions bar the developer defined
        return new CustomizedSuggestStripView(getContext());
    }

ZengineInputMethodService provides showSuggestionView() / hideSuggestionView() methods to help the developer to control the display/hide SuggestStripView.

ChineseSuggestStripView

When using Chinese Input Method, Zengine also provides default ChineseSuggestStripView and its operations.

If you would like to customize ChineseSuggestStripView, you need to extend com.nlptech.keyboardview.keyboard.chinese.ChineseSuggestStripView and implement functions down below.

setChineseSuggestStripViewListener() :

This method will ba called by ZengineInputMethodService.class. You need to update the SuggestionStripViewListener and make sure the method pickSuggestionManually() will be called when a word is chosen from the SuggestionStripView. Due to the data structure designed of the Chinese characters, the parameter of this method is "�the index of your chosen word".

setChineseSuggestion() :

Pass candidate words (if there are enough suggestion words, it will provide 10 words at first by default)

getMoreSuggestionsList() :

If there're enough suggested words, you can get more suggested words by passing fetch size.

getSuggestionsList() :

Return a list of suggestion words that have been retrieved for the current input.

Example :

CustomizedChineseSuggestStripView:

public class CustomizedChineseSuggestStripView extends ChineseSuggestStripView implements View.OnClickListener {

	 … … … …
	 @Override
    public void setChineseSuggestStripViewListener(ChineseSuggestStripViewListener chineseSuggestStripViewListener) {
        mChineseSuggestStripViewListener = chineseSuggestStripViewListener;
        // Call this in a proper position
        // mChineseSuggestStripViewListener.pickSuggestionManually(index);
    }

    @Override
    public void setChineseSuggestion(List<String> list, boolean enableActiveHighlight) {
        // only get more 50 items
        getMoreSuggestionsList(50);

        // implement related behaviors
    }
    … … … …
}

LatinIME.java:

    // Pass customized ChineseSuggestStripView by overriding getChineseSuggestionView() of LatinIME.java
    @Override
    public ChineseSuggestStripView getChineseSuggestionView() {
        // Return the View of of the custom keyboard suggestion bar
        return new CustomizedChineseSuggestionView(getContext());
    }

ChineseComposingTextView

When using Chinese Input Method, there's a default ChineseSuggestStripView at the upper left corner of the KeyboardView.

If you would like to customize ChineseComposingTextView, you need to extend com.nlptech.keyboardview.keyboard.chinese. ChineseComposingTextView and implement function down below.

setComposingText() :

Update the corresponding content under the current composing state

Example :

CustomizedChineseComposingTextView.java:

public class CustomizedChineseComposingTextView extends ChineseComposingTextView {
	 … … … …
	 @Override
    public void setComposingText(String s) {
    	  // implement related behaviors
        mComposingTextView.setText(s);
    }
    … … … …
}

LatinIME.java:

    // Pass customized ChineseSuggestStripView by overriding getChineseSuggestionView() of LatinIME.java
    @Override
    public ChineseComposingTextView getChineseComposingTextView()  {
        // Return View of suggestion bar customized by the developer
        return new Customized ChineseComposingTextView(getContext());
    }

5. Input Event Callback

LatinIME.java:

… … … … …
public void onCreate() {
    DebugFlags.init(PreferenceManager.getDefaultSharedPreferences(this));
    RichInputMethodManager.init(this);
    mRichImm = RichInputMethodManager.getInstance();
    Agent.getInstance().onCreate(this, mInputLogic, new LanguageCallback() {
        @Override
        public void onIMELanguageChanged(InputMethodSubtype subtype) {
            onCurrentInputMethodSubtypeChanged(subtype);
        }
    });
   
    //Callback for input events (Optional)
    Agent.getInstance().setUserInputCallback(
        new IUserInputCallback() {
            @Override
            public void onUserTyping(String wordComposing) { }
            @Override
            public void onUserTyped(String text) { }
            @Override
            public void onTextChanged(int direction) { }
        });
    }

6. Custom ThemePreview

You can get all the Id of Theme through:

Agent.getInstance().getThemeIds(context);

To create ThemeContext, build a view container and use Agent to put theme preview in.

Context themeContext = Agent.getInstance().getThemeContext(context, themeId);

Example:

View myView = LayoutInflater.from(themeContext).inflate(R.layout.my_view, null);
ViewGroup myContainer = myView.findViewById(R.id.my_view_preview_container);
Agent.getInstance().showThemePreview(myContainer, themeId)

Last, you can call it in the component's onPause or onDestroy:

Agent.getInstance().dismissThemePreview();

[zengine v1.3]

7. Floating Keyboard

First, you need add FloatingKeyboard layout in your input_view.xml, for example:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    style="?attr/inputViewStyle"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- This is the FloatingKeyboard layout, wrapping up your keyboard layout content. -->
    <com.nlptech.keyboardview.floatingkeyboard.FloatingKeyboard
        android:id="@+id/floating_kb"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <FrameLayout
            android:id="@+id/kb_container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true" />

        <LinearLayout
            android:id="@+id/toolbar_items_container"
            android:layout_width="match_parent"
            android:layout_height="@dimen/config_suggestions_strip_height"
            android:layout_alignTop="@id/kb_container"
            android:background="@android:color/black"
            android:layoutDirection="ltr" />

        <FrameLayout
            android:id="@+id/keyboard_widget_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </com.nlptech.keyboardview.floatingkeyboard.FloatingKeyboard>

</RelativeLayout>

Add this code in the InputMethodService.onCreateInputView():

Agent.getInstance().onCreateInputView(kbContainer, floatinKeyboard, mIsHardwareAcceleratedDrawingEnabled);

You can use those code to:

Control the floating keyboard switch:

KeyboardSwitcher.getInstance().switchFloatingKeyboard(context);

Get the floating keyboard switch on or off:

KeyboardSwitcher.getInstance().isFloatingKeyboard();

Enter the floating keyboard resize mode:

KeyboardSwitcher.getInstance().switchFloatingKeyboardResizeMode(shown);

[zengine v1.3.9]

8. Download theme

Get Download Theme and Status

The SDK can automatically get all of download theme 's downlaod info. You can use this code to get DownloadTheme as a KeyboardTheme:

KeyboardThemeManager.getInstance().getAvailableThemeArray(context)

The DownloadTheme 's themeType is KeyboardTheme.ThemeType.DOWNLOAD.

You can use this code to get the DownloadTheme 's status:

DownloadTheme downloadTheme = (DownloadTheme) keyboarTheme;
int status = downloadTheme.getDownloadStatus();

The status value will be:

Status Description
DownloadTheme.DOWNLOAD_STATUS_DOWNLOADABLE 可下載
DownloadTheme.DOWNLOAD_STATUS_DOWNLOADING 下載中
DownloadTheme.DOWNLOAD_STATUS_DOWNLOADED 已下載的

Download and Delete

You can use this code to download the theme 's resource:

ThemeDownloadInfo themeDownloadInfo = downloadTheme.getDownloadInfo();
DownloadThemeManager.getInstance().downloadTheme(context, themeDownloadInfo);

You can use this code to delete the theme 's resource::

DownloadThemeManager.getInstance().deleteTheme(context, downloadTheme);

Make a BroadcastReceiver to listen the DownloadTheme 's status be changed:

private DownloadThemeReceiver receiver = new DownloadThemeReceiver();

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    ......
    IntentFilter intentFilter = new IntentFilter(DownloadThemeManager.ACTION_UPDATE_DOWNLOAD_THEME);
    registerReceiver(receiver, intentFilter);
}

@Override
protected void onDestroy() {
    ......
    unregisterReceiver(receiver);
}

public static class DownloadThemeReceiver : BroadcastReceiver() {
    @Override
    public void onReceive(final Context context, final Intent intent) {
            if (DownloadThemeManager.ACTION_UPDATE_DOWNLOAD_THEME != intent.action) {
                return
            }

            String  themeId = intent.getStringExtra(DownloadThemeManager.KEY_DOWNLOAD_THEME_ID);
            // The themeId is by user call setThemeId() when creating ThemeDownloadInfo
            if(themeId == null){
                return
            }
            int status = intent.getIntExtra(DownloadThemeManager.KEY_DOWNLOAD_THEME_STATUS, -1);
            // status:
            // THEME_DOWNLOAD_STATUS_DOWNLOADABLE
            // THEME_DOWNLOAD_STATUS_DOWNLOADING
            // THEME_DOWNLOAD_STATUS_DOWNLOADED
            // THEME_DOWNLOAD_STATUS_DELETED
            if (status == -1) {
                return
            }
            
            // TODO: You can refresh your theme list here.
        }
    }

If you want to create your DownloadTheme 's resource on your server, please follow 8.3 ~ 8.6

Resource Format

Every download theme must have a resource, the format is in Resource Format. You can create your resource as zip and upload to your server.

Theme Download Info

Your server need to provide API for APP witch implements DownloadThemeManager.Listener to fetch all of the download theme 's download info。

Download theme 's download info has those fields:

field type description
themeId String You can defind yourself.
themeName String Theme name.
themeUrl String Theme resource zip 's download url.
themeCover String Theme 's placeholder.
themeCoverWithBorder String Theme 's placeholder with border, can be null if none.
mode Integer 0: Light、1: Dark,When the theme ids are same and mode are different , you can let yoyr user switch Light/Dark mode.
md5 String resource zip 's md5.
size Integer resource zip 's file size.
version Integer resource version, according to version, SDK will update theme resource or not.

Fetch Theme Download Info

APP implements DownloadThemeManager.Listener, for example:

public class DownloadThemeDataFetcher implements DownloadThemeManager.Listener {
    private static final String TAG = DownloadThemeDataFetcher.class.getSimpleName();

    @Override
    @WorkerThread
    public ArrayList<ThemeDownloadInfo> onFetchThemeDownloadInfo() {
        ArrayList<ThemeDownloadInfo> result = new ArrayList<>();
        // Fetch download theme 's download info from your server.
        ......
        ......
        ......

        // Create the ThemeDownloadInfo.
        for (YourDataObject item : items) {
                ThemeDownloadInfo downloadInfo = new ThemeDownloadInfo();
                downloadInfo.setThemeId(item.getTheme_id());
                downloadInfo.setThemeName(item.getTheme_name());
                downloadInfo.setThemeUrl(item.getTheme_url());
                downloadInfo.setThemeCover(item.getTheme_cover()); // url
                downloadInfo.setThemeCoverWithBorder(item.getTheme_cover_with_border()); // url
                downloadInfo.setMode(Integer.parseInt(item.getMode()));
                downloadInfo.setMd5(item.getMd5());
                downloadInfo.setSize(item.getSize());
                downloadInfo.setVersion(item.getVersion());
                result.add(downloadInfo);
        }

        return result;
    }
}

Call this code to set DownloadThemeDataFetcher(recommend in Application.onCreate()):

DownloadThemeManager.getInstance().setDownloadThemeDataListener(new DownloadThemeDataFetcher());

Trigger Theme Download Info

SDK will trigger to fetch theme 's download info at the Application.onCreate() and InputMethodService.onWindowHide().

But you can trigger on demand:

DownloadThemeManager.getInstance().triggerFetchData(context);

If it is first time or cache is time out, SDK will use DownloadThemeDataFetcher to fetch theme 's download info.

You can also use this code to set cache timeout duration, default is 12 hour:

DownloadThemeManager.getInstance().setFetchDownloadThemeDataDuration(duration);