I am working on an app, in which I am want to use a pop-up menu to control some actions and settings. However, when I launch the app in my emulator, the items appear blank, although when I click on them, the action is fired and it works. Here is a screen of the emulator:
I am following the guide, so my code does not differ much from the dev guides, but here is my code:
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view,
int position, long ID)
{
// TODO Auto-generated method stub
courseId = ID;
fields = sqldbase.query(DBHelper.courseTable, new String[] {
DBHelper.courseID, DBHelper.courseName,
DBHelper.courseProf, DBHelper.averageGrade },
DBHelper.courseID + " = " + ID, null, null, null, null);
PopupMenu popup = new PopupMenu(getBaseContext(), view);
popup.getMenuInflater().inflate(R.menu.courses_popup_menu,
popup.getMenu());
popup.show();
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener()
{
#Override
public boolean onMenuItemClick(MenuItem item)
{
Log.i(TAG,"OnMenuItemClick Fired"); return false;
}
});
return false;
}
});
Could this be related to a problem with themes? I have been trying to use a Holo.light.NoTitleBar theme, so in my xml in eclipse, the word Passbook does not show, and everything is white, instead of black. However, after running in the emulator, the theme is ignored, and this shows up.
Thanks.
fixed it. apparently, popup menus use the attribute android:title instead of android:text.
Related
I'm trying to perform long click on searchView menu item in xml menu in android java.
I want to find a way in java code to perform long click on this menu item(the icon not the searchbar) the menu item use app:actionViewClass="android.support.v7.widget.SearchView"
I tried many solutions but none of those working.
Can you lend me an hand please?
EDIT:
Here the code that i try
searchItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
final int itemId = searchItem.getItemId();
View actionView = searchItem.getActionView();
/** define view on long click listener */
final View.OnLongClickListener toolbarItemLongClicked = new View.OnLongClickListener() {
int counter;
#Override
public boolean onLongClick(View view) {
Log.d("longclick", "Long click performed");
return true;
}
};
Hello I am making a small app where i have a list and different popup menus.
I am shading the selected item when the popup menu is triggered.
Is there a way to check if the popup menu that has been active is now not active any more?
For instance I have the popup menu open and i press somewhere else on the screen. The popup menu Disappears. Is there a listener to capture that?
popupMenu2 = new PopupMenu(getContext(), v);
popupMenu2.getMenuInflater().inflate(R.menu.popup_unknown_number,
popupMenu2.getMenu());
popupMenu2.setOnMenuItemClickListener(new
PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
if (item.getItemId() == R.id.delete_unknown) deleteVM(v,model);
return true;
}
});
popupMenu2.show();
Shading is done by
v.setSelected(true);
Found he answer. There is a dismiss listener for PopupMenus
popupMenu.setOnDismissListener(new PopupMenu.OnDismissListener(){
#Override
public void onDismiss(PopupMenu popupMenu) {
// TODO Auto-generated method stub
}
});
Right now I am working on an Android application that requires allowing the user to cut copy and paste onto an editText fields. But when I copy a formatted string from other places (i.e. a string that is underlined) and paste it on to the editText field, it shows it as a formatted version. How do I remove this?
I have tried to add a textwatcher by adding addTextChangedListener, and in the after text change I just do edittext.setText(s.toString()+"") but this creates an infinite loop. :(
Please help! Thanks in advance.
Edit----
I have made some progress by setting setCustomSelectionActionModeCallback
editDestination_.setCustomSelectionActionModeCallback(new Callback() {
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {return true;}
#Override
public void onDestroyActionMode(ActionMode mode) {}
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
menu.removeItem(android.R.id.paste);
menu.removeItem(android.R.id.selectAll);
menu.add(0, CUSTOM_PASTE, 0, "Paste").setIcon(R.drawable.paste_ic);
return true;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case CUSTOM_PASTE:
edittext.setText(readFromClipboard(aContext_));
// Finish and close the ActionMode
mode.finish();
return true;
default:
break;
}
return false;
}
});
This is working pretty well until I realize there are two types of cut/copy/and paste on my phone. One is when the edit text is empty and I long click on the field. This bring up a popup menu. The other one is when there is text in the field, and when I long click, this bring up a cut/copy/and paste bar below my action bar. My code from above is only affecting the bar-below-action bar one. :(
PROBLEM :
The thing you are doing is creating an infinite loop because everytime you call setText(), again afterTextChanged() gets called (because you are changing the text inside the EditText.
SOLUTION :
Suppose the EditText is editTextToClearStyle
EditText editTextToClearStyle = (EditText)findViewById(R.id.youredittextname);
editTextToClearStyle.addTextChangedListener(new TextWatcher(){
public void afterTextChanged(Editable s) {
editTextToClearStyle.setTextAppearance(getApplicationContext(),R.style.normalText);
}
I have solved it.
I set a onLongClickListener to catch it before the popup-cut/copy/paste menu shows up.
CharSequence actions[] = new CharSequence[] {"paste"};
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setCancelable(true);
builder.setItems(actions, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
edittext.setText(readFromClipboard(aContext_));
}
});
builder.show();
Then if there is a string already present in the EditText, I return false to allow normal android system below-action-bar-cut/copy/paste function to work.
I found a workaround to actually enable the ActionBar home button on the nested PreferenceScreen... however it doesn't call OnOptionsItemSelected in my PreferenceActivity. Anyone know a way to actually use the home button on a nested PreferenceScreen?
Modification of post 35 here:
http://code.google.com/p/android/issues/detail?id=4611
#Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference)
{
super.onPreferenceTreeClick(preferenceScreen, preference);
if (preference!=null)
if (preference instanceof PreferenceScreen)
if (((PreferenceScreen)preference).getDialog()!=null)
((PreferenceScreen)preference).getDialog().getActionBar().setHomeButtonEnabled(true);
return false;
}
I had this problem recently and this is how I solved it. Firstly to access the PreferenceScreen I use the exact same method you mentioned above.
#Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
super.onPreferenceTreeClick(preferenceScreen, preference);
// If the user has clicked on a preference screen, set up the action bar
if (preference instanceof PreferenceScreen) {
initializeActionBar((PreferenceScreen) preference);
}
return false;
}
From here I looked into what a PreferenceScreen is, and I was saddened to find out it is just wrapper of a Dialog. Moving forward, I then set the actionbar display options and attempt find the home button area. This unfortunately wasn't too easy to get, but with the help of the hierarchy viewer I managed to gain access by finding the home icon and then its parent views. Once we have access to the containing LinearLayout, we can attach an onClickListener where we dismiss the PreferenceScreen's dialog, which calls PreferenceScreen's onDismissListener and returns us to the previous screen.
/** Sets up the action bar for an {#link PreferenceScreen} */
public static void initializeActionBar(PreferenceScreen preferenceScreen) {
final Dialog dialog = preferenceScreen.getDialog();
if (dialog != null) {
// Inialize the action bar
dialog.getActionBar().setDisplayHomeAsUpEnabled(true);
// Apply custom home button area click listener to close the PreferenceScreen because PreferenceScreens are dialogs which swallow
// events instead of passing to the activity
// Related Issue: https://code.google.com/p/android/issues/detail?id=4611
View homeBtn = dialog.findViewById(android.R.id.home);
if (homeBtn != null) {
OnClickListener dismissDialogClickListener = new OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
}
};
// Prepare yourselves for some hacky programming
ViewParent homeBtnContainer = homeBtn.getParent();
// The home button is an ImageView inside a FrameLayout
if (homeBtnContainer instanceof FrameLayout) {
ViewGroup containerParent = (ViewGroup) homeBtnContainer.getParent();
if (containerParent instanceof LinearLayout) {
// This view also contains the title text, set the whole view as clickable
((LinearLayout) containerParent).setOnClickListener(dismissDialogClickListener);
} else {
// Just set it on the home button
((FrameLayout) homeBtnContainer).setOnClickListener(dismissDialogClickListener);
}
} else {
// The 'If all else fails' default case
homeBtn.setOnClickListener(dismissDialogClickListener);
}
}
}
}
I have been unable to find a tutorial helping with multi-selects using cursors. As of right now my logic is working the way I want but the check boxes will not update properly. What am I overlooking?
return new AlertDialog.Builder(this).setTitle("Items")
.setMultiChoiceItems(cur, CHECK, EDATE, new DialogInterface.OnMultiChoiceClickListener() {
#Override
public void onClick(DialogInterface dialog, int position, boolean checked)
{
DBM.open();
AlertDialog AD = (AlertDialog) dialog;
ListView list = AD.getListView();
list.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
itemCur = (Cursor) list.getItemAtPosition(position);
if (checked)
{
//update query
DBM.setChecked(checkCur.getInt(checkCur.getColumnIndex(ID)), itemId, userId, 1);
list.setItemChecked(1, true);
} else
{
DBM.setChecked(checkCur.getInt(checkCur.getColumnIndex(ID)), itemId, userId, 0);
list.setItemChecked(1, false);
}
DBM.close();
}
}).setPositiveButton("OK", new DialogButtonClickHandler()).create();
Dialogs on android can't be modified. If you look at the source code you will see that dialogbuilder delegates all the presentation work to some components and you don't have access to them after creation. Thus changing the state of the components you use for building the dialog won't update the dialog components afterwards.
You can see this mechanism here and here : you don't have access to the access controller after onCreate has been called on the alert controller.
The best if you want to achieve this is to rebuild a new activity and give it a dialog theme.
You can just use the setCursor() method for AlertDialog. Its pretty simple so you probably wouldn't need a tutorial.
A relevant SO questions is here and the docs for it are here
So after digging into the issue a bit and going through a couple different iterations I finally found a solution that I am fairly happy with. With school and work pushing hard I have had little time outside to work on extra projects and I have been sitting with this solution for while now but unable to get it posted.
The final piece to my puzzle was finding the changeCursor function, this fixed the issue of the old data that no longer matched the DB to load. My current hurdle is the time it takes to check a box, there is an obvious lag from clicked to updated. I have found that mutliple records update when one is clicked. I have not been able to find a valid reason for these extra updates.
Below is the code I currently have implemented to have the multi-select working. This just the dialog code, for a working demo I will be posting a project on GitHub for a working prototype of it all in action. (Now made public, Multiselect Dialog)
I am a fairly new Android developer, majority of my Android knowledge has been self taught and learned through the knowledge of online resources. I was working on a school project and wanted to implement a multiselect in a dialog that would update the main activity with the selected choices. Please lend any advice you can on how to improve this.
Pros:
- Populates check boxes properly on load.
- Updates database when check is clicked.
- Keeps display updated after data change.
Cons:
- Must click check box to update value.
- Unable to undo changes made while in dialog. The values save onClick, I have not been able to think of a way to temporarily store the new values until confirmed by the user.
- A single click updates multiple records, also sometimes when choices scroll off the screen values update
#Override
protected Dialog onCreateDialog(int id)
{
switch (id) {
case 0:
LayoutInflater factory = LayoutInflater.from(this);
// Setup of the view for the dialog
final View bindListDialog = factory.inflate(R.layout.multi_list_layout, null);
multiListView = (ListView) bindListDialog.findViewById(R.id.multiList);
// Because I do not know how to properly handle an undo in this situation
// I make the dialog only close if the button is pressed and confirms the changes
return new AlertDialog.Builder(MultiSelectDemoActivity.this).setTitle(R.string.multiSelectTitle)
.setCancelable(false).setView(bindListDialog)
.setPositiveButton(R.string.btnClose, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton)
{
updateItemList(); // In my implementation there is a list view
// that shows what has been selected.
}
}).create();
default:
return null;
}
}
private static final boolean ONCREATE = true;
private static final boolean ONUPDATE = false;
private void setupMultiList(Boolean newList)
{
demoDBM.open();
multiCur = demoDBM.getList(userId); // Gets all items tied to the user.
startManagingCursor(multiCur);
// Uses the cursor to populate a List item with an invisible ID column,
// a name column, and the checkbox
demoDBM.close();
if (newList)
{
// Creates a new adapter to populate the list view on the dialog
multiAdapter = new SimpleCursorAdapter(this, R.layout.check_list_item, multiCur, new String[] { DemoDBM.ID,
DemoDBM.NAME, DemoDBM.SEL }, new int[] { R.id.itemId, R.id.itemName, R.id.itemCheck });
multiAdapter.setViewBinder(new MyViewBinder());
multiListView.setAdapter(multiAdapter);
} else
{
// updates the previously made adapter with the new cursor, without changing position
multiAdapter.changeCursor(multiCur);
}
}
#Override
protected void onPrepareDialog(final int id, final Dialog dialog, Bundle args)
{
setupMultiList(ONCREATE);
}
public class MyViewBinder implements ViewBinder
{
#Override
public boolean setViewValue(View view, Cursor cursor, int columnIndex)
{
int checkId = cursor.getColumnIndex(DemoDBM.SEL);
if (columnIndex == checkId)
{
CheckBox cb = (CheckBox) view;
// Sets checkbox to the value in the cursor
boolean bChecked = (cursor.getInt(checkId) != 0);
cb.setChecked(bChecked); // Switches the visual checkbox.
cb.setOnCheckedChangeListener(new MyOnCheckedChangeListener());
return true;
}
return false;
}
}
public class MyOnCheckedChangeListener implements OnCheckedChangeListener
{
#Override
public void onCheckedChanged(CompoundButton checkBox, boolean newVal)
{
View item = (View) checkBox.getParent(); // Gets the plain_list_item(Parent) of the Check Box
// Gets the DB _id value of the row clicked and updates the Database appropriately.
int itemId = Integer.valueOf(((TextView) item.findViewById(R.id.itemId)).getText().toString());
demoDBM.open();
demoDBM.setChecked(itemId, userId, newVal);
demoDBM.close();
setupMultiList(ONUPDATE);
}
}