Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/384.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java OnKeyListener.onKey未被调用_Java_Android_Android Layout_Android Activity - Fatal编程技术网

Java OnKeyListener.onKey未被调用

Java OnKeyListener.onKey未被调用,java,android,android-layout,android-activity,Java,Android,Android Layout,Android Activity,我正在学习一本书中的教程。我知道怎么做对吗?不管怎样,我已经到了一个地步,我们正在制作一个简单的应用程序,允许用户输入文本并按下按钮。按下按钮时,输入的文本将转换为所有大写字母 有一个步骤,我们在应用程序中添加一个功能,这样当用户按enter键时(输入所需文本后),文本就会转换。(无需按下转换按钮) 我已经运行了我的应用程序,并试图调试它,但没有得到任何进展。从logcat所说的(或者更像是不说的)来看,onKey永远不会被调用 有什么我遗漏的吗?下面是java类和活动的布局。提前谢谢 java

我正在学习一本书中的教程。我知道怎么做对吗?不管怎样,我已经到了一个地步,我们正在制作一个简单的应用程序,允许用户输入文本并按下按钮。按下按钮时,输入的文本将转换为所有大写字母

有一个步骤,我们在应用程序中添加一个功能,这样当用户按enter键时(输入所需文本后),文本就会转换。(无需按下转换按钮)

我已经运行了我的应用程序,并试图调试它,但没有得到任何进展。从logcat所说的(或者更像是不说的)来看,onKey永远不会被调用

有什么我遗漏的吗?下面是java类和活动的布局。提前谢谢

java(别问我为什么给它起这个名字)

以下是此活动的布局XML

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:id="@+id/base"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.njh.add.tipclaculator.TipCal" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="My First Android Application"
        android:id="@+id/my_TextView" />

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Touch Me"
            android:id="@+id/my_Button" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Quit"
            android:id="@+id/quit" />
    </LinearLayout>

    <EditText 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:hint="Type something to get turned into CAPS"
        android:id="@+id/my_EditText" />
</LinearLayout>

更新

到目前为止,我发现TextWatcher实际上正在点击我的代码。这很好。现在,当我按enter键时,我的应用程序崩溃了

但是

我要这个。我认为新的问题是,当你创建一个TextWatcher时,你所实现的三个功能会在你按下的每一个键时被调用两次。(在向下键和向上键上)。这只是一个猜测。有人肯定知道吗

更新
TextWatcher
没有在每次更改时多次调用其方法。软键盘正在更新诸如自动添加空格或自动更正之类的内容。当我输入“ll”时我注意到了这一点,我的键盘将其更新为“lol”,这将导致它从“ll”更新为“lol”

我要再挖一点。如果我总结出一个可行的解决方案,我将发布分享财富的帖子。

OnKeyListener“这只对硬件键盘有用”。这是一个直接引自

@安特罗米特,你建议我看看这个,我照做了。这让我开始了

然后我遇到了索引越界异常。使用Android Studio可以极大地帮助解决这个问题

我找到了一个使用TextWatcher调用其他函数的解决方案。下面是我的修复程序的Java文件。正如我所看到的,我的XML中没有任何问题。你会注意到我已经改变了名字以及与之相关的东西,比如包裹。这是因为我在这次围棋中使用了Android Studio,而不是Eclipse。由于我在工作中使用Intellij,而且Android Studio也是由同一个人创建的,因此我发现使用AS进行调试要容易得多

因为我重写了这个,一些变量名已经改变了。您应该仍然能够遵循此代码。其设置与OP中的设置相同

package com.example.developer.demo;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import java.util.Locale;

//NOTE I now implement TextWatch not OnKeyListener
//the AppCompatActivity was changed because ActionBarActivity is deprecated
//look it up on StackOverflow I'll post the link at the bottom of this answer
public class Demo extends AppCompatActivity implements OnClickListener, TextWatcher {

    private TextView textView = null;
    private Button convertButton = null;
    private Button quitButton = null;
    private EditText editText = null;

    private int before = 0;
    private int on = 0;
    private int after = 0;

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

        textView = (TextView)findViewById(R.id.app_info_tv);
        convertButton = (Button)findViewById(R.id.convert_but);
        quitButton = (Button)findViewById(R.id.quit_but);
        editText = (EditText)findViewById(R.id.main_et);

        convertButton.setOnClickListener(this);
        quitButton.setOnClickListener(this);
        editText.addTextChangedListener(this); //use this instead of OnKeyListener

        Log.d("Demo","in onCreate");
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        //the same as in OP
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        //the same as in OP
    }


    @Override
    public void onClick(View v) {
        Log.d("Demo","in onClick");

        //See what View was clicked
        if(v == convertButton) {
            //turn the inputted sting into all Caps
            String textToConvert = editText.getText().toString();
            textToConvert = textToConvert.toUpperCase(Locale.getDefault());
            textView.setText(textToConvert);
            editText.setText("");
        }else if(v == quitButton){
            this.finish();
        }
    }

    //Instead on onKey with OnKeyListener you get three functions with
    //TextWatcher. Like their names suggest one is called before changes,
    //one during, and one after. 

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        Log.d("****","***************");
        Log.d("Demo","in BTC: "+String.valueOf(before++));
        Log.d("Demo","\ts: "+s.toString());
        Log.d("Demo","\tstart: "+String.valueOf(start));
        Log.d("Demo","\tcount: "+String.valueOf(count));
        Log.d("Demo","\tafter: "+String.valueOf(after));
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        Log.d("Demo","in OTC: "+String.valueOf(on++));
        Log.d("Demo","\ts: "+s.toString());
        Log.d("Demo","\tstart: "+String.valueOf(start));
        Log.d("Demo","\tcount: "+String.valueOf(count));
        Log.d("Demo","\tbefore: "+String.valueOf(before));
    }

    @Override
    public void afterTextChanged(Editable s) {
        Log.d("Demo","in ATC: "+after++);
        Log.d("Demo","\ts: "+s.toString());
        String textToConvert = s.toString();
        if(textToConvert.length() > 0 && Character.compare(textToConvert.charAt(textToConvert.length()-1),'\n') == 0){
            onClick(convertButton);
        }
    }
}
如果有人对调试日志感兴趣,请告诉我我会发布它。它帮助我了解我是如何得到我的例外

那么最棒的部分…我做了什么

在我的应用程序中,我想将
onClick
功能“绑定”到软键盘上的“回车”按钮以及布局中的转换
按钮
对象

我意识到我的
onClick
函数与
TextWatcher
所在的
EditText
对象发生了冲突。因此,我必须找出一种方法,来判断
TextWatcher
OnClickListener
何时调用
onClick

“回车”按钮将在字符串的末尾添加“\n”(换行符)。所以我会检查一下。如果它在那里,我会点击
onClick

然后,
onClick
EditText
中的文本设置为空字符串“”。更改文本导致
TextWatcher
再次执行它的三种方法。当它得到
posterextchange
时,它将索引一个
String
,该字符串为空且KABOOM。(因为我试图抓住最后一个字符,即长度-1)

^^^不,布埃诺^^^

因此,我添加了一个字符串长度大于0的检查。现在我可以相信我不会索引成空字符串

我已经对我的应用程序进行了一次很好的测试,无论是以任何方式还是以任何顺序调用
onClick
。一切都很顺利


我在代码中提到的为什么使用AppCompactActivity的链接是。它几乎使它成为一个ActionBarActivity,尽管该类现在已被弃用

你在用软件键盘打字吗?e、 屏幕上的g?是的。我刚找到一个帖子,也许能回答我的问题。onKey在软硬件KBs上都能工作吗?我不知道,我只知道我曾经遇到过软键盘的一些问题,让我知道它是否能与硬件一起工作。你也应该看看。给出了一个如何使用它的例子。嗨!你解决问题了吗?TextWatcher很原始,无法克服OnKeyListener中的一些困难。
package com.example.developer.demo;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import java.util.Locale;

//NOTE I now implement TextWatch not OnKeyListener
//the AppCompatActivity was changed because ActionBarActivity is deprecated
//look it up on StackOverflow I'll post the link at the bottom of this answer
public class Demo extends AppCompatActivity implements OnClickListener, TextWatcher {

    private TextView textView = null;
    private Button convertButton = null;
    private Button quitButton = null;
    private EditText editText = null;

    private int before = 0;
    private int on = 0;
    private int after = 0;

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

        textView = (TextView)findViewById(R.id.app_info_tv);
        convertButton = (Button)findViewById(R.id.convert_but);
        quitButton = (Button)findViewById(R.id.quit_but);
        editText = (EditText)findViewById(R.id.main_et);

        convertButton.setOnClickListener(this);
        quitButton.setOnClickListener(this);
        editText.addTextChangedListener(this); //use this instead of OnKeyListener

        Log.d("Demo","in onCreate");
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        //the same as in OP
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        //the same as in OP
    }


    @Override
    public void onClick(View v) {
        Log.d("Demo","in onClick");

        //See what View was clicked
        if(v == convertButton) {
            //turn the inputted sting into all Caps
            String textToConvert = editText.getText().toString();
            textToConvert = textToConvert.toUpperCase(Locale.getDefault());
            textView.setText(textToConvert);
            editText.setText("");
        }else if(v == quitButton){
            this.finish();
        }
    }

    //Instead on onKey with OnKeyListener you get three functions with
    //TextWatcher. Like their names suggest one is called before changes,
    //one during, and one after. 

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        Log.d("****","***************");
        Log.d("Demo","in BTC: "+String.valueOf(before++));
        Log.d("Demo","\ts: "+s.toString());
        Log.d("Demo","\tstart: "+String.valueOf(start));
        Log.d("Demo","\tcount: "+String.valueOf(count));
        Log.d("Demo","\tafter: "+String.valueOf(after));
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        Log.d("Demo","in OTC: "+String.valueOf(on++));
        Log.d("Demo","\ts: "+s.toString());
        Log.d("Demo","\tstart: "+String.valueOf(start));
        Log.d("Demo","\tcount: "+String.valueOf(count));
        Log.d("Demo","\tbefore: "+String.valueOf(before));
    }

    @Override
    public void afterTextChanged(Editable s) {
        Log.d("Demo","in ATC: "+after++);
        Log.d("Demo","\ts: "+s.toString());
        String textToConvert = s.toString();
        if(textToConvert.length() > 0 && Character.compare(textToConvert.charAt(textToConvert.length()-1),'\n') == 0){
            onClick(convertButton);
        }
    }
}
String empty = "";
int length = empty.length(); // 0
empty.charAt(length - 1); //if empty had three thing in it the length - 1 would be 2 (the index of the last character in the String)
//BUT it doesn't so empty[-1] is bad