Android 仿微信發(fā)動(dòng)態(tài)九宮格拖拽、刪除功能
1、完美1比1 仿照微信仿微信發(fā)動(dòng)態(tài) 九宮格拖拽、刪除
暴力拖拽ui有點(diǎn)問(wèn)題,不影響使用,資源文件自己找個(gè)+號(hào)
2、微信發(fā)動(dòng)態(tài)拖拽bug
當(dāng)選擇完圖片,長(zhǎng)按圖片拖拽過(guò)程中按下屏幕home鍵盤,再次進(jìn)入這時(shí)候就不能點(diǎn)擊輸入文字,點(diǎn)擊輸入文字的時(shí)候會(huì)觸發(fā)選擇相冊(cè)事件
3、拖拽事件用的basequickadapter
implementation 'com.android.support:recyclerview-v7:28.0.0' implementation "com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.50" implementation "com.github.bumptech.glide:glide:4.9.0"
4、演示
5、快速入手
activity NineGridChooseImage nineGridChooseImage = findViewById(R.id.nineGridChooseImage); FrameLayout frameLayout= findViewById(R.id.frameLayout); nineGridChooseImage.init(frameLayout); int statusBarHeight = 0; int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); if (resourceId > 0) { statusBarHeight = getResources().getDimensionPixelSize(resourceId); } nineGridChooseImage.setFixH(statusBarHeight);//自己對(duì)一下高度 nineGridChooseImage.setAddClick(new NineGridChooseImage.AddClick() { @Override public void onAdd() { /* List<String> list = new LinkedList<>(); for(int i = 0;i<5;i++){ list.add("https://xx.jpg"); }*/ nineGridChooseImage.addData("https://xxx.jpg"); } });
xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/frameLayout" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".Main11Activity"> <com.example.hotfix_01.view.NineGridChooseImage android:background="#A8A1A1" android:layout_marginTop="100dp" android:id="@+id/nineGridChooseImage" android:layout_width="match_parent" android:layout_height="wrap_content" /> </FrameLayout>
5、實(shí)現(xiàn)過(guò)程
如果幫助到你請(qǐng)關(guān)注點(diǎn)贊一下
NineGridChooseImage.java package com.example.hotfix_01.view; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.app.Activity; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Point; import android.graphics.Rect; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.helper.ItemTouchHelper; import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; import android.view.Display; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.bumptech.glide.Glide; import com.chad.library.adapter.base.BaseItemDraggableAdapter; import com.chad.library.adapter.base.BaseViewHolder; import com.chad.library.adapter.base.callback.ItemDragAndSwipeCallback; import com.chad.library.adapter.base.listener.OnItemDragListener; import java.util.LinkedList; import java.util.List; import top.antaikeji.base.R; import top.antaikeji.foundation.utils.DisplayUtil; import static android.support.v7.widget.helper.ItemTouchHelper.ACTION_STATE_IDLE; /** * Author: flyzhang */ public class NineGridChooseImage extends RecyclerView { private Rect lastRect = new Rect(); private Rect rect = new Rect(); private boolean isDel = false, tempImageDel = false; private int mSelectPosition = 0; private int SCREEN_W, SCREEN_H; private int mImageWH; private int mImageCount = 4; private DraggableAdapter mDraggableAdapter; private LinearLayout mBottomView; private FrameLayout mFrameLayout; private AddClick mAddClick; private DragCallBack mDragCallBack; private ImageView mTempImage; ; private int mFixH = 0; private int bottomViewH = 55; private ImageView trash; private int margin = 2; public NineGridChooseImage(@NonNull Context context) { super(context); } public NineGridChooseImage(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public void init(FrameLayout f) { this.mFrameLayout = f; Display defaultDisplay = ((Activity) getContext()).getWindowManager().getDefaultDisplay(); Point point = new Point(); defaultDisplay.getSize(point); SCREEN_H = point.y; SCREEN_W = point.x; mImageWH = SCREEN_W / 3 - 2 * DisplayUtil.dpToPx(5) - 4 * DisplayUtil.pxToDp(20) - DisplayUtil.pxToDp(50); bottomViewH = DisplayUtil.dpToPx(bottomViewH); margin = DisplayUtil.dpToPx(margin); mTempImage = new ImageView(getContext()); mTempImage.setScaleType(ImageView.ScaleType.FIT_XY); //初始化底部view mBottomView = new LinearLayout(getContext()); mBottomView.setGravity(Gravity.CENTER); mBottomView.setBackgroundColor(Color.RED); FrameLayout.LayoutParams bottomLayoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, bottomViewH); bottomLayoutParams.gravity = Gravity.BOTTOM; trash = new ImageView(getContext()); int wh = DisplayUtil.dpToPx(25); FrameLayout.LayoutParams trashParams = new FrameLayout.LayoutParams(wh, wh); trash.setLayoutParams(trashParams); mBottomView.addView(trash); TextView tipTextView = new TextView(getContext()); tipTextView.setTextColor(Color.WHITE); tipTextView.setText("拖拽此處刪除"); mBottomView.addView(tipTextView); mBottomView.setOrientation(LinearLayout.VERTICAL); mBottomView.setLayoutParams(bottomLayoutParams); mBottomView.setVisibility(GONE); out(); mFrameLayout.addView(mBottomView); GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), 3); setLayoutManager(gridLayoutManager); List<String> data = new LinkedList<>(); data.add(""); mDraggableAdapter = new DraggableAdapter(data); DragAndSwipeCallback mItemDragAndSwipeCallback = new DragAndSwipeCallback(mDraggableAdapter); ItemTouchHelper itemTouchHelper = new ItemTouchHelper(mItemDragAndSwipeCallback); itemTouchHelper.attachToRecyclerView(this); mDraggableAdapter.enableDragItem(itemTouchHelper, R.id.image, true); mItemDragAndSwipeCallback.setSwipeMoveFlags(ItemTouchHelper.START | ItemTouchHelper.END); mDraggableAdapter.setOnItemDragListener(new OnItemDragListener() { @Override public void onItemDragStart(RecyclerView.ViewHolder viewHolder, int pos) { if(null!=mDragCallBack){ mDragCallBack.onStart(); } mSelectPosition = pos; mFrameLayout.removeView(mTempImage); tempImageDel = false; isDel = false; in(); ImageView imageView = viewHolder.itemView.findViewById(R.id.image); mTempImage.setImageDrawable(imageView.getDrawable()); ViewGroup.LayoutParams l = new ViewGroup.LayoutParams(imageView.getWidth(), imageView.getHeight()); mTempImage.setLayoutParams(l); imageView.getGlobalVisibleRect(lastRect); mTempImage.setX(lastRect.left); mTempImage.setY(lastRect.top - mFixH); mTempImage.setScaleX(1.2f); mTempImage.setScaleY(1.2f); mFrameLayout.addView(mTempImage); imageView.setAlpha(0f); } @Override public void onItemDragMoving(RecyclerView.ViewHolder source, int from, RecyclerView.ViewHolder target, int to) { target.itemView.findViewById(R.id.image).getGlobalVisibleRect(lastRect); mSelectPosition = to; } @Override public void onItemDragEnd(RecyclerView.ViewHolder viewHolder, int pos) { if(null!=mDragCallBack){ mDragCallBack.onEnd(); } ImageView imageView = viewHolder.itemView.findViewById(R.id.image); imageView.setScaleX(1f); imageView.setScaleY(1f); if (tempImageDel) { mDraggableAdapter.remove(mSelectPosition); } else { imageView.setAlpha(1f); mFrameLayout.removeView(mTempImage); } out(); } }); setAdapter(mDraggableAdapter); } public void setFixH(int mFixH) { this.mFixH = mFixH; } /** * 拖住adapter */ private class DraggableAdapter extends BaseItemDraggableAdapter<String, BaseViewHolder> { private DraggableAdapter(List<String> data) { super(R.layout.base_iamge_item, data); } @Override protected void convert(@NonNull BaseViewHolder helper, String item) { ImageView imageView = helper.getView(R.id.image);//圖片 LinearLayout.LayoutParams l = (LinearLayout.LayoutParams) imageView.getLayoutParams(); l.height = mImageWH; l.width = mImageWH; l.rightMargin = margin; l.bottomMargin = margin; l.topMargin = margin; imageView.setLayoutParams(l); ImageView imageView2 = helper.getView(R.id.image2);//加號(hào) LinearLayout.LayoutParams l2 = (LinearLayout.LayoutParams) imageView.getLayoutParams(); l2.height = mImageWH; l2.width = mImageWH; l2.rightMargin = margin; l2.bottomMargin = margin; l2.topMargin = margin; imageView2.setLayoutParams(l2); /** * 如果list的長(zhǎng)度等于mImageCount 最后一張最后一張顯示正常圖片 * */ if(TextUtils.isEmpty(item)){ if(mImageCount <= helper.getAdapterPosition()){ imageView.setVisibility(View.GONE); imageView2.setVisibility(View.GONE); }else{ imageView.setVisibility(View.GONE); imageView2.setVisibility(View.VISIBLE); imageView2.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (null != mAddClick) { mAddClick.onAdd(); } } }); } }else{ imageView.setVisibility(View.VISIBLE); imageView2.setVisibility(View.GONE); Glide.with(mContext).load(item).into(imageView); } imageView.setAlpha(1f); } } /** * 拖拽監(jiān)聽 */ private class DragAndSwipeCallback extends ItemDragAndSwipeCallback { private DragAndSwipeCallback(BaseItemDraggableAdapter adapter) { super(adapter); } @Override public boolean canDropOver(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder current, @NonNull RecyclerView.ViewHolder target) { if (target.getAdapterPosition() == mDraggableAdapter.getData().size() - 1 || current.getAdapterPosition() == mDraggableAdapter.getData().size() - 1) { return false; } return super.canDropOver(recyclerView, current, target); } @Override public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) { super.onSelectedChanged(viewHolder, actionState); if (actionState == ACTION_STATE_IDLE) { //空閑狀態(tài) if (isDel) { isDel = false; tempImageDel = true; mFrameLayout.removeView(mTempImage); } } } @Override public void onChildDrawOver(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { super.onChildDrawOver(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); if (tempImageDel) { return; } ImageView tempImageView = viewHolder.itemView.findViewById(R.id.image); boolean b = tempImageView.getGlobalVisibleRect(rect); Log.e("TAG", "dX:" + dX); Log.e("TAG", "dY:" + dY); if (b && dX > 0 && dY > 0) { mTempImage.setX(rect.left); mTempImage.setY(rect.top - mFixH); } else { mTempImage.setX(lastRect.left + dX); mTempImage.setY(lastRect.top - mFixH + dY); } mTempImage.getGlobalVisibleRect(rect); if (SCREEN_H - bottomViewH < rect.bottom) { isDel = true; trash.setBackgroundResource(R.drawable.base_trash_open); } else { isDel = false; trash.setBackgroundResource(R.drawable.base_trash_close); } } } public void addData(String path) { mDraggableAdapter.addData(0, path); mDraggableAdapter.notifyItemChanged(mDraggableAdapter.getData().size()-1); } public void addData(List<String> path){ int size = mDraggableAdapter.getData().size(); int offset = mImageCount - size + 1; if(offset > path.size()){ offset = path.size(); } mDraggableAdapter.addData(0, path.subList(0,offset)); mDraggableAdapter.notifyItemChanged(mDraggableAdapter.getData().size() -1); } public void setImageCount(int mImageCount) { this.mImageCount = mImageCount; } public void setAddClick(AddClick mAddClick) { this.mAddClick = mAddClick; } public void setDragCallBack(DragCallBack mDragCallBack) { this.mDragCallBack = mDragCallBack; } /** * 獲取列表 * * @return */ public List<String> getData() { List<String> res = new LinkedList<>(); for (int i = 0; i < mDraggableAdapter.getData().size() - 1; i++) { res.add(mDraggableAdapter.getData().get(i)); } return res; } /** * 底部進(jìn)入 */ private void in() { mBottomView.setVisibility(View.VISIBLE); ObjectAnimator animator = ObjectAnimator.ofFloat(mBottomView, "translationY", 0) .setDuration(200); animator.start(); } /** * 底部移除屏幕外部 */ private void out() { final int moveX = DisplayUtil.dpToPx(55); ObjectAnimator animator = ObjectAnimator.ofFloat(mBottomView, "translationY", moveX) .setDuration(200); animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); mBottomView.setVisibility(View.GONE); trash.setBackgroundResource(R.drawable.base_trash_close); } }); animator.start(); } public interface AddClick { void onAdd(); } public interface DragCallBack{ void onStart(); void onEnd(); } }
iamge_item.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/l" android:layout_width="wrap_content" android:layout_height="wrap_content" > <ImageView android:scaleType="fitXY" android:id="@+id/image" android:layout_width="149dp" android:layout_height="149dp" /> <ImageView android:id="@+id/image2" android:visibility="gone" android:layout_width="149dp" android:layout_height="149dp" /> </LinearLayout>
總結(jié)
以上所述是小編給大家介紹的Android 仿微信發(fā)動(dòng)態(tài)九宮格拖拽、刪除功能,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)我們網(wǎng)站的支持!
如果你覺得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
上一篇:Android RadioGroup多行顯示效果 解決單選問(wèn)題
欄 目:Android
下一篇:Android自定義View之RadioGroup實(shí)現(xiàn)跨多行顯示
本文標(biāo)題:Android 仿微信發(fā)動(dòng)態(tài)九宮格拖拽、刪除功能
本文地址:http://mengdiqiu.com.cn/a1/Android/9086.html
您可能感興趣的文章
- 01-10Android自定義View之繪制圓形頭像功能
- 01-10Android實(shí)現(xiàn)雙擊返回鍵退出應(yīng)用實(shí)現(xiàn)方法詳解
- 01-10android實(shí)現(xiàn)記住用戶名和密碼以及自動(dòng)登錄
- 01-10android實(shí)現(xiàn)簡(jiǎn)單計(jì)算器功能
- 01-10Android 友盟第三方登錄與分享的實(shí)現(xiàn)代碼
- 01-10android實(shí)現(xiàn)指紋識(shí)別功能
- 01-10Emoji表情在Android JNI中的兼容性問(wèn)題詳解
- 01-10Android實(shí)現(xiàn)圓形漸變加載進(jìn)度條
- 01-10android開發(fā)環(huán)境中SDK文件夾下的所需內(nèi)容詳解
- 01-10android異步消息機(jī)制 源碼層面徹底解析(1)


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 01-10Android自定義View之繪制圓形頭像功能
- 01-10Android實(shí)現(xiàn)雙擊返回鍵退出應(yīng)用實(shí)現(xiàn)方
- 01-10android實(shí)現(xiàn)簡(jiǎn)單計(jì)算器功能
- 01-10android實(shí)現(xiàn)記住用戶名和密碼以及自動(dòng)
- 01-10C++自定義API函數(shù)實(shí)現(xiàn)大數(shù)相乘算法
- 01-10Android 友盟第三方登錄與分享的實(shí)現(xiàn)代
- 01-10android實(shí)現(xiàn)指紋識(shí)別功能
- 01-10如何給Flutter界面切換實(shí)現(xiàn)點(diǎn)特效
- 01-10Android實(shí)現(xiàn)圓形漸變加載進(jìn)度條
- 01-10Emoji表情在Android JNI中的兼容性問(wèn)題詳
隨機(jī)閱讀
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 01-10C#中split用法實(shí)例總結(jié)
- 01-10delphi制作wav文件的方法
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 04-02jquery與jsp,用jquery
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置