I'm having difficulty getting my main View's onKey event to trigger. I'm not sure what I'm doing wrong, I have correctly implemented the onClick event but cannot seem to figure out the onKey event.
Here's the relevant code:
public class MyActivity extends Activity {
private RelativeLayout main;
private ApplicationToolbar toolbar;
public void onCreate(Bundle savedInstanceState) {
...
this.main = (RelativeLayout) this.findViewById(R.id.main);
this.toolbar = new ApplicationToolbar(this);
// toolbar is added to main later on in the code...
this.main.setOnClickListener(mClickListener);
this.main.setOnKeyListener(mKeyListener);
}
private OnClickListener mClickListener = new OnClickListener() {
public void onClick(View v) {
toolbar.setVisibility(View.VISIBLE); // Works correctly.
}
};
private OnKeyListener mKeyListener = new OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
toolbar.setBackgroundColor(0xFF0000FF); // Does not work.
return true;
}
};
}
In fact, no matter what code I put within mKeyListener it does not execute, which leads me to believe that the event itself is never being triggered, even when I pressed a bunch of keys on my physical keyboard (Motorola Droid, Android 2.1).
You can try overriding onKeyDown(int keyCode, KeyEvent event)
Check:
Back and other hard keys: three stories
is there a default back key(on device) listener in android?
Related
I have been getting into the android app world as of late. I understand that you want to place what variables you can into the onCreate method so that you can start using your variables right away. However, I am at a loss for a part of my code where I need to define onEditActionListener's to listen for user input but then also once enter is pressed get their text and send it to another activity. My research has shown I want to define these using the EditText and onEditActionListeners. however, I am at a loss as to how to go about this. Do I need to create a class that extends onEditActionListener?
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_horde_calculator);
EditText myText = (EditText) findViewById(R.id.numToSend);
OnEditorActionListener onEditorActionListener = new myClass();
myText.setOnEditorActionListener(onEditorActionListener);
}
that is a copy of my current code and I am unsure if this is the correct way to go about doing it. If I was to create a new onEditActionListener wouldn't that make my onCreate more complex than having a few lines of variables? I feel that there might be a more clear way of going about this. However, after looking through stack overflow I couldnt' seem to find something that made sense. I didn't want to just copy and paste code, but really understand how it all flows together.
Just another idea of how you can achieve this:
public class MainActivity extends AppCompatActivity implements TextView.OnEditorActionListener {
EditText editText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
editText = (EditText) findViewById(R.id.numToSend);
editText.setOnEditorActionListener(this);
}
#Override
public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_NULL
&& event.getAction() == KeyEvent.ACTION_DOWN) {
//both attempt are the same
Log.d("onEditorAction", view.getText().toString());
Log.d("onEditorAction", editText.getText().toString());
}
return true;
}
}
Use TextView.OnEditorActionListener :
TextView.OnEditorActionListener listener = new TextView.OnEditorActionListener(){
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_NULL
&& event.getAction() == KeyEvent.ACTION_DOWN) {
//call your new activity here
}
return true;
}
};
myText.setOnEditorActionListener(listener);
in my MainActivity, which extends from AppCompatActivity, I want to override the onBackPressed method like so:
#Override
public void onBackPressed() {
Log.d("MainActivity","onBackPressed");
Toast.makeText(getApplicationContext(),"onBackPressed",Toast.LENGTH_SHORT).show();
}
but onBackPressed does not get called. How ever if I do not override onBackPressed, the application closes, when I press the backbutton and if I do override it it doesn't.
The rest of my activity looks like this:
public class MainActivity extends AppCompatActivity {
private Toolbar toolbar;
private Drawer drawer;
private FloatingActionButton fab_test;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
fab_test = (FloatingActionButton) findViewById(R.id.fab_test);
fab_test.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getApplicationContext(),"FAB Test pressed",Toast.LENGTH_SHORT).show();
}
});
buildDrawer();
getSupportFragmentManager().beginTransaction().add(R.id.fragmentContainer,page).commit();
}
#Override
public void onBackPressed() {
Log.d("MainActivity","onBackPressed");
Toast.makeText(getApplicationContext(),"onBackPressed",Toast.LENGTH_SHORT).show();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu);
return true;
}
}
EDIT: I'm talking about the hardware-backbutton(not the actionbar one)
This question is already answered, but I feel to clear something here in this topic. Most comments and answeres point out to use super.onBackPressed() and that this is the cause of the not working method onBackPressed(). But that is not correct and important to let other beginners know. The method onBackPressed() does not need to use super.onBackPressed() . onBackPressed()also works if somebody, for example, comment super.onBackPressed() out.
As the questionier has written, he won´t use super.onBackPressed() because it will close the activity. So, the cause of this why it isn´t working, could be seperated into three possible causes:
The Log doesn´t work because of a wrong filter in the logcat console
The Toast dosn´t work because of the wrong passed context
The OS is implemented wrong by the supplier.
Usually, the toast works by passing the correct context. In the case of questioner, simply passing this .
#Override
public void onBackPressed() {
Log.d("MainActivity","onBackPressed");
Toast.makeText(this,"onBackPressed",Toast.LENGTH_SHORT).show();
}
For the Log, simply set the correct filter on logcat.
I don´t care if somebody give downvotes now, but it must be clear for other beginners, that super.onBackPressed() must not be used.
Anyway, the use of onKeyDown() also is a solution.
The onBackPressed() is a default action called from onKeyDown() in API < 5 and a default action called from onKeyUp() from API level 5 and up. If onKeyUp() does not call super.onKeyUp(), onBackPressed() will not be called.
Documentation onKeyDown()
Documentation onKeyUp().
#Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
/*
* without call to super onBackPress() will not be called when
* keyCode == KeyEvent.KEYCODE_BACK
*/
return super.onKeyUp(keyCode, event);
}
Also another reason that onBackPressed() may not be called is because you are using the soft back button on the actionbar, it that case the following is needed:
#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.
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
You are missing, super.onBackPressed();
#Override
public void onBackPressed() {
super.onBackPressed();
}
or you can use
#Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
//replaces the default 'Back' button action
if(keyCode==KeyEvent.KEYCODE_BACK) {
// something here
finish();
}
return true;
}
thanks
make sure you are not calling onkeydown in your super view as it handles the back button clicking first.
working fine onKeyDown function return type false;
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
return false;
}
For whoever is wondering, as most functionality is deprected API 30>, the following will surely help you a lot.
public class MainActivity extends AppCompatActivity {
private OnBackPressedCallback onBackPressedCallback;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
onBackPressedCallback = new OnBackPressedCallback(true) {
#Override
public void handleOnBackPressed() {
// Your business logic to handle the back pressed event
Log.d(TAG, "onBackPressedCallback: handleOnBackPressed");
}
};
getOnBackPressedDispatcher().addCallback(this, onBackPressedCallback);
}
}
Just Remove super.onBackPressed() it will work
I have a (seemingly) simple problem: I'm trying to set an onTouchListener on a child linear layout but I can't get my code to compile. I get the error "Cannot Resolve Symbol setOnTouchListener" when I try to use setOnTouchListener() on my chosen view.
How can I record touches on my LinearLayout? What am I doing wrong?
MainActivity.java
public class MainActivity extends FragmentActivity {
public static LinearLayout glView;
public static OpenGL_GLSurface foo;
public TouchController touchSurface;
void configView(){ // used to configure an opengl view
foo = new OpenGL_GLSurface(this);
setContentView(R.layout.activity_main);
glView = (LinearLayout)findViewById(R.id.openglsurface);
RelativeLayout.LayoutParams glParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
glView.addView(foo, glParams);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
...
touchSurface = new TouchController(this); //initialize touchable surface
}}
TouchController.java
public class TouchController {
private Context mContext;
public TouchController(Context c) { //constructor
mContext = c;
}
View.OnTouchListener touch = new View.OnTouchListener() { //set OnTouchListener to OpenGL View
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (maskedAction) {
//do stuff
}
return true;
}
};
MainActivity.glView.setOnTouchListener(touch); //Compilation Error here # setOnTouchListener
}
The issue is in your TouchController, when you are setting the touch listener, this line:
MainActivity.glView.setOnTouchListener(touch);
That line of code is invalid java code because is just hanging around in the class. It must be inside a method like the constructor. Like this:
Edit:
public class TouchController {
private Context mContext;
public TouchController(Context c) { //constructor
mContext = c;
View.OnTouchListener touch = new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (maskedAction) {
//do stuff
}
return true;
}
};
//Register touch listener here in constructor or in another method
CourseListActivity.glView.setOnTouchListener(touch);
}
}
You should consider moving the assignment of your member variable "touch" inside the constructor too, just before you set the touch listener. It will be more organized.
i have 4 tab with activity group..all tab contain list of item and on press of any item its discriptioo will be displayed in new activity..
i m using activitygroup to embedded child activity in tab.and i m using replace contentview to change the activitygroup view.
when i press back button i call finish() from child and i immediately get out of application..is there any way to return back to parent activity using activity group...???
i m using following code to chang activitygroup view..bt dont know how to come back to this activity..
public void replaceContentView(String id, Intent newIntent)
{
View mview = getLocalActivityManager().startActivity(id,newIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)).getDecorView();
this.setContentView(mview);
}
I was also stuck with this problem but solved it have a look a t below code hope will help you also
Your activityGroup should be something like this
public class ABCGroup extends ActivityGroup{
public static ABCGroup group;
private ArrayList<View> history;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.history = new ArrayList<View>();
group = this;
View view = getLocalActivityManager().startActivity
("ParentActivity",
new Intent(this, ParentActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP))
.getDecorView();
replaceView(view);
}
public void replaceView(View v) {
// Adds the old one to history
history.add(v);
// Changes this Groups View to the new View.
setContentView(v);
}
public void back() {
if(history.size() > 0) {
history.remove(history.size()-1);
if(history.size()<=0){
finish();
}else{
setContentView(history.get(history.size()-1));
}
}else {
finish();
}
}
#Override
public void onBackPressed() {
ABCGroup.group.back();
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event){
if (keyCode == KeyEvent.KEYCODE_BACK){
ABCGroup.group.back();
return true;
}
return super.onKeyDown(keyCode, event);
}
}
In your parent activity
View mview = getLocalActivityManager().startActivity(id,newIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)).getDecorView();
ABCGroup.group.replaceView(v);
In your child activity use
public boolean onKeyDown(int keyCode, KeyEvent event){
if (keyCode == KeyEvent.KEYCODE_BACK){
ABCGroup.group.back();
return true;
}
return super.onKeyDown(keyCode, event);
}
I just registered an OnLongClickListener on my my MapView on an Android app I'm currently writing. For some reason however the onLongClick event doesn't fire.
Here's what I've written so far:
public class FriendMapActivity extends MapActivity implements OnLongClickListener {
private static final int CENTER_MAP = Menu.FIRST;
private MapView mapView;
private MapController mapController;
//...
private boolean doCenterMap = true;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.friendmapview);
this.mapView = (MapView) findViewById(R.id.map_view);
this.mapController = mapView.getController();
mapView.setBuiltInZoomControls(true);
mapView.displayZoomControls(true);
mapView.setLongClickable(true);
mapView.setOnLongClickListener(new OnLongClickListener() {
public boolean onLongClick(View v) {
//NEVER FIRES!!
return false;
}
});
//...
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_3:
mapController.zoomIn();
break;
case KeyEvent.KEYCODE_1:
mapController.zoomOut();
break;
}
return super.onKeyDown(keyCode, event);
}
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
int actionType = ev.getAction();
switch (actionType) {
case MotionEvent.ACTION_MOVE:
doCenterMap = false;
break;
}
return super.dispatchTouchEvent(ev);
}
...
}
May overlays which I'm adding cause the problem?? Any suggestions?
I ran into the same problem and there is a simple solution to your problem actually; it's because you're using the wrong type of listener.
You should use the OnMapLongClickListener() object from the OnMapLongClickListener interface.
Hopefully everything should work properly :)
Please tell me if it works.
I just ran into this problem. I tried the solution above, but it doesn't quite work 100% in that we want the long press action to fire, even if the user is still holding a finger down.
This is how I implemented a solution, using a handler and a delayed task -
As a side note, I used a similar type implementation, but in reverse, to hide/show zoom controls on touch/etc..
private Handler mHandler = new Handler();
private final Runnable mTask = new Runnable() {
#Override
public void run() {
// your code here
}
};
#Override
public boolean onTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
// record the start time, start the timer
mEventStartTime = ev.getEventTime();
mHandler.postDelayed(mTask, LONG_PRESS_TIME);
} else if (ev.getAction() == MotionEvent.ACTION_UP) {
// record the end time, dont show if not long enough
mEventEndTime = ev.getEventTime();
if (mEventEndTime - mEventStartTime < LONG_PRESS_TIME) {
mHandler.removeCallbacks(mTask);
}
} else {
// moving, panning, etc .. up to you whether you want to
// count this as a long press - reset timing to start from now
mEventStartTime = ev.getEventTime();
mHandler.removeCallbacks(mTask);
mHandler.postDelayed(mTask, LONG_PRESS_TIME);
}
return super.onTouchEvent(ev);
}
In the mean time I found the "solution" (or workaround, call it as you like) by myself. The way I worked through this issue is by using a GestureDetector and forwarding all touch events to that object by implementing an according OnGestureListener interface.
I've posted some code on my blog if anyone is interested:
http://juristr.com/blog/2009/12/mapview-doesnt-fire-onlongclick-event/
Don't ask me why this didn't work by hooking up the OnLongClickListener directly on the MapView. If someone has an explanation let me know :)
UPDATE:
My previously suggested solution using a GestureDetector posed some drawbacks. So I updated the blog post on my site.
In WebView framework code performLongClick() is used to handle long press event, this is how Android copy Text Feature is implemented in Browser, that is why onLongClick is not been fired.