diff --git a/app/build.gradle b/app/build.gradle
index 9757dfe..f563439 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -25,4 +25,7 @@ dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
+
+ implementation project(path: ':emojireactionlibrary')
+
}
diff --git a/app/src/main/java/com/ritik/emojireactionview/MainActivity.java b/app/src/main/java/com/ritik/emojireactionview/MainActivity.java
index 1355196..db72ad1 100644
--- a/app/src/main/java/com/ritik/emojireactionview/MainActivity.java
+++ b/app/src/main/java/com/ritik/emojireactionview/MainActivity.java
@@ -2,12 +2,44 @@
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
+import android.view.View;
+import android.widget.Toast;
+
+import com.ritik.emojireactionlibrary.ClickInterface;
+import com.ritik.emojireactionlibrary.EmojiReactionView;
public class MainActivity extends AppCompatActivity {
+ EmojiReactionView myImage;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
+
+ myImage=findViewById(R.id.image);
+
+ myImage.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+
+ }
+ });
+ myImage.setOnEmojiClickListener(new ClickInterface() {
+ @Override
+ public void onEmoji1Clicked(int x, int y) {
+ Toast.makeText(MainActivity.this, "em1!", Toast.LENGTH_SHORT).show();
+
+ }
+
+ @Override
+ public void onEmoji2Clicked(int x, int y) {
+ Toast.makeText(MainActivity.this, "em2!", Toast.LENGTH_SHORT).show();
+
+ }
+ });
+ }
+
+ public void test(View view) {
+ Toast.makeText(this, "tested!", Toast.LENGTH_SHORT).show();
}
}
diff --git a/app/src/main/res/drawable/android1.jpg b/app/src/main/res/drawable/android1.jpg
new file mode 100644
index 0000000..90ea1a7
Binary files /dev/null and b/app/src/main/res/drawable/android1.jpg differ
diff --git a/app/src/main/res/drawable/em1_min.png b/app/src/main/res/drawable/em1_min.png
new file mode 100644
index 0000000..3c829b7
Binary files /dev/null and b/app/src/main/res/drawable/em1_min.png differ
diff --git a/app/src/main/res/drawable/em2_min.png b/app/src/main/res/drawable/em2_min.png
new file mode 100644
index 0000000..18e42fa
Binary files /dev/null and b/app/src/main/res/drawable/em2_min.png differ
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 84f1951..25a527b 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -1,18 +1,42 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index b4c378b..02ca8ac 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,3 +1,8 @@
EmojiReactionView
+
+
+ - @drawable/em1_min
+ - @drawable/em2_min
+
diff --git a/emojireactionlibrary/.gitignore b/emojireactionlibrary/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/emojireactionlibrary/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/emojireactionlibrary/build.gradle b/emojireactionlibrary/build.gradle
new file mode 100644
index 0000000..94db2ff
--- /dev/null
+++ b/emojireactionlibrary/build.gradle
@@ -0,0 +1,34 @@
+apply plugin: 'com.android.library'
+
+android {
+ compileSdkVersion 27
+
+
+
+ defaultConfig {
+ minSdkVersion 19
+ targetSdkVersion 27
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+
+ implementation 'com.android.support:appcompat-v7:27.1.1'
+ testImplementation 'junit:junit:4.12'
+ androidTestImplementation 'com.android.support.test:runner:1.0.2'
+ androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
+}
diff --git a/emojireactionlibrary/proguard-rules.pro b/emojireactionlibrary/proguard-rules.pro
new file mode 100644
index 0000000..f1b4245
--- /dev/null
+++ b/emojireactionlibrary/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/emojireactionlibrary/src/androidTest/java/com/ritik/emojireactionlibrary/ExampleInstrumentedTest.java b/emojireactionlibrary/src/androidTest/java/com/ritik/emojireactionlibrary/ExampleInstrumentedTest.java
new file mode 100644
index 0000000..2474c42
--- /dev/null
+++ b/emojireactionlibrary/src/androidTest/java/com/ritik/emojireactionlibrary/ExampleInstrumentedTest.java
@@ -0,0 +1,26 @@
+package com.ritik.emojireactionlibrary;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getTargetContext();
+
+ assertEquals("com.ritik.emojireactionlibrary.test", appContext.getPackageName());
+ }
+}
diff --git a/emojireactionlibrary/src/main/AndroidManifest.xml b/emojireactionlibrary/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..ceab57e
--- /dev/null
+++ b/emojireactionlibrary/src/main/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
diff --git a/emojireactionlibrary/src/main/java/com/ritik/emojireactionlibrary/ClickInterface.java b/emojireactionlibrary/src/main/java/com/ritik/emojireactionlibrary/ClickInterface.java
new file mode 100644
index 0000000..1b7692a
--- /dev/null
+++ b/emojireactionlibrary/src/main/java/com/ritik/emojireactionlibrary/ClickInterface.java
@@ -0,0 +1,9 @@
+package com.ritik.emojireactionlibrary;
+
+public interface ClickInterface {
+
+ void onEmoji1Clicked(int x, int y);
+
+ void onEmoji2Clicked(int x, int y);
+
+}
\ No newline at end of file
diff --git a/emojireactionlibrary/src/main/java/com/ritik/emojireactionlibrary/EmojiReactionView.java b/emojireactionlibrary/src/main/java/com/ritik/emojireactionlibrary/EmojiReactionView.java
new file mode 100644
index 0000000..27f48f6
--- /dev/null
+++ b/emojireactionlibrary/src/main/java/com/ritik/emojireactionlibrary/EmojiReactionView.java
@@ -0,0 +1,363 @@
+package com.ritik.emojireactionlibrary;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Path;
+import android.graphics.PathMeasure;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.support.annotation.DrawableRes;
+import android.support.annotation.Nullable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.widget.ImageView;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+public class EmojiReactionView extends ImageView {
+
+ private static final ScaleType SCALE_TYPE = ScaleType.FIT_XY;
+
+ private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
+ private static final int COLORDRAWABLE_DIMENSION = 2;
+ ClickInterface mClickInterface;
+ int iCurStep = 0;// current step
+ ExecuteAsync task;
+ Timer moveBeadTimer;
+ private Rect emojiRect1 = new Rect();
+ private Rect emojiRect2 = new Rect();
+ private Rect emojiRect3 = new Rect();
+ private Rect emojiRect4 = new Rect();
+ private int[] centre = new int[2];
+ private int radius = 150;
+ private double angle = Math.PI / 3;
+ private int[] emojiPoint1 = new int[2];
+ private int[] emojiPoint2 = new int[2];
+ private int[] emojiPoint3 = new int[2];
+ private int[] emojiPoint4 = new int[2];
+ private float[] emojiMovingPoint1 = new float[2];
+ private float[] emojiMovingPoint2 = new float[2];
+ private float[] emojiMovingPoint3 = new float[2];
+ private float[] emojiMovingPoint4 = new float[2];
+ private Path emojiPath1 = new Path();
+ private Path emojiPath2 = new Path();
+ private Bitmap mBitmap;
+ private Bitmap emojiBitmap1;
+ private Bitmap emojiBitmap2;
+ private Bitmap emojiBitmap3;
+ private Bitmap emojiBitmap4;
+ private int coordLeft = 0;
+
+ private boolean mReady;
+ private boolean mSetupPending, alternater = false;
+ private Context mContext;
+
+ public EmojiReactionView(Context context) {
+ super(context);
+ Log.i("point mi69", "const");
+
+ init();
+ }
+
+ public EmojiReactionView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public EmojiReactionView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ this.mContext = context;
+ this.initBaseXMLAttrs(context, attrs);
+ Log.i("point mi81", "attrs");
+
+ setScaleType(ScaleType.FIT_XY);
+ init();
+ }
+
+ final void initBaseXMLAttrs(Context context, AttributeSet attrs) {
+ final TypedArray arr = context.obtainStyledAttributes(attrs, R.styleable.EmojiReactionView);
+
+ final int arrayResourceId = arr.getResourceId(
+ R.styleable.EmojiReactionView_emojis, 0);
+ Log.i("point mi93", "attrs"+arrayResourceId);
+
+ if (arrayResourceId != 0) {
+ final TypedArray resourceArray = context.getResources().obtainTypedArray(arrayResourceId);
+ for (int i = 0; i < resourceArray.length(); i++) {
+ final int resourceId = resourceArray.getResourceId(i, 0);
+ emojiBitmap1 = getBitmapFromDrawable(getResources().getDrawable(resourceId));
+ Log.i("point mi89", "attrs");
+
+ }
+ resourceArray.recycle();
+ }
+
+ arr.recycle();
+ }
+
+ private void init() {
+ super.setScaleType(SCALE_TYPE);
+ Log.i("point mi73", "init");
+ mReady = true;
+
+ if (mSetupPending) {
+ setup();
+ mSetupPending = false;
+ }
+ }
+
+ public void setOnEmojiClickListener(@Nullable ClickInterface l) {
+ this.mClickInterface = l;
+ }
+
+ @Override
+ public ScaleType getScaleType() {
+ return SCALE_TYPE;
+ }
+
+ void timer() {
+ if (moveBeadTimer == null) {
+ moveBeadTimer = new Timer();
+ moveBeadTimer.scheduleAtFixedRate(new TimerTask() {
+ @Override
+ public void run() {
+// Log.i("point ma255", "run started");
+ task = new ExecuteAsync();
+ task.execute(new String[]{null});
+ }
+ }, 5, 100);
+ }
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ Log.i("point mi113", "draw" + (emojiBitmap1 == null));
+ super.onDraw(canvas);
+// if (mBitmap == null) {
+// return;
+// }
+//
+// Log.i("point mi206", "draw" + emojiRect1.left + " " + emojiRect1.top);
+//
+// canvas.drawBitmap(emojiBitmap2, null, calculateNewRect(emojiRect2, (int) emojiMovingPoint2[0], (int) emojiMovingPoint2[1]), null);
+ Log.i("point mi209", "draw" + emojiRect1.left + " " + emojiRect1.top);
+ canvas.drawBitmap(emojiBitmap1, null, calculateNewRect(emojiRect1, (int) emojiMovingPoint1[0], (int) emojiMovingPoint1[1]), null);
+// Log.i("point mi211", "draw" + emojiRect1.left + " " + emojiRect1.top);
+ startcircleAnim();
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ Log.i("point mi213", event.getX() + " " + event.getY());
+
+ if (emojiRect1.contains((int) event.getX(), (int) event.getY())) {
+ mClickInterface.onEmoji1Clicked((int) event.getX(), (int) event.getY());
+ } else if (emojiRect2.contains((int) event.getX(), (int) event.getY())) {
+ mClickInterface.onEmoji2Clicked((int) event.getX(), (int) event.getY());
+ }
+ return false;
+
+ //TODO: want onclick of user to work, return correctclick && super.onTouchEvent(event)
+ }
+
+ @Override
+ public boolean performClick() {
+ return super.performClick();
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ setup();
+ }
+
+ @Override
+ public void setPadding(int left, int top, int right, int bottom) {
+ super.setPadding(left, top, right, bottom);
+ setup();
+ }
+
+ @Override
+ public void setPaddingRelative(int start, int top, int end, int bottom) {
+ super.setPaddingRelative(start, top, end, bottom);
+ setup();
+ }
+
+ @Override
+ public void setImageBitmap(Bitmap bm) {
+ super.setImageBitmap(bm);
+ initializeBitmap();
+ }
+
+ @Override
+ public void setImageDrawable(Drawable drawable) {
+ super.setImageDrawable(drawable);
+ initializeBitmap();
+ }
+
+ @Override
+ public void setImageResource(@DrawableRes int resId) {
+ super.setImageResource(resId);
+ initializeBitmap();
+ }
+
+ @Override
+ public void setImageURI(Uri uri) {
+ super.setImageURI(uri);
+ initializeBitmap();
+ }
+
+ private Bitmap getBitmapFromDrawable(Drawable drawable) {
+ if (drawable == null) {
+ return null;
+ }
+
+ if (drawable instanceof BitmapDrawable) {
+ return ((BitmapDrawable) drawable).getBitmap();
+ }
+
+ try {
+ Bitmap bitmap;
+
+ if (drawable instanceof ColorDrawable) {
+ bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG);
+ } else {
+ bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG);
+ }
+
+ Canvas canvas = new Canvas(bitmap);
+ drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
+ drawable.draw(canvas);
+ return bitmap;
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+
+ }
+
+ private void initializeBitmap() {
+ mBitmap = getBitmapFromDrawable(getDrawable());
+// emojiBitmap 1 = getBitmapFromDrawable(getResources().getDrawable(R.drawable.em1));
+// emojiBitmap2 = getBitmapFromDrawable(getResources().getDrawable(R.drawable.em2));
+ setup();
+ }
+
+ private void setup() {
+ Log.i("point mi257", "setup");
+ if (!mReady) {
+ mSetupPending = true;
+ return;
+ }
+ Log.i("point mi262", "setup");
+
+ if (getWidth() == 0 && getHeight() == 0) {
+ return;
+ }
+ if (mBitmap == null) {
+ invalidate();
+ return;
+ }
+ Log.i("point mi273", "here");
+
+ emojiRect1 = new Rect(coordLeft, 20, coordLeft + 80, 70);
+ emojiRect2 = new Rect(coordLeft, 60, coordLeft + 80, 120);
+// timer();
+
+ centre[0] = (getWidth() + getPaddingLeft() - getPaddingRight()) / 2;
+ centre[1] = getHeight() - getPaddingBottom();
+
+ emojiPoint1[0] = (int) (centre[0] + radius * Math.cos(angle + Math.PI));
+ emojiPoint1[1] = (int) (centre[1] + radius * Math.sin(angle + Math.PI));
+
+ emojiPoint2[0] = (int) (centre[0] + radius * Math.cos(2 * angle + Math.PI));
+ emojiPoint2[1] = (int) (centre[1] + radius * Math.sin(2 * angle + Math.PI));
+ Log.i("point mi340", "centre " + centre[0] + " " + centre[1] + " emojiPoint1 " + emojiPoint1[0] + " " + emojiPoint1[1] + " emojiPoint2 " + emojiPoint2[0] + " " + emojiPoint2[1]);
+
+ emojiPath1.moveTo(centre[0], centre[1]);
+ emojiPath1.lineTo(emojiPoint1[0], emojiPoint1[1]);
+//
+ emojiPath2.moveTo(centre[0], centre[1]);
+ emojiPath2.lineTo(emojiPoint2[0], emojiPoint2[1]);
+
+// Log.i("point mi326", "pl" + getPaddingLeft() + " pr " + getPaddingRight() + " w " + getWidth());
+
+ startcircleAnim();
+ }
+
+ private void startcircleAnim() {
+ PathMeasure pm = new PathMeasure(emojiPath1, false);
+ PathMeasure pm2 = new PathMeasure(emojiPath2, false);
+ float fSegmentLen = pm.getLength() / 20;//20 animation steps
+ Log.i("point mi368", iCurStep + " " + emojiMovingPoint1[0] + " " + emojiMovingPoint1[1]);
+ if (iCurStep <= 20) {
+ pm.getPosTan(fSegmentLen * iCurStep, emojiMovingPoint1, null);
+ pm2.getPosTan(fSegmentLen * iCurStep, emojiMovingPoint2, null);
+ iCurStep++;
+// Log.i("point mi197", + emojiMovingPoint1[0] + " " + emojiMovingPoint1[1]);
+
+ invalidate();
+ } else {
+ iCurStep = 0;
+ }
+ }
+
+ private RectF calculateBounds() {
+ return new RectF(getPaddingLeft(), getPaddingTop(), getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
+ }
+
+ private Rect calculateNewRect(Rect initialRect, int x, int y) {
+
+ int width = 80;
+ int height = 80;
+ initialRect.left = x - 40;
+ initialRect.right = x + 40;
+ initialRect.top = y - 40;
+ initialRect.bottom = y + 40;
+ return initialRect;
+// return new Rect(x-40, y-40, x+40, y+40);
+ }
+
+ // asynctask to reduce load on main thread
+ private class ExecuteAsync extends AsyncTask {
+
+ public ExecuteAsync() {
+ }
+
+ @Override
+ protected String doInBackground(String... urls) {
+ //alternative generate and dissolve cycles
+ Log.i("point mi137", "coordleft" + coordLeft);
+
+ coordLeft += 20;
+ emojiRect1 = new Rect(coordLeft, 20, coordLeft + 80, 70);
+ emojiRect2 = new Rect(coordLeft, 80, coordLeft + 80, 120);
+ return null;
+ }
+
+ @Override
+ protected void onPreExecute() {
+ super.onPreExecute();
+ }
+
+ @Override
+ protected void onPostExecute(String result) {
+ invalidate();
+ }
+
+ @Override
+ protected void onProgressUpdate(String... values) {
+ super.onProgressUpdate(values);
+ }
+ }
+
+}
diff --git a/emojireactionlibrary/src/main/res/values/attrs.xml b/emojireactionlibrary/src/main/res/values/attrs.xml
new file mode 100644
index 0000000..24ef14e
--- /dev/null
+++ b/emojireactionlibrary/src/main/res/values/attrs.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/emojireactionlibrary/src/main/res/values/strings.xml b/emojireactionlibrary/src/main/res/values/strings.xml
new file mode 100644
index 0000000..5f66a4c
--- /dev/null
+++ b/emojireactionlibrary/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ EmojiReactionLibrary
+
diff --git a/emojireactionlibrary/src/test/java/com/ritik/emojireactionlibrary/ExampleUnitTest.java b/emojireactionlibrary/src/test/java/com/ritik/emojireactionlibrary/ExampleUnitTest.java
new file mode 100644
index 0000000..56bf545
--- /dev/null
+++ b/emojireactionlibrary/src/test/java/com/ritik/emojireactionlibrary/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package com.ritik.emojireactionlibrary;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
index e7b4def..2fef54a 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1 +1 @@
-include ':app'
+include ':app', ':emojireactionlibrary'