I have an abstract Activity as most of my activities share the same menu:
public abstract class ActivityBase extends Activity {
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menubar, menu);
return true;
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
//...
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
//...
}
}
Now, when I use that class (inherit from it), the findViewById() method doesn't work anymore. Doesn't matter if I even inherit from it in that particular class, once it is somewhere in the inheritance tree, it doesn't work anymore. For example:
public class SomeOther extends ActivityBase {
}
public class Home extends Activity {
#Override
public void onCreate (Bundle savedInstance) {
super.onCreate(savedInstance);
setContentView(R.layout.main);
Button b = (Button)findViewById(R.id.button); // fails, NullPointerException
}
What could be the cause of this, and even more importantly, how can I fix it?
In my case this work perfect (try this)...
public abstract class ActivityBase extends Activity {
#Override
public boolean onCreateOptionsMenu(Menu menu) {
return true;
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
//..
return true;
}
}
and
public class MyActActivity extends ActivityBase {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.e("HI", "Hello");
TextView tv=(TextView)findViewById(R.id.Settings_phoneNumbersT1);
Log.e("HI", tv.toString());
}
}
and main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:id="#+id/Settings_phoneNumbersT1"
android:textSize="14sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ffffff" android:text="Hellofffff"/>
</LinearLayout>
So, I don't think it is problem of Abstract ActivityBase class.
try this...
Button b = (Button)Home.this.findViewById(R.id.button);
its to make sure that your present class's findviewById is called and not the super class's..
The NullPointerException was caused someplace else and just manifested with that method. If you derive from Application and try to call getSharedPreferences, it fails, but you can't pinpoint it.
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'm trying to get this code to show whatever is typed in search view as a text in the textview of the layout. But when I run the app nothing is shown.
public class MainActivity extends AppCompatActivity {
TextView textview;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_search);
textview = (TextView) findViewById(R.id.search_result);
}
#Override
public boolean onCreateOptionsMenu(Menu menu){
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.search_menu,menu);
SearchView searchView = (SearchView) menu.findItem(R.id.search_box).getActionView();
searchView.setQueryHint("Search Here");
searchView.setIconifiedByDefault(false);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener(){
#Override
public boolean onQueryTextSubmit(String search){
return false;
}
#Override
public boolean onQueryTextChange(String search){
String result= "You have searched for "+search;
textview.setText(result);
return false;
}
});
return super.onCreateOptionsMenu(menu);
}
}
What should I do to show the search the search string in textview?
edit
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="#+id/search_box"
android:title="search here"
android:icon="#android:drawable/ic_menu_search"
app:actionViewClass="android.widget.SearchView"
app:showAsAction="always"/>
</menu>
When I enter a search query to the search box it isn't being shown on the textview widget on the layout.
You might also be interested in looking at databinding to solve this problem:
https://developer.android.com/topic/libraries/data-binding/
From this page:
<TextView
android:text="#{viewmodel.userName}" />
To update a UI object you must use the main thread, in your code you is updating the textview on another thread. Try change your method onQueryTextChange to use the main thread to update your TextView.
#Override
public boolean onQueryTextChange(String search){
String result= "You have searched for "+search;
runOnUiThread(new Runnable() {
#Override
public void run() {
textview.setText(result);
}
});
return false;
}
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.
I have a main class called BaseActivity which has a method
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getSupportMenuInflater().inflate(R.menu.main, menu);
return true;
}
Now i extend this class like this...
public class MainActivity extends BaseActivity {
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
Log.d("Its called", "Kevin");
menuInflater.inflate(R.menu.othermenu, menu);
}
}
How would i override this method here, should it be a boolean or void.
Update:
public class FragmentClass extends android.support.v4.app.Fragment {
// How would i over-ride the onCreateOptionsMenu() here of BaseActivity.
}
Any overriding method needs to have the same signature as the method it is overriding. Don't forget to call super, like so:
public class MainActivity extends BaseActivity {
#Override
public boolean onCreateOptionsMenu( Menu menu ) {
if( super.onCreateOptionsMenu( menu ) ) {
Log.d("Its called", "Kevin");
getSupportMenuInflater().inflate(R.menu.othermenu, menu);
return true;
} else {
return false;
}
}
}
My Question: Is there a work-around for using an onTouchEvent in a FragmentActivity?
My Situation: I'm writing a simple flashlight app and I have a FragmentActivity where a user can swipe between colors (the whole screen is just one color. This app is for personal improvement). I want to be able to do a onLongPress event for options, a onDoubleTap event for hiding the navigation bar, and most importantly a touch event to control brightness of the app (I want to let the user scroll up and down for brightness changes, any ideas here are welcome! is the onFling event good for this?)
What I've tried: I have a GestureDetector with my implementation of an SimpleOnGestureListener. I override the onTouchEvent in the FragmentActivity, but I have just found out that this method is never called in a FragmentActivity (I also tested this with a Log.print in the method and it's never called). Is there a work-around? Thanks!
Salient Code:
MainActivity:
public class MainActivity extends FragmentActivity {
private GestureDetector gestureDetector;
private FragmentPagerAdapter mAdapter;
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
gestureDetector = new GestureDetector(getApplicationContext(), new MyGestureListener(getWindow()));
mAdapter = new ColorFragmentAdapter(getSupportFragmentManager(), getDefaultColorList());
ViewPager pager = (ViewPager) super.findViewById(R.id.viewpager);
pager.setAdapter(mAdapter);
pager.setCurrentItem(Math.round(mAdapter.getCount() / 2)); //Set current fragment to middle fragment
}
#Override
public boolean onTouchEvent(MotionEvent event) {
print("Sending touch event to gestureDetector.");
//This line is never run.
return gestureDetector.onTouchEvent(event);
}
/**
* Prints the given object to the log with the debug priority with the tag FLASHLIGHT
*
* #param object
*/
public static void print(Object object) {
Log.println(Log.DEBUG, "FLASHLIGHT", object.toString());
}
}
MyGestureListener :
public class MyGestureListener extends SimpleOnGestureListener {
private final Window window;
public MyGestureListener(Window window) {
super();
this.window = window;
}
#Override
public void onLongPress(MotionEvent e) {
//onLongPress code
}
#Override
public boolean onDoubleTap(MotionEvent e) {
//onDoubleTap code
}
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
//onFling cod
}
}
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<android.support.v4.view.ViewPager
android:id="#+android:id/viewpager"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
I don't think you'd need anything else to answer the question, but let me know if you do.
So the solution to this is relatively easy. The problem is that the ViewPager is eating the touch event. So what I did was write my own implementation of a ViewPager and overrided the onTouchEvent(MotionEvent event) method by calling super.onTouchEvent(event) and then passing the event to the gestureDetector within the class.
Relevant Code:
MainActivity
public class MainActivity extends FragmentActivity {
private FragmentPagerAdapter mAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_main);
mAdapter = new FragmentAdapter(getSupportFragmentManager());
MyViewPager pager = (MyViewPager) findViewById(R.id.viewpager);
pager.setGestureDetector(new GestureDetector(this, new MyGestureListener(this)));
pager.setAdapter(mAdapter);
pager.setCurrentItem(Math.round(mAdapter.getCount() / 2));
}
}
MyViewPager
public class MyViewPager extends ViewPager {
private GestureDetector gestureDetector;
public MyViewPager(Context context) {
super(context);
}
public MyViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean onTouchEvent(MotionEvent e) {
return super.onTouchEvent(e) && gestureDetector.onTouchEvent(e);
}
}
MyGestureListener
public class MyGestureListener extends SimpleOnGestureListener {
private final Activity activity;
public MyGestureListener(Activity activity) {
super();
this.activity = activity;
}
#Override
public boolean onDoubleTap(MotionEvent e) {
//...
}
#Override
public boolean onSingleTapConfirmed(MotionEvent e) {
//...
}
//... etc...
}
layout_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<com.kentcdodds.flashlight.MyViewPager
android:id="#+android:id/viewpager"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
try doing this:
gestureDetector = new GestureDetector(this);
and on the TouchEvent this:
#Override
public boolean onTouchEvent(MotionEvent me) {
return gestureDetector.onTouchEvent(me);
}
Source
If you just want to simply detect when a user touches on the fragmentActivity use the following method:
public void onUserInteraction(){
Log.d("FragmentActivity","touched");
}
More info at : http://developer.android.com/reference/android/support/v4/app/FragmentActivity.html