I am trying to implement the app similar to true caller,I am able to get the phone number when the phone rings using broadcast receiver and opening the MyCustomDialog Activity
This is my receiver class by which I am getting the Call State that the call is starts or ends. In this, I make some methods which I am using in CallReceiver.java
PhonecallReceiver.java
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import java.util.Date;
public abstract class PhonecallReceiver extends BroadcastReceiver
{
private static int lastState = TelephonyManager.CALL_STATE_IDLE;
private static Date callStartTime;
private static boolean isIncoming;
private static String savedNumber;
#Override
public void onReceive(Context context, Intent intent)
{
try
{
if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL"))
{
savedNumber = intent.getExtras().getString("android.intent.extra.PHONE_NUMBER");
}
else
{
String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
int state = 0;
if(stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE))
{
state = TelephonyManager.CALL_STATE_IDLE;
}
else if(stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK))
{
state = TelephonyManager.CALL_STATE_OFFHOOK;
}
else if(stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING))
{
state = TelephonyManager.CALL_STATE_RINGING;
}
onCallStateChanged(context, state, number);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
//Derived classes should override these to respond to specific events of interest
protected void onIncomingCallStarted(Context ctx, String number, Date start){}
protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end){}
public void onCallStateChanged(Context context, int state, String number)
{
if(lastState == state)
{
//No change, debounce extras
return;
}
switch (state)
{
case TelephonyManager.CALL_STATE_RINGING:
isIncoming = true;
callStartTime = new Date();
savedNumber = number;
onIncomingCallStarted(context, number, callStartTime);
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
if (isIncoming)
{
onIncomingCallEnded(context,savedNumber,callStartTime,new Date());
}
case TelephonyManager.CALL_STATE_IDLE:
if(isIncoming)
{
onIncomingCallEnded(context, savedNumber, callStartTime, new Date());
}
}
lastState = state;
}
}
CallReceiver.java
import android.app.Activity;
import android.app.Dialog;
import android.app.Notification;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.ColorDrawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.Toast;
import android.os.Handler;
import java.util.Date;
import dootam.dspl.com.lawyercasecall.R;
public class CallReceiver extends PhonecallReceiver
{
Context context;
#Override
protected void onIncomingCallStarted(final Context ctx, String number, Date start)
{
Toast.makeText(ctx,"Kushal Incoming Call"+ number,Toast.LENGTH_LONG).show();
context = ctx;
final Intent intent = new Intent(context, MyCustomDialog.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtra("phone_no",number);
new Handler().postDelayed(new Runnable()
{
#Override
public void run()
{
context.startActivity(intent);
}
},2000);
// MyCus/*tomDialog dialog = new MyCustomDialog(context);
// dialog.*/show();
}
#Override
protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end)
{
Toast.makeText(ctx,"Bye Bye"+ number,Toast.LENGTH_LONG).show();
}
}
MyCustomDialog.java
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.TextView;
import dootam.dspl.com.lawyercasecall.R;
public class MyCustomDialog extends Activity
{
TextView tv_client;
String phone_no;
Button dialog_ok;
#Override
protected void onCreate(Bundle savedInstanceState)
{
try
{
requestWindowFeature(Window.FEATURE_NO_TITLE);
this.setFinishOnTouchOutside(false);
super.onCreate(savedInstanceState);
setContentView(R.layout.dialog);
initializeContent();
/*WindowManager.LayoutParams params = getWindow().getAttributes();
params.x = -100;
params.height = 70;
params.width = 1000;
params.y = -50;
this.getWindow().setAttributes(params);*/
phone_no = getIntent().getExtras().getString("phone_no");
tv_client.setText(""+phone_no +" is calling you");
dialog_ok.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
MyCustomDialog.this.finish();
// this.setFinishOnTouchOutside(false);
System.exit(0);
}
});
}
catch (Exception e)
{
Log.d("Exception", e.toString());
e.printStackTrace();
}
}
private void initializeContent()
{
tv_client = (TextView) findViewById(R.id.tv_client);
dialog_ok = (Button) findViewById(R.id.dialog_ok);
}
}
My AndroidManifest.xml
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".AddCasesActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".receiver.MyCustomDialog"
android:theme="#android:style/Theme.Dialog"
android:noHistory="true"
/>
<receiver android:name=".receiver.CallReceiver" >
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" tools:ignore="ProtectedPermissions"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
By implementing all this stuff I am getting the desired output
Please guide me how to make this activity dialog dragable like the popup of the truecaller app.
I am searching for the dialog similar to this image ,
It is possible through OnTouchListener, Try this https://github.com/andreilisun/Swipe-To-Dismiss-Dialog
The Dialog is draggable, I have changed the SwipeDimissDialog to remove dismissal of Dialog in the following class -
public class SwipeDismissDialog extends FrameLayout {
private final Params params;
private View dialog;
protected SwipeDismissDialog(#NonNull Context context, Params params) {
super(context);
this.params = params;
init();
}
private void init() {
setOnClickListener(overlayClickListener);
setBackgroundColor(params.overlayColor);
dialog = params.view;
if (dialog == null) {
dialog = LayoutInflater.from(getContext()).inflate(params.layoutRes, this, false);
}
LayoutParams layoutParams = (LayoutParams) dialog.getLayoutParams();
if (layoutParams == null) {
layoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER);
} else {
layoutParams.gravity = Gravity.CENTER;
}
dialog.setOnTouchListener(touchListener);
addView(dialog, layoutParams);
}
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN
&& event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
cancel();
return true;
}
return false;
}
public SwipeDismissDialog show() {
WindowManager windowManager = (WindowManager)
getContext().getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
layoutParams.height = WindowManager.LayoutParams.MATCH_PARENT;
layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION;
layoutParams.format = PixelFormat.TRANSLUCENT;
windowManager.addView(this, layoutParams);
return this;
}
public void cancel() {
if (params.cancelListener != null) {
params.cancelListener.onCancel(dialog);
}
if (params.dismissOnCancel) {
dismiss();
}
}
public void dismiss() {
dialog.setOnTouchListener(null);
removeView(dialog);
WindowManager windowManager = (WindowManager)
getContext().getSystemService(Context.WINDOW_SERVICE);
windowManager.removeViewImmediate(this);
}
private void dismiss(SwipeDismissDirection direction) {
if (params.swipeDismissListener != null) {
params.swipeDismissListener.onSwipeDismiss(this, direction);
}
dismiss();
}
private final OnTouchListener touchListener = new OnTouchListener() {
private float initCenterX;
private float lastEventY;
private float lastEventX;
private float initY;
private float initX;
public boolean onTouch(View view, MotionEvent motionEvent) {
/*Fling detected*/
int action = motionEvent.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN: {
initX = view.getX();
initY = view.getY();
lastEventX = motionEvent.getRawX();
lastEventY = motionEvent.getRawY();
initCenterX = initX + view.getWidth() / 2;
break;
}
case MotionEvent.ACTION_MOVE: {
float eventX = motionEvent.getRawX();
float eventY = motionEvent.getRawY();
float eventDx = eventX - lastEventX;
float eventDy = eventY - lastEventY;
float centerX = view.getX() + eventDx + view.getWidth() / 2;
float centerDx = centerX - initCenterX;
view.setX(view.getX() + eventDx);
view.setY(view.getY() + eventDy);
//view.invalidate();
lastEventX = eventX;
lastEventY = eventY;
break;
}
}
return true;
}
};
private final OnClickListener overlayClickListener = new OnClickListener() {
#Override
public void onClick(View v) {
cancel();
}
};
public static class Builder {
private final Params params;
private final Context context;
public Builder(Context context) {
this.context = context;
this.params = new Params();
}
public Builder setView(#NonNull View view) {
params.view = view;
params.layoutRes = 0;
return this;
}
public Builder setLayoutResId(#LayoutRes int layoutResId) {
params.layoutRes = layoutResId;
params.view = null;
return this;
}
public SwipeDismissDialog build() {
if (params.view == null && params.layoutRes == 0) {
throw new IllegalStateException("view should be set with setView(View view) " +
"or with setLayoutResId(int layoutResId)");
}
return new SwipeDismissDialog(context, params);
}
}
}
Related
I have build an app where I need to show card on an incoming call. It works fine in Kitkat, but in Android L, M, N the card appears twice, why?
Result (Kitkat)
Result (Lollipop-Nougat-Marshmallow)
My code
package tutorials.hackro.com.callincoming;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.PixelFormat;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
/**
* Created by hackro on 4/03/17.
*/
public class MyPhoneBroadcastReceiver extends BroadcastReceiver {
private WindowManager wm;
private WindowManager.LayoutParams params;
private LinearLayout ly;
private View view;
private TextView lblCelular,nameContact;
private Button btnExpediente;
private int height;
private Context context;
private String number;
private Display display;
private LayoutInflater mInflater;
private Bundle bundle;
private TelephonyManager telephony;
private boolean callincoming;
public void onReceive(final Context cc, Intent intent) {
this.context= cc;
bundle = intent.getExtras();
number = bundle.getString("incoming_number");
intializeElements();
initializeUI();
initializeValuesElements();
events();
telephony = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
telephony.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}
private PhoneStateListener phoneStateListener = new PhoneStateListener() {
public void onCallStateChanged(int state, String incomingNumber) {
if (state == TelephonyManager.CALL_STATE_RINGING) {
if(!callincoming){
wm.addView(ly, params);
Log.e("a","a");
callincoming = !callincoming;
}
}
if (state == TelephonyManager.CALL_STATE_OFFHOOK) {
System.exit(0);
}
if (state == TelephonyManager.CALL_STATE_IDLE) {
System.exit(0);
}
}
};
private void intializeElements() {
wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
ly = new LinearLayout(context);
mInflater = LayoutInflater.from(context);
view = mInflater.inflate(R.layout.call,null);
display = wm.getDefaultDisplay();
height = display.getHeight();
initializeParams();
ly.addView(view,params);
}
public void events(){
ly.setOnTouchListener(new View.OnTouchListener() {
private int initialX;
private int initialY;
private float initialTouchX;
private float initialTouchY;
#Override public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
initialX = params.x;
initialY = params.y;
initialTouchX = event.getRawX();
initialTouchY = event.getRawY();
return true;
case MotionEvent.ACTION_UP:
return true;
case MotionEvent.ACTION_MOVE:
params.x = initialX + (int) (event.getRawX() - initialTouchX);
params.y = initialY + (int) (event.getRawY() - initialTouchY);
wm.updateViewLayout(ly, params);
return true;
}
return false;
}
});
btnExpediente.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
params.height = 0;
ly.removeView(view);
wm.updateViewLayout(ly,params);
Intent i = new Intent(context,Main2Activity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
});
}
public static String getContactName(Context context, String phoneNumber) {
ContentResolver cr = context.getContentResolver();
Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
Cursor cursor = cr.query(uri, new String[]{ContactsContract.PhoneLookup.DISPLAY_NAME}, null, null, null);
if (cursor == null) {
return null;
}
String contactName = null;
if(cursor.moveToFirst()) {
contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME));
}
if(cursor != null && !cursor.isClosed()) {
cursor.close();
}
return contactName;
}
private void initializeParams(){
params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT |
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSPARENT);
int SDK_INT = android.os.Build.VERSION.SDK_INT;
if(SDK_INT >= Build.VERSION_CODES.KITKAT && SDK_INT <= Build.VERSION_CODES.LOLLIPOP){
params.height = (height/2);
}
else if(SDK_INT >= Build.VERSION_CODES.LOLLIPOP && SDK_INT <= Build.VERSION_CODES.M){
params.height = (height/4) + (height/15);
}
else if(SDK_INT >= Build.VERSION_CODES.M && SDK_INT <= Build.VERSION_CODES.N){
params.height = (height/4) + (height/15);
}
else if(SDK_INT >= Build.VERSION_CODES.N){
params.height = (height/4) + (height/15);
}
params.height = (height/2);
params.width = WindowManager.LayoutParams.MATCH_PARENT;
params.gravity = Gravity.TOP;
params.format = PixelFormat.TRANSLUCENT;
}
public void initializeUI(){
lblCelular = (TextView) view.findViewById(R.id.lblCelular);
nameContact= (TextView) view.findViewById(R.id.nameContact);
btnExpediente = (Button) view.findViewById(R.id.btnExpediente);
}
public void initializeValuesElements(){
nameContact.setText(getContactName(context,number));
lblCelular.setText(number);
}
public void onDestroy() {
telephony.listen(null, PhoneStateListener.LISTEN_NONE);
}
}
I solved my problem.
The problem is multiple call onReceive
SOLUTION
public static final String TAG = "PHONE STATE";
private static String mLastState;
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if (!state.equals(mLastState)) {
mLastState = state;
Log.e(TAG, state);
telephony = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
telephony.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}
You can see more details here
this is my service class in my app.
this is a app that shows two icon (imageView) as system_alert_window that these icons can open two activity.
when start service, after several minutes or after execute a activity from service and then comeback, after several seconds service has been force close two times.
package com.MDGH.Always_Accessible;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences.Editor;
import android.graphics.PixelFormat;
import android.os.CountDownTimer;
import android.os.IBinder;
import android.text.Html;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationSet;
import android.view.animation.RotateAnimation;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
public class ServiceStart extends Service implements OnClickListener , OnTouchListener{
private static WindowManager wm;
private View topLeftView;
private int originalXpos, originalYpos, originalXpos2, originalYpos2;
private float offsetX, offsetY, offsetX2, offsetY2;
public static FrameLayout popup_show_overlay,sms_read_overlay;
public static ImageView popup_show_icon,sms_RW_icon;
private boolean moving, moving2;
public static boolean popup_show_Swap=false,sms_read_Swap=false, serviceButtonClicked=false;
private static FrameLayout subScript_overlay;
private static boolean trueTopFalseBottom=false;
private static TextView subScriptTextView;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
LayoutInflater inflater = (LayoutInflater)getApplicationContext().getSystemService(LAYOUT_INFLATER_SERVICE);
sms_read_overlay = (FrameLayout)inflater.inflate(R.layout.floating_sms_read, null);
popup_show_overlay = (FrameLayout)inflater.inflate(R.layout.floating_popup_show, null);
subScript_overlay = (FrameLayout)inflater.inflate(R.layout.floating_subscript, null);
subScriptTextView = (TextView)subScript_overlay.findViewById(R.id.subScriptTextView);
sms_RW_icon = (ImageView)sms_read_overlay.findViewById(R.id.sms_read);
popup_show_icon = (ImageView)popup_show_overlay.findViewById(R.id.popup_show);
if(sms_read_Swap==false)sms_RW_icon.setImageResource(R.drawable.sms_write);
else sms_RW_icon.setImageResource(R.drawable.sms_read);
ApplyAppearances();
sms_RW_icon.setVisibility(View.INVISIBLE);
sms_read_overlay.setVisibility(View.INVISIBLE);
subScript_overlay.setVisibility(View.INVISIBLE);
subScriptTextView.setVisibility(View.INVISIBLE);
popup_show_overlay.setOnTouchListener(this);
sms_read_overlay.setOnTouchListener(this);
popup_show_overlay.setOnClickListener(this);
sms_read_overlay.setOnClickListener(this);
subScript_overlay.setOnTouchListener(this);
subScript_overlay.setOnClickListener(this);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, PixelFormat.TRANSLUCENT);
params.gravity = Gravity.LEFT | Gravity.TOP;
params.x = 0;
params.y = 0;
wm.addView(subScript_overlay, params);
params.gravity = Gravity.LEFT | Gravity.TOP;
params.x = 3000;
params.y = ConfigMain.popup_show_height+10;
wm.addView(sms_read_overlay, params);
params.gravity = Gravity.LEFT | Gravity.TOP;
params.x = 3000;
params.y = 0;
wm.addView(popup_show_overlay, params);
topLeftView = new View(this);
WindowManager.LayoutParams topLeftparams = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, PixelFormat.TRANSLUCENT);
topLeftparams.gravity = Gravity.LEFT | Gravity.TOP;
topLeftparams.x = 0;
topLeftparams.y = 0;
topLeftparams.width = 0;
topLeftparams.height = 0;
wm.addView(topLeftView, topLeftparams);
sms_read_overlay.setOnLongClickListener(new OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
if(!moving2){
}
return false;
}
});
/*
popup_show_overlay.setOnLongClickListener(new OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
if(!moving){
}
return false;
}
});*/
}
#Override
public void onDestroy() {
super.onDestroy();
if(SmsBoxWrite.smsBoxWriteHasRuning)SmsBoxWrite.popUpWindowWrite.dismiss();
if(SmsBoxRead.smsBoxReadHasRuning)SmsBoxRead.popUpWindowRead.dismiss();
if(popup_show_overlay!=null){
wm.removeView(popup_show_overlay);
popup_show_overlay=null;
}
if(sms_read_overlay!=null){
wm.removeView(sms_read_overlay);
sms_read_overlay=null;
}
if(subScript_overlay!=null){
wm.removeView(subScript_overlay);
subScript_overlay=null;
}
wm.removeView(topLeftView);
topLeftView=null;
Editor editor = ConfigMain.sp.edit();
editor.putBoolean("isActive", false);
editor.commit();
Toast.makeText(getApplicationContext(), "Destroy",Toast.LENGTH_SHORT).show();
//popup_show_overlay.setVisibility(View.INVISIBLE);
}
long sdf1,sdf2;
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (v.getId()) {
case R.id.popup_show_frame:
if(event.getAction() == MotionEvent.ACTION_DOWN){
sdf1 = System.currentTimeMillis();
float x = event.getRawX();
float y = event.getRawY();
moving = false;
int[] location = new int[2];
popup_show_overlay.getLocationOnScreen(location);
originalXpos = location[0];
originalYpos = location[1];
offsetX = originalXpos -x ;
offsetY = originalYpos -y;
}
else if( event.getAction() == MotionEvent.ACTION_MOVE){
sdf2 = System.currentTimeMillis();
if((sdf2-sdf1)>2000)serviceExit();
int[] topLeftLocationOnScreen = new int[2];
topLeftView.getLocationOnScreen(topLeftLocationOnScreen);
System.out.println("topLeftY="+topLeftLocationOnScreen[1]);
System.out.println("originalY="+originalYpos);
float x = event.getRawX();
float y = event.getRawY();
WindowManager.LayoutParams params = (LayoutParams)popup_show_overlay.getLayoutParams();
int newX = (int) (offsetX + x);
int newY = (int) (offsetY + y);
if(Math.abs(newX -originalXpos)<1 && Math.abs(newY - originalYpos) <1 && !moving)return false;
params.x = newX - (topLeftLocationOnScreen[0]);
params.y = newY - (topLeftLocationOnScreen[1]);
wm.updateViewLayout(popup_show_overlay, params);
moving =true;}
else if ( event.getAction() == MotionEvent.ACTION_UP){
boolean moving22 = moving;
moving=false;
if(moving22) return true;
}
return false;
case R.id.sms_read_frame:
if(event.getAction() == MotionEvent.ACTION_DOWN){
float x2 = event.getRawX();
float y2 = event.getRawY();
moving2 = false;
int[] location2 = new int[2];
sms_read_overlay.getLocationOnScreen(location2);
originalXpos2 = location2[0];
originalYpos2 = location2[1];
offsetX2 = originalXpos2 -x2 ;
offsetY2 = originalYpos2 -y2;
}
else if( event.getAction() == MotionEvent.ACTION_MOVE){
int[] topLeftLocationOnScreen = new int[2];
topLeftView.getLocationOnScreen(topLeftLocationOnScreen);
System.out.println("topLeftY="+topLeftLocationOnScreen[1]);
System.out.println("originalY="+originalYpos2);
float x2 = event.getRawX();
float y2 = event.getRawY();
WindowManager.LayoutParams params = (LayoutParams)sms_read_overlay.getLayoutParams();
int newX2 = (int) (offsetX2 + x2);
int newY2 = (int) (offsetY2 + y2);
if(Math.abs(newX2 -originalXpos2)<1 && Math.abs(newY2 - originalYpos2) <1 && !moving2) return false;
params.x = newX2 - (topLeftLocationOnScreen[0]);
params.y = newY2 - (topLeftLocationOnScreen[1]);
wm.updateViewLayout(sms_read_overlay, params);
moving2 =true;}
else if ( event.getAction() == MotionEvent.ACTION_UP){
boolean moving22 = moving2;
moving2=false;
if(moving22) return true;
}
return false;
default:
return false;
}
}
private void serviceExit() {
Editor editor = ConfigMain.sp.edit();
editor.putBoolean("isActive", false);
editor.commit();
ScaleAnimation sc = new ScaleAnimation(1,0, 1, 0, ConfigMain.popup_show_width/2, ConfigMain.popup_show_height/2);
sc.setDuration((int)(300*ConfigMain.animationSpeed));
ServiceStart.popup_show_icon.startAnimation(sc);
sc.setAnimationListener(new AnimationListener() {
public void onAnimationStart(Animation arg0) {}
public void onAnimationRepeat(Animation arg0) {}
#Override
public void onAnimationEnd(Animation arg0) {
stopSelf();
int pid = android.os.Process.myPid();
android.os.Process.killProcess(pid);
}});
}
#Override
public void onClick(View v) {
if((moving2)||(moving))return;
switch (v.getId()) {
case R.id.popup_show_frame:
popup_show_Swap=!popup_show_Swap;
if(popup_show_Swap==true){
AlphaAnimation al = new AlphaAnimation(1, 4/10);
al.setDuration((int)(200*ConfigMain.animationSpeed));
popup_show_icon.startAnimation(al);
al.setAnimationListener(new AnimationListener() {
public void onAnimationStart(Animation arg0) {}
public void onAnimationRepeat(Animation arg0) {}
#Override
public void onAnimationEnd(Animation arg0) {
popup_show_icon.setImageResource(R.drawable.tick);
AlphaAnimation al = new AlphaAnimation(4/10, 1);
al.setDuration((int)(200*ConfigMain.animationSpeed));
popup_show_icon.startAnimation(al);
}
});
}
else{
AlphaAnimation al = new AlphaAnimation(1, 4/10);
al.setDuration((int)(400*ConfigMain.animationSpeed));
popup_show_icon.startAnimation(al);
al.setAnimationListener(new AnimationListener() {
public void onAnimationStart(Animation arg0) {}
public void onAnimationRepeat(Animation arg0) {}
#Override
public void onAnimationEnd(Animation arg0) {
popup_show_icon.setImageResource(R.drawable.not);
AlphaAnimation al = new AlphaAnimation(4/10, 1);
al.setDuration((int)(400*ConfigMain.animationSpeed));
popup_show_icon.startAnimation(al);
}});
}
serviceButtonClicked=true;
if(popup_show_Swap==true){
smsReadIconVisibleWithAnim();
if(sms_read_Swap==true){
SmsTextBoxReadVisible();
}
else if(sms_read_Swap==false){
SmsTextBoxWriteVisible();
}
}
else if(popup_show_Swap==false){
smsReadIconDisibleWithAnim();
if(SmsBoxWrite.smsBoxWriteHasRuning)SmsBoxWrite.popUpWindowWrite.dismiss();
if(SmsBoxRead.smsBoxReadHasRuning)SmsBoxRead.popUpWindowRead.dismiss();
sms_read_overlay.setVisibility(View.INVISIBLE);
sms_RW_icon.setVisibility(View.INVISIBLE);
//Toast.makeText(getApplicationContext(), "Default", Toast.LENGTH_SHORT).show();
}
break;
case R.id.sms_read_frame:
smsReadWriteChangeIconWithAnim1();
break;
case R.id.subScriptFrame:
trueTopFalseBottom=!trueTopFalseBottom;
int subScriptWidth = (int) ((subScriptTextView.getText().toString().length())*(ConfigMain.width/35));
WindowManager.LayoutParams params = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, PixelFormat.TRANSLUCENT);
params.width = (int) (subScriptWidth*1.5);
if(trueTopFalseBottom==true) params.gravity = Gravity.TOP;
if(trueTopFalseBottom==false) params.gravity = Gravity.BOTTOM;
params.x = 0;
params.y = 0;
wm.updateViewLayout(subScript_overlay, params);
break;
}
}
private void SmsTextBoxWriteVisible() {
Intent dialogIntent = new Intent(ServiceStart.this, SmsBoxWrite.class);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
dialogIntent.addFlags(Intent.FLAG_FROM_BACKGROUND);
getApplicationContext().startActivity(dialogIntent);
//Toast.makeText(getApplicationContext(), "WriteVisible", Toast.LENGTH_SHORT).show();
}
private void SmsTextBoxReadVisible() {
Intent dialogIntent = new Intent(ServiceStart.this, SmsBoxRead.class);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
dialogIntent.addFlags(Intent.FLAG_FROM_BACKGROUND);
getApplicationContext().startActivity(dialogIntent);
//Toast.makeText(getApplicationContext(), "ReadVisible", Toast.LENGTH_SHORT).show();
}
public static void messageReceiveListener(String newMessage , String phoneNumber){
if(popup_show_Swap==true)popup_show_icon.setImageResource(R.drawable.tick_new_msgn);
else popup_show_icon.setImageResource(R.drawable.not_new_msgn);
try {SmsBoxRead.messageReceiveListener(newMessage, phoneNumber);} catch (Exception e) {e.printStackTrace();}
subScriptStart();
}
public static void smsReadIconDisibleWithAnim() {
AnimationSet set = new AnimationSet(false);
RotateAnimation rt = new RotateAnimation(0, 90,ConfigMain.sms_read_width/2,ConfigMain.sms_read_height/2);
rt.setDuration((int)(700*ConfigMain.animationSpeed));
TranslateAnimation tr = new TranslateAnimation(0, ConfigMain.sms_read_width, 0, -ConfigMain.sms_read_height);
tr.setDuration((int)(700*ConfigMain.animationSpeed));
AlphaAnimation al = new AlphaAnimation(1, 0);
al.setDuration((int)(700*ConfigMain.animationSpeed));
set.addAnimation(rt);
set.addAnimation(tr);
set.addAnimation(al);
sms_RW_icon.startAnimation(set);
set.setAnimationListener(new AnimationListener() {
public void onAnimationStart(Animation arg0) {}
public void onAnimationRepeat(Animation arg0) {}
#Override
public void onAnimationEnd(Animation arg0) {
sms_RW_icon.setVisibility(View.INVISIBLE);}});
}
private void smsReadIconVisibleWithAnim() {
int[] location = new int[2];
sms_read_overlay.setVisibility(View.VISIBLE);
popup_show_overlay.getLocationOnScreen(location);
WindowManager.LayoutParams params = (LayoutParams)sms_read_overlay.getLayoutParams();
params.x = location[0];
params.y = location[1]+ConfigMain.popup_show_height/2;
wm.updateViewLayout(sms_read_overlay, params);
AnimationSet set = new AnimationSet(false);
RotateAnimation rt = new RotateAnimation(90, 0,ConfigMain.sms_read_width/2,ConfigMain.sms_read_height/2);
rt.setDuration((int)(700*ConfigMain.animationSpeed));
TranslateAnimation tr = new TranslateAnimation(ConfigMain.sms_read_width, 0, -ConfigMain.sms_read_height, 0);
tr.setDuration((int)(700*ConfigMain.animationSpeed));
AlphaAnimation al = new AlphaAnimation(0, 1);
al.setDuration((int)(700*ConfigMain.animationSpeed));
set.addAnimation(rt);
set.addAnimation(tr);
set.addAnimation(al);
sms_RW_icon.startAnimation(set);
sms_RW_icon.setVisibility(View.VISIBLE);
}
private void smsReadWriteChangeIconWithAnim1() {
AnimationSet set = new AnimationSet(false);
RotateAnimation rt = new RotateAnimation(0,180,ConfigMain.sms_read_width/2,ConfigMain.sms_read_height/2);
rt.setDuration((int)(500*ConfigMain.animationSpeed));
AlphaAnimation al = new AlphaAnimation(1, 5/10);
al.setDuration((int)(500*ConfigMain.animationSpeed));
set.addAnimation(rt);
set.addAnimation(al);
sms_RW_icon.startAnimation(set);
sms_RW_icon.setVisibility(View.VISIBLE);
sms_read_Swap=!sms_read_Swap;
serviceButtonClicked=true;
set.setAnimationListener(new AnimationListener() {
public void onAnimationStart(Animation arg0) {
if(sms_read_Swap==true){
CountDownTimer cont = new CountDownTimer(500, 50) {
public void onTick(long arg0) {}
#Override
public void onFinish() {
SmsTextBoxReadVisible();
}
}.start();
if(SmsBoxWrite.smsBoxWriteHasRuning)SmsBoxWrite.popUpWindowWrite.dismiss();
if(SmsBoxWrite.popUpWindowWrite.isShowing())SmsBoxWrite.popUpWindowWrite.dismiss();
}else{
sms_read_overlay.setEnabled(false);
CountDownTimer cont = new CountDownTimer(500, 50) {
public void onTick(long arg0){}
#Override
public void onFinish() {
SmsTextBoxWriteVisible();
sms_read_overlay.setEnabled(true);
this.cancel();
}
}.start();
if(SmsBoxRead.smsBoxReadHasRuning)SmsBoxRead.popUpWindowRead.dismiss();
if(SmsBoxRead.popUpWindowRead.isShowing())SmsBoxRead.popUpWindowRead.dismiss();
}
}
public void onAnimationRepeat(Animation arg0) {}
#Override
public void onAnimationEnd(Animation arg0) {
smsReadWriteChangeIconWithAnim2();
if(sms_read_Swap==true)sms_RW_icon.setImageResource(R.drawable.sms_read);
else sms_RW_icon.setImageResource(R.drawable.sms_write);
}
});
}
private void smsReadWriteChangeIconWithAnim2() {
AnimationSet set = new AnimationSet(false);
RotateAnimation rt = new RotateAnimation(180,360,ConfigMain.sms_read_width/2,ConfigMain.sms_read_height/2);
rt.setDuration((int)(500*ConfigMain.animationSpeed));
AlphaAnimation al = new AlphaAnimation(0, 1);
al.setDuration((int)(500*ConfigMain.animationSpeed));
set.addAnimation(rt);
set.addAnimation(al);
sms_RW_icon.startAnimation(set);
sms_RW_icon.setVisibility(View.VISIBLE);
if(sms_read_Swap==true)sms_RW_icon.setImageResource(R.drawable.sms_read);
else sms_RW_icon.setImageResource(R.drawable.sms_write);
}
private void ApplyAppearances() {
//ConfigMain.sp = getApplicationContext().getSharedPreferences("Config",0);
ConfigMain.sms_read_width=ConfigMain.sp.getInt("smsReadWidth", 70);
ConfigMain.popup_show_height=ConfigMain.sp.getInt("popupShowHeight", 70);
ConfigMain.sms_read_height=ConfigMain.sp.getInt("smsReadHeight", 70);
ConfigMain.popup_show_width=ConfigMain.sp.getInt("popupShowWidth", 70);
ConfigMain.animationSpeed=ConfigMain.sp.getInt("animationSpeed", 1);
sms_RW_icon.getLayoutParams().height=ConfigMain.sms_read_height; // Get from User!!!!!!!!!!!
sms_RW_icon.getLayoutParams().width=ConfigMain.sms_read_width;
popup_show_icon.getLayoutParams().height=ConfigMain.popup_show_height;
popup_show_icon.getLayoutParams().width=ConfigMain.popup_show_width;
}
private static void subScriptStart() {
String newMessage, contact;
newMessage = IncommingSms.messagE;
contact = SmsBoxRead.getPhoneName(IncommingSms.phoneNumbeR);
subScriptTextView.setText(Html.fromHtml("<font color=red>"+contact+ ": </font><font color=blue>" +newMessage+"</font><br><br/>"));
subScript_overlay.setVisibility(View.VISIBLE);
subScriptTextView.setVisibility(View.VISIBLE);
int subScriptWidth = (int) ((newMessage.length()+contact.length())*(ConfigMain.width/35));
WindowManager.LayoutParams params = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, PixelFormat.TRANSLUCENT);
params.width = (int) (subScriptWidth*1.5);
if(trueTopFalseBottom==true) params.gravity = Gravity.TOP;
if(trueTopFalseBottom==false) params.gravity = Gravity.BOTTOM;
params.x = 0;
params.y = 0;
wm.updateViewLayout(subScript_overlay, params);
float toXdelta = -(subScriptWidth-ConfigMain.width);
//Toast.makeText(ConfigMain.con1, "subScriptWidth: "+subScriptWidth +"\n ConfigMain.width:"+ConfigMain.width, Toast.LENGTH_LONG).show();
TranslateAnimation tr = new TranslateAnimation(ConfigMain.width, -subScriptWidth, 0, 0);
tr.setDuration(10000);
subScriptTextView.startAnimation(tr);
CountDownTimer cont = new CountDownTimer(10000, 1000) {
public void onTick(long arg0) {}
#Override
public void onFinish() {
Toast.makeText(ConfigMain.con1, "end", Toast.LENGTH_SHORT).show();
subScriptTextView.setVisibility(View.INVISIBLE);
subScript_overlay.setVisibility(View.INVISIBLE);
this.cancel(); }
}.start();
}
}
when force closed service shown these errors:
10-09 11:37:24.730: E/AndroidRuntime(13444): FATAL EXCEPTION: main
10-09 11:37:24.730: E/AndroidRuntime(13444): java.lang.RuntimeException: Unable to create service com.MDGH.Always_Accessible.ServiceStart: java.lang.NullPointerException
10-09 11:37:24.730: E/AndroidRuntime(13444): at android.app.ActivityThread.handleCreateService(ActivityThread.java:2407)
10-09 11:37:24.730: E/AndroidRuntime(13444): at android.app.ActivityThread.access$1600(ActivityThread.java:138)
10-09 11:37:24.730: E/AndroidRuntime(13444): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1287)
10-09 11:37:24.730: E/AndroidRuntime(13444): at android.os.Handler.dispatchMessage(Handler.java:99)
10-09 11:37:24.730: E/AndroidRuntime(13444): at android.os.Looper.loop(Looper.java:137)
10-09 11:37:24.730: E/AndroidRuntime(13444): at android.app.ActivityThread.main(ActivityThread.java:4954)
10-09 11:37:24.730: E/AndroidRuntime(13444): at java.lang.reflect.Method.invokeNative(Native Method)
10-09 11:37:24.730: E/AndroidRuntime(13444): at java.lang.reflect.Method.invoke(Method.java:511)
10-09 11:37:24.730: E/AndroidRuntime(13444): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:798)
10-09 11:37:24.730: E/AndroidRuntime(13444): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:565)
10-09 11:37:24.730: E/AndroidRuntime(13444): at dalvik.system.NativeStart.main(Native Method)
10-09 11:37:24.730: E/AndroidRuntime(13444): Caused by: java.lang.NullPointerException
10-09 11:37:24.730: E/AndroidRuntime(13444): at com.MDGH.Always_Accessible.ServiceStart.ApplyAppearances(ServiceStart.java:489)
10-09 11:37:24.730: E/AndroidRuntime(13444): at com.MDGH.Always_Accessible.ServiceStart.onCreate(ServiceStart.java:70)
10-09 11:37:24.730: E/AndroidRuntime(13444): at android.app.ActivityThread.handleCreateService(ActivityThread.java:2397)
10-09 11:37:24.730: E/AndroidRuntime(13444): ... 10 more
thanks
Update:
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.MDGH.Always_Accessible"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="22" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.WRITE_SMS"/>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".ConfigMain"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".ServiceStart" android:stopWithTask="false"> </service>
<activity android:name=".SmsBoxRead"
android:theme="#android:style/Theme.Translucent.NoTitleBar"> </activity>
<activity android:name=".SmsBoxWrite"
android:theme="#android:style/Theme.Translucent.NoTitleBar"> </activity>
<receiver android:name=".IncommingSms">
<intent-filter android:priority="999">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
</application>
</manifest>
Update2:
My first Activity:
package com.MDGH.Always_Accessible;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.Toast;
import android.widget.ToggleButton;
public class ConfigMain extends Activity implements OnClickListener {
public static ToggleButton ActiveButton;
private ImageButton ExitButton;
private Intent intent;
public static Context con1;
public static int height,width;
public static float animationSpeed,fontSize;
public static int sms_read_width,popup_show_width,sms_read_height,popup_show_height, popUpHeight ,popUpWidth;
public static boolean firstExecute=true;
public static SharedPreferences sp;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.config_main);
sp = getApplicationContext().getSharedPreferences("Config",0);
ActiveButton = (ToggleButton)findViewById(R.id.configStart);
ExitButton = (ImageButton)findViewById(R.id.configExit);
intent = new Intent(ConfigMain.this, ServiceStart.class);
GetDisplayMeasures();
SetAppearances();
ActiveButton.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton arg0, boolean arg1) {
if(ActiveButton.isChecked()){
// Active Commands
Editor editor = sp.edit();
editor.putBoolean("isActive",true);
editor.commit();
startService(intent);
finish();
}else{
// DeActive Commands
Editor editor = sp.edit();
editor.putBoolean("isActive",false);
editor.commit();
stopService(intent);
}
}
});
}
private void SetAppearances(){
ActiveButton.setChecked(ConfigMain.sp.getBoolean("isActive", false));
fontSize=ConfigMain.sp.getFloat("fontSize", 1);
}
private void GetDisplayMeasures() {
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
height= dm.heightPixels;
width= dm.widthPixels;
}
#Override
public void onClick(View clickId) {
switch (clickId.getId()) {
case R.id.configExit:
ConfigMain.this.finish();
break;}
}
#Override
protected void onStart() {
con1 = getApplicationContext();
super.onStart();
}
}
The error occurs when trying to create the Service.
You have not implemented onStartCommand(), so the default implementation returns START_STICKY. This means that once your service is started, Android will restart it (if necessary) until the service is stopped.
Your process is getting killed by Android. This can happen pretty much anytime that Android decides it needs the resources. Then, because your service has returned START_STICKY from onStartCommand(), Android will restart your service. Android creates a new instance of your Service class and calls onCreate() on it. In this case, since your ConfigMain hasn't been started yet (since Android killed the process), ConfigMain.sp is null.
Also, don't do this:
int pid = android.os.Process.myPid();
android.os.Process.killProcess(pid);
Just let Android kill your process itself when it is ready to.
I am trying to use a Bulider from a library that i have imported in my project but for some reason the Builder doesn't accept 'this' as Service context. if anyone can help me out i would truly appreciate it. Thanks
import android.app.Service;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
import com.oguzdev.circularfloatingactionmenu.library.FloatingActionMenu;
import com.oguzdev.circularfloatingactionmenu.library.FloatingActionButton;
import com.oguzdev.circularfloatingactionmenu.library.SubActionButton;
import com.example.andrew.reddit2go.R;
import java.util.Calendar;
/**
* Created by Justeen on 2015-02-26.
*/
public class FloatService extends Service {
private WindowManager windowManager;
public TextView textView;
private final IBinder mBinder = new LocalBinder();
private FloatingActionButton rightLowerButton;
private FloatingActionButton topCenterButton;
private FloatingActionMenu rightLowerMenu;
private FloatingActionMenu topCenterMenu;
private boolean serviceWillBeDismissed;
//keep track of an instance to communicate with
private static FloatService floatingInstance;
public class LocalBinder extends Binder {
FloatService getService() {
// Return this instance of LocalService so clients can call public methods
return FloatService.this;
}
}
public FloatService(){
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public void onCreate() {
super.onCreate();
serviceWillBeDismissed = false;
floatingInstance = FloatService.this;
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
textView = new TextView(this);
textView.setBackgroundResource(R.drawable.icon);
textView.setTypeface(null, Typeface.BOLD);
textView.setTextColor(Color.GRAY);
textView.setText("0");
Resources res = getResources();
Drawable shape = res.getDrawable(R.drawable.gradient_box);
//textView.findViewById(R.id.textView);
textView.setBackground(shape);
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.TOP | Gravity.LEFT;
params.x = 0;
params.y = 100;
windowManager.addView(textView, params);
try {
textView.setOnTouchListener(new View.OnTouchListener() {
private int initialX;
private int initialY;
private float initialTouchX;
private float initialTouchY;
private final int MAX_CLICK_DURATION = 200;
private long startClickTime;
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
initialX = params.x;
initialY = params.y;
initialTouchX = event.getRawX();
initialTouchY = event.getRawY();
startClickTime = Calendar.getInstance().getTimeInMillis();
return true;
case MotionEvent.ACTION_UP:
long clickDuration = Calendar.getInstance().getTimeInMillis() - startClickTime;
//if this is not a move, consider it a click and start the activity to see the posts
if(clickDuration < MAX_CLICK_DURATION) {
Intent activityStart = new Intent(getApplicationContext(), MainActivity.class);
activityStart.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(activityStart);
}
return true;
case MotionEvent.ACTION_MOVE:
params.x = initialX + (int) (event.getRawX() - initialTouchX);
params.y = initialY + (int) (event.getRawY() - initialTouchY);
windowManager.updateViewLayout(textView, params);
return true;
}
return false;
}
});
} catch (Exception e) {
// TODO: handle exception
}
rightLowerButton = new FloatingActionButton.Builder(this)
.setContentView(textView)
.setSystemOverlay(true)
.setLayoutParams(params)
.build();
}
#Override
public int onStartCommand( Intent intent , int flags , int startId ) {
super.onStartCommand(intent, flags, startId);
return START_REDELIVER_INTENT;
}
#Override
public void onDestroy() {
super.onDestroy();
if (textView != null) windowManager.removeView(textView);
floatingInstance = null;
}
//called to update the number on this ChatHead
public void updateUnreadNum(int unreadPosts){
if (null != textView) {
Log.d("Reddit2Go", "number of posts is: " + unreadPosts);
textView.setText(""+unreadPosts);
}
}
//called to update the list of available networks and the number on this ChatHead
public void updateUnreadNum(int unreadPosts, String networkList){
if (null != textView) {
Log.d("Reddit2Go", "number of posts is: " + unreadPosts);
//textView.setTextAlignment(TextView.TEXT_ALIGNMENT_CENTER);
textView.setGravity(Gravity.CENTER);
textView.setText(""+unreadPosts+" Cached\n" + networkList);
}
}
//get a reference to a running instance of this service
public static FloatService getFloatingInstance(){
return floatingInstance;
}
}
I'm following the Android Game Programming for Dummies by: Derek James. It looks outdated too me because in the book it doesn't include the fragment_main. So I just copied the fragment_main and replaced it in the activity_main and deleted the fragment_main (I followed the how to get rid of fragment_main tutorial on this forum).
I'm trying to make the whack a mole game in the book.
Anyways I get two errors when I followed the book and it said I can run the program now but I am unable to do that because of:
background cannot be resolved or is not a field
title cannot be resolved or is not a field
I have everything the same as the book but why do I get these errors, I checked all over Google to find an answer or something similar but I can't find the error, I would really appreciate if someone can help me out. Sorry for writing a whole paragraph but I should let you know what I did.
This is my WhackAMoleView.java
package com.whackamole;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class WhackAMoleView extends SurfaceView implements
SurfaceHolder.Callback {
private Context myContext;
private SurfaceHolder mySurfaceHolder;
private Bitmap backgroundImg;
private int screenW = 1;
private int screenH = 1;
private boolean running = false;
private boolean onTitle = true;
private WhackAMoleThread thread;
public WhackAMoleView(Context context, AttributeSet attrs) {
super(context, attrs);
SurfaceHolder holder = getHolder();
holder.addCallback(this);
thread = new WhackAMoleThread(holder, context, new Handler()
{
#Override
public void handleMessage(Message m) {
}
});
setFocusable(true);
}
public WhackAMoleThread getThread() {
return thread;
}
class WhackAMoleThread extends Thread {
public WhackAMoleThread(SurfaceHolder surfaceHolder, Context context,
Handler handler) {
mySurfaceHolder = surfaceHolder;
myContext = context;
backgroundImg = BitmapFactory.decodeResource(
context.getResources(), R.drawable.title);
}
#Override
public void run() {
while (running) {
Canvas c = null;
try {
c = mySurfaceHolder.lockCanvas(null);
synchronized (mySurfaceHolder) {
draw(c);
}
} finally {
if (c != null) {
mySurfaceHolderunlockCanvasAndPost(c);
}
}
}
}
private void mySurfaceHolderunlockCanvasAndPost(Canvas c) {
// TODO Auto-generated method stub
}
private void draw(Canvas canvas) {
try {
canvas.drawBitmap(backgroundImg, 0, 0, null);
} catch (Exception e) {
}
}
boolean doTouchEvent(MotionEvent event) {
synchronized (mySurfaceHolder) {
int eventaction = event.getAction();
int x = (int) event.getX();
int Y = (int) event.getY();
switch (eventaction) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
if (onTitle) {
backgroundImg = BitmapFactory
.decodeResource(myContext.getResources(),
R.drawable.background);
backgroundImg = Bitmap.createScaledBitmap(
backgroundImg, screenW, screenH, true);
onTitle = false;
}
break;
}
}
return true;
}
public void setSurfaceSize(int width, int height) {
synchronized (mySurfaceHolder) {
screenW = width;
screenH = height;
backgroundImg = Bitmap.createScaledBitmap(backgroundImg, width,
height, true);
}
}
public void setRunning(boolean b) {
running = b;
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
return thread.doTouchEvent(event);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
thread.setSurfaceSize(width, height);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
thread.setRunning(true);
if (thread.getState() == Thread.State.NEW) {
thread.start();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
thread.setRunning(false);
}
}
This is my MainActivity.java
package com.whackamole;
import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
public class MainActivity extends Activity {
private WhackAMoleView myWhackAMoleView;
/**Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags
(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.whackamole_layout);
myWhackAMoleView = (WhackAMoleView)
findViewById(R.id.mole);
myWhackAMoleView.setKeepScreenOn(true);
}
}
This is my AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.whackamole"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name">
<activity
android:name="com.whackamole.MainActivity"
android:screenOrientation="landscape"
android:configChanges="keyboardHidden|orientation"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
mySurfaceHolderunlockCanvasAndPost(c);
}
}
}
}
mySurfaceHolderunlockCanvasAndPost should be mySurfaceHolder.unlockCanvasAndPost
*private void mySurfaceHolderunlockCanvasAndPost(Canvas c) {
// TODO Auto-generated method stub
}* should not be here
I want to implement Swipe in ListView like in Samsung Android Phones calling function
I have a list shown in below image :
Now when I swipe right side at some distance of swipe from left i.e 25% distance it just changed background, like call function in Samsung device or like SwipeListView:
need solution for this.
try this code :
main.xml file
<ListView
android:id="#+id/listView1"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>
raw.xml
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:gravity="left"
android:text="ABC"
android:textSize="22sp" />
<LinearLayout
android:id="#+id/delete_lay"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#55ff0000"
android:visibility="gone" >
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp"
android:src="#drawable/ic_menu_delete"
android:visibility="visible" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp"
android:gravity="left"
android:text="Deleting..."
android:textColor="#ff0000"
android:textSize="22sp"
android:textStyle="bold" />
</LinearLayout>
MainActivity.java
import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.LayoutParams;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import de.timroes.swipetodismiss.SwipeDismissList;
import de.timroes.swipetodismiss.SwipeDismissList.SwipeDirection;
import de.timroes.swipetodismiss.SwipeDismissList.UndoMode;
import de.timroes.swipetodismiss.SwipeDismissList.Undoable;
public class MainActivity extends Activity {
ArrayList<String> listData;
ListView listView;
ArrayAdapter<String> adapter;
SwipeListAdapter listAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.listView1);
listData = new ArrayList<String>();
listData.add("item 1");
listData.add("item 2");
listData.add("item 3");
listData.add("item 4");
listData.add("item 5");
listData.add("item 6");
listData.add("item 7");
listData.add("item 8");
listData.add("item 9");
listData.add("item 10");
listData.add("item 11");
listData.add("item 12");
listData.add("item 13");
listData.add("item 14");
listData.add("item 15");
listData.add("item 16");
listData.add("item 17");
listAdapter = new SwipeListAdapter(MainActivity.this);
listView.setAdapter(listAdapter);
listAdapter.notifyDataSetChanged();
SwipeDismissList.OnDismissCallback callback = new SwipeDismissList.OnDismissCallback() {
#Override
public Undoable onDismiss(AbsListView listView, int position) {
View view = (View) listView.getChildAt(0);
view.animate().alpha(1).setDuration(200).translationX(10);
listAdapter.remove(position);
return null;
}
};
UndoMode mode = SwipeDismissList.UndoMode.SINGLE_UNDO;
SwipeDismissList swipeList = new SwipeDismissList(listView, callback,
mode);
swipeList.setSwipeDirection(SwipeDirection.END);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
class SwipeListAdapter extends BaseAdapter {
Context mContext;
public SwipeListAdapter(Context context) {
this.mContext = context;
}
#Override
public int getCount() {
return listData.size();
}
#Override
public Object getItem(int position) {
return listData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
private void remove(int pos) {
listData.remove(pos);
notifyDataSetChanged();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
try {
if (convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(
R.layout.raw, null);
}
TextView textView = (TextView) convertView
.findViewById(R.id.name);
textView.setText(listData.get(position));
RelativeLayout layout = (RelativeLayout) convertView
.findViewById(R.id.parentLayout);
LayoutParams params = new LayoutParams(
LayoutParams.MATCH_PARENT, 50);
layout.setLayoutParams(params);
} catch (Exception e) {
e.printStackTrace();
}
return convertView;
}
}
}
SwipeDismissList.java
import static com.nineoldandroids.view.ViewHelper.setAlpha;
import static com.nineoldandroids.view.ViewHelper.setTranslationX;
import static com.nineoldandroids.view.ViewPropertyAnimator.animate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
import android.content.Context;
import android.graphics.Rect;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.Button;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.nineoldandroids.animation.Animator;
import com.nineoldandroids.animation.AnimatorListenerAdapter;
import com.nineoldandroids.animation.ValueAnimator;
public final class SwipeDismissList implements View.OnTouchListener {
// Cached ViewConfiguration and system-wide constant values
private int mSlop;
private int mMinFlingVelocity;
private int mMaxFlingVelocity;
private long mAnimationTime;
// Fixed properties
private AbsListView mListView;
private OnDismissCallback mCallback;
private int mViewWidth = 1; // 1 and not 0 to prevent dividing by zero
// Transient properties
private SortedSet<PendingDismissData> mPendingDismisses = new TreeSet<PendingDismissData>();
private int mDismissAnimationRefCount = 0;
private float mDownX;
private boolean mSwiping;
private VelocityTracker mVelocityTracker;
private int mDownPosition;
private View mDownView;
private boolean mPaused;
private float mDensity;
private boolean mSwipeDisabled;
private UndoMode mMode;
private List<Undoable> mUndoActions;
private Handler mHandler;
private PopupWindow mUndoPopup;
private TextView mUndoText;
private Button mUndoButton;
private SwipeDirection mSwipeDirection = SwipeDirection.BOTH;
private int mAutoHideDelay = 5000;
private String mDeleteString = "Item deleted";
private String mDeleteMultipleString = "%d items deleted";
private boolean mTouchBeforeAutoHide = true;
private int mDelayedMsgId;
View frontView;
View backView;
RelativeLayout layout ;
public enum UndoMode {
SINGLE_UNDO,
MULTI_UNDO,
COLLAPSED_UNDO
};
public enum SwipeDirection {
BOTH,
START,
END
}
public interface OnDismissCallback {
Undoable onDismiss(AbsListView listView, int position);
}
public abstract static class Undoable {
public String getTitle() {
return null;
}
public abstract void undo();
public void discard() { }
}
public SwipeDismissList(AbsListView listView, OnDismissCallback callback) {
this(listView, callback, UndoMode.SINGLE_UNDO);
}
public SwipeDismissList(AbsListView listView, OnDismissCallback callback, UndoMode mode) {
if(listView == null) {
throw new IllegalArgumentException("listview must not be null.");
}
mHandler = new HideUndoPopupHandler();
mListView = listView;
mCallback = callback;
mMode = mode;
ViewConfiguration vc = ViewConfiguration.get(listView.getContext());
mSlop = vc.getScaledTouchSlop();
mMinFlingVelocity = vc.getScaledMinimumFlingVelocity();
mMaxFlingVelocity = vc.getScaledMaximumFlingVelocity();
mAnimationTime = listView.getContext().getResources().getInteger(
android.R.integer.config_shortAnimTime);
mDensity = mListView.getResources().getDisplayMetrics().density;
// -- Load undo popup --
LayoutInflater inflater = (LayoutInflater) mListView.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.undo_popup, null);
mUndoButton = (Button)v.findViewById(R.id.undo);
mUndoButton.setOnClickListener(new UndoHandler());
mUndoButton.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
// If user tabs "undo" button, reset delay time to remove popup
mDelayedMsgId++;
return false;
}
});
mUndoText = (TextView)v.findViewById(R.id.text);
mUndoPopup = new PopupWindow(v);
mUndoPopup.setAnimationStyle(R.style.fade_animation);
// Get scren width in dp and set width respectively
int xdensity = (int)(mListView.getContext().getResources().getDisplayMetrics().widthPixels / mDensity);
if(xdensity < 300) {
mUndoPopup.setWidth((int)(mDensity * 280));
} else if(xdensity < 350) {
mUndoPopup.setWidth((int)(mDensity * 300));
} else if(xdensity < 500) {
mUndoPopup.setWidth((int)(mDensity * 330));
} else {
mUndoPopup.setWidth((int)(mDensity * 450));
}
mUndoPopup.setHeight((int)(mDensity * 56));
// -- END Load undo popu --
listView.setOnTouchListener(this);
listView.setOnScrollListener(this.makeScrollListener());
switch(mode) {
case SINGLE_UNDO:
mUndoActions = new ArrayList<Undoable>(1);
break;
default:
mUndoActions = new ArrayList<Undoable>(10);
break;
}
}
private void setEnabled(boolean enabled) {
mPaused = !enabled;
}
public void setAutoHideDelay(int delay) {
mAutoHideDelay = delay;
}
public void setSwipeDirection(SwipeDirection direction) {
mSwipeDirection = direction;
}
public void setUndoString(String msg) {
mDeleteString = msg;
}
public void setUndoMultipleString(String msg) {
mDeleteMultipleString = msg;
}
public void setRequireTouchBeforeDismiss(boolean require) {
mTouchBeforeAutoHide = require;
}
public void discardUndo() {
for(Undoable undoable : mUndoActions) {
undoable.discard();
}
mUndoActions.clear();
mUndoPopup.dismiss();
}
private AbsListView.OnScrollListener makeScrollListener() {
return new AbsListView.OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView absListView, int scrollState) {
setEnabled(scrollState != AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
}
#Override
public void onScroll(AbsListView absListView, int i, int i1, int i2) {
}
};
}
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (this.mSwipeDisabled) {
return false;
}
if (mViewWidth < 2) {
mViewWidth = mListView.getWidth();
}
switch (motionEvent.getActionMasked()) {
case MotionEvent.ACTION_DOWN: {
if (mPaused) {
return false;
}
// TODO: ensure this is a finger, and set a flag
// Find the child view that was touched (perform a hit test)
Rect rect = new Rect();
int childCount = mListView.getChildCount();
int[] listViewCoords = new int[2];
mListView.getLocationOnScreen(listViewCoords);
int x = (int) motionEvent.getRawX() - listViewCoords[0];
int y = (int) motionEvent.getRawY() - listViewCoords[1];
View child;
for (int i = 0; i < childCount; i++) {
child = mListView.getChildAt(i);
child.getHitRect(rect);
if (rect.contains(x, y)) {
mDownView = child;
break;
}
}
if (mDownView != null) {
mDownX = motionEvent.getRawX();
mDownPosition = mListView.getPositionForView(mDownView);
mVelocityTracker = VelocityTracker.obtain();
mVelocityTracker.addMovement(motionEvent);
}
view.onTouchEvent(motionEvent);
return true;
}
case MotionEvent.ACTION_UP: {
if (mVelocityTracker == null) {
break;
}
float deltaX = motionEvent.getRawX() - mDownX;
mVelocityTracker.addMovement(motionEvent);
mVelocityTracker.computeCurrentVelocity(1000);
float velocityX = Math.abs(mVelocityTracker.getXVelocity());
float velocityY = Math.abs(mVelocityTracker.getYVelocity());
boolean dismiss = false;
boolean dismissRight = false;
if (Math.abs(deltaX) > mViewWidth / 2 && mSwiping) {
dismiss = true;
dismissRight = deltaX > 0;
} else if (mMinFlingVelocity <= velocityX && velocityX <= mMaxFlingVelocity
&& velocityY < velocityX && mSwiping && isDirectionValid(mVelocityTracker.getXVelocity())
&& deltaX >= mViewWidth * 0.2f) {
dismiss = true;
dismissRight = mVelocityTracker.getXVelocity() > 0;
}
if (dismiss) {
// dismiss
final View downView = frontView; // mDownView gets null'd before animation ends
final int downPosition = mDownPosition;
++mDismissAnimationRefCount;
animate(frontView)
.translationX(dismissRight ? mViewWidth : -mViewWidth)
.alpha(0)
.setDuration(mAnimationTime)
.setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
performDismiss(downView, downPosition);
}
});
} else {
// cancel
animate(frontView)
.translationX(0)
.alpha(1)
.setDuration(mAnimationTime)
.setListener(null);
}
mVelocityTracker = null;
mDownX = 0;
mDownView = null;
mDownPosition = ListView.INVALID_POSITION;
mSwiping = false;
if(backView != null) {
backView.setVisibility(View.GONE);
frontView.setVisibility(View.VISIBLE);
setTranslationX(frontView, 0);
layout = null;
backView = null;
frontView = null;
}
break;
}
case MotionEvent.ACTION_MOVE: {
if(mTouchBeforeAutoHide && mUndoPopup.isShowing()) {
// Send a delayed message to hide popup
mHandler.sendMessageDelayed(mHandler.obtainMessage(mDelayedMsgId),
mAutoHideDelay);
}
if (mVelocityTracker == null || mPaused) {
break;
}
mVelocityTracker.addMovement(motionEvent);
float deltaX = motionEvent.getRawX() - mDownX;
// Only start swipe in correct direction
if(isDirectionValid(deltaX)) {
if (Math.abs(deltaX) > mSlop) {
mSwiping = true;
mListView.requestDisallowInterceptTouchEvent(true);
// Cancel ListView's touch (un-highlighting the item)
MotionEvent cancelEvent = MotionEvent.obtain(motionEvent);
cancelEvent.setAction(MotionEvent.ACTION_CANCEL
| (motionEvent.getActionIndex()
<< MotionEvent.ACTION_POINTER_INDEX_SHIFT));
mListView.onTouchEvent(cancelEvent);
}
} else {
mDownX = motionEvent.getRawX();
deltaX = 0;
}
if(layout == null) {
layout = (RelativeLayout) mDownView;
frontView = layout.getChildAt(0);
backView = layout.getChildAt(1);
}
if(deltaX > 50) {
backView.setVisibility(View.VISIBLE);
}
if (mSwiping) {
setTranslationX(frontView, deltaX);
setAlpha(frontView, Math.max(0f, Math.min(1f,
1f - 2f * Math.abs(deltaX) / mViewWidth)));
return true;
}
break;
}
}
return false;
}
private boolean isDirectionValid(float deltaX) {
int rtlSign = 1;
// On API level 17 and above, check if we are in a Right-To-Left layout
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
if(mListView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
rtlSign = -1;
}
}
// Check if swipe has been done in the corret direction
switch(mSwipeDirection) {
default:
case BOTH:
return true;
case START:
return rtlSign * deltaX < 0;
case END:
return rtlSign * deltaX > 0;
}
}
class PendingDismissData implements Comparable<PendingDismissData> {
public int position;
public View view;
public PendingDismissData(int position, View view) {
this.position = position;
this.view = view;
}
#Override
public int compareTo(PendingDismissData other) {
// Sort by descending position
return other.position - position;
}
}
private void performDismiss(final View dismissView, final int dismissPosition) {
// Animate the dismissed list item to zero-height and fire the dismiss callback when
// all dismissed list item animations have completed. This triggers layout on each animation
// frame; in the future we may want to do something smarter and more performant.
final ViewGroup.LayoutParams lp = dismissView.getLayoutParams();
final int originalHeight = dismissView.getHeight();
ValueAnimator animator = ValueAnimator.ofInt(originalHeight, 1).setDuration(mAnimationTime);
animator.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
--mDismissAnimationRefCount;
if (mDismissAnimationRefCount == 0) {
// No active animations, process all pending dismisses.
for(PendingDismissData dismiss : mPendingDismisses) {
if(mMode == UndoMode.SINGLE_UNDO) {
for(Undoable undoable : mUndoActions) {
undoable.discard();
}
mUndoActions.clear();
}
Undoable undoable = mCallback.onDismiss(mListView, dismiss.position);
if(undoable != null) {
mUndoActions.add(undoable);
}
mDelayedMsgId++;
}
if(!mUndoActions.isEmpty()) {
changePopupText();
changeButtonLabel();
// Show undo popup
mUndoPopup.showAtLocation(mListView,
Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM,
0, (int)(mDensity * 15));
// Queue the dismiss only if required
if(!mTouchBeforeAutoHide) {
// Send a delayed message to hide popup
mHandler.sendMessageDelayed(mHandler.obtainMessage(mDelayedMsgId),
mAutoHideDelay);
}
}
ViewGroup.LayoutParams lp;
for (PendingDismissData pendingDismiss : mPendingDismisses) {
// Reset view presentation
setAlpha(pendingDismiss.view, 1f);
setTranslationX(pendingDismiss.view, 0);
lp = pendingDismiss.view.getLayoutParams();
lp.height = originalHeight;
pendingDismiss.view.setLayoutParams(lp);
}
mPendingDismisses.clear();
}
}
});
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
lp.height = (Integer) valueAnimator.getAnimatedValue();
dismissView.setLayoutParams(lp);
}
});
mPendingDismisses.add(new PendingDismissData(dismissPosition, dismissView));
animator.start();
}
private void changePopupText() {
String msg = "";
if(mUndoActions.size() > 1 && mDeleteMultipleString != null) {
msg = String.format(mDeleteMultipleString, mUndoActions.size());
} else if(mUndoActions.size() >= 1) {
// Set title from single undoable or when no multiple deletion string
// is given
if(mUndoActions.get(mUndoActions.size() - 1).getTitle() != null) {
msg = mUndoActions.get(mUndoActions.size() - 1).getTitle();
} else {
msg = mDeleteString;
}
}
mUndoText.setText(msg);
}
private void changeButtonLabel() {
String msg;
if(mUndoActions.size() > 1 && mMode == UndoMode.COLLAPSED_UNDO) {
msg = mListView.getResources().getString(R.string.undoall);
} else {
msg = mListView.getResources().getString(R.string.undo);
}
mUndoButton.setText(msg);
}
/**
* Takes care of undoing a dismiss. This will be added as a
* {#link View.OnClickListener} to the undo button in the undo popup.
*/
private class UndoHandler implements View.OnClickListener {
public void onClick(View v) {
if(!mUndoActions.isEmpty()) {
switch(mMode) {
case SINGLE_UNDO:
mUndoActions.get(0).undo();
mUndoActions.clear();
break;
case COLLAPSED_UNDO:
Collections.reverse(mUndoActions);
for(Undoable undo : mUndoActions) {
undo.undo();
}
mUndoActions.clear();
break;
case MULTI_UNDO:
mUndoActions.get(mUndoActions.size() - 1).undo();
mUndoActions.remove(mUndoActions.size() - 1);
break;
}
}
// Dismiss dialog or change text
if(mUndoActions.isEmpty()) {
mUndoPopup.dismiss();
} else {
changePopupText();
changeButtonLabel();
}
mDelayedMsgId++;
}
}
/**
* Handler used to hide the undo popup after a special delay.
*/
private class HideUndoPopupHandler extends Handler {
#Override
public void handleMessage(Message msg) {
if(msg.what == mDelayedMsgId) {
// Call discard on any element
for(Undoable undo : mUndoActions) {
undo.discard();
}
mUndoActions.clear();
mUndoPopup.dismiss();
}
}
}
/**
* Enable/disable swipe.
*/
public void setSwipeDisabled(boolean disabled) {
this.mSwipeDisabled = disabled;
}
}
enjoy!
Use a ListView extension such as android-swipelistview.
You may also need to refer to the demo source. Instructions for setting up the demo can be found here.
To make a phone call when the user swipes left, add the below code to the instance of SwipeListView:
src > activities > SwipeListViewExampleActivity.java > onCreate()
swipeListView.setSwipeListViewListener(new BaseSwipeListViewListener() {
#Override
public void onOpened(int position, boolean toRight) {
if(!toRight) {
Intent intent = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:0123456789"));
startActivity(intent);
}
}
});
For swipe right you can set it to dismiss which should be sufficient for what you are trying to achieve.
res > layout > swipe-list-view-activity.xml > SwipeListView
swipe:swipeActionRight="dismiss"
you can use this library https://github.com/timroes/EnhancedListView An Android ListView with enhanced functionality (e.g. Swipe To Dismiss or Undo).