/* * Copyright 2015 Hippo Seven * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.hippo.nimingban.ui; import android.content.ClipData; import android.content.ClipboardManager; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import android.widget.Toast; import com.h6ah4i.android.widget.advrecyclerview.animator.GeneralItemAnimator; import com.h6ah4i.android.widget.advrecyclerview.animator.SwipeDismissItemAnimator; import com.h6ah4i.android.widget.advrecyclerview.swipeable.RecyclerViewSwipeManager; import com.h6ah4i.android.widget.advrecyclerview.swipeable.SwipeableItemAdapter; import com.h6ah4i.android.widget.advrecyclerview.swipeable.SwipeableItemConstants; import com.h6ah4i.android.widget.advrecyclerview.swipeable.action.SwipeResultAction; import com.h6ah4i.android.widget.advrecyclerview.swipeable.action.SwipeResultActionRemoveItem; import com.h6ah4i.android.widget.advrecyclerview.touchguard.RecyclerViewTouchActionGuardManager; import com.h6ah4i.android.widget.advrecyclerview.utils.AbstractSwipeableItemViewHolder; import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils; import com.hippo.easyrecyclerview.EasyRecyclerView; import com.hippo.effect.ViewTransition; import com.hippo.nimingban.R; import com.hippo.nimingban.dao.DraftRaw; import com.hippo.nimingban.util.DB; import com.hippo.nimingban.util.ReadableTime; import com.hippo.nimingban.util.Settings; import com.hippo.nimingban.widget.FontTextView; import com.hippo.util.DrawableManager; import com.hippo.widget.Snackbar; import com.hippo.yorozuya.LayoutUtils; import com.hippo.yorozuya.ResourcesUtils; import de.greenrobot.dao.query.LazyList; public final class DraftActivity extends TranslucentActivity implements EasyRecyclerView.OnItemClickListener { private LazyList<DraftRaw> mLazyList; private View mTip; private EasyRecyclerView mRecyclerView; private ViewTransition mViewTransition; private RecyclerView.LayoutManager mLayoutManager; private RecyclerView.Adapter mAdapter; private RecyclerView.Adapter mWrappedAdapter; private RecyclerViewSwipeManager mRecyclerViewSwipeManager; private RecyclerViewTouchActionGuardManager mRecyclerViewTouchActionGuardManager; @Override protected int getLightThemeResId() { return Settings.getColorStatusBar() ? R.style.NormalActivity : R.style.NormalActivity_NoStatus; } @Override protected int getDarkThemeResId() { return Settings.getColorStatusBar() ? R.style.NormalActivity_Dark : R.style.NormalActivity_Dark_NoStatus; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setStatusBarColor(ResourcesUtils.getAttrColor(this, R.attr.colorPrimaryDark)); ToolbarActivityHelper.setContentView(this, R.layout.activity_draft); setActionBarUpIndicator(DrawableManager.getDrawable(this, R.drawable.v_arrow_left_dark_x24)); mTip = findViewById(R.id.tip); mRecyclerView = (EasyRecyclerView) findViewById(R.id.recycler_view); mViewTransition = new ViewTransition(mTip, mRecyclerView); // Layout Manager mLayoutManager = new LinearLayoutManager(this); // touch guard manager (this class is required to suppress scrolling while swipe-dismiss animation is running) mRecyclerViewTouchActionGuardManager = new RecyclerViewTouchActionGuardManager(); mRecyclerViewTouchActionGuardManager.setInterceptVerticalScrollingWhileAnimationRunning(true); mRecyclerViewTouchActionGuardManager.setEnabled(true); // swipe manager mRecyclerViewSwipeManager = new RecyclerViewSwipeManager(); mAdapter = new DraftAdapter(); mAdapter.setHasStableIds(true); mWrappedAdapter = mRecyclerViewSwipeManager.createWrappedAdapter(mAdapter); // wrap for swiping final GeneralItemAnimator animator = new SwipeDismissItemAnimator(); // Change animations are enabled by default since support-v7-recyclerview v22. // Disable the change animation in order to make turning back animation of swiped item works properly. animator.setSupportsChangeAnimations(false); mRecyclerView.hasFixedSize(); mRecyclerView.setLayoutManager(mLayoutManager); mRecyclerView.setAdapter(mWrappedAdapter); // requires *wrapped* adapter mRecyclerView.setItemAnimator(animator); mRecyclerView.setOnItemClickListener(this); // NOTE: // The initialization order is very important! This order determines the priority of touch event handling. // // priority: TouchActionGuard > Swipe > DragAndDrop mRecyclerViewTouchActionGuardManager.attachRecyclerView(mRecyclerView); mRecyclerViewSwipeManager.attachRecyclerView(mRecyclerView); updateLazyList(); checkEmpty(false); } @Override protected void onDestroy() { super.onDestroy(); if (mRecyclerViewSwipeManager != null) { mRecyclerViewSwipeManager.release(); mRecyclerViewSwipeManager = null; } if (mRecyclerViewTouchActionGuardManager != null) { mRecyclerViewTouchActionGuardManager.release(); mRecyclerViewTouchActionGuardManager = null; } if (mRecyclerView != null) { mRecyclerView.setItemAnimator(null); mRecyclerView.setAdapter(null); mRecyclerView = null; } if (mWrappedAdapter != null) { WrapperAdapterUtils.releaseAll(mWrappedAdapter); mWrappedAdapter = null; } mAdapter = null; mLayoutManager = null; if (mLazyList != null) { mLazyList.close(); } } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: finish(); return true; default: return super.onOptionsItemSelected(item); } } // Remember to notify private void updateLazyList() { LazyList<DraftRaw> lazyList = DB.getDraftLazyList(); if (mLazyList != null) { mLazyList.close(); } mLazyList = lazyList; } private void checkEmpty(boolean animation) { if (mAdapter.getItemCount() == 0) { mViewTransition.showView(0, animation); } else { mViewTransition.showView(1, animation); } } @Override public boolean onItemClick(EasyRecyclerView parent, View view, int position, long id) { DraftRaw draftRaw = mLazyList.get(position); ClipboardManager cbm = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); cbm.setPrimaryClip(ClipData.newPlainText(null, draftRaw.getContent())); Toast.makeText(this, R.string.draft_copied_clipboard, Toast.LENGTH_SHORT).show(); return false; } private class DraftHolder extends AbstractSwipeableItemViewHolder { private View swipable; public TextView time; public FontTextView content; public DraftHolder(View itemView) { super(itemView); swipable = itemView.findViewById(R.id.swipable); time = (TextView) itemView.findViewById(R.id.time); content = (FontTextView) itemView.findViewById(R.id.content); } @Override public View getSwipeableContainerView() { return swipable; } } private class DraftAdapter extends RecyclerView.Adapter<DraftHolder> implements SwipeableItemAdapter<DraftHolder> { @Override public DraftHolder onCreateViewHolder(ViewGroup parent, int viewType) { return new DraftHolder(DraftActivity.this.getLayoutInflater().inflate(R.layout.item_draft, parent, false)); } @Override public void onBindViewHolder(DraftHolder holder, int position) { DraftRaw draftRaw = mLazyList.get(position); holder.time.setText(ReadableTime.getDisplayTime(draftRaw.getTime())); holder.content.setText(draftRaw.getContent()); holder.content.setTextSize(Settings.getFontSize()); holder.content.setLineSpacing(LayoutUtils.dp2pix(DraftActivity.this, Settings.getLineSpacing()), 1.0f); if (Settings.getFixEmojiDisplay()) { holder.content.useCustomTypeface(); } else { holder.content.useOriginalTypeface(); } } @Override public long getItemId(int position) { return mLazyList.get(position).getId(); } @Override public int getItemCount() { return mLazyList.size(); } @Override public int onGetSwipeReactionType(DraftHolder holder, int position, int x, int y) { return SwipeableItemConstants.REACTION_CAN_SWIPE_BOTH_H; } @Override public void onSetSwipeBackground(DraftHolder holder, int position, int type) { // Empty } @Override public void onSwipeItemStarted(DraftHolder holder, int position) { // Empty } @Override public SwipeResultAction onSwipeItem(DraftHolder holder, int position, int result) { switch (result) { // swipe right case SwipeableItemConstants.RESULT_SWIPED_RIGHT: case SwipeableItemConstants.RESULT_SWIPED_LEFT: return new DeleteAction(position); case SwipeableItemConstants.RESULT_CANCELED: default: return null; } } } private class DeleteAction extends SwipeResultActionRemoveItem { private int mPosition; public DeleteAction(int position) { mPosition = position; } @Override protected void onPerformAction() { super.onPerformAction(); final int position = mPosition; final DraftRaw raw = mLazyList.get(position); if (raw != null) { DB.removeDraft(raw.getId()); updateLazyList(); mAdapter.notifyItemRemoved(position); checkEmpty(true); Snackbar snackbar = Snackbar.make(mRecyclerView, R.string.draft_deleted, Snackbar.LENGTH_LONG); snackbar.setAction(R.string.undo, new View.OnClickListener() { @Override public void onClick(View v) { DB.addDraft(raw.getContent(), raw.getTime()); updateLazyList(); mAdapter.notifyDataSetChanged(); checkEmpty(true); } }); snackbar.show(); } } } }