我正在阅读一本书中的教程。我知道anceint怎么了?好吧无论如何我已经到了一个点,我们正在制作一个简单的应用程序,允许用户输入文本和按下按钮。按下按钮时,输入的文本将转换为所有CAPS。
有一个步骤,我们向应用程序添加一个功能,以便当用户按下Enter键时(在输入所需文本后),文本将被转换。 (无需按转换按钮)
我已经运行了我的应用程序并尝试对其进行调试,但却没有在哪里。从logcat所说的(或者更像是不说)onKey永远不会被调用。
我有什么遗失的东西吗?下面是java类和Activity的布局。提前谢谢。
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;
}
}
以下是此活动的布局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实际上是在点击我的代码。这很好。现在,当我按下回车键时,我的应用程序崩溃了。
BUT!
我会接受的。我认为新问题是当您按下每个键时,为TextWatcher调用两次时实现的三个函数。 (在keydown和keyup上)。这只是猜测。有人知道吗?
更新
TextWatcher
每次更改都没有多次调用它的方法。软键盘正在更新自动添加空格或自动校正等内容。当我输入&#34; ll&#34;我的键盘更新为&#34; lol&#34;这会导致它更新来自&#34; ll&#34;到&#34; lol&#34;到&#34; lol&#34;。
我即将进行更多挖掘。 如果我总结了一个可行的解决方案,我将发布以分享财富。
答案 0 :(得分:2)
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);
}
}
}
如果有人对调试日志感到好奇,请告诉我我会发布它。它让我看到了我的例外情况。
所以最好的部分......我做了什么?
在我的应用程序中,我想将onClick
函数“绑定”到软键盘上的“Enter”按钮以及布局中的转换Button
对象。
我意识到我的onClick
函数正在弄乱EditText
所在的TextWatcher
对象。所以我必须想办法告诉onClick
或TextWatcher
调用OnClickListener
的时间。
“Enter”按钮将在字符串末尾添加“\ n”(换行符)。所以我会检查一下。如果它在那里我会打电话给onClick
。
然后onClick
会将EditText
中的文本设置为空字符串“”。更改文字会导致TextWatcher
通过三种方法再次。当它获得afterTextChange
时,它将索引为String
为空且 KABOOM 。 (因为我试图抓住最后一个长度为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,即使该类现已弃用。