gpt4 book ai didi

java - OnKeyListener.onKey 未被调用

转载 作者:太空宇宙 更新时间:2023-11-03 10:18:01 30 4
gpt4 key购买 nike

我正在学习一本书中的教程。我知道怎么猜对了吗?好吧,无论如何,我已经到了我们正在制作一个允许用户输入文本并按下按钮的简单应用程序的地步。按下按钮时,输入的文本将全部转换为大写。

我们在应用程序中添加了一个功能,以便在用户按下回车键时(在输入所需文本后)转换文本。 (无需按转换按钮)

我已经运行了我的应用程序并尝试对其进行调试,但没有成功。根据 logcat 所说(或更像是不说)永远不会调用 onKey。

有什么我想念的吗?下面是 Activity 的 java 类和布局。提前致谢。

TipCal.java(不要问我为什么这么命名)

package com.njh.add.tipclaculator;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnKeyListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class TipCal extends Activity implements OnClickListener, OnKeyListener{

private TextView tv = null;
private Button convertButton = null;
private Button quitButton = null;
private EditText et = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tip_cal);
tv = (TextView)findViewById(R.id.my_TextView);
convertButton = (Button)findViewById(R.id.my_Button);
quitButton = (Button)findViewById(R.id.quit);
et = (EditText)findViewById(R.id.my_EditText);

convertButton.setOnClickListener(this);
quitButton.setOnClickListener(this);
et.setOnKeyListener(this);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.tip_cal, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}

@Override
public void onClick(View v) {
Log.d(v.toString(),"In onClick");
if(v == convertButton){
//Take the text from the EditText and make it all CAPS
//Then update the TextView with the CAPS string
String editTextContent = et.getText().toString();
editTextContent = editTextContent.toUpperCase();
tv.setText(editTextContent);
et.setText("");
}else if(v == quitButton){
this.finish();
}
}

@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
//When the user press enter after typing in what they want to
//convert the conversion is done. No need to press any other button

Log.d(v.toString(),"In onKey");

if(event.getAction() == KeyEvent.ACTION_DOWN){
if(event.getKeyCode() == KeyEvent.KEYCODE_ENTER){
this.onClick(v); //Not sure this is legal but don't see why I couldn't do this.
}
}

return false;
}
}

这是这个 Activity 的布局 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 确实命中了我的代码。哪个好。现在,当我按下回车键时,我的应用程序崩溃了。

但是!

我会接受的。我认为新问题是您在制作 TextWatcher 时实现的三个功能,您按下的每个键都会调用两次。 (在 keydown 和 keyup 上)。这只是一个猜测。有人确定吗?

更新TextWatcher 没有在每次更改时多次调用其方法。软键盘正在更新自动添加空格或自动更正等功能。当我输入“ll”并且我的键盘将其更新为“lol”时我注意到了这一点,这将导致它更新从“ll”到“lol”再到“lol”的变化。

我将要进行更多挖掘。 如果我得出一个可行的解决方案,我将发布以分享财富。

最佳答案

OnKeyListener “这只对硬件键盘有用”。这是来自 View.OnKeyListener 的直接引用.

@Antrromet 你建议看看这个post ,我做到了。它让我开始了。

然后我遇到了索引越界异常。使用 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);
}
}
}

如果有人对调试日志感到好奇,请告诉我,我会发布它。它帮助我了解了我是如何获得异常(exception)的。

那么最重要的是……我做了什么?

在我的应用程序中,我想将 onClick 函数“绑定(bind)”到软键盘上的“Enter”按钮以及布局中的转换 Button 对象。

我意识到我的 onClick 函数干扰了 TextWatcher 所在的 EditText 对象。所以我必须找出一种方法来判断 onClick 何时被 TextWatcherOnClickListener 调用。

“Enter”按钮将在字符串末尾放置一个“\n”(换行符)。所以我会检查一下。如果它在那里,我会调用 onClick

然后 onClick 会将 EditText 中的文本设置为空字符串 ""。更改文本会导致 TextWatcher 再次通过它的三个方法。当它得到 afterTextChange 时,它会索引一个空的 StringKABOOM。 (因为我试图捕获长度为 - 1 的最后一个字符)

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

^^^没有布埃诺^^^

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

我已经对我的应用程序进行了一些测试,以任何顺序调用 onClick。一切正常。

我在代码中谈到为什么我使用 AppCompactActivity 的链接是 here .它几乎使它成为 ActionBarActivity,即使该类现在已被弃用。

关于java - OnKeyListener.onKey 未被调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32028908/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com