package io.virtualapp.home; import android.animation.Animator; import android.animation.ObjectAnimator; import android.content.Context; import android.content.Intent; import android.graphics.Canvas; import android.graphics.Color; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.support.annotation.Nullable; import android.support.v7.app.AlertDialog; import android.support.v7.widget.OrientationHelper; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.StaggeredGridLayoutManager; import android.support.v7.widget.helper.ItemTouchHelper; import android.view.View; import android.view.ViewGroup; import com.melnykov.fab.FloatingActionButton; import java.util.List; import io.virtualapp.R; import io.virtualapp.VCommends; import io.virtualapp.abs.nestedadapter.SmartRecyclerAdapter; import io.virtualapp.abs.ui.VActivity; import io.virtualapp.abs.ui.VUiKit; import io.virtualapp.home.adapters.LaunchpadAdapter; import io.virtualapp.home.adapters.decorations.ItemOffsetDecoration; import io.virtualapp.home.models.AppData; import io.virtualapp.home.models.AppInfoLite; import io.virtualapp.home.models.EmptyAppData; import io.virtualapp.home.models.PackageAppData; import io.virtualapp.widgets.CircularAnim; import io.virtualapp.widgets.TwoGearsView; import static android.support.v7.widget.helper.ItemTouchHelper.ACTION_STATE_DRAG; import static android.support.v7.widget.helper.ItemTouchHelper.DOWN; import static android.support.v7.widget.helper.ItemTouchHelper.END; import static android.support.v7.widget.helper.ItemTouchHelper.LEFT; import static android.support.v7.widget.helper.ItemTouchHelper.RIGHT; import static android.support.v7.widget.helper.ItemTouchHelper.START; import static android.support.v7.widget.helper.ItemTouchHelper.UP; /** * @author Lody */ public class HomeActivity extends VActivity implements HomeContract.HomeView { private static final String TAG = HomeActivity.class.getSimpleName(); private HomeContract.HomePresenter mPresenter; private TwoGearsView mLoadingView; private RecyclerView mLauncherView; private FloatingActionButton mFloatingButton; private View bottomArea; private View createShortcutArea; private View deleteAppArea; private LaunchpadAdapter mLaunchpadAdapter; private Handler mUiHandler; public static void goHome(Context context) { Intent intent = new Intent(context, HomeActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); } @Override protected void onCreate(@Nullable Bundle savedInstanceState) { overridePendingTransition(0, 0); super.onCreate(savedInstanceState); setContentView(R.layout.activity_home); mUiHandler = new Handler(Looper.getMainLooper()); bindViews(); initLaunchpad(); initFab(); new HomePresenterImpl(this).start(); } private void bindViews() { mLoadingView = (TwoGearsView) findViewById(R.id.pb_loading_app); mLauncherView = (RecyclerView) findViewById(R.id.home_launcher); mFloatingButton = (FloatingActionButton) findViewById(R.id.home_fab); bottomArea = findViewById(R.id.bottom_area); createShortcutArea = findViewById(R.id.create_shortcut_area); deleteAppArea = findViewById(R.id.delete_app_area); } private void initLaunchpad() { mLauncherView.setHasFixedSize(true); StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(3, OrientationHelper.VERTICAL); mLauncherView.setLayoutManager(layoutManager); mLaunchpadAdapter = new LaunchpadAdapter(this); SmartRecyclerAdapter wrap = new SmartRecyclerAdapter(mLaunchpadAdapter); View footer = new View(this); footer.setLayoutParams(new StaggeredGridLayoutManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, VUiKit.dpToPx(this, 60))); wrap.setFooterView(footer); mLauncherView.setAdapter(wrap); mLauncherView.addItemDecoration(new ItemOffsetDecoration(this, R.dimen.desktop_divider)); ItemTouchHelper touchHelper = new ItemTouchHelper(new LauncherTouchCallback()); touchHelper.attachToRecyclerView(mLauncherView); mLaunchpadAdapter.setAppClickListener((pos, data) -> { if (!data.isLoading()) { mLaunchpadAdapter.notifyItemChanged(pos); mPresenter.launchApp(data); } }); } private void initFab() { mFloatingButton.setOnClickListener(v -> { CircularAnim.fullActivity(this, mFloatingButton) .colorOrImageRes(R.color.colorPrimaryRavel) .go(() -> ListAppActivity.gotoListApp(this)); }); } private void deleteApp(int position) { AppData data = mLaunchpadAdapter.getList().get(position); new AlertDialog.Builder(this) .setTitle("Delete app") .setMessage("Do you want to delete " + data.getName() + "?") .setPositiveButton(android.R.string.yes, (dialog, which) -> { mPresenter.deleteApp(data); }) .setNegativeButton(android.R.string.no, null) .show(); } private void createShortcut(int position) { AppData model = mLaunchpadAdapter.getList().get(position); if (model instanceof PackageAppData) { mPresenter.createShortcut(model); } } @Override public void setPresenter(HomeContract.HomePresenter presenter) { mPresenter = presenter; } @Override public void showBottomAction() { hideFab(); bottomArea.setTranslationY(bottomArea.getHeight()); bottomArea.setVisibility(View.VISIBLE); bottomArea.animate().translationY(0).setDuration(500L).start(); } @Override public void hideBottomAction() { bottomArea.setTranslationY(0); ObjectAnimator transAnim = ObjectAnimator.ofFloat(bottomArea, "translationY", 0, bottomArea.getHeight()); transAnim.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { } @Override public void onAnimationEnd(Animator animator) { bottomArea.setVisibility(View.GONE); showFab(); } @Override public void onAnimationCancel(Animator animator) { bottomArea.setVisibility(View.GONE); showFab(); } @Override public void onAnimationRepeat(Animator animator) { } }); transAnim.setDuration(500L); transAnim.start(); } @Override public void showLoading() { mFloatingButton.hide(false); mLoadingView.setVisibility(View.VISIBLE); mLoadingView.startAnim(); } @Override public void hideLoading() { mFloatingButton.show(); mLoadingView.setVisibility(View.GONE); mLoadingView.stopAnim(); } @Override public void loadFinish(List<AppData> list) { while (list.size() < 9) { list.add(new EmptyAppData()); } mLaunchpadAdapter.setList(list); hideLoading(); } @Override public void loadError(Throwable err) { err.printStackTrace(); hideLoading(); } @Override public void showGuide() { } @Override public void addAppToLauncher(AppData model) { List<AppData> dataList = mLaunchpadAdapter.getList(); boolean replaced = false; for (int i = 0; i < dataList.size(); i++) { AppData data = dataList.get(i); if (data instanceof EmptyAppData) { mLaunchpadAdapter.replace(i, model); replaced = true; break; } } if (!replaced) { mLaunchpadAdapter.add(model); mLauncherView.smoothScrollToPosition(mLaunchpadAdapter.getItemCount() - 1); } } @Override public void removeAppToLauncher(AppData model) { mLaunchpadAdapter.remove(model); } @Override public void refreshLauncherItem(AppData model) { mLaunchpadAdapter.refresh(model); } @Override public void showFab() { mFloatingButton.show(); } @Override public void hideFab() { mFloatingButton.hide(); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK && data != null) { List<AppInfoLite> appList = data.getParcelableArrayListExtra(VCommends.EXTRA_APP_INFO_LIST); if (appList != null) { for (AppInfoLite info : appList) { mPresenter.addApp(info); } } } } private class LauncherTouchCallback extends ItemTouchHelper.SimpleCallback { int[] location = new int[2]; boolean upAtDeleteAppArea; boolean upAtCreateShortcutArea; RecyclerView.ViewHolder dragHolder; LauncherTouchCallback() { super(UP | DOWN | LEFT | RIGHT | START | END, 0); } @Override public int interpolateOutOfBoundsScroll(RecyclerView recyclerView, int viewSize, int viewSizeOutOfBounds, int totalSize, long msSinceStartScroll) { return 0; } @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { try { AppData data = mLaunchpadAdapter.getList().get(viewHolder.getAdapterPosition()); if (!data.canReorder()) { return makeMovementFlags(0, 0); } } catch (IndexOutOfBoundsException e) { e.printStackTrace(); } return super.getMovementFlags(recyclerView, viewHolder); } @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { int pos = viewHolder.getAdapterPosition(); int targetPos = target.getAdapterPosition(); mLaunchpadAdapter.moveItem(pos, targetPos); return true; } @Override public boolean isLongPressDragEnabled() { return true; } @Override public boolean isItemViewSwipeEnabled() { return false; } @Override public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) { if (viewHolder instanceof LaunchpadAdapter.ViewHolder) { if (actionState == ACTION_STATE_DRAG) { if (dragHolder != viewHolder) { dragHolder = viewHolder; viewHolder.itemView.setScaleX(1.2f); viewHolder.itemView.setScaleY(1.2f); if (bottomArea.getVisibility() == View.GONE) { showBottomAction(); } } } } super.onSelectedChanged(viewHolder, actionState); } @Override public boolean canDropOver(RecyclerView recyclerView, RecyclerView.ViewHolder current, RecyclerView.ViewHolder target) { if (upAtCreateShortcutArea || upAtDeleteAppArea) { return false; } try { AppData data = mLaunchpadAdapter.getList().get(target.getAdapterPosition()); return data.canReorder(); } catch (IndexOutOfBoundsException e) { e.printStackTrace(); } return false; } @Override public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { if (viewHolder instanceof LaunchpadAdapter.ViewHolder) { LaunchpadAdapter.ViewHolder holder = (LaunchpadAdapter.ViewHolder) viewHolder; viewHolder.itemView.setScaleX(1f); viewHolder.itemView.setScaleY(1f); viewHolder.itemView.setBackgroundColor(holder.color); } super.clearView(recyclerView, viewHolder); if (dragHolder == viewHolder) { if (bottomArea.getVisibility() == View.VISIBLE) { mUiHandler.postDelayed(HomeActivity.this::hideBottomAction, 200L); if (upAtCreateShortcutArea) { createShortcut(viewHolder.getAdapterPosition()); } else if (upAtDeleteAppArea) { deleteApp(viewHolder.getAdapterPosition()); } } dragHolder = null; } } @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { } @Override public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); if (actionState != ACTION_STATE_DRAG || !isCurrentlyActive) { return; } View itemView = viewHolder.itemView; itemView.getLocationInWindow(location); int x = (int) (location[0] + dX); int y = (int) (location[1] + dY); bottomArea.getLocationInWindow(location); int baseLine = location[1] - bottomArea.getHeight(); if (y >= baseLine) { deleteAppArea.getLocationInWindow(location); int deleteAppAreaStartX = location[0]; if (x < deleteAppAreaStartX) { upAtCreateShortcutArea = true; upAtDeleteAppArea = false; createShortcutArea.setBackgroundColor(Color.parseColor("#0099cc")); deleteAppArea.setBackgroundColor(Color.TRANSPARENT); createShortcutArea.setAlpha(0.7f); deleteAppArea.setAlpha(1f); } else { upAtDeleteAppArea = true; upAtCreateShortcutArea = false; deleteAppArea.setBackgroundColor(Color.RED); createShortcutArea.setBackgroundColor(Color.TRANSPARENT); deleteAppArea.setAlpha(0.7f); createShortcutArea.setAlpha(1f); } } else { upAtCreateShortcutArea = false; upAtDeleteAppArea = false; createShortcutArea.setBackgroundColor(Color.TRANSPARENT); deleteAppArea.setBackgroundColor(Color.TRANSPARENT); createShortcutArea.setAlpha(1f); deleteAppArea.setAlpha(1f); } } } }