diff --git a/app/build.gradle b/app/build.gradle
index dbf7c23..274eb52 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -32,4 +32,8 @@
//QRコードリーダー
implementation 'com.journeyapps:zxing-android-embedded:3.6.0'
implementation 'com.android.support:design:28.0.0'
+ //cropView
+ implementation 'com.oginotihiro:cropview:1.0.0'
+ api 'com.theartofdev.edmodo:android-image-cropper:2.7.+'
+ implementation project(path: ':dynamicgrid')
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 26cd441..694e8e9 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -4,23 +4,26 @@
package="com.example.cosmosclient">
-
-
+
+
+
+
+ android:label="IDでグループに入る" />
@@ -31,9 +34,9 @@
-
-
+
@@ -41,12 +44,16 @@
-
+
+
-
+ android:theme="@style/AppTheme.NoActionBar" />
+
-
+ android:theme="@style/AppTheme.NoActionBar">
\ No newline at end of file
diff --git a/app/src/main/java/com/example/cosmosclient/app/Cosmos.java b/app/src/main/java/com/example/cosmosclient/app/Cosmos.java
index 63fd1cc..632820b 100644
--- a/app/src/main/java/com/example/cosmosclient/app/Cosmos.java
+++ b/app/src/main/java/com/example/cosmosclient/app/Cosmos.java
@@ -4,24 +4,17 @@
import com.example.cosmosclient.entities.Group;
-import java.util.ArrayList;
-import java.util.List;
-
public class Cosmos extends Application {
- //token処理
- private List token;
+ private String token=null;
private Group curGroup=null;
+ private String uId=null;
- public Cosmos(){
- this.token = new ArrayList();
- }
-
- public void setToken(List token){
+ //token処理
+ public void setToken(String token){
this.token = token;
}
-
- public List getToken(){
- return new ArrayList(token);
+ public String getToken(){
+ return token;
}
//Group処理
@@ -32,5 +25,11 @@
return curGroup;
}
-
+ //uId処理
+ public void setuId(String uId){
+ this.uId = uId;
+ }
+ public String getuId(){
+ return uId;
+ }
}
diff --git a/app/src/main/java/com/example/cosmosclient/entities/SigninResponse.java b/app/src/main/java/com/example/cosmosclient/entities/SigninResponse.java
index 269b78a..8600404 100644
--- a/app/src/main/java/com/example/cosmosclient/entities/SigninResponse.java
+++ b/app/src/main/java/com/example/cosmosclient/entities/SigninResponse.java
@@ -1,7 +1,6 @@
package com.example.cosmosclient.entities;
-import java.util.List;
-
public class SigninResponse {
- public List token;
+ public String token;
+ public String uId;
}
diff --git a/app/src/main/java/com/example/cosmosclient/entities/SignupResponse.java b/app/src/main/java/com/example/cosmosclient/entities/SignupResponse.java
index 4a52150..712e2fd 100644
--- a/app/src/main/java/com/example/cosmosclient/entities/SignupResponse.java
+++ b/app/src/main/java/com/example/cosmosclient/entities/SignupResponse.java
@@ -1,13 +1,10 @@
package com.example.cosmosclient.entities;
-import java.util.List;
-
public class SignupResponse {
public String uId;
public String name;
- public String pw;
public String uri;
- public List token;
+ public String token;
public String iconUri;
public boolean login;
diff --git a/app/src/main/java/com/example/cosmosclient/resources/GroupsRest.java b/app/src/main/java/com/example/cosmosclient/resources/GroupsRest.java
index 6635b43..52bbefd 100644
--- a/app/src/main/java/com/example/cosmosclient/resources/GroupsRest.java
+++ b/app/src/main/java/com/example/cosmosclient/resources/GroupsRest.java
@@ -1,4 +1,14 @@
package com.example.cosmosclient.resources;
+import com.example.cosmosclient.entities.Group;
+
+import retrofit2.Call;
+import retrofit2.http.Field;
+import retrofit2.http.FormUrlEncoded;
+import retrofit2.http.POST;
+
public interface GroupsRest {
+ @POST("groups")
+ @FormUrlEncoded
+ Call createGroup(@Field("name") String name,@Field("uId") String uId,@Field("token") String token);
}
diff --git a/app/src/main/java/com/example/cosmosclient/resources/UsersRest.java b/app/src/main/java/com/example/cosmosclient/resources/UsersRest.java
index d4ddb3e..205b4a2 100644
--- a/app/src/main/java/com/example/cosmosclient/resources/UsersRest.java
+++ b/app/src/main/java/com/example/cosmosclient/resources/UsersRest.java
@@ -12,10 +12,10 @@
public interface UsersRest {
@POST("users/{uId}/login")
- Call loginList(@Path("uId") String uId, @Query("pw") String pw);
+ @FormUrlEncoded
+ Call login(@Path("uId") String uId,@Field("pw") String pw);
@POST("users")
@FormUrlEncoded
Call createUser(@Field("name") String name, @Field("pw") String pw, @Field("icon-image") String icon_image);
-
}
diff --git a/app/src/main/java/com/example/cosmosclient/views/CheeseDynamicAdapter.java b/app/src/main/java/com/example/cosmosclient/views/CheeseDynamicAdapter.java
new file mode 100644
index 0000000..5c62d2b
--- /dev/null
+++ b/app/src/main/java/com/example/cosmosclient/views/CheeseDynamicAdapter.java
@@ -0,0 +1,73 @@
+package com.example.cosmosclient.views;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.example.cosmosclient.R;
+
+import org.askerov.dynamicgrid.BaseDynamicGridAdapter;
+
+import java.util.List;
+
+public class CheeseDynamicAdapter extends BaseDynamicGridAdapter {
+ public CheeseDynamicAdapter(Context context, List> items, int columnCount) {
+ super(context, items, columnCount);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ CheeseViewHolder holder;
+ if (convertView == null) {
+ convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_grid, null);
+ holder = new CheeseViewHolder(convertView);
+ convertView.setTag(holder);
+ } else {
+ holder = (CheeseViewHolder) convertView.getTag();
+ }
+ switch (position) {
+ case 0:
+ convertView.setBackgroundColor(Color.argb(100, 200, 100, 100));
+ break;
+ case 1:
+ convertView.setBackgroundColor(Color.argb(100, 200, 200, 100));
+ break;
+ case 2:
+ convertView.setBackgroundColor(Color.argb(100, 100, 100, 100));
+ break;
+ case 3:
+ convertView.setBackgroundColor(Color.argb(100, 200, 100, 200));
+ break;
+ case 4:
+ convertView.setBackgroundColor(Color.argb(100, 100, 200, 100));
+ break;
+ case 5:
+ convertView.setBackgroundColor(Color.argb(100, 100, 200, 200));
+ break;
+ case 6:
+ convertView.setBackgroundColor(Color.argb(100, 100, 100, 200));
+ break;
+ }
+ holder.build(getItem(position).toString());
+ return convertView;
+ }
+
+ private class CheeseViewHolder {
+ private TextView titleText;
+ private ImageView image;
+
+ private CheeseViewHolder(View view) {
+ titleText = (TextView) view.findViewById(R.id.item_title);
+ image = (ImageView) view.findViewById(R.id.item_img);
+ }
+
+ void build(String title) {
+ titleText.setText(title);
+ //image.setImageResource(R.drawable.ic_launcher);
+ }
+ }
+}
diff --git a/app/src/main/java/com/example/cosmosclient/views/Cheeses.java b/app/src/main/java/com/example/cosmosclient/views/Cheeses.java
new file mode 100644
index 0000000..d57f508
--- /dev/null
+++ b/app/src/main/java/com/example/cosmosclient/views/Cheeses.java
@@ -0,0 +1,13 @@
+package com.example.cosmosclient.views;
+
+public class Cheeses {
+ public static final String[] sCheeseStrings = {
+ "ファミリー\n 紙コップ\n 延長ケーブル",
+ "会社\n からし",
+ "Group3\n ケーキ\n ほげほげ",
+ "Group4\n ほげほげ\n ほげほげ",
+ "Group5\n ほげほげ\n ほげほげ\n ほげほげ\n ほげほげ",
+ "Group6\n ほげほげ\n ほげほげ\n ほげほげ",
+ "Group7\n ほげほげ\n ほげほげ"
+ };
+}
diff --git a/app/src/main/java/com/example/cosmosclient/views/CreateGroupActivity.java b/app/src/main/java/com/example/cosmosclient/views/CreateGroupActivity.java
new file mode 100644
index 0000000..d83bf9e
--- /dev/null
+++ b/app/src/main/java/com/example/cosmosclient/views/CreateGroupActivity.java
@@ -0,0 +1,93 @@
+package com.example.cosmosclient.views;
+
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.Toast;
+
+import com.example.cosmosclient.R;
+import com.example.cosmosclient.app.Cosmos;
+import com.example.cosmosclient.entities.Group;
+import com.example.cosmosclient.resources.GroupsRest;
+
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+import retrofit2.Retrofit;
+import retrofit2.converter.jackson.JacksonConverterFactory;
+
+public class CreateGroupActivity extends AppCompatActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_make_group);
+
+ //各種IDを取得
+ final EditText groupNameText = findViewById(R.id.groupNameText);
+ Button createGroupButton = findViewById(R.id.createGroupButton);
+ final String uId,token;
+
+ //グループ作成に必要な情報の取得
+ Cosmos app = (Cosmos) getApplication();
+ uId = app.getuId();
+ ////サインアップでトークンが返ってきてないため一時コメントアウト
+ //token = app.getToken();
+ token="abcdef";
+
+ //retrofitの処理
+ final Retrofit retrofit = new Retrofit.Builder()
+ .baseUrl("http://nitta-lab-www.is.konan-u.ac.jp/cosmos/")
+ .addConverterFactory(JacksonConverterFactory.create())
+ .build();
+ //interfaceから実装を取得
+ final GroupsRest createGroupService = retrofit.create(GroupsRest.class);
+
+ //グループ作成ボタン処理
+ createGroupButton.setOnClickListener(new View.OnClickListener(){
+ @Override
+ public void onClick(View view){
+ try {
+ Call createGroup = createGroupService.createGroup(groupNameText.getText().toString(), uId, token);
+
+ createGroup.enqueue(new Callback() {
+ @Override
+ public void onResponse(Call call, Response response) {
+ if (response.isSuccessful()) {
+ //成功時
+ Group result = response.body();
+
+// //確認用
+// System.out.println(result.getgId());
+// System.out.println(result.getName());
+// System.out.println(result.getRequests());
+// System.out.println(result.getUri());
+
+ Toast.makeText(CreateGroupActivity.this,
+ "グループを作成しました", Toast.LENGTH_SHORT).show();
+ finish();
+ } else {
+ //onFailureでキャッチできない用のエラー
+ System.out.println("");
+ Toast.makeText(CreateGroupActivity.this,
+ "通信エラー",Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ @Override
+ public void onFailure(Call call, Throwable t) {
+ //失敗時
+ t.printStackTrace();
+ Toast.makeText(CreateGroupActivity.this,
+ "グループ作成失敗",Toast.LENGTH_SHORT);
+ }
+ });
+ }catch(Exception e){
+ e.printStackTrace();
+ }
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/com/example/cosmosclient/views/DynamicGridView.java b/app/src/main/java/com/example/cosmosclient/views/DynamicGridView.java
new file mode 100644
index 0000000..8478f82
--- /dev/null
+++ b/app/src/main/java/com/example/cosmosclient/views/DynamicGridView.java
@@ -0,0 +1,1140 @@
+package com.example.cosmosclient.views;
+
+import android.animation.*;
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.os.Build;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.Pair;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewTreeObserver;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.widget.AbsListView;
+import android.widget.AdapterView;
+import android.widget.GridView;
+import android.widget.ListAdapter;
+
+import com.example.cosmosclient.R;
+
+import org.askerov.dynamicgrid.DynamicGridAdapterInterface;
+import org.askerov.dynamicgrid.DynamicGridUtils;
+
+import java.util.*;
+
+public class DynamicGridView extends GridView{
+ private static final int INVALID_ID = -1;
+
+ private static final int MOVE_DURATION = 300;
+ private static final int SMOOTH_SCROLL_AMOUNT_AT_EDGE = 8;
+
+ private BitmapDrawable mHoverCell;
+ private Rect mHoverCellCurrentBounds;
+ private Rect mHoverCellOriginalBounds;
+
+ private int mTotalOffsetY = 0;
+ private int mTotalOffsetX = 0;
+
+ private int mDownX = -1;
+ private int mDownY = -1;
+ private int mLastEventY = -1;
+ private int mLastEventX = -1;
+
+ //used to distinguish straight line and diagonal switching
+ private int mOverlapIfSwitchStraightLine;
+
+ private List idList = new ArrayList();
+
+ private long mMobileItemId = INVALID_ID;
+
+ private boolean mCellIsMobile = false;
+ private int mActivePointerId = INVALID_ID;
+
+ private boolean mIsMobileScrolling;
+ private int mSmoothScrollAmountAtEdge = 0;
+ private boolean mIsWaitingForScrollFinish = false;
+ private int mScrollState = OnScrollListener.SCROLL_STATE_IDLE;
+
+ private boolean mIsEditMode = false;
+ private List mWobbleAnimators = new LinkedList();
+ private boolean mHoverAnimation;
+ private boolean mReorderAnimation;
+ private boolean mWobbleInEditMode = true;
+ private boolean mIsEditModeEnabled = true;
+
+ private OnScrollListener mUserScrollListener;
+ private OnDropListener mDropListener;
+ private OnDragListener mDragListener;
+ private OnEditModeChangeListener mEditModeChangeListener;
+
+ private OnItemClickListener mUserItemClickListener;
+ private OnItemClickListener mLocalItemClickListener = new OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ if (!isEditMode() && isEnabled() && mUserItemClickListener != null) {
+ mUserItemClickListener.onItemClick(parent, view, position, id);
+ }
+ }
+ };
+
+ private boolean mUndoSupportEnabled;
+ private Stack mModificationStack;
+ private DynamicGridModification mCurrentModification;
+
+ private OnSelectedItemBitmapCreationListener mSelectedItemBitmapCreationListener;
+ private View mMobileView;
+
+
+ public DynamicGridView(Context context) {
+ super(context);
+ init(context);
+ }
+
+ public DynamicGridView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(context);
+ }
+
+ public DynamicGridView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init(context);
+ }
+
+ @Override
+ public void setOnScrollListener(OnScrollListener scrollListener) {
+ this.mUserScrollListener = scrollListener;
+ }
+
+ public void setOnDropListener(OnDropListener dropListener) {
+ this.mDropListener = dropListener;
+ }
+
+ public void setOnDragListener(OnDragListener dragListener) {
+ this.mDragListener = dragListener;
+ }
+
+ /**
+ * Start edit mode without starting drag;
+ */
+ public void startEditMode() {
+ startEditMode(-1);
+ }
+
+ /**
+ * Start edit mode with position. Useful for start edit mode in
+ * {@link android.widget.AdapterView.OnItemClickListener}
+ * or {@link android.widget.AdapterView.OnItemLongClickListener}
+ */
+ public void startEditMode(int position) {
+ if (!mIsEditModeEnabled)
+ return;
+ requestDisallowInterceptTouchEvent(true);
+ if (isPostHoneycomb() && mWobbleInEditMode)
+ startWobbleAnimation();
+ if (position != -1) {
+ startDragAtPosition(position);
+ }
+ mIsEditMode = true;
+ if (mEditModeChangeListener != null)
+ mEditModeChangeListener.onEditModeChanged(true);
+ }
+
+ public void stopEditMode() {
+ mIsEditMode = false;
+ requestDisallowInterceptTouchEvent(false);
+ if (isPostHoneycomb() && mWobbleInEditMode)
+ stopWobble(true);
+ if (mEditModeChangeListener != null)
+ mEditModeChangeListener.onEditModeChanged(false);
+ }
+
+ public boolean isEditModeEnabled() {
+ return mIsEditModeEnabled;
+ }
+
+ public void setEditModeEnabled(boolean enabled) {
+ this.mIsEditModeEnabled = enabled;
+ }
+
+ public void setOnEditModeChangeListener(OnEditModeChangeListener editModeChangeListener) {
+ this.mEditModeChangeListener = editModeChangeListener;
+ }
+
+ public boolean isEditMode() {
+ return mIsEditMode;
+ }
+
+ public boolean isWobbleInEditMode() {
+ return mWobbleInEditMode;
+ }
+
+ public void setWobbleInEditMode(boolean wobbleInEditMode) {
+ this.mWobbleInEditMode = wobbleInEditMode;
+ }
+
+ @Override
+ public void setOnItemClickListener(OnItemClickListener listener) {
+ this.mUserItemClickListener = listener;
+ super.setOnItemClickListener(mLocalItemClickListener);
+ }
+
+ public boolean isUndoSupportEnabled() {
+ return mUndoSupportEnabled;
+ }
+
+ public void setUndoSupportEnabled(boolean undoSupportEnabled) {
+ if (this.mUndoSupportEnabled != undoSupportEnabled) {
+ if (undoSupportEnabled) {
+ this.mModificationStack = new Stack();
+ } else {
+ this.mModificationStack = null;
+ }
+ }
+
+ this.mUndoSupportEnabled = undoSupportEnabled;
+ }
+
+ public void undoLastModification() {
+ if (mUndoSupportEnabled) {
+ if (mModificationStack != null && !mModificationStack.isEmpty()) {
+ DynamicGridModification modification = mModificationStack.pop();
+ undoModification(modification);
+ }
+ }
+ }
+
+ public void undoAllModifications() {
+ if (mUndoSupportEnabled) {
+ if (mModificationStack != null && !mModificationStack.isEmpty()) {
+ while (!mModificationStack.isEmpty()) {
+ DynamicGridModification modification = mModificationStack.pop();
+ undoModification(modification);
+ }
+ }
+ }
+ }
+
+ public boolean hasModificationHistory() {
+ if (mUndoSupportEnabled) {
+ if (mModificationStack != null && !mModificationStack.isEmpty()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void clearModificationHistory() {
+ mModificationStack.clear();
+ }
+
+ public void setOnSelectedItemBitmapCreationListener(OnSelectedItemBitmapCreationListener selectedItemBitmapCreationListener) {
+ this.mSelectedItemBitmapCreationListener = selectedItemBitmapCreationListener;
+ }
+
+ private void undoModification(DynamicGridModification modification) {
+ for (Pair transition : modification.getTransitions()) {
+ reorderElements(transition.second, transition.first);
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ private void startWobbleAnimation() {
+ for (int i = 0; i < getChildCount(); i++) {
+ View v = getChildAt(i);
+ if (v != null && Boolean.TRUE != v.getTag(R.id.dgv_wobble_tag)) {
+ if (i % 2 == 0)
+ animateWobble(v);
+ else
+ animateWobbleInverse(v);
+ v.setTag(R.id.dgv_wobble_tag, true);
+ }
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ private void stopWobble(boolean resetRotation) {
+ for (Animator wobbleAnimator : mWobbleAnimators) {
+ wobbleAnimator.cancel();
+ }
+ mWobbleAnimators.clear();
+ for (int i = 0; i < getChildCount(); i++) {
+ View v = getChildAt(i);
+ if (v != null) {
+ if (resetRotation) v.setRotation(0);
+ v.setTag(R.id.dgv_wobble_tag, false);
+ }
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ private void restartWobble() {
+ stopWobble(false);
+ startWobbleAnimation();
+ }
+
+ public void init(Context context) {
+ super.setOnScrollListener(mScrollListener);
+ DisplayMetrics metrics = context.getResources().getDisplayMetrics();
+ mSmoothScrollAmountAtEdge = (int) (SMOOTH_SCROLL_AMOUNT_AT_EDGE * metrics.density + 0.5f);
+ mOverlapIfSwitchStraightLine = getResources().getDimensionPixelSize(R.dimen.dgv_overlap_if_switch_straight_line);
+ }
+
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ private void animateWobble(View v) {
+ ObjectAnimator animator = createBaseWobble(v);
+ animator.setFloatValues(-2, 2);
+ animator.start();
+ mWobbleAnimators.add(animator);
+ }
+
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ private void animateWobbleInverse(View v) {
+ ObjectAnimator animator = createBaseWobble(v);
+ animator.setFloatValues(2, -2);
+ animator.start();
+ mWobbleAnimators.add(animator);
+ }
+
+
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ private ObjectAnimator createBaseWobble(final View v) {
+
+ if (!isPreLollipop())
+ v.setLayerType(LAYER_TYPE_SOFTWARE, null);
+
+ ObjectAnimator animator = new ObjectAnimator();
+ animator.setDuration(180);
+ animator.setRepeatMode(ValueAnimator.REVERSE);
+ animator.setRepeatCount(ValueAnimator.INFINITE);
+ animator.setPropertyName("rotation");
+ animator.setTarget(v);
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ v.setLayerType(LAYER_TYPE_NONE, null);
+ }
+ });
+ return animator;
+ }
+
+
+ private void reorderElements(int originalPosition, int targetPosition) {
+ if (mDragListener != null)
+ mDragListener.onDragPositionsChanged(originalPosition, targetPosition);
+ getAdapterInterface().reorderItems(originalPosition, targetPosition);
+ }
+
+ private int getColumnCount() {
+ return getAdapterInterface().getColumnCount();
+ }
+
+ private DynamicGridAdapterInterface getAdapterInterface() {
+ return ((DynamicGridAdapterInterface) getAdapter());
+ }
+
+ /**
+ * Creates the hover cell with the appropriate bitmap and of appropriate
+ * size. The hover cell's BitmapDrawable is drawn on top of the bitmap every
+ * single time an invalidate call is made.
+ */
+ private BitmapDrawable getAndAddHoverView(View v) {
+
+ int w = v.getWidth();
+ int h = v.getHeight();
+ int top = v.getTop();
+ int left = v.getLeft();
+
+ Bitmap b = getBitmapFromView(v);
+
+ BitmapDrawable drawable = new BitmapDrawable(getResources(), b);
+
+ mHoverCellOriginalBounds = new Rect(left, top, left + w, top + h);
+ mHoverCellCurrentBounds = new Rect(mHoverCellOriginalBounds);
+
+ drawable.setBounds(mHoverCellCurrentBounds);
+
+ return drawable;
+ }
+
+ /**
+ * Returns a bitmap showing a screenshot of the view passed in.
+ */
+ private Bitmap getBitmapFromView(View v) {
+ Bitmap bitmap = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ v.draw(canvas);
+ return bitmap;
+ }
+
+
+ private void updateNeighborViewsForId(long itemId) {
+ idList.clear();
+ int draggedPos = getPositionForID(itemId);
+ for (int pos = getFirstVisiblePosition(); pos <= getLastVisiblePosition(); pos++) {
+ if (draggedPos != pos && getAdapterInterface().canReorder(pos)) {
+ idList.add(getId(pos));
+ }
+ }
+ }
+
+ /**
+ * Retrieves the position in the grid corresponding to itemId
+ */
+ public int getPositionForID(long itemId) {
+ View v = getViewForId(itemId);
+ if (v == null) {
+ return -1;
+ } else {
+ return getPositionForView(v);
+ }
+ }
+
+ public View getViewForId(long itemId) {
+ int firstVisiblePosition = getFirstVisiblePosition();
+ ListAdapter adapter = getAdapter();
+ for (int i = 0; i < getChildCount(); i++) {
+ View v = getChildAt(i);
+ int position = firstVisiblePosition + i;
+ long id = adapter.getItemId(position);
+ if (id == itemId) {
+ return v;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ switch (event.getAction() & MotionEvent.ACTION_MASK) {
+ case MotionEvent.ACTION_DOWN:
+ mDownX = (int) event.getX();
+ mDownY = (int) event.getY();
+ mActivePointerId = event.getPointerId(0);
+ if (mIsEditMode && isEnabled()) {
+ layoutChildren();
+ int position = pointToPosition(mDownX, mDownY);
+ startDragAtPosition(position);
+ } else if (!isEnabled()) {
+ return false;
+ }
+
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+ if (mActivePointerId == INVALID_ID) {
+ break;
+ }
+
+ int pointerIndex = event.findPointerIndex(mActivePointerId);
+
+ mLastEventY = (int) event.getY(pointerIndex);
+ mLastEventX = (int) event.getX(pointerIndex);
+ int deltaY = mLastEventY - mDownY;
+ int deltaX = mLastEventX - mDownX;
+
+ if (mCellIsMobile) {
+ mHoverCellCurrentBounds.offsetTo(mHoverCellOriginalBounds.left + deltaX + mTotalOffsetX,
+ mHoverCellOriginalBounds.top + deltaY + mTotalOffsetY);
+ mHoverCell.setBounds(mHoverCellCurrentBounds);
+ invalidate();
+ handleCellSwitch();
+ mIsMobileScrolling = false;
+ handleMobileCellScroll();
+ return false;
+ }
+ break;
+
+ case MotionEvent.ACTION_UP:
+ touchEventsEnded();
+
+ if (mUndoSupportEnabled) {
+ if (mCurrentModification != null && !mCurrentModification.getTransitions().isEmpty()) {
+ mModificationStack.push(mCurrentModification);
+ mCurrentModification = new DynamicGridModification();
+ }
+ }
+
+ if (mHoverCell != null) {
+ if (mDropListener != null) {
+ mDropListener.onActionDrop();
+ }
+ }
+ break;
+
+ case MotionEvent.ACTION_CANCEL:
+ touchEventsCancelled();
+
+ if (mHoverCell != null) {
+ if (mDropListener != null) {
+ mDropListener.onActionDrop();
+ }
+ }
+ break;
+
+ case MotionEvent.ACTION_POINTER_UP:
+ /* If a multitouch event took place and the original touch dictating
+ * the movement of the hover cell has ended, then the dragging event
+ * ends and the hover cell is animated to its corresponding position
+ * in the listview. */
+ pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >>
+ MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+ final int pointerId = event.getPointerId(pointerIndex);
+ if (pointerId == mActivePointerId) {
+ touchEventsEnded();
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return super.onTouchEvent(event);
+ }
+
+ private void startDragAtPosition(int position) {
+ mTotalOffsetY = 0;
+ mTotalOffsetX = 0;
+ int itemNum = position - getFirstVisiblePosition();
+ View selectedView = getChildAt(itemNum);
+ if (selectedView != null) {
+ mMobileItemId = getAdapter().getItemId(position);
+ if (mSelectedItemBitmapCreationListener != null)
+ mSelectedItemBitmapCreationListener.onPreSelectedItemBitmapCreation(selectedView, position, mMobileItemId);
+ mHoverCell = getAndAddHoverView(selectedView);
+ if (mSelectedItemBitmapCreationListener != null)
+ mSelectedItemBitmapCreationListener.onPostSelectedItemBitmapCreation(selectedView, position, mMobileItemId);
+ if (isPostHoneycomb())
+ selectedView.setVisibility(View.INVISIBLE);
+ mCellIsMobile = true;
+ updateNeighborViewsForId(mMobileItemId);
+ if (mDragListener != null) {
+ mDragListener.onDragStarted(position);
+ }
+ }
+ }
+
+ private void handleMobileCellScroll() {
+ mIsMobileScrolling = handleMobileCellScroll(mHoverCellCurrentBounds);
+ }
+
+ public boolean handleMobileCellScroll(Rect r) {
+ int offset = computeVerticalScrollOffset();
+ int height = getHeight();
+ int extent = computeVerticalScrollExtent();
+ int range = computeVerticalScrollRange();
+ int hoverViewTop = r.top;
+ int hoverHeight = r.height();
+
+ if (hoverViewTop <= 0 && offset > 0) {
+ smoothScrollBy(-mSmoothScrollAmountAtEdge, 0);
+ return true;
+ }
+
+ if (hoverViewTop + hoverHeight >= height && (offset + extent) < range) {
+ smoothScrollBy(mSmoothScrollAmountAtEdge, 0);
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public void setAdapter(ListAdapter adapter) {
+ super.setAdapter(adapter);
+ }
+
+ private void touchEventsEnded() {
+ final View mobileView = getViewForId(mMobileItemId);
+ if (mobileView != null && (mCellIsMobile || mIsWaitingForScrollFinish)) {
+ mCellIsMobile = false;
+ mIsWaitingForScrollFinish = false;
+ mIsMobileScrolling = false;
+ mActivePointerId = INVALID_ID;
+
+ // If the autoscroller has not completed scrolling, we need to wait for it to
+ // finish in order to determine the final location of where the hover cell
+ // should be animated to.
+ if (mScrollState != OnScrollListener.SCROLL_STATE_IDLE) {
+ mIsWaitingForScrollFinish = true;
+ return;
+ }
+
+ mHoverCellCurrentBounds.offsetTo(mobileView.getLeft(), mobileView.getTop());
+
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB) {
+ animateBounds(mobileView);
+ } else {
+ mHoverCell.setBounds(mHoverCellCurrentBounds);
+ invalidate();
+ reset(mobileView);
+ }
+ } else {
+ touchEventsCancelled();
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ private void animateBounds(final View mobileView) {
+ TypeEvaluator sBoundEvaluator = new TypeEvaluator() {
+ public Rect evaluate(float fraction, Rect startValue, Rect endValue) {
+ return new Rect(interpolate(startValue.left, endValue.left, fraction),
+ interpolate(startValue.top, endValue.top, fraction),
+ interpolate(startValue.right, endValue.right, fraction),
+ interpolate(startValue.bottom, endValue.bottom, fraction));
+ }
+
+ public int interpolate(int start, int end, float fraction) {
+ return (int) (start + fraction * (end - start));
+ }
+ };
+
+
+ ObjectAnimator hoverViewAnimator = ObjectAnimator.ofObject(mHoverCell, "bounds",
+ sBoundEvaluator, mHoverCellCurrentBounds);
+ hoverViewAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator valueAnimator) {
+ invalidate();
+ }
+ });
+ hoverViewAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mHoverAnimation = true;
+ updateEnableState();
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mHoverAnimation = false;
+ updateEnableState();
+ reset(mobileView);
+ }
+ });
+ hoverViewAnimator.start();
+ }
+
+ private void reset(View mobileView) {
+ idList.clear();
+ mMobileItemId = INVALID_ID;
+ mobileView.setVisibility(View.VISIBLE);
+ mHoverCell = null;
+ if (isPostHoneycomb() && mWobbleInEditMode) {
+ if (mIsEditMode) {
+ restartWobble();
+ } else{
+ stopWobble(true);
+ }
+ }
+ //ugly fix for unclear disappearing items after reorder
+ for (int i = 0; i < getLastVisiblePosition() - getFirstVisiblePosition(); i++) {
+ View child = getChildAt(i);
+ if (child != null) {
+ child.setVisibility(View.VISIBLE);
+ }
+ }
+ invalidate();
+ }
+
+ private void updateEnableState() {
+ setEnabled(!mHoverAnimation && !mReorderAnimation);
+ }
+
+ /**
+ * Seems that GridView before HONEYCOMB not support stable id in proper way.
+ * That cause bugs on view recycle if we will animate or change visibility state for items.
+ *
+ * @return
+ */
+ private boolean isPostHoneycomb() {
+ return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
+ }
+
+ /**
+ * The GridView from Android Lollipoop requires some different
+ * setVisibility() logic when switching cells.
+ *
+ * @return true if OS version is less than Lollipop, false if not
+ */
+ public static boolean isPreLollipop() {
+ return Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP;
+ }
+
+ private void touchEventsCancelled() {
+ View mobileView = getViewForId(mMobileItemId);
+ if (mCellIsMobile) {
+ reset(mobileView);
+ }
+ mCellIsMobile = false;
+ mIsMobileScrolling = false;
+ mActivePointerId = INVALID_ID;
+
+ }
+
+ private void handleCellSwitch() {
+ final int deltaY = mLastEventY - mDownY;
+ final int deltaX = mLastEventX - mDownX;
+ final int deltaYTotal = mHoverCellOriginalBounds.centerY() + mTotalOffsetY + deltaY;
+ final int deltaXTotal = mHoverCellOriginalBounds.centerX() + mTotalOffsetX + deltaX;
+ mMobileView = getViewForId(mMobileItemId);
+ View targetView = null;
+ float vX = 0;
+ float vY = 0;
+ Point mobileColumnRowPair = getColumnAndRowForView(mMobileView);
+ for (Long id : idList) {
+ View view = getViewForId(id);
+ if (view != null) {
+ Point targetColumnRowPair = getColumnAndRowForView(view);
+ if ((aboveRight(targetColumnRowPair, mobileColumnRowPair)
+ && deltaYTotal < view.getBottom() && deltaXTotal > view.getLeft()
+ || aboveLeft(targetColumnRowPair, mobileColumnRowPair)
+ && deltaYTotal < view.getBottom() && deltaXTotal < view.getRight()
+ || belowRight(targetColumnRowPair, mobileColumnRowPair)
+ && deltaYTotal > view.getTop() && deltaXTotal > view.getLeft()
+ || belowLeft(targetColumnRowPair, mobileColumnRowPair)
+ && deltaYTotal > view.getTop() && deltaXTotal < view.getRight()
+ || above(targetColumnRowPair, mobileColumnRowPair)
+ && deltaYTotal < view.getBottom() - mOverlapIfSwitchStraightLine
+ || below(targetColumnRowPair, mobileColumnRowPair)
+ && deltaYTotal > view.getTop() + mOverlapIfSwitchStraightLine
+ || right(targetColumnRowPair, mobileColumnRowPair)
+ && deltaXTotal > view.getLeft() + mOverlapIfSwitchStraightLine
+ || left(targetColumnRowPair, mobileColumnRowPair)
+ && deltaXTotal < view.getRight() - mOverlapIfSwitchStraightLine)) {
+ float xDiff = Math.abs(DynamicGridUtils.getViewX(view) - DynamicGridUtils.getViewX(mMobileView));
+ float yDiff = Math.abs(DynamicGridUtils.getViewY(view) - DynamicGridUtils.getViewY(mMobileView));
+ if (xDiff >= vX && yDiff >= vY) {
+ vX = xDiff;
+ vY = yDiff;
+ targetView = view;
+ }
+ }
+ }
+ }
+ if (targetView != null) {
+ final int originalPosition = getPositionForView(mMobileView);
+ int targetPosition = getPositionForView(targetView);
+
+ final DynamicGridAdapterInterface adapter = getAdapterInterface();
+ if (targetPosition == INVALID_POSITION || !adapter.canReorder(originalPosition) || !adapter.canReorder(targetPosition)) {
+ updateNeighborViewsForId(mMobileItemId);
+ return;
+ }
+ reorderElements(originalPosition, targetPosition);
+
+ if (mUndoSupportEnabled) {
+ mCurrentModification.addTransition(originalPosition, targetPosition);
+ }
+
+ mDownY = mLastEventY;
+ mDownX = mLastEventX;
+
+ SwitchCellAnimator switchCellAnimator;
+
+ if (isPostHoneycomb() && isPreLollipop()) //Between Android 3.0 and Android L
+ switchCellAnimator = new KitKatSwitchCellAnimator(deltaX, deltaY);
+ else if (isPreLollipop()) //Before Android 3.0
+ switchCellAnimator = new PreHoneycombCellAnimator(deltaX, deltaY);
+ else //Android L
+ switchCellAnimator = new LSwitchCellAnimator(deltaX, deltaY);
+
+ updateNeighborViewsForId(mMobileItemId);
+
+ switchCellAnimator.animateSwitchCell(originalPosition, targetPosition);
+ }
+ }
+
+ private interface SwitchCellAnimator {
+ void animateSwitchCell(final int originalPosition, final int targetPosition);
+ }
+
+ private class PreHoneycombCellAnimator implements SwitchCellAnimator {
+ private int mDeltaY;
+ private int mDeltaX;
+
+ public PreHoneycombCellAnimator(int deltaX, int deltaY) {
+ mDeltaX = deltaX;
+ mDeltaY = deltaY;
+ }
+
+ @Override
+ public void animateSwitchCell(int originalPosition, int targetPosition) {
+ mTotalOffsetY += mDeltaY;
+ mTotalOffsetX += mDeltaX;
+ }
+ }
+
+ /**
+ * A {@link org.askerov.dynamicgrid.DynamicGridView.SwitchCellAnimator} for versions KitKat and below.
+ */
+ private class KitKatSwitchCellAnimator implements SwitchCellAnimator {
+
+ private int mDeltaY;
+ private int mDeltaX;
+
+ public KitKatSwitchCellAnimator(int deltaX, int deltaY) {
+ mDeltaX = deltaX;
+ mDeltaY = deltaY;
+ }
+
+ @Override
+ public void animateSwitchCell(final int originalPosition, final int targetPosition) {
+ assert mMobileView != null;
+ getViewTreeObserver().addOnPreDrawListener(new AnimateSwitchViewOnPreDrawListener(mMobileView, originalPosition, targetPosition));
+ mMobileView = getViewForId(mMobileItemId);
+ }
+
+ private class AnimateSwitchViewOnPreDrawListener implements ViewTreeObserver.OnPreDrawListener {
+
+ private final View mPreviousMobileView;
+ private final int mOriginalPosition;
+ private final int mTargetPosition;
+
+ AnimateSwitchViewOnPreDrawListener(final View previousMobileView, final int originalPosition, final int targetPosition) {
+ mPreviousMobileView = previousMobileView;
+ mOriginalPosition = originalPosition;
+ mTargetPosition = targetPosition;
+ }
+
+ @Override
+ public boolean onPreDraw() {
+ getViewTreeObserver().removeOnPreDrawListener(this);
+
+ mTotalOffsetY += mDeltaY;
+ mTotalOffsetX += mDeltaX;
+
+ animateReorder(mOriginalPosition, mTargetPosition);
+
+ mPreviousMobileView.setVisibility(View.VISIBLE);
+
+ if (mMobileView != null) {
+ mMobileView.setVisibility(View.INVISIBLE);
+ }
+ return true;
+ }
+ }
+ }
+
+ /**
+ * A {@link org.askerov.dynamicgrid.DynamicGridView.SwitchCellAnimator} for versions L and above.
+ */
+ private class LSwitchCellAnimator implements SwitchCellAnimator {
+
+ private int mDeltaY;
+ private int mDeltaX;
+
+ public LSwitchCellAnimator(int deltaX, int deltaY) {
+ mDeltaX = deltaX;
+ mDeltaY = deltaY;
+ }
+
+ @Override
+ public void animateSwitchCell(final int originalPosition, final int targetPosition) {
+ getViewTreeObserver().addOnPreDrawListener(new AnimateSwitchViewOnPreDrawListener(originalPosition, targetPosition));
+ }
+
+ private class AnimateSwitchViewOnPreDrawListener implements ViewTreeObserver.OnPreDrawListener {
+ private final int mOriginalPosition;
+ private final int mTargetPosition;
+
+ AnimateSwitchViewOnPreDrawListener(final int originalPosition, final int targetPosition) {
+ mOriginalPosition = originalPosition;
+ mTargetPosition = targetPosition;
+ }
+
+ @Override
+ public boolean onPreDraw() {
+ getViewTreeObserver().removeOnPreDrawListener(this);
+
+ mTotalOffsetY += mDeltaY;
+ mTotalOffsetX += mDeltaX;
+
+ animateReorder(mOriginalPosition, mTargetPosition);
+
+ assert mMobileView != null;
+ mMobileView.setVisibility(View.VISIBLE);
+ mMobileView = getViewForId(mMobileItemId);
+ assert mMobileView != null;
+ mMobileView.setVisibility(View.INVISIBLE);
+ return true;
+ }
+ }
+ }
+
+ private boolean belowLeft(Point targetColumnRowPair, Point mobileColumnRowPair) {
+ return targetColumnRowPair.y > mobileColumnRowPair.y && targetColumnRowPair.x < mobileColumnRowPair.x;
+ }
+
+ private boolean belowRight(Point targetColumnRowPair, Point mobileColumnRowPair) {
+ return targetColumnRowPair.y > mobileColumnRowPair.y && targetColumnRowPair.x > mobileColumnRowPair.x;
+ }
+
+ private boolean aboveLeft(Point targetColumnRowPair, Point mobileColumnRowPair) {
+ return targetColumnRowPair.y < mobileColumnRowPair.y && targetColumnRowPair.x < mobileColumnRowPair.x;
+ }
+
+ private boolean aboveRight(Point targetColumnRowPair, Point mobileColumnRowPair) {
+ return targetColumnRowPair.y < mobileColumnRowPair.y && targetColumnRowPair.x > mobileColumnRowPair.x;
+ }
+
+ private boolean above(Point targetColumnRowPair, Point mobileColumnRowPair) {
+ return targetColumnRowPair.y < mobileColumnRowPair.y && targetColumnRowPair.x == mobileColumnRowPair.x;
+ }
+
+ private boolean below(Point targetColumnRowPair, Point mobileColumnRowPair) {
+ return targetColumnRowPair.y > mobileColumnRowPair.y && targetColumnRowPair.x == mobileColumnRowPair.x;
+ }
+
+ private boolean right(Point targetColumnRowPair, Point mobileColumnRowPair) {
+ return targetColumnRowPair.y == mobileColumnRowPair.y && targetColumnRowPair.x > mobileColumnRowPair.x;
+ }
+
+ private boolean left(Point targetColumnRowPair, Point mobileColumnRowPair) {
+ return targetColumnRowPair.y == mobileColumnRowPair.y && targetColumnRowPair.x < mobileColumnRowPair.x;
+ }
+
+ private Point getColumnAndRowForView(View view) {
+ int pos = getPositionForView(view);
+ int columns = getColumnCount();
+ int column = pos % columns;
+ int row = pos / columns;
+ return new Point(column, row);
+ }
+
+ private long getId(int position) {
+ return getAdapter().getItemId(position);
+ }
+
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ private void animateReorder(final int oldPosition, final int newPosition) {
+ boolean isForward = newPosition > oldPosition;
+ List resultList = new LinkedList();
+ if (isForward) {
+ for (int pos = Math.min(oldPosition, newPosition); pos < Math.max(oldPosition, newPosition); pos++) {
+ View view = getViewForId(getId(pos));
+ if ((pos + 1) % getColumnCount() == 0) {
+ resultList.add(createTranslationAnimations(view, -view.getWidth() * (getColumnCount() - 1), 0,
+ view.getHeight(), 0));
+ } else {
+ resultList.add(createTranslationAnimations(view, view.getWidth(), 0, 0, 0));
+ }
+ }
+ } else {
+ for (int pos = Math.max(oldPosition, newPosition); pos > Math.min(oldPosition, newPosition); pos--) {
+ View view = getViewForId(getId(pos));
+ if ((pos + getColumnCount()) % getColumnCount() == 0) {
+ resultList.add(createTranslationAnimations(view, view.getWidth() * (getColumnCount() - 1), 0,
+ -view.getHeight(), 0));
+ } else {
+ resultList.add(createTranslationAnimations(view, -view.getWidth(), 0, 0, 0));
+ }
+ }
+ }
+
+ AnimatorSet resultSet = new AnimatorSet();
+ resultSet.playTogether(resultList);
+ resultSet.setDuration(MOVE_DURATION);
+ resultSet.setInterpolator(new AccelerateDecelerateInterpolator());
+ resultSet.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mReorderAnimation = true;
+ updateEnableState();
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mReorderAnimation = false;
+ updateEnableState();
+ }
+ });
+ resultSet.start();
+ }
+
+
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ private AnimatorSet createTranslationAnimations(View view, float startX, float endX, float startY, float endY) {
+ ObjectAnimator animX = ObjectAnimator.ofFloat(view, "translationX", startX, endX);
+ ObjectAnimator animY = ObjectAnimator.ofFloat(view, "translationY", startY, endY);
+ AnimatorSet animSetXY = new AnimatorSet();
+ animSetXY.playTogether(animX, animY);
+ return animSetXY;
+ }
+
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ super.dispatchDraw(canvas);
+ if (mHoverCell != null) {
+ mHoverCell.draw(canvas);
+ }
+ }
+
+
+ public interface OnDropListener {
+ void onActionDrop();
+ }
+
+ public interface OnDragListener {
+
+ public void onDragStarted(int position);
+
+ public void onDragPositionsChanged(int oldPosition, int newPosition);
+ }
+
+ public interface OnEditModeChangeListener {
+ public void onEditModeChanged(boolean inEditMode);
+ }
+
+ public interface OnSelectedItemBitmapCreationListener {
+ public void onPreSelectedItemBitmapCreation(View selectedView, int position, long itemId);
+
+ public void onPostSelectedItemBitmapCreation(View selectedView, int position, long itemId);
+ }
+
+
+ /**
+ * This scroll listener is added to the gridview in order to handle cell swapping
+ * when the cell is either at the top or bottom edge of the gridview. If the hover
+ * cell is at either edge of the gridview, the gridview will begin scrolling. As
+ * scrolling takes place, the gridview continuously checks if new cells became visible
+ * and determines whether they are potential candidates for a cell swap.
+ */
+ private OnScrollListener mScrollListener = new OnScrollListener() {
+
+ private int mPreviousFirstVisibleItem = -1;
+ private int mPreviousVisibleItemCount = -1;
+ private int mCurrentFirstVisibleItem;
+ private int mCurrentVisibleItemCount;
+ private int mCurrentScrollState;
+
+ public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
+ int totalItemCount) {
+ mCurrentFirstVisibleItem = firstVisibleItem;
+ mCurrentVisibleItemCount = visibleItemCount;
+
+ mPreviousFirstVisibleItem = (mPreviousFirstVisibleItem == -1) ? mCurrentFirstVisibleItem
+ : mPreviousFirstVisibleItem;
+ mPreviousVisibleItemCount = (mPreviousVisibleItemCount == -1) ? mCurrentVisibleItemCount
+ : mPreviousVisibleItemCount;
+
+ checkAndHandleFirstVisibleCellChange();
+ checkAndHandleLastVisibleCellChange();
+
+ mPreviousFirstVisibleItem = mCurrentFirstVisibleItem;
+ mPreviousVisibleItemCount = mCurrentVisibleItemCount;
+ if (isPostHoneycomb() && mWobbleInEditMode) {
+ updateWobbleState(visibleItemCount);
+ }
+ if (mUserScrollListener != null) {
+ mUserScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ private void updateWobbleState(int visibleItemCount) {
+ for (int i = 0; i < visibleItemCount; i++) {
+ View child = getChildAt(i);
+
+ if (child != null) {
+ if (mMobileItemId != INVALID_ID && Boolean.TRUE != child.getTag(R.id.dgv_wobble_tag)) {
+ if (i % 2 == 0)
+ animateWobble(child);
+ else
+ animateWobbleInverse(child);
+ child.setTag(R.id.dgv_wobble_tag, true);
+ } else if (mMobileItemId == INVALID_ID && child.getRotation() != 0) {
+ child.setRotation(0);
+ child.setTag(R.id.dgv_wobble_tag, false);
+ }
+ }
+
+ }
+ }
+
+ @Override
+ public void onScrollStateChanged(AbsListView view, int scrollState) {
+ mCurrentScrollState = scrollState;
+ mScrollState = scrollState;
+ isScrollCompleted();
+ if (mUserScrollListener != null) {
+ mUserScrollListener.onScrollStateChanged(view, scrollState);
+ }
+ }
+
+ /**
+ * This method is in charge of invoking 1 of 2 actions. Firstly, if the gridview
+ * is in a state of scrolling invoked by the hover cell being outside the bounds
+ * of the gridview, then this scrolling event is continued. Secondly, if the hover
+ * cell has already been released, this invokes the animation for the hover cell
+ * to return to its correct position after the gridview has entered an idle scroll
+ * state.
+ */
+ private void isScrollCompleted() {
+ if (mCurrentVisibleItemCount > 0 && mCurrentScrollState == SCROLL_STATE_IDLE) {
+ if (mCellIsMobile && mIsMobileScrolling) {
+ handleMobileCellScroll();
+ } else if (mIsWaitingForScrollFinish) {
+ touchEventsEnded();
+ }
+ }
+ }
+
+ /**
+ * Determines if the gridview scrolled up enough to reveal a new cell at the
+ * top of the list. If so, then the appropriate parameters are updated.
+ */
+ public void checkAndHandleFirstVisibleCellChange() {
+ if (mCurrentFirstVisibleItem != mPreviousFirstVisibleItem) {
+ if (mCellIsMobile && mMobileItemId != INVALID_ID) {
+ updateNeighborViewsForId(mMobileItemId);
+ handleCellSwitch();
+ }
+ }
+ }
+
+ /**
+ * Determines if the gridview scrolled down enough to reveal a new cell at the
+ * bottom of the list. If so, then the appropriate parameters are updated.
+ */
+ public void checkAndHandleLastVisibleCellChange() {
+ int currentLastVisibleItem = mCurrentFirstVisibleItem + mCurrentVisibleItemCount;
+ int previousLastVisibleItem = mPreviousFirstVisibleItem + mPreviousVisibleItemCount;
+ if (currentLastVisibleItem != previousLastVisibleItem) {
+ if (mCellIsMobile && mMobileItemId != INVALID_ID) {
+ updateNeighborViewsForId(mMobileItemId);
+ handleCellSwitch();
+ }
+ }
+ }
+ };
+
+ private static class DynamicGridModification {
+
+ private List> transitions;
+
+ DynamicGridModification() {
+ super();
+ this.transitions = new Stack>();
+ }
+
+ public boolean hasTransitions() {
+ return !transitions.isEmpty();
+ }
+
+ public void addTransition(int oldPosition, int newPosition) {
+ transitions.add(new Pair(oldPosition, newPosition));
+ }
+
+ public List> getTransitions() {
+ Collections.reverse(transitions);
+ return transitions;
+ }
+ }
+
+}
diff --git a/app/src/main/java/com/example/cosmosclient/views/GroupListActivity.java b/app/src/main/java/com/example/cosmosclient/views/GroupListActivity.java
index c7515bf..1c51c9c 100644
--- a/app/src/main/java/com/example/cosmosclient/views/GroupListActivity.java
+++ b/app/src/main/java/com/example/cosmosclient/views/GroupListActivity.java
@@ -1,7 +1,9 @@
package com.example.cosmosclient.views;
import android.content.Intent;
+import android.nfc.Tag;
import android.os.Bundle;
+import android.util.Log;
import android.view.View;
import android.support.v4.view.GravityCompat;
import android.support.v7.app.ActionBarDrawerToggle;
@@ -12,13 +14,27 @@
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.GridView;
+import android.widget.ListAdapter;
import android.widget.TextView;
+import android.widget.Toast;
+
+import com.example.cosmosclient.views.DynamicGridView;
import com.example.cosmosclient.R;
+import java.util.ArrayList;
+import java.util.Arrays;
+
public class GroupListActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
+ private static final String TAG = GroupListActivity.class.getName();
+ private DynamicGridView gridView;
+
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -26,6 +42,44 @@
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
+ String[] list = {"ファミリー\n 紙コップ\n 延長ケーブル", "Group2\n からし", "Group3\n ケーキ\n something"};
+
+ gridView = (DynamicGridView) findViewById(R.id.dynamic_grid);
+ gridView.setAdapter((ListAdapter) new CheeseDynamicAdapter(this,
+ new ArrayList(Arrays.asList(Cheeses.sCheeseStrings)),
+ getResources().getInteger(R.integer.column_count)));
+
+ gridView.setOnDragListener(new DynamicGridView.OnDragListener() {
+ @Override
+ public void onDragStarted(int position) {
+ Log.d(TAG, "drag started at position" + position);
+ }
+
+ @Override
+ public void onDragPositionsChanged(int oldPosition, int newPosition) {
+ Log.d(TAG, String.format("drag item position changed from %d to %d", oldPosition, newPosition));
+ }
+
+ });
+
+ gridView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
+ @Override
+ public boolean onItemLongClick(AdapterView> parent, View view, int position, long id) {
+ gridView.startEditMode(position);
+ return true;
+ }
+ });
+
+ gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+// Toast.makeText(GroupListActivity.this, parent.getAdapter().getItem(position).toString(),
+// Toast.LENGTH_SHORT).show();
+ Intent intent=new Intent(GroupListActivity.this, com.example.cosmosclient.views.RequestListActivity.class);
+ startActivity(intent);
+ }
+ });
+
/* とりあえずの画面遷移なので変更するかも */
TextView group1 = findViewById(R.id.group1);
group1.setOnClickListener(new View.OnClickListener() {
@@ -51,6 +105,8 @@
DrawerLayout drawer = findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
+ } else if (gridView.isEditMode()) {
+ gridView.stopEditMode();
} else {
super.onBackPressed();
}
@@ -82,11 +138,11 @@
@Override
public boolean onNavigationItemSelected(MenuItem item) {
-
// Handle navigation view item clicks here.
int id = item.getItemId();
if ( id == R.id.createNewGroupButton){
-
+ Intent intent=new Intent(GroupListActivity.this, com.example.cosmosclient.views.CreateGroupActivity.class);
+ startActivity(intent);
} else if (id == R.id.joinGroupButton){
Intent intent=new Intent(GroupListActivity.this, com.example.cosmosclient.views.JoinGroupActionsActivity.class);
startActivity(intent);
diff --git a/app/src/main/java/com/example/cosmosclient/views/SigninActivity.java b/app/src/main/java/com/example/cosmosclient/views/SigninActivity.java
index 2cbe6b6..7214bb7 100644
--- a/app/src/main/java/com/example/cosmosclient/views/SigninActivity.java
+++ b/app/src/main/java/com/example/cosmosclient/views/SigninActivity.java
@@ -58,7 +58,7 @@
@Override
public void onClick(View v) {
//APIに値を送信
- Call call = signinService.loginList(UserIdText.getText().toString(), PasswordText.getText().toString());
+ Call call = signinService.login(UserIdText.getText().toString(), PasswordText.getText().toString());
//サーバからのレスポンス
call.enqueue(new Callback() {
@@ -71,7 +71,9 @@
//app/Cosmosに情報保存
Cosmos app = (Cosmos)getApplication();
app.setToken(result.token);
+ app.setuId(result.uId);
+ //画面遷移
Intent intent = new Intent(getApplication(), GroupListActivity.class);
startActivity(intent);
Toast.makeText(SigninActivity.this,
diff --git a/app/src/main/java/com/example/cosmosclient/views/SignupActivity.java b/app/src/main/java/com/example/cosmosclient/views/SignupActivity.java
index e130633..fe6d66f 100644
--- a/app/src/main/java/com/example/cosmosclient/views/SignupActivity.java
+++ b/app/src/main/java/com/example/cosmosclient/views/SignupActivity.java
@@ -1,6 +1,8 @@
package com.example.cosmosclient.views;
+
import android.content.Intent;
+import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
@@ -8,12 +10,15 @@
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
+import android.widget.ImageView;
import android.widget.Toast;
import com.example.cosmosclient.R;
import com.example.cosmosclient.app.Cosmos;
import com.example.cosmosclient.entities.SignupResponse;
import com.example.cosmosclient.resources.UsersRest;
+import com.theartofdev.edmodo.cropper.CropImage;
+import com.theartofdev.edmodo.cropper.CropImageView;
import retrofit2.Call;
@@ -27,6 +32,7 @@
private boolean pwEnable;
private boolean cpwEnable;
private Button MakeAccountButton;
+ private ImageView iconChoice;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -47,6 +53,8 @@
final EditText NameText = findViewById(R.id.NameText);
final EditText PasswordText = findViewById(R.id.PasswordText);
final EditText ConfirmPasswordText = findViewById(R.id.ConfirmPasswordText);
+ iconChoice = findViewById(R.id.choiceImage);
+
//
// //入力欄監視
// NameText.addTextChangedListener(new GenericTextWatcher(NameText));
@@ -57,14 +65,14 @@
// MakeAccountButton.setEnabled(false);
//Make Accountボタンの処理
- MakeAccountButton.setOnClickListener(new View.OnClickListener(){
+ MakeAccountButton.setOnClickListener(new View.OnClickListener() {
@Override
- public void onClick(View v){
+ public void onClick(View v) {
String pw = PasswordText.getText().toString();
String confirmPw = ConfirmPasswordText.getText().toString();
//パスワードと確認パスワードが一致していない際の処理
- if(!pw.equals(confirmPw)){
+ if (!pw.equals(confirmPw)) {
PasswordText.setError("入力されたパスワードが一致しません");
ConfirmPasswordText.setError("入力されたパスワードが一致しません");
return;
@@ -72,7 +80,7 @@
//API呼び出しのための値入力
Call call = signupService.createUser(NameText.getText().toString(),
- PasswordText.getText().toString(),"https://yumenavi.info/live/2018/photo/k/s015980019.jpg");
+ PasswordText.getText().toString(), "https://yumenavi.info/live/2018/photo/k/s015980019.jpg");
//サーバからデータ受け取り
call.enqueue(new Callback() {
@@ -82,8 +90,10 @@
if (response.isSuccessful()) {
SignupResponse result = response.body();
- Cosmos app = (Cosmos)getApplication();
+ //app/Cosmosに情報保存
+ Cosmos app = (Cosmos) getApplication();
app.setToken(result.token);
+ app.setuId(result.uId);
Intent intent = new Intent(getApplication(), GroupListActivity.class);
@@ -97,13 +107,13 @@
startActivity(intent);
Toast.makeText(SignupActivity.this,
- "アカウントを作成しました",Toast.LENGTH_SHORT);
+ "アカウントを作成しました", Toast.LENGTH_SHORT).show();
finish();
- }else{
+ } else {
//onFailureでキャッチできないエラー用
Toast.makeText(SignupActivity.this,
- "アカウント作成失敗",Toast.LENGTH_SHORT);
+ "通信エラー", Toast.LENGTH_SHORT).show();
}
}
@@ -112,21 +122,46 @@
public void onFailure(Call call, Throwable t) {
t.printStackTrace();
Toast.makeText(SignupActivity.this,
- "アカウント作成失敗",Toast.LENGTH_SHORT);
+ "アカウント作成失敗", Toast.LENGTH_SHORT).show();
}
});
}
});
//サインイン画面への遷移処理
- LoginButton.setOnClickListener(new View.OnClickListener(){
+ LoginButton.setOnClickListener(new View.OnClickListener() {
@Override
- public void onClick(View v){
- Intent intent = new Intent(getApplication(),SigninActivity.class);
+ public void onClick(View v) {
+ Intent intent = new Intent(getApplication(), SigninActivity.class);
startActivity(intent);
finish();
}
});
+
+ //アイコン選択
+ iconChoice.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ CropImage.activity()
+ .setAspectRatio(1,1)
+ .setGuidelines(CropImageView.Guidelines.ON)
+ .start(SignupActivity.this);
+ }
+ });
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ //トリミング後の処理
+ if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
+ CropImage.ActivityResult result = CropImage.getActivityResult(data);
+ if (resultCode == RESULT_OK) {
+ Uri resultUri = result.getUri();
+ iconChoice.setImageURI(resultUri);
+ } else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {
+ Exception error = result.getError();
+ }
+ }
}
//入力欄監視処理内容
@@ -171,7 +206,7 @@
if(nameEnable && pwEnable && cpwEnable){
MakeAccountButton.setEnabled(true);
}else{
- MakeAccountButton.setEnabled(false);
+ MakeAccountButton.setEnabled(false);
}
}
}
diff --git a/app/src/main/res/drawable/borderless_button.xml b/app/src/main/res/drawable/borderless_button.xml
index 7a4684f..a8b409b 100644
--- a/app/src/main/res/drawable/borderless_button.xml
+++ b/app/src/main/res/drawable/borderless_button.xml
@@ -1,14 +1,4 @@
- -
-
-
-
-
- -
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_make_group.xml b/app/src/main/res/layout/activity_make_group.xml
new file mode 100644
index 0000000..0762055
--- /dev/null
+++ b/app/src/main/res/layout/activity_make_group.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_signup.xml b/app/src/main/res/layout/activity_signup.xml
index 92cbdbe..bf45ed6 100644
--- a/app/src/main/res/layout/activity_signup.xml
+++ b/app/src/main/res/layout/activity_signup.xml
@@ -157,4 +157,15 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/content_group_list.xml b/app/src/main/res/layout/content_group_list.xml
index 44667b0..28cf0c7 100644
--- a/app/src/main/res/layout/content_group_list.xml
+++ b/app/src/main/res/layout/content_group_list.xml
@@ -28,6 +28,26 @@
app:layout_constraintTop_toBottomOf="@+id/group1"
app:layout_constraintVertical_bias="1.0" />
+
+
@@ -48,6 +69,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="object1"
+ android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="@+id/group1"
app:layout_constraintEnd_toEndOf="@+id/group1"
app:layout_constraintHorizontal_bias="0.246"
@@ -60,6 +82,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="object2"
+ android:visibility="invisible"
app:layout_constraintEnd_toEndOf="@+id/checkBox"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="@+id/checkBox"
diff --git a/app/src/main/res/layout/item_grid.xml b/app/src/main/res/layout/item_grid.xml
new file mode 100644
index 0000000..89e6a64
--- /dev/null
+++ b/app/src/main/res/layout/item_grid.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/integers.xml b/app/src/main/res/values/integers.xml
new file mode 100644
index 0000000..08d8b8b
--- /dev/null
+++ b/app/src/main/res/values/integers.xml
@@ -0,0 +1,4 @@
+
+
+ 2
+
\ No newline at end of file
diff --git a/dynamicgrid/AndroidManifest.xml b/dynamicgrid/AndroidManifest.xml
new file mode 100644
index 0000000..0eaebcc
--- /dev/null
+++ b/dynamicgrid/AndroidManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
diff --git a/dynamicgrid/build.gradle b/dynamicgrid/build.gradle
new file mode 100644
index 0000000..15877a3
--- /dev/null
+++ b/dynamicgrid/build.gradle
@@ -0,0 +1,22 @@
+apply plugin: 'com.android.library'
+
+android {
+ compileSdkVersion 28
+
+ defaultConfig {
+ minSdkVersion 14
+ targetSdkVersion 28
+ }
+
+ sourceSets {
+ main {
+ manifest.srcFile 'AndroidManifest.xml'
+ java.srcDirs = ['src']
+ resources.srcDirs = ['src']
+ aidl.srcDirs = ['src']
+ renderscript.srcDirs = ['src']
+ res.srcDirs = ['res']
+ assets.srcDirs = ['assets']
+ }
+ }
+}
\ No newline at end of file
diff --git a/dynamicgrid/build/generated/source/buildConfig/androidTest/debug/org/askerov/dynamicgrid/test/BuildConfig.java b/dynamicgrid/build/generated/source/buildConfig/androidTest/debug/org/askerov/dynamicgrid/test/BuildConfig.java
new file mode 100644
index 0000000..62d67e0
--- /dev/null
+++ b/dynamicgrid/build/generated/source/buildConfig/androidTest/debug/org/askerov/dynamicgrid/test/BuildConfig.java
@@ -0,0 +1,13 @@
+/**
+ * Automatically generated file. DO NOT MODIFY
+ */
+package org.askerov.dynamicgrid.test;
+
+public final class BuildConfig {
+ public static final boolean DEBUG = Boolean.parseBoolean("true");
+ public static final String APPLICATION_ID = "org.askerov.dynamicgrid.test";
+ public static final String BUILD_TYPE = "debug";
+ public static final String FLAVOR = "";
+ public static final int VERSION_CODE = -1;
+ public static final String VERSION_NAME = "";
+}
diff --git a/dynamicgrid/build/generated/source/buildConfig/debug/org/askerov/dynamicgrid/BuildConfig.java b/dynamicgrid/build/generated/source/buildConfig/debug/org/askerov/dynamicgrid/BuildConfig.java
new file mode 100644
index 0000000..7d59d2c
--- /dev/null
+++ b/dynamicgrid/build/generated/source/buildConfig/debug/org/askerov/dynamicgrid/BuildConfig.java
@@ -0,0 +1,13 @@
+/**
+ * Automatically generated file. DO NOT MODIFY
+ */
+package org.askerov.dynamicgrid;
+
+public final class BuildConfig {
+ public static final boolean DEBUG = Boolean.parseBoolean("true");
+ public static final String APPLICATION_ID = "org.askerov.dynamicgrid";
+ public static final String BUILD_TYPE = "debug";
+ public static final String FLAVOR = "";
+ public static final int VERSION_CODE = 1;
+ public static final String VERSION_NAME = "1.0";
+}
diff --git a/dynamicgrid/build/intermediates/aapt_friendly_merged_manifests/debug/aapt/AndroidManifest.xml b/dynamicgrid/build/intermediates/aapt_friendly_merged_manifests/debug/aapt/AndroidManifest.xml
new file mode 100644
index 0000000..969f1b9
--- /dev/null
+++ b/dynamicgrid/build/intermediates/aapt_friendly_merged_manifests/debug/aapt/AndroidManifest.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dynamicgrid/build/intermediates/aapt_friendly_merged_manifests/debug/aapt/output.json b/dynamicgrid/build/intermediates/aapt_friendly_merged_manifests/debug/aapt/output.json
new file mode 100644
index 0000000..5858633
--- /dev/null
+++ b/dynamicgrid/build/intermediates/aapt_friendly_merged_manifests/debug/aapt/output.json
@@ -0,0 +1 @@
+[{"outputType":{"type":"AAPT_FRIENDLY_MERGED_MANIFESTS"},"apkData":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0","enabled":true,"outputFile":"dynamicgrid-debug.aar","fullName":"debug","baseName":"debug"},"path":"AndroidManifest.xml","properties":{"packageId":"org.askerov.dynamicgrid","split":""}}]
\ No newline at end of file
diff --git a/dynamicgrid/build/intermediates/annotation_processor_list/debug/annotationProcessors.json b/dynamicgrid/build/intermediates/annotation_processor_list/debug/annotationProcessors.json
new file mode 100644
index 0000000..9e26dfe
--- /dev/null
+++ b/dynamicgrid/build/intermediates/annotation_processor_list/debug/annotationProcessors.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/dynamicgrid/build/intermediates/apk_list/debug/mainApkListPersistenceDebug/apk-list.gson b/dynamicgrid/build/intermediates/apk_list/debug/mainApkListPersistenceDebug/apk-list.gson
new file mode 100644
index 0000000..23e2309
--- /dev/null
+++ b/dynamicgrid/build/intermediates/apk_list/debug/mainApkListPersistenceDebug/apk-list.gson
@@ -0,0 +1 @@
+[{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0","enabled":true,"outputFile":"dynamicgrid-debug.apk","fullName":"debug","baseName":"debug"}]
\ No newline at end of file
diff --git a/dynamicgrid/build/intermediates/bundle_manifest/debug/processDebugManifest/bundle-manifest/AndroidManifest.xml b/dynamicgrid/build/intermediates/bundle_manifest/debug/processDebugManifest/bundle-manifest/AndroidManifest.xml
new file mode 100644
index 0000000..969f1b9
--- /dev/null
+++ b/dynamicgrid/build/intermediates/bundle_manifest/debug/processDebugManifest/bundle-manifest/AndroidManifest.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dynamicgrid/build/intermediates/bundle_manifest/debug/processDebugManifest/bundle-manifest/output.json b/dynamicgrid/build/intermediates/bundle_manifest/debug/processDebugManifest/bundle-manifest/output.json
new file mode 100644
index 0000000..c0eb612
--- /dev/null
+++ b/dynamicgrid/build/intermediates/bundle_manifest/debug/processDebugManifest/bundle-manifest/output.json
@@ -0,0 +1 @@
+[{"outputType":{"type":"BUNDLE_MANIFEST"},"apkData":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0","enabled":true,"outputFile":"dynamicgrid-debug.apk","fullName":"debug","baseName":"debug"},"path":"AndroidManifest.xml","properties":{"packageId":"org.askerov.dynamicgrid","split":"","minSdkVersion":"14"}}]
\ No newline at end of file
diff --git a/dynamicgrid/build/intermediates/compatible_screen_manifest/debug/createDebugCompatibleScreenManifests/out/output.json b/dynamicgrid/build/intermediates/compatible_screen_manifest/debug/createDebugCompatibleScreenManifests/out/output.json
new file mode 100644
index 0000000..0637a08
--- /dev/null
+++ b/dynamicgrid/build/intermediates/compatible_screen_manifest/debug/createDebugCompatibleScreenManifests/out/output.json
@@ -0,0 +1 @@
+[]
\ No newline at end of file
diff --git a/dynamicgrid/build/intermediates/compile_library_classes/debug/classes.jar b/dynamicgrid/build/intermediates/compile_library_classes/debug/classes.jar
new file mode 100644
index 0000000..8040ff7
--- /dev/null
+++ b/dynamicgrid/build/intermediates/compile_library_classes/debug/classes.jar
Binary files differ
diff --git a/dynamicgrid/build/intermediates/compile_only_not_namespaced_r_class_jar/debug/generateDebugRFile/R.jar b/dynamicgrid/build/intermediates/compile_only_not_namespaced_r_class_jar/debug/generateDebugRFile/R.jar
new file mode 100644
index 0000000..20aacba
--- /dev/null
+++ b/dynamicgrid/build/intermediates/compile_only_not_namespaced_r_class_jar/debug/generateDebugRFile/R.jar
Binary files differ
diff --git a/dynamicgrid/build/intermediates/incremental/debug-mergeJniLibs/merge-state b/dynamicgrid/build/intermediates/incremental/debug-mergeJniLibs/merge-state
new file mode 100644
index 0000000..4577682
--- /dev/null
+++ b/dynamicgrid/build/intermediates/incremental/debug-mergeJniLibs/merge-state
Binary files differ
diff --git a/dynamicgrid/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml b/dynamicgrid/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml
new file mode 100644
index 0000000..7ae3cc3
--- /dev/null
+++ b/dynamicgrid/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/dynamicgrid/build/intermediates/incremental/mergeDebugShaders/merger.xml b/dynamicgrid/build/intermediates/incremental/mergeDebugShaders/merger.xml
new file mode 100644
index 0000000..e63d0d4
--- /dev/null
+++ b/dynamicgrid/build/intermediates/incremental/mergeDebugShaders/merger.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/dynamicgrid/build/intermediates/incremental/packageDebugAssets/merger.xml b/dynamicgrid/build/intermediates/incremental/packageDebugAssets/merger.xml
new file mode 100644
index 0000000..fec599c
--- /dev/null
+++ b/dynamicgrid/build/intermediates/incremental/packageDebugAssets/merger.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/dynamicgrid/build/intermediates/incremental/packageDebugResources/compile-file-map.properties b/dynamicgrid/build/intermediates/incremental/packageDebugResources/compile-file-map.properties
new file mode 100644
index 0000000..c1e61e4
--- /dev/null
+++ b/dynamicgrid/build/intermediates/incremental/packageDebugResources/compile-file-map.properties
@@ -0,0 +1 @@
+#Tue Jun 25 13:06:52 JST 2019
diff --git a/dynamicgrid/build/intermediates/incremental/packageDebugResources/merged.dir/values/values.xml b/dynamicgrid/build/intermediates/incremental/packageDebugResources/merged.dir/values/values.xml
new file mode 100644
index 0000000..29b2c0a
--- /dev/null
+++ b/dynamicgrid/build/intermediates/incremental/packageDebugResources/merged.dir/values/values.xml
@@ -0,0 +1,5 @@
+
+
+ 16dp
+
+
\ No newline at end of file
diff --git a/dynamicgrid/build/intermediates/incremental/packageDebugResources/merger.xml b/dynamicgrid/build/intermediates/incremental/packageDebugResources/merger.xml
new file mode 100644
index 0000000..e654bbb
--- /dev/null
+++ b/dynamicgrid/build/intermediates/incremental/packageDebugResources/merger.xml
@@ -0,0 +1,2 @@
+
+16dp
\ No newline at end of file
diff --git a/dynamicgrid/build/intermediates/instant_app_manifest/debug/AndroidManifest.xml b/dynamicgrid/build/intermediates/instant_app_manifest/debug/AndroidManifest.xml
new file mode 100644
index 0000000..bb00f40
--- /dev/null
+++ b/dynamicgrid/build/intermediates/instant_app_manifest/debug/AndroidManifest.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dynamicgrid/build/intermediates/instant_app_manifest/debug/output.json b/dynamicgrid/build/intermediates/instant_app_manifest/debug/output.json
new file mode 100644
index 0000000..49dde6d
--- /dev/null
+++ b/dynamicgrid/build/intermediates/instant_app_manifest/debug/output.json
@@ -0,0 +1 @@
+[{"outputType":{"type":"INSTANT_APP_MANIFEST"},"apkData":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0","enabled":true,"outputFile":"dynamicgrid-debug.apk","fullName":"debug","baseName":"debug"},"path":"AndroidManifest.xml","properties":{"packageId":"org.askerov.dynamicgrid","split":"","minSdkVersion":"14"}}]
\ No newline at end of file
diff --git a/dynamicgrid/build/intermediates/instant_run_merged_manifests/debug/output.json b/dynamicgrid/build/intermediates/instant_run_merged_manifests/debug/output.json
new file mode 100644
index 0000000..9e89ad0
--- /dev/null
+++ b/dynamicgrid/build/intermediates/instant_run_merged_manifests/debug/output.json
@@ -0,0 +1 @@
+[{"outputType":{"type":"INSTANT_RUN_MERGED_MANIFESTS"},"apkData":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0","enabled":true,"outputFile":"dynamicgrid-debug.apk","fullName":"debug","baseName":"debug"},"path":"AndroidManifest.xml","properties":{"packageId":"org.askerov.dynamicgrid","split":"","minSdkVersion":"14"}}]
\ No newline at end of file
diff --git a/dynamicgrid/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/org/askerov/dynamicgrid/AbstractDynamicGridAdapter.class b/dynamicgrid/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/org/askerov/dynamicgrid/AbstractDynamicGridAdapter.class
new file mode 100644
index 0000000..8255073
--- /dev/null
+++ b/dynamicgrid/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/org/askerov/dynamicgrid/AbstractDynamicGridAdapter.class
Binary files differ
diff --git a/dynamicgrid/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/org/askerov/dynamicgrid/BaseDynamicGridAdapter.class b/dynamicgrid/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/org/askerov/dynamicgrid/BaseDynamicGridAdapter.class
new file mode 100644
index 0000000..5b9a838
--- /dev/null
+++ b/dynamicgrid/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/org/askerov/dynamicgrid/BaseDynamicGridAdapter.class
Binary files differ
diff --git a/dynamicgrid/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/org/askerov/dynamicgrid/BuildConfig.class b/dynamicgrid/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/org/askerov/dynamicgrid/BuildConfig.class
new file mode 100644
index 0000000..eeb491f
--- /dev/null
+++ b/dynamicgrid/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/org/askerov/dynamicgrid/BuildConfig.class
Binary files differ
diff --git a/dynamicgrid/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/org/askerov/dynamicgrid/DynamicGridAdapterInterface.class b/dynamicgrid/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/org/askerov/dynamicgrid/DynamicGridAdapterInterface.class
new file mode 100644
index 0000000..e2fdd98
--- /dev/null
+++ b/dynamicgrid/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/org/askerov/dynamicgrid/DynamicGridAdapterInterface.class
Binary files differ
diff --git a/dynamicgrid/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/org/askerov/dynamicgrid/DynamicGridUtils.class b/dynamicgrid/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/org/askerov/dynamicgrid/DynamicGridUtils.class
new file mode 100644
index 0000000..5999f16
--- /dev/null
+++ b/dynamicgrid/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/org/askerov/dynamicgrid/DynamicGridUtils.class
Binary files differ
diff --git a/dynamicgrid/build/intermediates/library_java_res/debug/res.jar b/dynamicgrid/build/intermediates/library_java_res/debug/res.jar
new file mode 100644
index 0000000..15cb0ec
--- /dev/null
+++ b/dynamicgrid/build/intermediates/library_java_res/debug/res.jar
Binary files differ
diff --git a/dynamicgrid/build/intermediates/library_manifest/debug/AndroidManifest.xml b/dynamicgrid/build/intermediates/library_manifest/debug/AndroidManifest.xml
new file mode 100644
index 0000000..969f1b9
--- /dev/null
+++ b/dynamicgrid/build/intermediates/library_manifest/debug/AndroidManifest.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dynamicgrid/build/intermediates/merged_manifests/debug/output.json b/dynamicgrid/build/intermediates/merged_manifests/debug/output.json
new file mode 100644
index 0000000..993b22e
--- /dev/null
+++ b/dynamicgrid/build/intermediates/merged_manifests/debug/output.json
@@ -0,0 +1 @@
+[{"outputType":{"type":"MERGED_MANIFESTS"},"apkData":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0","enabled":true,"outputFile":"dynamicgrid-debug.aar","fullName":"debug","baseName":"debug"},"path":"..\\..\\library_manifest\\debug\\AndroidManifest.xml","properties":{"packageId":"org.askerov.dynamicgrid","split":""}}]
\ No newline at end of file
diff --git a/dynamicgrid/build/intermediates/merged_manifests/debugAndroidTest/AndroidManifest.xml b/dynamicgrid/build/intermediates/merged_manifests/debugAndroidTest/AndroidManifest.xml
new file mode 100644
index 0000000..7f936b7
--- /dev/null
+++ b/dynamicgrid/build/intermediates/merged_manifests/debugAndroidTest/AndroidManifest.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dynamicgrid/build/intermediates/merged_manifests/debugAndroidTest/output.json b/dynamicgrid/build/intermediates/merged_manifests/debugAndroidTest/output.json
new file mode 100644
index 0000000..54376bf
--- /dev/null
+++ b/dynamicgrid/build/intermediates/merged_manifests/debugAndroidTest/output.json
@@ -0,0 +1 @@
+[{"outputType":{"type":"MERGED_MANIFESTS"},"apkData":{"type":"MAIN","splits":[],"versionCode":-1,"enabled":true,"outputFile":"dynamicgrid-debug-androidTest.apk","fullName":"debugAndroidTest","baseName":"debug-androidTest"},"path":"AndroidManifest.xml","properties":{}}]
\ No newline at end of file
diff --git a/dynamicgrid/build/intermediates/metadata_feature_manifest/debug/processDebugManifest/metadata-feature/output.json b/dynamicgrid/build/intermediates/metadata_feature_manifest/debug/processDebugManifest/metadata-feature/output.json
new file mode 100644
index 0000000..245d472
--- /dev/null
+++ b/dynamicgrid/build/intermediates/metadata_feature_manifest/debug/processDebugManifest/metadata-feature/output.json
@@ -0,0 +1 @@
+[{"outputType":{"type":"METADATA_FEATURE_MANIFEST"},"apkData":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0","enabled":true,"outputFile":"dynamicgrid-debug.apk","fullName":"debug","baseName":"debug"},"path":"AndroidManifest.xml","properties":{}}]
\ No newline at end of file
diff --git a/dynamicgrid/build/intermediates/packaged_res/debug/values/values.xml b/dynamicgrid/build/intermediates/packaged_res/debug/values/values.xml
new file mode 100644
index 0000000..29b2c0a
--- /dev/null
+++ b/dynamicgrid/build/intermediates/packaged_res/debug/values/values.xml
@@ -0,0 +1,5 @@
+
+
+ 16dp
+
+
\ No newline at end of file
diff --git a/dynamicgrid/build/intermediates/res/symbol-table-with-package/debug/package-aware-r.txt b/dynamicgrid/build/intermediates/res/symbol-table-with-package/debug/package-aware-r.txt
new file mode 100644
index 0000000..9dad010
--- /dev/null
+++ b/dynamicgrid/build/intermediates/res/symbol-table-with-package/debug/package-aware-r.txt
@@ -0,0 +1,3 @@
+org.askerov.dynamicgrid
+dimen dgv_overlap_if_switch_straight_line
+id dgv_wobble_tag
diff --git a/dynamicgrid/build/intermediates/runtime_library_classes/debug/classes.jar b/dynamicgrid/build/intermediates/runtime_library_classes/debug/classes.jar
new file mode 100644
index 0000000..8040ff7
--- /dev/null
+++ b/dynamicgrid/build/intermediates/runtime_library_classes/debug/classes.jar
Binary files differ
diff --git a/dynamicgrid/build/intermediates/symbols/debug/R.txt b/dynamicgrid/build/intermediates/symbols/debug/R.txt
new file mode 100644
index 0000000..2f85ae6
--- /dev/null
+++ b/dynamicgrid/build/intermediates/symbols/debug/R.txt
@@ -0,0 +1,2 @@
+int dimen dgv_overlap_if_switch_straight_line 0x7f070001
+int id dgv_wobble_tag 0x7f0b0001
diff --git a/dynamicgrid/build/intermediates/transforms/mergeJniLibs/debug/__content__.json b/dynamicgrid/build/intermediates/transforms/mergeJniLibs/debug/__content__.json
new file mode 100644
index 0000000..49b1382
--- /dev/null
+++ b/dynamicgrid/build/intermediates/transforms/mergeJniLibs/debug/__content__.json
@@ -0,0 +1 @@
+[{"name":"resources","index":0,"scopes":["PROJECT"],"types":["NATIVE_LIBS"],"format":"DIRECTORY","present":false}]
\ No newline at end of file
diff --git a/dynamicgrid/build/outputs/logs/manifest-merger-debug-report.txt b/dynamicgrid/build/outputs/logs/manifest-merger-debug-report.txt
new file mode 100644
index 0000000..6c0b85e
--- /dev/null
+++ b/dynamicgrid/build/outputs/logs/manifest-merger-debug-report.txt
@@ -0,0 +1,37 @@
+-- Merging decision tree log ---
+manifest
+ADDED from C:\Users\student\AndroidStudioProjects\cosmosCliant\dynamicgrid\AndroidManifest.xml:2:1-7:12
+INJECTED from C:\Users\student\AndroidStudioProjects\cosmosCliant\dynamicgrid\AndroidManifest.xml:2:1-7:12
+INJECTED from C:\Users\student\AndroidStudioProjects\cosmosCliant\dynamicgrid\AndroidManifest.xml:2:1-7:12
+INJECTED from C:\Users\student\AndroidStudioProjects\cosmosCliant\dynamicgrid\AndroidManifest.xml:2:1-7:12
+INJECTED from C:\Users\student\AndroidStudioProjects\cosmosCliant\dynamicgrid\AndroidManifest.xml:2:1-7:12
+INJECTED from C:\Users\student\AndroidStudioProjects\cosmosCliant\dynamicgrid\AndroidManifest.xml:2:1-7:12
+INJECTED from C:\Users\student\AndroidStudioProjects\cosmosCliant\dynamicgrid\AndroidManifest.xml:2:1-7:12
+ package
+ ADDED from C:\Users\student\AndroidStudioProjects\cosmosCliant\dynamicgrid\AndroidManifest.xml:3:11-44
+ INJECTED from C:\Users\student\AndroidStudioProjects\cosmosCliant\dynamicgrid\AndroidManifest.xml
+ INJECTED from C:\Users\student\AndroidStudioProjects\cosmosCliant\dynamicgrid\AndroidManifest.xml
+ android:versionName
+ ADDED from C:\Users\student\AndroidStudioProjects\cosmosCliant\dynamicgrid\AndroidManifest.xml:5:11-36
+ INJECTED from C:\Users\student\AndroidStudioProjects\cosmosCliant\dynamicgrid\AndroidManifest.xml
+ INJECTED from C:\Users\student\AndroidStudioProjects\cosmosCliant\dynamicgrid\AndroidManifest.xml
+ xmlns:android
+ ADDED from C:\Users\student\AndroidStudioProjects\cosmosCliant\dynamicgrid\AndroidManifest.xml:2:11-69
+ android:versionCode
+ ADDED from C:\Users\student\AndroidStudioProjects\cosmosCliant\dynamicgrid\AndroidManifest.xml:4:11-34
+ INJECTED from C:\Users\student\AndroidStudioProjects\cosmosCliant\dynamicgrid\AndroidManifest.xml
+ INJECTED from C:\Users\student\AndroidStudioProjects\cosmosCliant\dynamicgrid\AndroidManifest.xml
+uses-sdk
+INJECTED from C:\Users\student\AndroidStudioProjects\cosmosCliant\dynamicgrid\AndroidManifest.xml reason: use-sdk injection requested
+INJECTED from C:\Users\student\AndroidStudioProjects\cosmosCliant\dynamicgrid\AndroidManifest.xml
+INJECTED from C:\Users\student\AndroidStudioProjects\cosmosCliant\dynamicgrid\AndroidManifest.xml
+INJECTED from C:\Users\student\AndroidStudioProjects\cosmosCliant\dynamicgrid\AndroidManifest.xml
+INJECTED from C:\Users\student\AndroidStudioProjects\cosmosCliant\dynamicgrid\AndroidManifest.xml
+ android:targetSdkVersion
+ INJECTED from C:\Users\student\AndroidStudioProjects\cosmosCliant\dynamicgrid\AndroidManifest.xml
+ ADDED from C:\Users\student\AndroidStudioProjects\cosmosCliant\dynamicgrid\AndroidManifest.xml
+ INJECTED from C:\Users\student\AndroidStudioProjects\cosmosCliant\dynamicgrid\AndroidManifest.xml
+ android:minSdkVersion
+ INJECTED from C:\Users\student\AndroidStudioProjects\cosmosCliant\dynamicgrid\AndroidManifest.xml
+ ADDED from C:\Users\student\AndroidStudioProjects\cosmosCliant\dynamicgrid\AndroidManifest.xml
+ INJECTED from C:\Users\student\AndroidStudioProjects\cosmosCliant\dynamicgrid\AndroidManifest.xml
diff --git a/dynamicgrid/res/values/dimens.xml b/dynamicgrid/res/values/dimens.xml
new file mode 100644
index 0000000..61729a8
--- /dev/null
+++ b/dynamicgrid/res/values/dimens.xml
@@ -0,0 +1,4 @@
+
+
+ 16dp
+
\ No newline at end of file
diff --git a/dynamicgrid/res/values/id.xml b/dynamicgrid/res/values/id.xml
new file mode 100644
index 0000000..5935269
--- /dev/null
+++ b/dynamicgrid/res/values/id.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/dynamicgrid/src/org/askerov/dynamicgrid/AbstractDynamicGridAdapter.java b/dynamicgrid/src/org/askerov/dynamicgrid/AbstractDynamicGridAdapter.java
new file mode 100644
index 0000000..7075780
--- /dev/null
+++ b/dynamicgrid/src/org/askerov/dynamicgrid/AbstractDynamicGridAdapter.java
@@ -0,0 +1,88 @@
+package org.askerov.dynamicgrid;
+
+import android.widget.BaseAdapter;
+
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Author: alex askerov
+ * Date: 9/6/13
+ * Time: 7:43 PM
+ */
+
+
+/**
+ * Abstract adapter for {@link org.askerov.dynamicgrid.DynamicGridView} with sable items id;
+ */
+
+public abstract class AbstractDynamicGridAdapter extends BaseAdapter implements DynamicGridAdapterInterface {
+ public static final int INVALID_ID = -1;
+
+ private int nextStableId = 0;
+
+ private HashMap