Dropdown Navigation Android - android

I'm a beginning Android developer and I want to learn how to implement dropdown navigation in my app. Essentially, I would like a different layout to show on the screen when the user selects an item in a spinner in the action bar.
I created a new activity with the Dropdown navigation template in Android Studio but I don't know how to proceed. How would I go about accomplishing this?

To have a different view in the action bar spinner than in the spinner list, you can use a BaseAdapter or an ArrayAdapter and override some methods:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Return a view which appears in the action bar.
return yourCustomView..;
}
#Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
// Return a view which appears in the spinner list.
// Ignoring convertView to make things simpler, considering
// we have different types of views. If the list is long, think twice!
return super.getView(position, null, parent);
}
More specific details can be found from here: https://stackoverflow.com/a/15293471/1650683
==== EDIT ====
You can find how to integrate dropdown in ActionBar in This article, follow the instruction, you will get it done.
As to bring to a different layout after selecting an item on the spinner, you should set fragment after user clicks on the dropdown item. Sample code:
mOnNavigationListener = new OnNavigationListener() {
// Get the same strings provided for the drop-down's ArrayAdapter
String[] strings = getResources().getStringArray(R.array.action_list);
#Override
public boolean onNavigationItemSelected(int position, long itemId) {
// Create new fragment from our own Fragment class
ListContentFragment newFragment = new ListContentFragment();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
// Replace whatever is in the fragment container with this fragment
// and give the fragment a tag name equal to the string at the position
// selected
ft.replace(R.id.fragment_container, newFragment, strings[position]);
// Apply changes
ft.commit();
return true;
}
};

Use spinner for dropdown.This may help you.
ArrayAdapter<String> adapter = new ArrayAdapter<String>
(this, android.R.layout.simple_spinner_item, array_name);
adapter.setDropDownViewResource(R.layout.spinner_layout);
final Spinner s1 = (Spinner) findViewById(R.id.spinner1);
s1.setPrompt("Your Title");
s1.setAdapter(adapter);
s1.setOnItemSelectedListener(new OnItemSelectedListener()
{
#Override
public void onItemSelected(AdapterView<?> arg0, View arg1,
int arg2, long arg3)
{
--enter your code here--
}}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
}
});

Related

Android : Spinner OnSelectedItemListener

I have an application with a ListView that displays different transactions made by the user. My code doesn't seem to work.
The problem I have now is that I want to add a Spinner above this ListView to let the user choose whether the transactions should be ordered by date, amount or an own choice of an interval between two dates.
Heres my code for just the spinner onSelectedItem:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_income, container, false);
initializeComponents(view);
registerListeners();
spinnerOrderIncome = (Spinner) view.findViewById(R.id.spinnerOrderIncome);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this.getActivity(), R.array.spinnerSortIncome, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerOrderIncome.setAdapter(adapter);
spinnerOrderIncome.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
switch (spinnerOrderIncome.getSelectedItem().toString()) {
case "date":
lvIncome.setAdapter(new CustomIncomeListAdapter(activity, dbController.getDataFromIncomeTable()));
break;
case "amount":
lvIncome.setAdapter(new CustomIncomeListAdapter(activity, dbController.getSortedAmountFromIncomeTable()));
break;
}
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
The ListView is already populated with this method that gets the list from the DatabaseController:
public void populateListView() {
lvIncome.setAdapter(new CustomIncomeListAdapter(activity, dbController.getDataFromIncomeTable()));
}
The methods are seen in the switch-statement where thought to change the order of the ListView, but nothing happens when I select the different spinner items (date, amount) Am I on the right track? Help!
Instead of assigning a new adapter to the listView each time you change its data, I would just update the list it contains, then call notifyDataSetChanged to inform the adapter that its datased has changed (so the view will be redrawn).
Something like that, I guess (not tested) :
spinnerOrderIncome.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
CustomIncomeListAdapter myAdapter = (CustomIncomeListAdapter)lvIncome.getAdapter();
myAdapter.getDataSet().clear();
switch (spinnerOrderIncome.getSelectedItem().toString()) {
case "date":
myAdapter.getDataSet().addAll(dbController.getDataFromIncomeTable());
break;
case "amount":
myAdapter.getDataSet().addAll(dbController.getSortedAmountFromIncomeTable());
break;
}
myAdapter.notifyDataSetChanged();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
}

Android onListItemClick: How to get an object whose fields are displayed in the ListView item which was clicked?

I have an ArrayList of objects of class MyClass, each of which has four fields (namely firstItem, secondItem, thirdItem and fourthItem), the first three of which need to be displayed in the ListView of a ListFragment. For this, I have extended the ArrayAdapter, and overridden its getView() method, as follows:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
if (convertView == null) {
view = layoutInflater.inflate(
R.layout.myFragment_listview_item, parent, false);
} else {
view = convertView;
}
MyClass myClassItem = getItem(position);//******But this method is inside Adapter
((TextView) view
.findViewById(R.id.myclassListFragment_ListViewItem1))
.setText(myClassItem.firstItem);
((TextView) view
.findViewById(R.id.myclassListFragment_ListViewItem2))
.setText(myClassItem.secondItem);
((TextView) view
.findViewById(R.id.myclassListFragment_ListViewItem3))
.setText(myClassItem.thirdItem);
return view;
}
But when the user clicks an item from the ListView, the fourthItem field for the object whose other fields are displayed as that clicked listview item, should be displayed (in a TextView) in a separate Fragment (detailsFragment).
The program adds the new fragment on the click of an item from the ListView as follows, But the question is that how do I get the value of fourthItem field for the MyClass object whose corresponding ListView item had been clicked by the user, so that I can set it in a TextView in the detailsFragment?
In the mentioned first ListFragment:
The ListFragment implements LoaderManager.LoaderCallBacks<List<MyClass>>, which means that the List containing the MyClass objects is passed to the LoaderManager.LoaderCallBacks's onLoadFinished() method:
#Override
public void onLoadFinished(Loader<List<MyClass>> loader, List<MyClass> dataList) {
customArrayListAdapter.setData(dataList);
if (isResumed()) {setListShown(true);} else {setListShownNoAnimation(true);}
}
We have onListItemClick() method, which instantiates the new detailsFragment to display fourthItem in it:
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
showDetailsFragment(position);
}
private void showDetailsFragment(int index) {
listViewItemPosition = index;
DetailsFragment detailsFragment = DetailsFragment.newInstance(index);
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.myActivity_frameLayout1, detailsFragment);
fragmentTransaction.commit();
}
You can get selected row item object from ListView by calling getItem method of Adapter using getListAdapter as:
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
MyClass class = (MyClass)getListAdapter().getItem(position);
}
By using setTag() and getTag() mechanism to make your views remember something, that could be an object an integer a string or anything you like.
set this in getView()
view.SetTag(myClassItem );
use getTag() in onItemClickListener() to retrieve data from item
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
MyClass class = (MyClass) v.getTag();
}
Change your method like this
private void showDetailsFragment(int index) {
String fourthItem = ((MyClass)getListAdapter().getItem(index)).fourthItem;
DetailsFragment detailsFragment = DetailsFragment.newInstance(fourthItem);
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.myActivity_frameLayout1, detailsFragment);
fragmentTransaction.commit();
}
After this you will have to change the type of parameter passed in newInstance() of DetailsFragment to String and simply display that.

Select spinner without triggering listener

Long version I have two spinners on my screen and when I select the one, I do certain operations, and the other spinner should display the original selection, because of design patterns. In this situation, I let the user select the elements on a list by year, and by state. You would agree with me that when the user choose to select by year, the spinner regarding the state should display the default selection (the one that displays all of the item) and not the last selected one.
I am trying to do this from this morning, but when I found this solution I really though I was done.
Short version I want to setSelection(0) on the spinner which is not clicked, without triggering its listener (which by the way, will setSelection(0) on the first spinner, if triggered)
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
// irrelevant code...
mYearSpinner.setOnItemSelectedListener(onYearSelected);
mStateSpinner.setOnItemSelectedListener(onStateSelected);
// irrelevant code...
}
private AdapterView.OnItemSelectedListener onYearSelected = new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
mStateSpinner.setOnItemSelectedListener(null);
mStateSpinner.setSelection(0);
mStateSpinner.setOnItemSelectedListener(onStateSelected);
// Do something...
}
#Override
public void onNothingSelected(AdapterView<?> parent) { }
};
private AdapterView.OnItemSelectedListener onStateSelected = new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
mYearSpinner.setOnItemSelectedListener(null);
mYearSpinner.setSelection(0);
mYearSpinner.setOnItemSelectedListener(onYearSelected);
// Do something...
}
#Override
public void onNothingSelected(AdapterView<?> parent) { }
};
But no! The listeners will just fire, indiscriminately.
Is there someone who knows how to handle this problem?
Why this solution wouldn't work?
As requested, here is the full code of my onCreateView(...) method
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
Log.d(TAG, "onCreateView");
View view = inflater.inflate(R.layout.fragment_career, container, false);
mExamListView = (ListView) view.findViewById(R.id.exam_list_view);
mYearSpinner = (Spinner) view.findViewById(R.id.select_by_year_spinner);
mStateSpinner = (Spinner) view.findViewById(R.id.select_by_state_spinner);
mLoadingView = view.findViewById(R.id.fragment_career_loading_spinner);
mExamListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Exam exam = (Exam) parent.getItemAtPosition(position);
if (exam.isBookable()) {
FragmentManager fm = getActivity().getSupportFragmentManager();
SessionsDialogFragment.newInstance(exam).show(fm, null);
}
}
});
// Create an ArrayAdapter using the string array and a default spinner layout
ArrayAdapter<CharSequence> yearAdapter = ArrayAdapter.createFromResource(getActivity(),
R.array.spinner_year, android.R.layout.simple_spinner_item);
// Specify the layout to use when the list of choices appears
yearAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// Create an ArrayAdapter using the string array and a default spinner layout
ArrayAdapter<CharSequence> stateAdapter = ArrayAdapter.createFromResource(getActivity(),
R.array.spinner_state, android.R.layout.simple_spinner_item);
// Specify the layout to use when the list of choices appears
stateAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mYearSpinner.setAdapter(yearAdapter);
mStateSpinner.setAdapter(stateAdapter);
mYearSpinner.setOnItemSelectedListener(onYearSelected);
mStateSpinner.setOnItemSelectedListener(onStateSelected);
return view;
}
I tried implementing what --- suggested and I want to report here what happens.
When the application starts all the two listeners are executed only once.
Then, if I select an item on the first spinner (let's say the year spinner), the expected listener is executed only once (as it should be), and so it is, if I keep selecting items on it.
Ultimately, if I select and item on the state spinner, the listeners are executed in this way
1. onStateListener
2. onYearListener
3. onStateListener
From reading your comments it sounds like you want to set the selection of a second spinner to 0 from your first spinners onItemClick method without triggering its listener.
If you keep a record of the old position the spinners are at in integer variables we can check if the position has changed and only run the code if it has.
That way if we set the old position variable to 0 before changing the spinners current position to 0 it will think its position hasn't changed and so won't run the code in the listener.
private AdapterView.OnItemSelectedListener onYearSelected = new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (lastYearPosition != position) {
//Do you code here
lastStatePosition = 0;
mStateSpinner.setSelection(0);
}
lastYearPosition = position;
}
#Override
public void onNothingSelected(AdapterView<?> parent) { }
};
private AdapterView.OnItemSelectedListener onStateSelected = new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (lastStatePosition != position) {
//Do your code here
lastYearPosition = 0;
mYearSpinner.setSelection(0);
}
lastStatePosition = position;
}

Actionbar how to change view on item click

How can I change view of item in drop down navigation list in action bar on click?
After click, I want that displayed item shows another view (in layout it is set as invisible).
I've got onNavigationItemSelected method from ActionBar.OnNavigationListener but it does not pass view of the item clicked but just position of item in navigation spinner. Or in other words, why can I not get reference to selected view from actionbar spinner? (like I can get view with listview onItemClick from OnItemClickListener())
ActionBar's Spinner resource id is : android:id/action_bar_spinner
Get the Spinner resource id:
int resId = getResources().getIdentifier("action_bar_spinner", "id", "android");
Get the reference to Spinner widget using the resource id:
final Spinner spinner = (Spinner) getWindow().getDecorView().findViewById(resId);
Now you will be able to get access to the selected view:
CheckedTextView v = (CheckedTextView) spinner.getSelectedView();
You can modify the selected view right away in OnNavigationListener:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new MyFragment())
.commit();
SpinnerAdapter mSpinnerAdapter = ArrayAdapter.createFromResource(this,
R.array.action_list, android.R.layout.simple_spinner_dropdown_item);
getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
int resId = getResources().getIdentifier("action_bar_spinner", "id", "android");
final Spinner spinner = (Spinner) getWindow().getDecorView().findViewById(resId);
this.getActionBar().setListNavigationCallbacks(mSpinnerAdapter, new ActionBar.OnNavigationListener() {
#Override
public boolean onNavigationItemSelected(int itemPosition,
long itemId) {
CheckedTextView v = (CheckedTextView) spinner.getSelectedView();
// Modify selected view.
return true;
}
});
}
I was just trying to figure this out and managed to track it down.
Use setSelectedNavigationItem to do this.
With your navigationListener, you can try this :
OnNavigationListener navigationListener = new OnNavigationListener() {
#Override
public boolean onNavigationItemSelected(int itemPosition, long itemId) {
View convertView = null;
View view = adapter.getView(itemPosition, convertView, null);
TextView myTextView = (TextView) view
.findViewById(R.id.my_textView);
Toast.makeText(getBaseContext(), myTextView.getText(),
Toast.LENGTH_LONG).show();
return true;
}
You are then retrieving the item via the adapter. My only problem is now modifying the retrieved reference content. I can't seem to have it working.
I Hope it helps

Android Long Press Spinner View

I want to be able to long press items in the spinner view and have a contextMenu appear. I tried this code:
spinner = (Spinner) findViewById(R.id.catagorySpinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(context,android.R.layout.simple_dropdown_item_1line, data);
spinner.setAdapter(adapter);
registerForContextMenu(spinner);
but as you can guess this added a context menu to the actual Spinner and not to the contents inside. Does anyone know how i can do this?
Have you tried this?
spinner.setOnItemLongClickListener(new OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView<?> parent, View view, int arg2, long arg3) {
view.showContextMenu();
return true;
}
});
You can register for each item inside the adapter's getView() method.
View getView(View convertView, ... ) {
....
// inflate view or reuse.
....
getContext().registerForContextMenu(convertView);
....
return convertView;
}

Categories

Resources