首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OnKeyListener.onKey未被调用

OnKeyListener.onKey未被调用
EN

Stack Overflow用户
提问于 2015-08-15 20:11:09
回答 1查看 1.3K关注 0票数 4

我正在学习一本书中的教程。我知道什么是祖先对吧?无论如何,我已经到达了一个点,我们正在制作一个简单的应用程序,允许用户输入文本并按下按钮。当按下按钮时,输入的文本将转换为所有的大写。

有一个步骤,我们在应用程序中添加一个功能,以便当用户按回车(在输入所需的文本之后),文本被转换。(无需按转换按钮)

我运行了我的应用程序,并试图调试它,但没有得到任何地方。从logcat所说的(或者更像是没有说),onKey从来没有被调用过。

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

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

代码语言:javascript
复制
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

代码语言:javascript
复制
<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时,对您按下的每个键调用两次时所实现的三个函数。(在按键和键盘上)。这只是猜测而已。有人肯定知道吗?

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

我要做更多的调查。如果我总结出一个可行的解决方案,我将张贴分享财富。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-08-16 18:35:35

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

@Antrromet您建议查看这个帖子,而我确实这样做了。这让我开始了。

然后,我遇到了超出界限的索引异常。使用Android对此有很大帮助。

我已经找到了一个使用TextWatcher调用其他函数的解决方案。下面是我修复的Java文件。正如我所看到的,我的XML中没有任何问题。你,我的通知,我已经改变了名称和与之配套的东西,如包裹。这是因为我用Android做这个go,而不是Eclipse。由于我在工作中使用Intellij,而且Android是由相同的人构建的,所以我发现调试和使用AS要容易得多。

自从我重写了这个之后,一些变量的名称发生了变化。您仍然应该能够遵循这段代码。它的设置与OP中相同。

代码语言:javascript
复制
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);
        }
    }
}

如果有人对调试日志感兴趣,请让我知道我会发布它。它帮助我了解了我是如何得到我的例外的。

那么我做的最好的part...What呢?

在我的应用程序中,我希望将onClick函数“绑定”到软键盘上的"Enter“按钮以及布局中的Button对象。

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

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

然后onClickEditText中的文本设置为空字符串"“。更改文本使TextWatcher通过了它的三种方法--,再次是。当它得到afterTextChange时,它将索引int为空的StringKABOOM。(因为我试图抓住最后一个字符,长度- 1)

代码语言:javascript
复制
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的链接是这里。它几乎使它成为一个ActionBarActivity,尽管这个类现在已经被废弃了。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32028908

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档