contextual action mode only works for one time - action

i did a contextual action mode and it is working very well when i click on the options that i created but the problem is it the action mode only works for one time and to enable it again i have exit the app and run it again
here's my code
Button.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
if (actionMode != null) {
return false;
}
actionMode = startActionMode(startActionMode);
return true;
}
});
}
private ActionMode.Callback startActionMode = new ActionMode.Callback() {
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mode.getMenuInflater().inflate(R.menu.menu12, menu);
mode.setTitle("choose your option");
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.item1:
Toast.makeText(MainActivity.this, "item 1 pressed", Toast.LENGTH_SHORT).show();
mode.finish();
return true;
case R.id.item2:
Toast.makeText(MainActivity.this, "item 2 pressed", Toast.LENGTH_SHORT).show();
mode.finish();
return true;
default:
return false;
}
}
#Override
public void onDestroyActionMode(ActionMode mode) {
startActionMode = null;
}
};
}

Simply instead of
startActionMode = null;
use
actionMode = null;

Related

numeric soft keyboard in android using ndk

I have a java code that displays the numeric soft keyboard in Android:
public class MainActivity extends Activity {
EditText ed1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ed1 = (EditText) findViewById(R.id.editText1);
ed1.setInputType(InputType.TYPE_CLASS_NUMBER);
}
}
My activity_main.xml file:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="numberkeypad.inputmethod.MainActivity" >
<EditText
android:id="#+id/editText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:ems="10" >
</EditText>
The output is: numeric soft keyboard
I want to display the same keyboard using NDK JNI call and no EditText. I have implemented the default keyboard in this way using the following link:
How to show the soft keyboard on native activity
But I am facing a lot of trouble using the same methodology for the numeric keyboard. Any help would be great..Thanks!
Could not find a way to do this directly, had to override the onCreateInputConnection method of View class, and then make a JNI call to a function using the overridden method.
public class NumbersView extends View {
public NumbersView(Context context) {
super(context);
}
#Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
InputConnection inputConnection = super.onCreateInputConnection(outAttrs);
switch(SystemKeyboardType){
case InputType.TYPE_CLASS_PHONE:
outAttrs.inputType |= InputType.TYPE_CLASS_PHONE;
break;
case InputType.TYPE_CLASS_TEXT:
outAttrs.inputType |= InputType.TYPE_CLASS_TEXT;
break;
case InputType.TYPE_CLASS_NUMBER:
outAttrs.inputType |= InputType.TYPE_CLASS_NUMBER;
break;
case InputType.TYPE_CLASS_DATETIME:
outAttrs.inputType |= InputType.TYPE_CLASS_DATETIME;
break;
default:
outAttrs.inputType |= InputType.TYPE_CLASS_TEXT;
break;
}
return inputConnection;
}
}
**/
#Override
protected void onCreate(Bundle savedInstanceState) {
calculateDeviceDPI();
super.onCreate(savedInstanceState);
myView = new NumbersView(getApplicationContext());
addContentView(myView,new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
myView.setFocusable(true);
myView.setFocusableInTouchMode(true);
//myView.requestFocus();
mContext = this;
}
public void displaySystemKeyboard(String keyboardType){
if(keyboardType.equals("text")) {
SystemKeyboardType = InputType.TYPE_CLASS_TEXT;
}
else if(keyboardType.equals("phone")) {
SystemKeyboardType = InputType.TYPE_CLASS_PHONE;
}
else if(keyboardType.equals("number")) {
SystemKeyboardType = InputType.TYPE_CLASS_NUMBER;
}
else if(keyboardType.equals("datetime")) {
SystemKeyboardType = InputType.TYPE_CLASS_DATETIME;
}
else {
SystemKeyboardType = InputType.TYPE_CLASS_DATETIME;
}
Context ctx = getApplicationContext();
InputMethodManager mgr = (InputMethodManager) ctx.getSystemService(Context.INPUT_METHOD_SERVICE);
myView.requestFocus();
// only will trigger it if no physical keyboard is open
mgr.restartInput(myView);
mgr.showSoftInput(myView, 0);
}
public void hideSystemKeyboard(){
Context ctx = getApplicationContext();
View myView = this.getWindow().getDecorView();
InputMethodManager mgr = (InputMethodManager) ctx.getSystemService(Context.INPUT_METHOD_SERVICE);
mgr.hideSoftInputFromWindow(myView.getWindowToken(), 0);
}
And finally made a JNI call to the function:
if(pShow){
jmethodID showSysKeys = lJNIEnv->GetMethodID(lClassDeviceAPI,"displaySystemKeyboard","(Ljava/lang/String;)V");
if(showSysKeys == NULL){
LOGI("displaySystemKeyboard::Couldn't get void displaySystemKeyboard Method");
return;
}
jstring keyboardType = lJNIEnv->NewStringUTF(KeyboardType.c_str());
if(!keyboardType)
{
LOGI( "failed to alloc param string in java." );
return;
};
lJNIEnv->CallVoidMethod(lObjDeviceAPI,showSysKeys, keyboardType);
}
else{
jmethodID hideSysKeys = lJNIEnv->GetMethodID(lClassDeviceAPI,"hideSystemKeyboard","()V");
if(hideSysKeys == NULL){
LOGI("hideSystemKeyboard::Couldn't get void hideSystemKeyboard Method");
return;
}
lJNIEnv->CallVoidMethod(lObjDeviceAPI,hideSysKeys);
}
lJavaVM->DetachCurrentThread();

ViewPager not working in Google Glass after XE16 update

My Glass got updated to XE16 and thereafter Viewpagers used in Glassware is not working. It is not possible to move to any of the pagers by swiping.If anybody has encountered this before,please do help.
Thanks
Heh. Yeah, the update removed certain standard things from happening (like gestures on the touchpad moving focus etc).
What you have to do is implement a gesturerecogniser/listener and implement the necessary fields, like so (don't forget to instantiate/implement/import etc etc etc in the activity)):
private GestureDetector createGestureDetector(Context context) {
GestureDetector gestureDetector = new GestureDetector(context);
//Create a base listener for generic gestures
gestureDetector.setBaseListener( new GestureDetector.BaseListener() {
#Override
public boolean onGesture(Gesture gesture) {
if (gesture == Gesture.TAP) {
// do something on tap
//do ?
return false;
} else if (gesture == Gesture.TWO_TAP) {
// do something on two finger tap
return true;
} else if (gesture == Gesture.LONG_PRESS) {
// do something on long press
if (!showingMenu)
{
openOptionsMenu();
return true;
}
else
{
return false;
}
} else if (gesture == Gesture.SWIPE_RIGHT) {
// do something on right (forward) swipe
//next slide:
mPosition++;
if (mPosition >= cardArray.size())
{
mPosition = cardArray.size() -1;
}
mGallery.setSelection(mPosition);
return true;
} else if (gesture == Gesture.SWIPE_LEFT) {
// do something on left (backwards) swipe
//previous slide:
mPosition--;
if (mPosition < 0)
{
mPosition = 0;
}
mGallery.setSelection(mPosition);
return true;
}
return false;
}
});
gestureDetector.setFingerListener(new GestureDetector.FingerListener() {
#Override
public void onFingerCountChanged(int previousCount, int currentCount) {
// do something on finger count changes
}
});
/*gestureDetector.setScrollListener(new GestureDetector.ScrollListener() {
#Override
public boolean onScroll(float displacement, float delta, float velocity) {
// do something on scrolling
if (delta > 5.0f)
{
//scroll forwards:
//
}
else if (delta < -5.0f)
{
//scroll backwards:
//
}
return false;
}
});*/
return gestureDetector;
}
/*
* Send generic motion events to the gesture detector
*/
#Override
public boolean onGenericMotionEvent(MotionEvent event) {
if (mGestureDetector != null) {
return mGestureDetector.onMotionEvent(event);
}
return false;
}
I replaced my Viewpager with CardScrollView and it is pretty fast as well.
Do try that out.

Receiving touch events on CardScrollView

I have a CardScrollView that has multiple items in it and I would like to be able to pull up a menu on an item, similar to the built in Timeline.
I know Card cannot have a specific menu attached to it so I have the menu prepared at the Activity level.
However, something seems to be swallowing all onKeyDown events.
public class HostsView extends CardScrollView {
private String TAG = "HostsView";
private HostsCardScrollAdapter cards;
private Activity parent;
public HostsView(Activity parent, HostDatabase hostDb) {
super(parent);
cards = new HostsCardScrollAdapter(parent);
//populates the cards and what not
this.setAdapter(cards);
this.activate();
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
//I never see this log
Log.d(TAG, "Key event " + event.toString());
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
parent.openOptionsMenu();
return true;
}
return super.onKeyDown(keyCode, event);
}
}
If you only need to handle a simple tap on a card in a CardScrollView, you can call setOnItemClickListener to attach an AdapterView.OnItemClickListener, just as you would with a standard Android ListView. This is typically much simpler than working with GestureDetector for this basic use case.
yesterday I came across the same problem. I solved it with a GestureDetector, as the GDK documentation recommends. Here is the code I used:
private GestureDetector mGestureDetector;
#Override
public void onCreate(Bundle savedInstanceState) {
mGestureDetector = createGestureDetector(this);
}
private GestureDetector createGestureDetector(Context context) {
GestureDetector gestureDetector = new GestureDetector(context);
gestureDetector.setBaseListener( new GestureDetector.BaseListener() {
#Override
public boolean onGesture(Gesture gesture) {
if (gesture == Gesture.LONG_PRESS || gesture == Gesture.TAP) {
Log.d(MainActivity.TAG, "Tap"); //When I tap the touch panel, I only get LONG_PRESS
openOptionsMenu();
return true;
} else if (gesture == Gesture.TWO_TAP) {
return true;
} else if (gesture == Gesture.SWIPE_RIGHT) {
return true;
} else if (gesture == Gesture.SWIPE_LEFT) {
return true;
}
return false;
}
});
return gestureDetector;
}
#Override
public boolean onGenericMotionEvent(MotionEvent event) {
if (mGestureDetector != null) {
return mGestureDetector.onMotionEvent(event);
}
return false;
}
Your menu should open now!

Google Glass GDK Tap Gesture

With GDK and sample code provide by Google the TAP gesture is not being recognized as a TAP. Is returned as LONG_PRESS everytime. Below is the code:
import com.google.android.glass.touchpad.Gesture;
import com.google.android.glass.touchpad.GestureDetector;
public class MainActivity extends Activity {
Logger log = Logger.getLogger("MainActivity");
private GestureDetector mGestureDetector;
// ...
#Override
protected void onCreate(Bundle savedInstanceState) {
// ...
mGestureDetector = createGestureDetector(this);
}
private GestureDetector createGestureDetector(Context context) {
GestureDetector gestureDetector = new GestureDetector(context);
//Create a base listener for generic gestures
gestureDetector.setBaseListener( new GestureDetector.BaseListener() {
#Override
public boolean onGesture(Gesture gesture) {
log.info(gesture.name());
if (gesture == Gesture.TAP) {
// do something on tap
return true;
} else if (gesture == Gesture.TWO_TAP) {
// do something on two finger tap
return true;
} else if (gesture == Gesture.SWIPE_RIGHT) {
// do something on right (forward) swipe
return true;
} else if (gesture == Gesture.SWIPE_LEFT) {
// do something on left (backwards) swipe
return true;
}
return false;
}
});
gestureDetector.setFingerListener(new GestureDetector.FingerListener() {
#Override
public void onFingerCountChanged(int previousCount, int currentCount) {
// do something on finger count changes
}
});
gestureDetector.setScrollListener(new GestureDetector.ScrollListener() {
#Override
public boolean onScroll(float displacement, float delta, float velocity) {
// do something on scrolling
}
});
return gestureDetector;
}
/*
* Send generic motion events to the gesture detector
*/
#Override
public boolean onGenericMotionEvent(MotionEvent event) {
if (mGestureDetector != null) {
return mGestureDetector.onMotionEvent(event);
}
return false;
}
}
Am I missing something here or is this a bug?
If you're only looking to capture tap events for a UI (without using GestureDetector and everything), in Glass touchpad taps are registered as center clicking a d-pad, so you can simply intercept the KEYCODE_DPAD_CENTER key presses.
Try this:
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_DPAD_CENTER){
// The touchpad was tapped
return true;
}
return false;
}
I had the same problem as you and my answer could be strange but I avoided it using a switch instead of the if else structure. Moreover with this new code you will be able to capture the rest of the gestures.
I hope it will help you as well.
private GestureDetector createGestureDetector(Context context){
GestureDetector gestureDetector = new GestureDetector(context);
//Create a base listener for generic gestures
gestureDetector.setBaseListener( new GestureDetector.BaseListener() {
#Override
public boolean onGesture(Gesture gesture) {
Log.e(TAG,"gesture = " + gesture);
switch (gesture) {
case TAP:
Log.e(TAG,"TAP called.");
handleGestureTap();
break;
case LONG_PRESS:
Log.e(TAG,"LONG_PRESS called.");
return true;
case SWIPE_DOWN:
Log.e(TAG,"SWIPE_DOWN called.");
return true;
case SWIPE_LEFT:
Log.e(TAG,"SWIPE_LEFT called.");
return true;
case SWIPE_RIGHT:
Log.e(TAG,"SWIPE_RIGHT called.");
return true;
case SWIPE_UP:
Log.e(TAG,"SWIPE_UP called.");
return true;
case THREE_LONG_PRESS:
Log.e(TAG,"THREE_LONG_PRESS called.");
return true;
case THREE_TAP:
Log.e(TAG,"THREE_TAP called.");
return true;
case TWO_LONG_PRESS:
Log.e(TAG,"TWO_LONG_PRESS called.");
return true;
case TWO_SWIPE_DOWN:
Log.e(TAG,"TWO_SWIPE_DOWN called.");
return true;
case TWO_SWIPE_LEFT:
Log.e(TAG,"TWO_SWIPE_LEFT called.");
return true;
case TWO_SWIPE_RIGHT:
Log.e(TAG,"TWO_SWIPE_RIGHT called.");
return true;
case TWO_SWIPE_UP:
Log.e(TAG,"TWO_SWIPE_UP called.");
return true;
case TWO_TAP:
Log.e(TAG,"TWO_TAP called.");
return true;
}
return false;
}
});
gestureDetector.setFingerListener(new com.google.android.glass.touchpad.GestureDetector.FingerListener() {
#Override
public void onFingerCountChanged(int previousCount, int currentCount) {
// do something on finger count changes
Log.e(TAG,"onFingerCountChanged()");
}
});
gestureDetector.setScrollListener(new com.google.android.glass.touchpad.GestureDetector.ScrollListener() {
#Override
public boolean onScroll(float displacement, float delta, float velocity) {
// do something on scrolling
Log.e(TAG,"onScroll()");
return false;
}
});
return gestureDetector;
}
Copying and pasting the GestureDetector code from the GDK and modifying it is all you should need to do. If it's working for double tap then I'd suspect you may have some hardware issue with Glass.
Have you tried doing a Toast for Gesture.TAP? Perhaps TAP and LONG PRESS are the same?
The code below will call generateCard() when you tap Glass.
private GestureDetector createGestureDetector(Context context) {
GestureDetector gestureDetector = new GestureDetector(context);
//Create a base listener for generic gestures
gestureDetector.setBaseListener( new GestureDetector.BaseListener() {
#Override
public boolean onGesture(Gesture gesture) {
if (gesture == Gesture.TAP) { // On Tap, generate a new number
generateCard();
return true;
} else if (gesture == Gesture.TWO_TAP) {
// do something on two finger tap
return true;
} else if (gesture == Gesture.SWIPE_RIGHT) {
// do something on right (forward) swipe
return true;
} else if (gesture == Gesture.SWIPE_LEFT) {
// do something on left (backwards) swipe
return true;
}
return false;
}
});
gestureDetector.setFingerListener(new GestureDetector.FingerListener() {
#Override
public void onFingerCountChanged(int previousCount, int currentCount) {
// do something on finger count changes
}
});
gestureDetector.setScrollListener(new GestureDetector.ScrollListener() {
#Override
public boolean onScroll(float displacement, float delta, float velocity) {
// do something on scrolling
return false;
}
});
return gestureDetector;
}
/*
* Send generic motion events to the gesture detector
*/
#Override
public boolean onGenericMotionEvent(MotionEvent event) {
if (mGestureDetector != null) {
return mGestureDetector.onMotionEvent(event);
}
return false;
}

how to refresh the linear layout view after deleting an element

I have a simple app, in one activity I take name and date of birth. I store it in the database. and in the main activity I have linearlayout which will show all the names.
When I click on any of the name in the main activity, it should delete that name from the database and also refresh the view.
I am able to delete the entry from database, but my linear layout view is not being updated. Can some one pls help.
public class child extends Activity {
private Intent intent;
private LinearLayout layout;
private LayoutInflater linflater;
private int i =0;
private Cursor cr;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.child);
layout = (LinearLayout)findViewById(R.id.layout);
Button addBtn = (Button)findViewById(R.id.AddButton);
Button remBtn = (Button)findViewById(R.id.RemoveButton);
intent = new Intent(this,login.class);
layout = (LinearLayout) findViewById(R.id.mylayout1);
linflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//Check the database if there are any entries available. If available, then
//list them on the main screen
final myDBAdapter mydb = new myDBAdapter(getApplicationContext());
mydb.open();
cr = mydb.GetMyData();
if(cr.getCount()>0)
{
cr.moveToFirst();
for (int i=0;i<cr.getCount();i++)
{
cr.moveToPosition(i);
buildList(cr.getString(1),cr.getString(2));
}
}
//Start the login activity which will return the newly added baby name
addBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
startActivityForResult(intent, 1001);
}
});
//Remove all the entries from Database
remBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if(cr.getCount()>0)
{
cr.moveToFirst();
for (int i=0;i<cr.getCount();i++)
{
Toast.makeText(getApplicationContext(), cr.getString(1),
Toast.LENGTH_LONG).show();
mydb.RemoveEntry(cr.getString(1));
cr.moveToPosition(i);
}
}
}
});
mydb.close();
}
private void buildList(final String bname,String bsex)
{
final View customView = linflater.inflate(R.layout.child_view,
null);
TextView tv = (TextView) customView.findViewById(R.id.TextView01);
//tv.setId(i);
tv.setText(bname);
tv.setTextColor(getResources().getColor(R.color.black));
tv.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myDBAdapter mydb = new myDBAdapter(getApplicationContext());
mydb.open();
if (mydb.RemoveEntry(bname)>0)
{
Toast.makeText(getApplicationContext(), "Row deleted",
Toast.LENGTH_LONG).show();
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
WHAT IS REQUIRED HERE TO UPDATE THE VIEW???
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}
else
{
Toast.makeText(getApplicationContext(), "Row not deleted",
Toast.LENGTH_LONG).show();
}
}
});
layout.addView(customView);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
if(requestCode == 1001)
{
if(resultCode == RESULT_OK)
{
Bundle extras = data.getExtras();
buildList(extras.getString("bname"),extras.getString("bsex"));
}
}
}
}
Hmm I'm also trying to get this to work, Have you tried looking at maybe refreshing the LinearLayout every say 5 seconds using a game loop? This may prove to be useful as it helped me with my problem http://aubykhan.wordpress.com/2010/04/25/android-game-programming-the-game-loop/
You may also be able to call onCreate(Bundle) function again while this is a terrible terrible way to do this it will work.