I'm following a tutorial on ActionBarCompat that also enables a search text area. I extended the ActionBarActivity from the v7 support lib. When I try to override these two methods it can't find them in the superclass. I went to source and looked at the superclass' methods and I can't locate them there as well. The two methods are onQueryTextSubmit and onQueryTextChange
This was the tutorial.
Any idea what I am doing wrong?
This is the error when I hover over the methods:
The method onQueryTextChange(String) of type MainActivity must override or implement a supertype method
public class MainActivity extends ActionBarActivity{
private SearchView mSearchView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
ViewConfiguration config = ViewConfiguration.get(this);
Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
if(menuKeyField != null) {
menuKeyField.setAccessible(true);
menuKeyField.setBoolean(config, false);
}
} catch (Exception ex) {
// Ignore
}
}
#Override
public boolean onQueryTextSubmit(String s) {
Toast.makeText(this, s, Toast.LENGTH_LONG).show();
return true;
}
#Override
public boolean onQueryTextChange(String s) {
return false;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
MenuItem searchItem=menu.findItem(R.id.action_search);
mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()){
case R.id.action_search:
mSearchView.setIconified(false);
return true;
}
return false;
}
It sounds like you are not implementing the class that is needed for those methods.
public class MainActivity extends ActionBarActivity implements SearchView.OnQueryTextListener
Make sure that you implemented SearchView.OnQueryTextListener.
Related
I am new to Android.
I am trying to refer a View by Id from a separate class than MainActivity.
Note: My app has single activity.
Main Activity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState)//Activity Oncreate callback
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) //Oncreate Options_menu callback
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
case R.id.option1:
//Here am calling a method from another class
SecondClass secondClassObject=new SecondClass();
secondClassObject.method1();
}
return true;
}
Second Class:
public class SecondClass {
public void method1(){
TextView tv1 = (TextView)findViewById(R.id.textView);
tv1.setText("");
}
}
How to refer to the textView by ID in the SecondClass? How to set the context as MainActivity in this SecondClass?
Add an Activity parameter for your method
public void method1(Activity act){
TextView tv1 = (TextView)act.findViewById(R.id.textView);
tv1.setText("");
}
From your activity define an Activity variable Activity act; so as to use it across other functions .Assign a value of your Activity to the variable act=this; and finaly use it on the function you want.
public class MainActivity extends AppCompatActivity {
Activity act;
#Override
protected void onCreate(Bundle savedInstanceState)//Activity Oncreate callback
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
act=this;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) //Oncreate Options_menu callback
{
act=this;
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
case R.id.option1:
//Here am calling a method from another class
//SecondClass secondClassObject=new SecondClass();
//secondClassObject.method1();
SecondClass secondClassObject=new SecondClass();
secondClassObject.method1(act);
}
return true;
}
you can also pass the parent layout view
public void method1(View act){
TextView tv1 = (TextView)act.findViewById(R.id.textView);
tv1.setText("");
}
And call it like so
SecondClass secondClassObject=new SecondClass();
secondClassObject.method1(findViewById(R.id.your_parent_layout));
Avoid using passing Activity method if its not absolutely necessary to avoid possibilities of memory leaks.
I have been trying to build a searchable interface in this app for a while, and I've been using a lot of the Android developer guides to help, but I recently ran into this error to do with SearchView and OnQueryTextListener that I do not know how to resolve, but it is stopping my app from running.
Here is my MainActivity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar myToolbar = (Toolbar) findViewById(R.id.my_toolbar);
setSupportActionBar(myToolbar);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.overflow, menu);
MenuItem searchItem = menu.findItem(R.id.search);
SearchView searchView = (SearchView) menu.findItem(R.id.search).getActionView();
searchView.setOnQueryTextListener((OnQueryTextListener) searchView);
//this is where the program crashes
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchableInfo info = searchManager.getSearchableInfo(getComponentName());
searchView.setSearchableInfo(info);
return true;
}
public boolean onQueryTextSubmit(String query) {
// User pressed the search button
return false;
}
public boolean onQueryTextChange(String newText) {
// User changed the text
return false;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.constants:
startActivity(new Intent(MainActivity.this, FundamentalPhysicalConstants.class));
return true;
case R.id.joes_rules:
//go to rules
return true;
case R.id.home:
//Go back to the home screen
return true;
case R.id.search:
//open search
return true;
default:
// If we got here, the user's action was not recognized.
// Invoke the superclass to handle it.
return super.onOptionsItemSelected(item);
}
}
}
Here is my SearchableActivity:
public class SearchableActivity extends ListActivity {
DatabaseTable db= new DatabaseTable(this);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_searchable);
// get the intent sent when user searches from search widget, verify the action and exxtract what is typed in
Intent intent = getIntent();
handleIntent(intent);
}
public void onNewIntent(Intent intent) {
setIntent(intent);
handleIntent(intent);
}
private void handleIntent(Intent intent) {
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
Cursor c = db.getWordMatches(query, null);
//still need to process Cursor and display results
}
}
public void onListItemClick(ListView l,
View v, int position, long id) {
// call detail activity for clicked entry
}
private void doSearch(String queryStr) {
// get a Cursor, prepare the ListAdapter
// and set it
}
}
Here is my searchable.xml:
<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="#string/app_name"
android:hint="#string/search_hint">
</searchable>
Here is my logcat:
06-08 14:57:09.581 28388-28388/com.gmd.referenceapplication E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.gmd.referenceapplication, PID: 28388
java.lang.ClassCastException: android.support.v7.widget.SearchView cannot be cast to android.support.v7.widget.SearchView$OnQueryTextListener
at com.gmd.referenceapplication.MainActivity.onCreateOptionsMenu(MainActivity.java:55)
at android.app.Activity.onCreatePanelMenu(Activity.java:2846)
at android.support.v4.app.FragmentActivity.onCreatePanelMenu(FragmentActivity.java:340)
at android.support.v7.view.WindowCallbackWrapper.onCreatePanelMenu(WindowCallbackWrapper.java:85)
at android.support.v7.app.AppCompatDelegateImplBase$AppCompatWindowCallbackBase.onCreatePanelMenu(AppCompatDelegateImplBase.java:258)
at android.support.v7.view.WindowCallbackWrapper.onCreatePanelMenu(WindowCallbackWrapper.java:85)
at android.support.v7.app.ToolbarActionBar.populateOptionsMenu(ToolbarActionBar.java:454)
at android.support.v7.app.ToolbarActionBar$1.run(ToolbarActionBar.java:61)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
I have tried to do a lot of research on this, and I haven't had any luck. I would be extremely grateful for any help on this matter, thanks.
This line is just wrong:
searchView.setOnQueryTextListener((OnQueryTextListener) searchView);
You cannot cast the searchView into OnQueryTextListener. Instead give it a proper parameter as an anonymous class like this:
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
//your logic
}
#Override
public boolean onQueryTextChange(String newText) {
//your logic
}
});
I now see that you have tried to add these two methods in your Activity, which is not the proper way to do it. You either need to create your custom class that implements this SearchView.OnQueryTextListener interface, and then say:
searchView.setOnQueryTextListener(new MyClassThatImplementsTheInterface);
Or do it the way above that I gave you as the first solution. That is the more common way of doing this, using anonymous classes.
the error is clear from the logs you are casting the SearchView to a listener which is wrong try something like
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
return false;
}
});`
there are many questions about the topic but i can't figure out my problem. I have a menu declared in my MainActivity(ActionBarActivity). Now i want to work with MenuItem in onOptionsItemSelected of a Fragment class. Here is my MainActivity methods
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// toggle nav drawer on selecting action bar app icon/title
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
// Handle action bar actions click
switch (item.getItemId()) {
case R.id.add_note:
createNewNote();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void createNewNote() {
Intent addIntent = new Intent(MainActivity.this, AddNote.class);
startActivity(addIntent);
}
And Fragment methods
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.add_note:
Toast.makeText(getActivity(), "Entered into fragment", Toast.LENGTH_LONG).show();
createNewNote();
return true;
default:
break;
}
return super.onOptionsItemSelected(item);
}
private void createNewNote() {
Intent addIntent = new Intent(getActivity(), AddNote.class);
startActivity(addIntent);
}
Here in MainActivity onOptionsItemSelected get called even in Fragment but doesn't in Fragment as i don't see Toast in Fragment. I think something is missed in my code. Thanks in advance.
inside onOptionsItemSelected() in activity inside your switch after calling createNewNote() instead of returning true return super.onOptionsItemSelected(item)
you must call setHasOptionsMenu() inside onCreate of fragment for menu related method to work.
Your onCreateOptionsMenu() method does not inflate the menu file:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
}
I have a small question about the Data consistence in the onCreate() function. For better understanding my example:
public class Test extends Activity {
public String isThisConsistent1;
public int isThisConsistent2;
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.Test, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.Item_1:
getSomething();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.Test);
/*Very, very long taking code like a huge loop */
isThisConsistent1 = ...;
isThisConsistent2 = ...;
}
private void getSomething(){
String test1 = isThisConsistent1;
int test2 = isThisConsistent2;
}
}
So my question is: Is it possible to click the Item on my ActionBar before the onCreate() function is finished? Because then I would call the function getSomething() before the Data was set in the onCreate() function.
As you can see in the lifecycle documentation, the onCreate method is called before view is visible. This means, the answer is no, you can't click the button before the onCreate finishes.
I'm very new to Android development.
In my MainActivity.java file, I've declared an onOptionsItemSelected(MenuItem menu) method that allows the user to jump between the current MainActivity.java page and another page I created called Settings.java.
When the user goes to the Settings.java page, and they click on the Home option from the menu, nothing happens. I know this is because the onOptionsItemSelected(MenuItem menu) is only defined in the MainActivity.java class and not in the Settings.java class.
I'm overcoming this right now by copying the onOptionsItemSelected(MenuItem menu) from MainActivity.java into Settings.java. But this is very redundant.
Where should I be declaring methods that could be reused in different classes?
MainActivity.java
public class MainActivity extends Activity {
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_settings:
showMsg("Settings Clicked");
this.startActivity(new Intent(this, Settings.class));
return true;
case R.id.action_home:
showMsg("Home clicked");
this.startActivity(new Intent(this, MainActivity.class));
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void showMsg(String msg) {
Toast toast = Toast.makeText(this.getBaseContext(), msg, Toast.LENGTH_LONG);
toast.show();
}
}
Settings.java
public class Settings extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_settings:
this.startActivity(new Intent(this, Settings.class));
return true;
case R.id.action_home:
this.startActivity(new Intent(this, MainActivity.class));
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
If you create an Activity called BaseActivity that has your common onOptionsItemSelected() code then extend this class to create MainActivity and Settings both of these classes will use the super class' (i.e. BaseActivity's) onOptionsItemSelected().
Another approach is to switch to Fragments, since Fragments use the host Activity's onOptionsItemSelected() as well as their own. Both of these tactics allow you to use "centralized" code and not have to maintain multiple "cut and paste" copies.