СоХабр закрыт.

С 13.05.2019 изменения постов больше не отслеживаются, и новые посты не сохраняются.

| сохранено

H Разработка кастомной клавиатры под android в черновиках Recovery Mode

Кастомная клавиатура — попытка № 2


Добрый день/вечер/ночь всем кто читает эту статью. Первая моя статья , которая была тоже связана с этой темой оказалась не очень успешной, т.к у меня был не шипко большой опыт разработки. Но время прошло, я стал думать иначе и осознал свои ошибки. По названию статьи можно понять, что именно мы будем делать — кастомную клавиатуру, так что начнём.

Наша клавиатура так же как и прошлая будет не большой, дабы сильно не париться пусть на ней будут цифры и кнопка очистки.

Для всего этого нам нужно несколько классов
  • CustomKeyboard — собственно сама клавиатур
  • interaface OnCustomKeyBoardListener для отлова нажатий клавиш на клавиатуру
  • CustomEditText


Создадим проект в android studio и назовём его как-нибудь — например — KeyBoardSecondTry
Чтобы создать нашу клавиатуру создадим класс, описанный выше — CustomKeyboard, этот класс будет унаследован от LinearLayout, для размещения элементов, для больших вариаций можно конечно использовать GridLayout, но в нашем случае мы будем использовать LinearLayout, дабы не заморачиваться.

Вот код нашего класса CustomKeyboard
package com.sunplacestudio.keyboardsecondtry;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;

public class CustomKeyboard extends LinearLayout {
    private float scale;
    private OnCustomKeyBoardListener onCustomKeyBoardListener;

    interface OnCustomKeyBoardListener { // Интерфейс обратного вызова
        void onKeyBoardClear();
        void onKeyBoardClick(String text);
    }

    public void setOnCustomKeyBoardListener(OnCustomKeyBoardListener onCustomKeyBoardListener) {
        this.onCustomKeyBoardListener = onCustomKeyBoardListener;
    }

    public CustomKeyboard(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
        setOrientation(HORIZONTAL);
        setMinimumHeight((int) (scale * 50 + 0.5f));
        scale = context.getResources().getDisplayMetrics().density;
        for (int i = 1; i <= 9; i++)
            addView(getButton(String.valueOf(i)));
        addView(getButton("0")); // Кидаем все кнопки в наш лайаут
        Button button = getButton("C");
        button.setOnClickListener(new OnClickListener() {
            @Override public void onClick(View view) {
                if (onCustomKeyBoardListener != null)
                    onCustomKeyBoardListener.onKeyBoardClear();
            }
        });
        addView(button);
    }

    private Button getButton(final String text) {
        Button button = new Button(getContext());
        LinearLayout.LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) (scale * 50 + 0.5f));
        layoutParams.weight = 1;
        button.setLayoutParams(layoutParams);
        button.setText(text);
        button.setOnClickListener(new OnClickListener() {
            @Override public void onClick(View view) {
                if (onCustomKeyBoardListener != null)
                    onCustomKeyBoardListener.onKeyBoardClick(text); // вызываем нажатие кнопки
            }
        });
        return button;
    }

}


Вы скорее всего спросите, а зачем нам кастомный editText, а я скажу — дело в том, что при повторном(я имею ввиду нажали, прошло несколько секунд, нажали снова) нажатии на EditText не срабатывает его OnClickListener, у меня он почему-то не срабатывает, я эту проблему так и не решил, хотя по идее тут не должно быть ничего сложного, если вдруг кто-то решил эту проблему, прошу в комментарии, буду благодарен, т.к я так и не нашёл решения. Так вот, в нашем кастомном editText мы просто имплементируемся от View.OnTouchListener, создаём ещё один интерфейс обратного вызова и всё.
Код предствден ниже.
package com.sunplacestudio.keyboardsecondtry;

import android.content.Context;
import android.support.v7.widget.AppCompatEditText;
import android.text.InputType;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;

public class CustomEditText extends AppCompatEditText implements View.OnTouchListener {

    private OnCustomEditTextListener onCustomEditTextListener;

    public void setOnCustomEditTextListener(OnCustomEditTextListener onCustomEditTextListener) { this.onCustomEditTextListener = onCustomEditTextListener; }

    public interface OnCustomEditTextListener {
        void onClick();
    }

    public CustomEditText(Context context) {
        super(context);
        setOnTouchListener(this);
        setInputType(InputType.TYPE_NULL);
        setSelected(false);
        setGravity(Gravity.CENTER);
    }

    public CustomEditText(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
        setOnTouchListener(this);
        setInputType(InputType.TYPE_NULL);
        setSelected(false);
        setGravity(Gravity.CENTER);
    }

    @Override public boolean onTouch(View view, MotionEvent event) {
        super.onTouchEvent(event);
        if (event.getAction() == MotionEvent.ACTION_DOWN && onCustomEditTextListener != null)
            onCustomEditTextListener.onClick();
        return false;
    }
}



И пропишем теперь нашу основную активити с её layout
package com.sunplacestudio.keyboardsecondtry;

package com.sunplacestudio.keyboardsecondtry;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity {
    private CustomKeyboard customKeyboard;

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

        final CustomEditText customEditText = findViewById(R.id.edittext);
        customKeyboard = findViewById(R.id.keyboard);

        customEditText.setOnCustomEditTextListener(new CustomEditText.OnCustomEditTextListener() {
            @Override public void onClick() {
                customKeyboard.setVisibility(View.VISIBLE);
            }
        });

        customKeyboard.setOnCustomKeyBoardListener(new CustomKeyboard.OnCustomKeyBoardListener() {
            @Override public void onKeyBoardClear() {
                customEditText.setText(""); // очишаем текст
            }

            @Override public void onKeyBoardClick(String text) {
                String result = customEditText.getText() + text; // обновляем наш текст
                customEditText.setText(result); // выводим его
            }
        });
    }

    @Override public void onBackPressed() {
        customKeyboard.setVisibility(View.GONE); // Прячем нашу клавиатуру - как отловить это событие внутри самой клавиатуры я так и не нашёл
    }
}



Код самого лайота здесь тоже
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
    tools:context=".MainActivity">
    <com.sunplacestudio.keyboardsecondtry.CustomEditText
        android:id="@+id/edittext"
        android:layout_width="match_parent"
        android:layout_height="50dp" />
    <com.sunplacestudio.keyboardsecondtry.CustomKeyboard
        android:visibility="gone"
        android:id="@+id/keyboard"
        android:layout_gravity="bottom"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</FrameLayout>

Собственно — это всё, если у вас будут какие-либо вопросы или комментарии, прошу в комментарии, надеюсь, что второй мой подход по поводу решения этой проблемы оказался лучше предыдущего.

комментарии (0)