Starting to learn about creating the settings page, but my app crashes when I select 'settings' from the action bar, and I get this error in logcat:
Caused by: java.lang.ClassCastException: com.myexamlpe.thing.Preference cannot be cast to android.app.Activity
Here's how I call it from my main class:
public class RCs extends FragmentActivity implements
rcfrequency.ToolbarListener, RCButtons.ToolbarListener {
.
.
.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_settings:
Intent myIntent = new Intent(this, Preference.class);
startActivity(myIntent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
Here's my Preference class:
public class Preference extends PreferenceFragment implements OnSharedPreferenceChangeListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
The error happens because you are trying to open a PreferenceFragment as a PreferenceActivity
public class Preference extends PreferenceFragment implements OnSharedPreferenceChangeListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
The error is cast, because its Preference class inherits from PreferenceFragment soon there may not be opened as an Activity
Caused by: java.lang.ClassCastException: com.myexamlpe.thing.Preference cannot be cast to android.app.Activity
change to :
public class Preference extends PreferenceActivity implements OnSharedPreferenceChangeListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
See a example here, how to use PreferenceFragment:
http://www.cs.dartmouth.edu/~campbell/cs65/lecture12/lecture12.html
The problem is that you declare class Preference extends PreferenceFragment but try to start it with an Intent. As Andre stated, you can fix this by extending PreferenceActivity. Alternatively, you can use a the FragmentManager to display your Preference. This requires learning a little about fragments and how they interact with activities. This is what was meant by the suggestion that you should use PreferenceFragment over PreferenceActivity.
Related
Is there a way I can use two classes or more for one Activity in android studio?
I used this Test code but this App crashes:
Note : This is for learning purposes so that it can be used to split up huge classes into sub classes
//Main Activity Class
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Test ob=new Test ();
ob.test();
}
}
// Test Class
public class Test extends MainActivity {
public void test()
{
TextView t=findViewById(R.id.h);
t.setText("Miaooo");
}
}
What you can do is to pass the activity with as the parameter of constructor and use that reference to call "findViewbyId()"
public class Test{
public void test(Activity activity)
{
TextView t=activity.findViewById(R.id.h);
t.setText("Miaooo");
}
while in your main activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Test ob=new Test (this);
ob.test();
}
If you want to your "Test" class to be extended by an activity than you should use activity creation wizard to setup all the stuff in manifest and .xml. It would be quite long process to do it manually.
When you write class Test extends MainActivity it means that Test should be activity too and you have to write setContentView(R.layout.your_layout); to set the view layer for your activity. Also, Test should be registered as Activity in your manifest file. Anyway if you want to change the text of the TextView why you want to create a new activity?
place your code in the activity main.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
test();
}
public void test()
{
TextView t=findViewById(R.id.h);
t.setText("Miaooo");
}
It's quite long to change the code:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
to:
public class MainActivity extends AppCompatActivity {
ActivityMainBinding mainBinding;
#Override
protected void onCreate(Bundle savedInstanceState) {
mainBinding = ActivityMainBinding.inflate(getLayoutInflater());
super.onCreate(savedInstanceState);
setContentView(mainBinding.getRoot());
}
}
every time I create a new project or an activity. Is it possible to automate this process?
You can not automate the process since we have to provide the layoutId ourself. Activity is not gonna bind to a layout automatically. What you can do is Create a BaseActivity and inherit it from all your Activites. Below is a template with binding .
public abstract class BaseActivity<B extends ViewDataBinding> extends AppCompatActivity {
protected abstract int getContentViewId();
protected B binding;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, getContentViewId())
}
}
class MainActivity extends BaseActivity<ActivityMainBinding> {
#Override
public int getContentViewId() {
return R.layout.activity_main;
}
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// now you can directly access binding here
}
}
This is just for Binding you can Also add some reusable method in BaseActivity and use them in Any Activity without writing them again. and super.onCreate(savedInstanceState) should be first line for call .
No, I think it's not possible but you can make Live Template to get it frequently.
Or Simple that you can make a copy of that folder as a template. Whenever you need to create a new project it will be easy to copy/paste and just change the name of the project.
Thank you.
I was following this documentations to create a setting page. I have created two java classes based on the documentation:
SettingsFragment.java:
public static class SettingsFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.preferences);
}
...
}
SettingsActivity.java
public class SettingsActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Display the fragment as the main content.
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new SettingsFragment())
.commit();
}
}
In the preference I have an item with key premium_support which I want to create a click listener for it.
<CheckBoxPreference
android:key="#string/premium_support"
android:title="Premium Support"
android:summary="Purchase premium support"
android:defaultValue="false" />
I can't create a click listener in the fragment because I have my in app billing codes in the SettingsActivity. I tried this answer but seems like findPreference is only for the preferencefragment.
Any idea how to implement the click listener in SettingsActivity?
In the onCreate() method of SettingsActivity:
Preference preference = findPreference("prefs_key");
preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
#Override
public boolean onPreferenceClick(Preference preference) {
Toast.makeText(SettingsActivity.this, "Clicked", Toast.LENGTH_SHORT).show();
return true;
}
});
The 'findPreference' method can only be called on the settingsfragment because it extends preferencefragment. You need to get a reference to the settingsfragment class in the settings activity like below:
private SettingsFragment settingsFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle("SETTINGS");
//instantiate the settings fragment
settingsFragment= new SettingsFragment();
getFragmentManager().beginTransaction()
.replace(android.R.id.content, settingsFragment)
.commit();
}
You then override onResume and set the preferenceclicklistener in onresume and not oncreate because the commit() method is called asynchronously ( i.e the code does not execute immediately) and the preference value might be null if you call findpreference immediately after commiting the fragment transaction in oncreate.
#Override
protected void onResume() {
super.onResume();
Preference preference =
settingsFragment.findPreference(getString(R.string.pref_key));
preference.setOnPreferenceClickListener(new
Preference.OnPreferenceClickListener() {
#Override
public boolean onPreferenceClick(Preference preference) {
//respond to click events here
return true;
}
});
}
i am creating two java file 1st main activity.java file 2nd fragment.java file create button on fragment.java how to click listener written on activity.java help me
fragment.java
public class fragment extends fragment{
Button btn;
// some code
btn = (Button)layout.findviewbyid(R.id.btn1);
}
}
activity.java
public class activity extends Activity
{
// how to access the click action btn here
btn.setOnclicklistner(new View.OnClickLisitner(){
public OnClick(){
}
To use the button in activity from the fragment, you have to use getActivity()
In your fragment,
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_item_select, container, false);
btn = (Button) getActivity().findViewById(R.id.btn);
}
btn is the button in activity
getActivity() in a Fragment returns the Activity the Fragment is currently associated with. (see http://developer.android.com/reference/android/app/Fragment.html#getActivity()).
You can define custom clickListener class and create it's instance in fragment and set listener instance there. Now you can write code in that class. Hope it will help you.
public class MyCustomListener implements OnClickListener{
#override
public void onClick(View v){
// you stuff
}
}
then in your fragment call this
MyCustomListener listener=new MyCustomListener();
btn.setOnClickListener(listener);
Here is my take on the issue, both in Java and Kotlin.
Java:
public final class YourActivity extends AppCompatActivity {
/***/
public final void yourMethod() {
printIn("Printing from yourMethod!")
}
}
public final class YourFragment extends Fragment {
/***/
#Override
public void onViewCreated(View v, Bundle savedInstanceState) {
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
YourActivity yourActivity = (YourActivity) getActivity();
yourActivity.yourMethod();
}
}));
}
}
Kotlin:
class YourActivity : AppCompatActivity() {
/***/
fun yourMethod() {
print("Printing from yourMethod!")
}
}
class YourFragment: Fragment() {
/***/
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
button.setOnClickListener {
val yourActivity = activity as YourActivity
yourActivity.yourMethod()
}
}
}
I hope it helps someone out there =)
If I understand your problem correctly, you want to delegate a button click inside a fragment back to its parent activity.
Keep a reference to the parent activity inside your fragment. Then set the listener to your button in your fragment like this:
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
parentActivity.doStuff();
}
};
In your parent Activity, define method doStuff():
public void doStuff() {
// handle button click event here
}
I was wondering how do i attach this(OnGenericMotionListener) listener inside an activity. Do i have to register it to each view? thanks
note: please provide code.
To add any interface to a class in java you just need to add the word implements and then the class name to the top of the activity declaration. So to add the OnGenericMotionListener you would use the code below.
public class MyActivity extends Activity implements OnGenericMotionListener {
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
TextView myView = new TextView(this);
myView.setOnGenericMotionListener(this);
}
#Override
public boolean onGenericMotion(View view, MotionEvent event) {
return false;
}
}
This would set the GenericMotionListener for myView so when the event occurs it will call the onGenericMotion function inside of your activity. If you want to attach it to multiple views just use a switch on the id of the view passed to the onGenericMotion function.