How to check which menu file is inflated in BottomNavigationView? - java

I use 2 different menu for my bottom navigation view called
bottom_navigation_menu.xml
bottom_navigation_menu_verified.xml
I need to set different action based on what is the current menu inflated in my bottom navigation view. I want to make something like this
lateinit var bottomNavigationView : BottomNavigationView
if (bottomNavigationView.menu == R.menu.bottom_navigation_menu_verified) {
// do something here
}
but the code above is invalid because bottomNavigationView.menu will return Menu data type and R.menu.bottom_navigation_menu_verified will return int, type doesn't match. so how to check what is the current inflated menu in my bottom navigation view ?
java/kotlin is okay

You can probably check for a specific MenuItem:
if (null != bottomNavigationView.menu.findItem(R.id.bottom_navigation_menu_item1)) {
// do something here
}

Related

How can i anchor a Snackbar to the android soft navigation bar?

Thank you in advance!
I decided to implement a Snackbar with this method (which will later be called in onClick method):
public void showSnackbar(int selector, int textSelector){
String sOne = (String) getResources().getText(R.string.charPart1);
String sTwo = String.valueOf(selector);
String sThree = (String) getResources().getText(R.string.charPart2);
String sFour = sOne.concat(sTwo.concat(sThree));
String sFive = (String) getResources().getText(R.string.charPart4);
String sSix = sFour.concat(sFive);
Snackbar notification = Snackbar.make(getWindow().getDecorView().getRootView(), "PLACEHOLDER", Snackbar.LENGTH_SHORT);
if (textSelector==1){
notification.setText(sFour);
notification.show();
}
else if (textSelector==2){
notification.setText(sSix);
notification.show();
}
}
I am facing this problem:
The Snackbar is displayed behind the system navigation bar:
My first idea was, that i could use the method Snackbar.setAnchorView(View anchorView) to position the Snackbar above the system navigation bar / soft navigation bar. Description of setAnchorView(View anchorView):
By default, Snackbars will be anchored to the bottom edge of their parent view. However, you can use the setAnchorView method to make a Snackbar appear above a specific view within your layout, e.g. a FloatingActionButton. This is especially helpful if you would like to place a Snackbar above navigational elements at the bottom of the screen, such as a BottomAppBar or BottomNavigationView.
I would like to position the Snackbar above the system navigation bar, but i donĀ“t know how to query the view id of the system navigation bar.
Snackbar notification = Snackbar.make(getWindow().getDecorView().getRootView(), "PLACEHOLDER", Snackbar.LENGTH_SHORT);
// View systemNavigationView = findViewById(int id) ;
notification.setAnchorView(systemNavigationView);
notification.show();
Is it at all possible to assume that the android system navigation bar has an assigned id that can be retrieved?
I only found this method for detecting if it exists, but no approach for getting the View or the id of the view:
public boolean hasNavBar (Resources resources)
{
int id = resources.getIdentifier("config_showNavigationBar", "bool", "android");
return id > 0 && resources.getBoolean(id);
}
You should place your snackbar inside a CoordinatorLayout view.

Disable underlyingFragment when Drawer is opened

Hey,
In my app I have a Drawer. When it's open the editText from the underlying fragment still works. Does anyone know how I can fix this?
At the red arrow is an editText that shouldn't respond right now, when the Drawer is opened.
x
A very simple way is to just hide the keyboard then the drawer opens. The only way to get the keyboard showing again is to click the edittext.
Here is one way to hide it:
fun hideKeyboard(activity: Activity) {
val imm = activity.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
//Find the currently focused view, so we can grab the correct window token from it.
var view: View? = activity.currentFocus
//If no view currently has focus, create a new one, just so we can grab a window token from it
if (view == null) {
view = View(activity)
}
imm.hideSoftInputFromWindow(view.windowToken, 0)
}

Issues adding custom layout within each Recycler view

I am building an app where publishers upload questions to database. Publishers can add as many questions they want, so i used a recycler view to handle that. When publisher clicks the button to add question a new layout is inflated as specified in my recyclerview adapter. TopicQuestionsAdapter is the name of my recycler view adapter
...
RecyclerView addTopicOfTheDayWhereDynamicLayoutsWillBeAdded;
TopicQuestionsAdapter topicQuestionsAdapter;
ArrayList<TopicQuestions> topicQuestionsList;
addTopicOfTheDayWhereDynamicLayoutsWillBeAdded.setHasFixedSize(true);
addTopicOfTheDayWhereDynamicLayoutsWillBeAdded.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false));
topicQuestionsList = new ArrayList<>();
...
addTopicOfTheDayAddQuiz.setOnClickListener(v29 -> {
...
// dynamically add questions layout on subsequent clicks
// here with an x button in each layout to remove the
// entire question layout
topicQuestionsList.add(new TopicQuestions());
topicQuestionsAdapter = new TopicQuestionsAdapter("Adapter", getContext(), topicQuestionsList);
addTopicOfTheDayWhereDynamicLayoutsWillBeAdded.setAdapter(topicQuestionsAdapter);
topicQuestionsAdapter.notifyItemInserted(topicQuestionsList.size());
}
});
Now the recycler view layout consists of four FABs to add the different types of questions and options, one textview and one image button to remove the whole view
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TopicQuestionsViewHolder {
//R.layout.add_question_layout is the layout
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.add_question_layout, parent, false)
return TopicQuestionsViewHolder(itemView)
}
/*this is where my problem is i observed that whenever i
add a new question, the layouts i had already added to previous
views get cleared. Recycler view destroys states*/
override fun onBindViewHolder(holder: TopicQuestionsViewHolder, position: Int) {
// the textview to show this question number
holder.questionNumber.text = "${position + 1}."
// the image button to remove the whole view
holder.removeQuestion.setOnClickListener {
topicQuestions.removeAt(position)
notifyItemRemoved(position)
notifyItemRangeChanged(position, topicQuestions.size)
}
holder.addField.setOnClickListener {
// need to fix this
when (holder.theFields.visibility == View.GONE) {
true -> {
holder.theFields.visibility = View.VISIBLE
holder.addField.setImageResource(R.drawable.close)
Log.wtf(TAG, "true")
}
false -> {
holder.theFields.visibility = View.GONE
holder.addField.setImageResource(R.drawable.add)
Log.wtf(TAG, "false")
}
}
}
// this button would add a question field to this view
holder.addQuestionField.setOnClickListener {
val lParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
lParams.topMargin = 16
val view = LayoutInflater.from(ctx).inflate(R.layout.add_question_field_to_question_layout, null)
view.layoutParams = lParams
holder.toAddViews.addView(view)
}
// this button would add an image question field to this view
holder.addImageQuestionField.setOnClickListener {
Log.wtf(TAG, "image question will be added here")
}
// this button would add toggle option to this view
holder.addToggleOption.setOnClickListener {
Log.wtf(TAG, "toggle option will be added here")
}
// this button would add check box option to this view
holder.addCheckBoxOption.setOnClickListener {
Log.wtf(TAG, "check box option will be added here")
}
}
as i had hinted earlier in my code whenever i click on the addTopicOfTheDayAddQuiz button which is supposed to add another view below the already exiting one(s) all child views inside the already existing views are cleared. Please what is a better approach to fix this issue?
Your Adapter is doing a lot of work in onBindViewHolder(): setting up lots of click listeners which in turn toggle the UI so the users can enter their question details without being bothered by UI elements they don't need.
BUT you do not seem to keep track anywhere of the selections the users made for each question.
AND each time the user adds a new question, you throw away the existing Adapter:
topicQuestionsAdapter = new TopicQuestionsAdapter("Adapter", getContext(), topicQuestionsList);
addTopicOfTheDayWhereDynamicLayoutsWillBeAdded.setAdapter(topicQuestionsAdapter);
Since you did not share enough code for me to debug your app and test my solution, I'll just sketch some ideas:
Instead of using a new Adapter each time a new question is created, just add the question to the list and then call (please note: topicQuestionsList.size() - 1)
topicQuestionsAdapter.notifyItemInserted(topicQuestionsList.size() - 1);
One other thing you need to do is keep track of the states of each list item (which Buttons etc. are visible, what is the content of EditTexts if there are any...). If the list gets longer and the users need to scroll, onBindViewHolder() will be called repeatedly even if you keep working with the same Adapter.
So you need a class - let's call it ListEntry - with fields to reflect the possible states of a list item. And inside the Adapter, you can keep a List<ListEntry> with one ListEntry for each item of your data list. Each time some Button becomes visible, you update the corresponding ListEntry. In onBindViewHolder() you evaluate the ListEntry for the given position and set the attributes of the child Views of holder.itemView accordingly.

Not able to change the image color of the image view

I need some help here. I am fetching the data from the JSON.Fetching data. It consists of images and text and I am using the Fast Adapter(mike penz) to populate into recycler view, but when I select the specified row from the recycler view, it needs to change the image color. Where can I change the text view color by using the selector but I can't change the color of the image in the image view of the selected row. Please help me out. Here is the code:
service_type_adapter.withOnClickListener(new FastAdapter.OnClickListener<Service_Type_Adapter>() {
#Override
public boolean onClick(View v, IAdapter<Service_Type_Adapter> adapter, Service_Type_Adapter item, int position) {
AppCompatImageView service_image= (AppCompatImageView) v.findViewById(R.id.service_image);
int service_imagecolors = ContextCompat.getColor(getApplicationContext(), R.color.skyblue);
service_image.setColorFilter(service_imagecolors, PorterDuff.Mode.SRC_IN);
service_type_adapter.select(position);
if (lastselectedposition != -1) {
service_type_adapter.deselect(lastselectedposition);
}
lastselectedposition = position;
servicetypename = item.getServicename();
action = item.getServiceid();
googlemap.clear();
onMapReady(googlemap);
return true;
}
});
The FastAdapter's OnClickListener already provides you everything you need. It passes the clicked item, and also the Adapter responsible for the specific item.
So when the user clicks on the item (and you have enabled selection for that item) the FastAdapter will automatically set the state of that item to selected.
There are multiple ways of automatically applying the color in that case:
Use ColorStateList
The easiest solution is to define a ColorStateList instead of a simple color for that item. For example you could have a Foreground and just define a translucent color if the state is selected.
A very simple ColorStateList could look like this:
return new ColorStateList(
new int[][]{
new int[]{android.R.attr.state_selected},
new int[]{}
},
new int[] {
colorSelected,
Color.TRANSPARENT
}
);
Automatically Notify the Adapter about the change
The FastAdapter allows you to enable the bindView being called in case of the selection. Enable this via: FastAdapter.withSelectWithItemUpdate(true) After this the bindView method of that element is called and you can simply check for isSelected and define the ColorFilter or not
Notify the Adapter manually
If the adapter should not automatically call the notify method you can do this on your own also by doing fastAdapter.notifyAdapterItemChanged(position) (you can optional pass a payload in addition, so you can check for that one in the bindView method) after that check again in the bindView method for isSelected or not and handle the UI as you need it

What action triggers onItemSelected in a ListView?

I have a ListView of Medications that use a CursorAdapter. My goal is to obtain a reference to the Cursor of the selected item when the user presses the submit button, but I keep getting a null value. Here is my current code:
mSubmitButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Cursor selectedMedication = (Cursor) mMedicationListView.getSelectedItem();
if(selectedMedication != null)
{
MedicationSelectionListener activity = (MedicationSelectionListener) getActivity();
activity.onMedicationSelected(new Medication(selectedMedication));
} else{
Toast.makeText(getActivity(), "Must select a medication.", Toast.LENGTH_SHORT).show();
}
}
});
When this executes, selectedMedication is always null. I have implemented a drawable selector.xml file that changes the background color of the item when it is pressed, and that works fine, so I was under the impression that clicking the item was enough.
I have also tried the following, by setting the selected medication variable each time an item is clicked:
mMedicationListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Cursor c = (Cursor) mMedicationListView.getItemAtPosition(position);
if(c.moveToFirst())
mSelectedMedication = new Medication(c);
}
});
This worked fine, but I felt it preformed a bunch of pointless operations when all I am interested in is the final selected item. Should clicking an item trigger mMedicationListView.onItemSelected()? If not, what action is used to ensure that happens?
so I was under the impression that clicking the item was enough.
Clicks are not selections with a ListView. A selection will occur either when:
you set a selection programmatically, or
the user uses a five-way navigation option (e.g., D-pad, trackball, arrow keys) and presses up/down on that to move a highlight bar around
all I am interested in is the final selected item
A ListView is a command widget by default. When the user taps on a row in a ListView, your app should go do something, usually getting rid of the ListView along the way.
If, OTOH, the user is choosing something, where the list and choice remain on-screen (e.g., master-detail pattern, choosing a state/province as part of filling in an address), then you should be using a choice mode. That could be a single-choice mode (usually represented with radio buttons down the right edge), multiple-choice mode (usually represented with checkboxes down the right edge), or multiple-choice-modal mode (usually represented by an "activated" state setting a persistent highlight, usually reserved for master-detail sorts of scenarios).
Do not attempt to overload "selection" to mean "choice". It sounds like you are presenting a ListView as part of something larger, where the user is making a choice, so use a choice mode for that.

Categories