Android get view of Preference in PreferenceActivity - android

I would like to get View instance that is used to display specific Preference in my
PreferenceActivity, so i can modify its properties, for example:
public class SettingsActivity extends PreferenceActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preference);
Preference pref = findPreference("key");
pref.getView().setVisibility(View.GONE);
//not necessarily setVisibility, i hope you get my point
}
}
I only found this method:
getView (View convertView, ViewGroup parent). But it seems confusing to me, that if i want to get View of my preference, i need to provide view and viewGroup as parameters??
Could someone explain how to use this method, or point me to another method to get View from my Preference instance.
PS: if possible, i would rather NOT extend Preference class, but i dont mind it if necessary

To get the view of a desired preference you can use this:
#Override
public void onWindowFocusChanged(boolean hasFocus)
{
super.onWindowFocusChanged(hasFocus);
Preference preference=findPreference(“preferenceKey”);
View preferenceView=getListView().getChildAt(preference.getOrder());
//Do your stuff
}
Note: You can not do this in the onCreate method because it will throw a NullPointerException.

PreferenceActivity inherits the ListActivity class. ListActivity has a method called getListView() which returns the ListView that displays your preferences.
EDIT: Here is the code in my comment formatted:
getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
// ... put listener code here
});

I'm not sure on how to get the view for a preference, but if you want to remove the view from the screen (set visibility to View.gone) you can use the following:
getPreferenceScreen().removePreference(thePreference)

Related

How to get context of the implemented callback inside a method of a fragment

I've defined the next header for a Fragment:
public class AllVideosFragment extends Fragment implements AutomaticCallback{
Inside of this Fragment, I have the next function to handle a spinner:
// Listener called when spinner item selected
spinnerLanguages.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parentView, View v, int position, long id) {
// Get selected row data to show on screen
String language = ((TextView) v.findViewById(R.id.tvSpinnerRow)).getText().toString();
if(language.equals(getString(R.string.str_en)))
Hawk.put(Config.TV_LANGUAGE, "en");
if(language.equals(getString(R.string.str_es)))
Hawk.put(Config.TV_LANGUAGE, "es");
//We need to retrive data again
new AutomaticRequest().getLives(String.valueOf(Hawk.get(Config.TV_LANGUAGE)), **CONTEXT OF THE CALLBACK**);
}
#Override
public void onNothingSelected(AdapterView<?> parentView) {
// your code here
}
});
If I would have the method outside of the spinner handle method, I could use "this", but inside I don't know what I need to use.
new AutomaticRequest().getLives(String.valueOf(Hawk.get(Config.TV_LANGUAGE)), this);
Which method I need to call in replacement of "this"?
Thank you for your help.
You are in an anonymous scope and this will refer to the scope. If you want to pass an outer this you have to explicitly name it in this case
AllVideosFragment.this
This will give you the current callback's context, FragmentName.this will refer to fragment context while getActivity() refers to the activity context on which your fragment is being hosted. For your ease simple make a Context context in global scope, initialise it in fragments' onViewCreated() method like, context = getActivity() and use it anywhere in your fragment.
the answer is:
new AutomaticRequest().getLives(String.valueOf(Hawk.get(Config.TV_LANGUAGE)), getActivity().this);
AllVideosFragment.this.getActivity();

Handling Spinner initialization and onItemSelected callback

I used to dynamically populate a Table Layout with different elements per row, among them a Spinner.
To handle the initialization of spinner values i used what most recommended: a boolean flag variable. The code went something like this
public class spinnerHandling implements OnItemSelectedListener{
public void dynamicallyPopulateTableLayout(int a){
...
//initialize spinner with default values
mySpinner.setSelection(a);
mySpinner.setTag(true);
mySpinner.setOnItemSelectedListener(this);
...
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position,
long id) {
if(!(Boolean)parent.getTag()){
//my code
...
}
parent.setTag(false);
}
}
This worked fine.
Later i decided that i should use a List View instead of a Table Layout. For that i have a custom ArrayAdapter that uses a row Layout, in which of course i have a Spinner, to populate the List View. As those of you who are familiar with List Views, understand its complex dynamic behavior, would know that the somehow static turn around of the boolean flag method wont work.
After three days of tremendous headache trying to find a way to resolve this issue, i just came across the spinner's isDirty() method that in contrast with isPressed(), isSelected(), etc. actually changes its boolean values when spinner item is selected by user.
the code is something like this:
public class spinnerHandling implements OnItemSelectedListener{
public void dynamicallyPopulateListView(int a){
...
//initialize spinner with default values
mySpinner.setSelection(a);
mySpinner.setOnItemSelectedListener(this);
...
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position,
long id) {
if(!parent.isDirty()){
//my code
...
}
}
}
This seems to work fine!
But i would like to make sure that isDirty() handles properly spinner initialization and user selection.
Can you please confirm or contradict this behavior?
Thank you.

How to attach GestureDetector to a ListPreference?

The challenge of attaching a GestureDetector to a ListPreference is 2-fold:
Getting a handle to a ListPreference that's only defined in a preferences.xml (i.e. not instantiated in Java code).
ListPreference is neither a View nor Activity subclass.
Is it possible at all to attach a GestureDetector to a ListPreference?
If so, how would one go about this? Where would I write the code to instantiate GestureDetector and implement the listener?
Unless I didn't quite catch the question correctly, the answer is probably simpler than you might think. The source code for ListPreferece teaches that it's little more than a wrapper around an AlertDialog that displays its various options in a ListView. Now, AlertDialog actually allows you to get a handle on the ListView it wraps, which is probably all you need.
In one of the comments you indicated that, at this stage, all you're interested in is detecting a long-press on any item in the list. So rather than answering that by attaching a GestureDetector, I'll simply use an OnItemLongClickListener.
public class ListPreferenceActivity extends PreferenceActivity implements OnPreferenceClickListener {
private ListPreference mListPreference;
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.list_prefs);
mListPreference = (ListPreference) findPreference("pref_list");
mListPreference.setOnPreferenceClickListener(this);
}
#Override
public boolean onPreferenceClick(Preference preference) {
AlertDialog dialog = (AlertDialog) mListPreference.getDialog();
dialog.getListView().setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override public boolean onItemLongClick(AdapterView<?> parent, View v, int position, long id) {
Toast.makeText(getApplicationContext(), "Long click on index " + position + ": "
+ parent.getItemAtPosition(position).toString(), Toast.LENGTH_SHORT).show();
return false;
}
});
return false;
}
}
The result (which the toast in the long-click displaying):
With a reference to the ListView, you could also attach an OnTouchListener, GestureDetector etc. Up to you to go from here.
As #TronicZomB suggested, this isn't directly possible.
You can work around this by creating your own ListPreference derived class, getting its view in the inherited onBindDialogView().
Remember however that the latter is tricky because onBindDialogView() is only called if onCreateDialogView() doesn't return null, and this can happen only if you create your own custom view for YourListPreference.
The recommended way to do this is to build a custom Preference.
Once you have done that, you have a reference to YourListPreference's view, which is mandatory for attaching GestureDetector because one of the steps requires setOnTouchListener() on the view.
I have set a GestrueDetector to a ScrollView using setOnTouchListener previously and searched for a similar method for ListPreference, however since the ListPreference does not contain such a method, I do not believe this will be possible.

Get checked Listitems from ListView and pass that to another activity

I'm developing a Androidapplication using ListView.
ListView have a one file in each and every ListItem. Here, I have set onItemClickin ListView. So, that if user clicks the ListItememail application gets open and attach the particular file in email. Its for the single File, this gets implemented and working fine.
Now I want attach the multiple file in email. i.e. the implementing the CheckBoxin each ListItemand checked items have to attached into the Mail.
I know its possible because its very similar to the file manager application that checking the multiple file and deleting the all file by clicking the single Button. But don't know how to do.
In you ListAdapter create a SparseBooleanArray
private SparseBooleanArray checkStatus;
This SparseBooleanArray stores the checked items. Now in getView do the following
#Override
public View getView(int position, View view, ViewGroup parent) {
ViewCache viewCache;
if (view == null){
viewCache = new ViewCache();
view = layoutInflater.inflate(R.layout.list_box, null, false);
viewCache.checkBox = view.findViewById(R.id.check_box);
viewCache.checkBox.setOnCheckedChangeListener(onCheckedChangeListener);
//other views in the list box
...........
}
vewCache = (ViewCache)view.getTag();
viewCache.checkBox.setTag(position);
viewCache.checkBox.setChecked(isChecked(position));
//set other views
........
}
This is the class ViewCache
private static class ViewCache{
CheckBox checkBox;
//other views in the list box
.......
}
This method checks whether the position is checked
private boolean isChecked(int position){
return checkStatus.get(position, false);
}
This is the onCheckChangeListener
CompoundButton.OnCheckedChangeListener onCheckedChangeListener = new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
checkStatus.put(((Integer)compoundButton.getTag()), b);
}
};
Finally you can get the checked items from the SparseBooleanArray checkStatus. Think it will help you.
You can try implementing your own ArrayAdapter. Initialize it with an array of your file objects and use it in the list view.
Next make a list of indexes that is visible by the adapter and can be manipulated from the outside. In your onItemClick method you have the position of the clicked item. If it's in that list remove it, otherwise - insert it. Let's call that list selection.
Next in your adapter's getView method construct a view with a checkbox inside. Again you have the current position, because it's passed as an argument. Set the checkbox state depending on the presence of the position in selection.
Finally implement your button's onClick so that it does whatever you do with your file objects only for those objects of your file_array whose positions are in your selection.
Hope that helps
In the above answers Sreejith has given a good explanation of how to store the states of the checked items in the list view using a SparseBooleanArray. This solves the first part of your problem.
The second part regarding the passing of the states of these items to the other activities can be achieved using the Application class.
Application class:
Base class for those who need to maintain global application state. Sometimes you want to store data, like global variables which need to be accessed from multiple Activities - sometimes everywhere within the application. In this case, the Application object will help you.
Here is a sample code for this:
public class TopClass extends Application {
private static TopClass topClass;
public TopClass getInstance()
{
return topClass;
}
#Override
public void onCreate ( )
{
super.onCreate();
topClass = this;
}
public ArrayList<String> arrList = new ArrayList<String>();
}
You need to set tag android:name="TopClass" in the application manifest file under the application tag. Something like this:
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:name="TopClass" >
....
....
Here is how you can access it from the activity:
TopClass top = (TopClass)getApplicationContext();
top.arrList.add("StackOverflow");
Now you can access the same variable from other activities similarly.

onClick attribute in XML linking to method in Activity class

There are quite a few questions about this subject, but could not find any with the specific problem I have...
In my layout.xml, I use the android:onClick tag for a Button to call the right onClickListener. I get the error :
java.lang.IllegalStateException: Could not find a method handle_cancel(View) in the activity class com.matthieu.HelloWorldApplication for onClick handler on view class android.widget.Button with id 'button_cancel'
I have that method implemented in the Activity, but it is looking for it in the class that extends Application... I don't understand why. The View and all that is setup only in the Activity.
If anyone needs, here is the declaration of that method (in my activity, NOT in HelloWorldApplication):
public void handle_cancel(View v) {
// do something useful here
}
Edit (from adamp request)... and probably answering my own question :
Here is part of the code where that layout is used...
public class AddVocabularyActivity extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.top); // that layout contains an empty LinearLayout id/main_content
}
private some_other_function() {
LinearLayout main_content = (LinearLayout) findViewById(R.id.main_content);
main_content.removeAllViews();
View.inflate(getApplicationContext(), R.layout.hello, main_content); // layout.hello is the one containing the button
}
// some other stuff
}
While copy/paste this code, I am guessing the problem is that I used getApplicationContext to inflate the View with that Button...
As mentioned in my edit, changing the getApplicationContext() with the Activity context fixes it...
The convention works like this:
In the layout xml file, you give this attribute:
android:onClick:"methodname"
Then, inside a class, you define a method like this:
public void methodname(View v){
//your method code
}
Any other way of doing this is not documented. If you need parameters, just call another method inside that method.

Categories

Resources