金山手机助手怎么卸载样卸载手机动漫

经验159 米
在线时间72 小时
版本6.7.14
积分 247, 距离下一级还需 253 积分
积分 247, 距离下一级还需 253 积分
机型小米手机4c
MIUI版本6.7.14
小米5应用卸载怎么没有动画特效了?就是那个卸载爆炸烟火的特效不知道怎么就没有了?
分享到微信朋友圈
打开微信,点击底部的“发现”,使用 “扫一扫” 即可将网页分享到我的朋友圈。
经验7389 米
在线时间99 小时
版本6.7.18
积分 8210, 距离下一级还需 11790 积分
积分 8210, 距离下一级还需 11790 积分
机型红米Note3 全网通
签到次数180
MIUI版本6.7.18
电池模式里选了性能优先吗。。
经验54797 米
威望1215 米
在线时间14537 小时
版本6.7.18
我是大水逼
机型小米Note
签到次数140
MIUI版本6.7.18
您好,楼主是改成了流畅模式吧?换成另外一个模式即可
如果对我的回答有疑问也请点我楼层下方回复按钮,而不要直接回复帖子...
做下广告,
MIUI 3000万
MIUI 3000万发烧友纪念勋章
MIUI 2000万
MIUI 2000万发烧友纪念勋章
MIUI 7纪念勋章
小米商城购买纪念勋章
论坛APP购买小米商品获得
小米平板2 Win10 荣誉内测
小米平板2 Win10 荣誉内测
MIUI五周年
MIUI五周年纪念勋章
已关注微信
已关注极客秀微信
关注腾讯微博
已关注腾讯微博
关注新浪微博
已关注新浪微博
Copyright (C) 2016 MIUI
京ICP备号 | 京公网安备34号 | 京ICP证110507号you have been blocked您所在的位置: &
有妖气漫画怎么删除已下载的漫画
时间: 14:38:22
编辑:xfront
来源:下载吧
有妖气漫画for Android是一款免费的手机...
中国最大的原创漫画中心,上万部网络漫画...
使用有妖气漫画的朋友想必会经常将漫画离线下载到手机或平板上看,随着时间的推移,下载的漫画越来越多,存储空间就会不够用了,此时就要删除已下载的漫画了。那么要如何删除已下载的有妖气漫画呢?
删除已下载的有妖气漫画的方法
1.在有妖气漫画的手机端、平板端,点击下方的“下载",再切换到”下载完成“。
2.点击右上角的”编辑“按钮,漫画名称右侧就会出现一个垃圾桶按钮,点击此按钮既可删除已下载的漫画。
OK,轻松删除下载好的有妖气漫画,存储空间又多出了一大截。
分享给朋友:
有妖气漫画删除已下载相关教程
下载1261次
热门关键字
扫红码得红包5亿红包100%中奖Android实现GridView的item长按拖动删除(带动画效果)
领导这几天让做一个项目,就是可以实现像支付宝首页一样的可以长按拖动,删除的界面,以前没做过,领导让我做的时候觉得简直是老虎吃天,无从下手啊,可是领导的任务还是要实现的,没办法,就自己网上找咯,但是网上的demo五花八门无法满足我的需求,而且bug还很多,所以最后就自己实现了,说实话,这个效果困扰了我好几个星期,因为其中牵扯的知识点太多了,什么事件分发机制,动画效果,互换位置的算法,还有拖动,这些我都没有接触过,所以只有一点一点来做咯,如果大家还没有了解过这些知识点,我建议搭建先去了解一下,毕竟这方面的知识也确实不少。
刚开始大家也不要灰心,毕竟做什么事都需要经历第一次,所以一定要迎风破浪,不要被困难吓倒,努力去克服它们,接下来我就先给大家说说具体的实现思路,毕竟我的gridview要实现长按拖动、删除,还带动画:
1、根据自己在屏幕上按下的X,Y的坐标来获取要拖动的item的索引
2、然后通过onInterceptTouchEvent方法,对事件进行分发,判断是长按还是点击
3、如果我们对item实现了长按的操作,先隐藏该item,然后创建一个item镜像来代替该item进行拖动
4、当我们移动到新的位置,通过onTouchEvent方法的ACTION_MOVE来判断我们是否移动到了一个新的位置
5、如果移动到了一个新的位置,就根据移动得位置来对其他的item也进行移动
6、松开时,判断当前是否移动到新的位置,如果是我,对其他的item依次进行移动,然后移除镜像,更新gridview
7、删除是对item的操作,在adapter里面实现即可,删除完之后先实现动画,然后再刷新界面
根据我上面说的这个步骤,我想大家应该都对这个效果心里有个大概的轮廓了吧,我这里实现的是批量操作,当前,如果大家想实现只对长按的那个item进行操作,只需要在onInterceptTouchEvent方法里面进行更改就可以了,我这里用了一个if语句进行判断,是否处于编辑状态,如果是,就不用再进行长安了,如果不是,则需要进行长按。
好了,废话不多说了,让我们来看看具体的实现吧,我先给大家介绍一个这个自定义控件的实现,在介绍完之后,我会把demo上传,大家可以自己去研究。
我们新建一个项目,DragGridView,在里面新建一个类,叫DragGrid.java,家下来我们看看代码,根据代码来具体讲解
package com.roch.water_source_zwb.
import java.util.ArrayL
import java.util.L
import com.roch.water_source_zwb.MainA
import com.roch.water_source_zwb.R;
import com.roch.water_source_zwb.adapter.DragA
import com.roch.water_source_zwb.adapter.DragMoreA
import com.roch.water_source_
import com.roch.water_source_zwb.utils.U
import android.animation.A
import android.animation.AnimatorListenerA
import android.animation.AnimatorS
import android.animation.ObjectA
import android.content.C
import android.graphics.B
import android.graphics.PixelF
import android.os.V
import android.util.AttributeS
import android.util.L
import android.view.G
import android.view.MotionE
import android.view.V
import android.view.ViewG
import android.view.ViewTreeO
import android.view.WindowM
import android.view.ViewTreeObserver.OnPreDrawL
import android.view.animation.AccelerateDecelerateI
import android.view.animation.A
import android.view.animation.Animation.AnimationL
import android.view.animation.TranslateA
import android.widget.AdapterV
import android.widget.GridV
import android.widget.ImageV
import android.widget.LinearL
import android.widget.RelativeL
import android.widget.TextV
import android.widget.T
import android.widget.AbsListView.LayoutP
* 首页HomeFragment中的GridView
* @author zhaodongshao
public class DragGrid extends GridView {
/** 是否在拖动*/
public boolean isDrag =
/** 点击时候的X位置 */
public int downX;
/** 点击时候的Y位置 */
public int downY;
/** 点击时候对应整个界面的X位置 */
public int windowX;
/** 点击时候对应整个界面的Y位置 */
public int windowY;
/** 屏幕上的X */
private int win_view_x;
/** 屏幕上的Y*/
private int win_view_y;
/** 拖动的里x的距离
int dragOffsetX;
/** 拖动的里Y的距离
int dragOffsetY;
/** 长按时候对应postion */
public int dragP
/** Up后对应的ITEM的Position */
private int dropP
/** 开始拖动的ITEM的Position*/
private int startP
/** item高 */
private int itemH
/** item宽 */
private int itemW
/** 拖动的时候对应ITEM的VIEW */
private View dragImageView =
/** 长按的时候ITEM的VIEW*/
private ViewGroup dragItemView =
/** WindowManager管理器 */
private WindowManager windowManager =
/** 需要拖动的镜像*/
private WindowManager.LayoutParams windowParams =
/** item总量*/
private int itemTotalC
/** 一行的ITEM数量*/
private int nColumns = 3;
/** 行数 */
private int nR
/** 剩余部分 */
private int R
/** 是否在移动 */
private boolean isMoving =
/** 需要移动的position*/
private int holdP
/** 拖动的时候放大的倍数 */
private double dragScale = 1.2D;
/** 震动器
private Vibrator mV
/** 每个ITEM之间的水平间距 */
private int mHorizontalSpacing = 15;
/** 每个ITEM之间的竖直间距 */
private int mVerticalSpacing = 15;
/* 移动时候最后个动画的ID */
private String LastAnimationID;
* 执行动画的布局
private RelativeLayout rootL
private Context mC
public DragGrid(Context context) {
super(context);
init(context);
public DragGrid(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
public DragGrid(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
public void init(Context context){
this.mContext =
//获取振动器
mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
//将布局文件中设置的间距dip转为px
mHorizontalSpacing = Utils.dip2px(context, mHorizontalSpacing);
* 获取状态栏的高度
private int getStatusBarHeight() {
int result = 0;
int resourceId = getResources().getIdentifier(&status_bar_height&, &dimen&, &android&);
if (resourceId & 0) {
result = getResources().getDimensionPixelSize(resourceId);
* 判断是否点击在指定view中
* @param view
* @param ev
private boolean inRangeOfView(View view, MotionEvent ev){
int[] location = new int[2];
view.getLocationOnScreen(location);
int downX = (int)ev.getX();
int downY = (int)ev.getY();
int x = location[0];
//这里需要减去状态栏的高度和导航栏的高度,否则座标会存在偏差
int y = location[1] - getStatusBarHeight() - MainActivity.StruesH
//获取当前item的宽和高
int viewWidth = view.getWidth();
int viewHeight = view.getHeight();
if(downX & x || downX & (x + viewWidth) || downY & y || downY & (y + viewHeight)){
public boolean onInterceptTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
downX = (int) ev.getX();
downY = (int) ev.getY();
windowX = (int) ev.getX();
windowY = (int) ev.getY();
//当前手指所点击的position
int position = pointToPosition(downX, downY);
if (position!=AdapterView.INVALID_POSITION) {
//获取当前点击的view
View view = getChildAt(position - getFirstVisiblePosition());
//得到该item中的删除按钮
ImageView iView = (ImageView)view.findViewById(R.id.delet_iv);
//这里判断是否处于编辑状态,如果是就不须要再长按,如果不是,还需要长按进入编辑状态,如果不想批量操作可以把这个if语句进行修改
if (isDrag) {
//判断是否点击在删除按钮中
if (!inRangeOfView(iView, ev)) {
int x = (int) ev.getX();// 长安事件的X位置
int y = (int) ev.getY();// 长安事件的y位置
startPosition = pointToPosition(x, y);// 第一次点击的postion
dragPosition = pointToPosition(x, y);//获取要拖动的item的position
if (dragPosition != AdapterView.INVALID_POSITION) {
ViewGroup dragViewGroup = (ViewGroup) getChildAt(dragPosition - getFirstVisiblePosition());
TextView dragTextView = (TextView)dragViewGroup.findViewById(R.id.name_tv);
dragTextView.setSelected(true);
dragTextView.setEnabled(false);
itemHeight = dragViewGroup.getHeight();
itemWidth = dragViewGroup.getWidth();
itemTotalCount = DragGrid.this.getCount();
int row = itemTotalCount / nC// 算出行数
Remainder = (itemTotalCount % nColumns);// 算出最后一行多余的数量
if (Remainder != 0) {
nRows = row + 1;
// 如果特殊的这个不等于拖动的那个,并且不等于-1
if (dragPosition != AdapterView.INVALID_POSITION) {
// 释放的资源使用的绘图缓存。如果你调用buildDrawingCache()手动没有调用setDrawingCacheEnabled(真正的),你应该清理缓存使用这种方法。
win_view_x = windowX - dragViewGroup.getLeft();//VIEW相对自己的X,半斤
win_view_y = windowY - dragViewGroup.getTop();//VIEW相对自己的y,半斤
dragOffsetX = (int) (ev.getRawX() - x);//手指在屏幕的上X位置-手指在控件中的位置就是距离最左边的距离
dragOffsetY = (int) (ev.getRawY() - y);//手指在屏幕的上y位置-手指在控件中的位置就是距离最上边的距离
//这里是为了获取当前item的图片缓存,提高绘图效率
dragItemView = dragViewG
dragViewGroup.destroyDrawingCache();
dragViewGroup.setDrawingCacheEnabled(true);
Bitmap dragBitmap = Bitmap.createBitmap(dragViewGroup.getDrawingCache());
mVibrator.vibrate(50);//设置震动时间
startDrag(dragBitmap, (int)ev.getRawX(),
(int)ev.getRawY());
hideDropItem();
//隐藏需要拖动的item本身
dragViewGroup.setVisibility(View.INVISIBLE);
isMoving =
requestDisallowInterceptTouchEvent(true);
Log.i(&DragGrid------------&&&&&&&&&&, &已点击&);
//实现长按item的操作
setOnClickListener(ev);
return super.onInterceptTouchEvent(ev);
* 删除item的消失动画
* @param position
public void deleteInfo(int position)
DeleteAnimation(position);
* 这里需要获取gridview最外层的布局,因为我们无法直接去对item进行动
画,所以需要创建一个镜像,对镜像进行动画操作
public void setRelativeLayout(RelativeLayout layout)
this.rootLayout =
* 删除View动画
* @param adapter
* @param 需要执行的动画的View
public void DeleteAnimation(final int position)
final View view = getChildAt(position);
view.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());
view.destroyDrawingCache();
//创建一个imageview来显示缓存图片
final ImageView imageView = new ImageView(mContext);
imageView.setImageBitmap(bitmap);
imageView.setLayoutParams(new LayoutParams((int) (Common.Width / 7),
(int) (Common.Width / 7)));
LayoutParams ivlp = new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
final int aimPosit = getCount() - 1;
//将imageview添加到gridview外层的布局文件中,否则会不显示
rootLayout.addView(imageView, ivlp);
//这里用到了属性动画,关于属性动画我会专门来讲,所以这里大家需要自己去了解
AnimatorSet animatorSet = createTranslationAnim(aimPosit, view, imageView);
animatorSet.setInterpolator(new AccelerateDecelerateInterpolator());
animatorSet.setDuration(500);
animatorSet.addListener(new AnimatorListenerAdapter() {
public void onAnimationStart(Animator animation) {
// TODO Auto-generated method stub
DragAdapter adapter = (DragAdapter)getAdapter();
adapter.setHidePosition(position);
Common.isAnimaEnd =
public void onAnimationEnd(Animator animation) {
// TODO Auto-generated method stub
imageView.setVisibility(View.GONE);
imageView.clearAnimation();
rootLayout.removeView(imageView);
DragAdapter adapter = (DragAdapter)getAdapter();
adapter.deletInfo(position);
final ViewTreeObserver vto = getViewTreeObserver();
vto.addOnPreDrawListener(new OnPreDrawListener() {
public boolean onPreDraw() {
// TODO Auto-generated method stub
vto.removeOnPreDrawListener(this);
animateReorder(position, aimPosit);
animatorSet.start();
* 平移动画
* @param view 需要移动的view
* @param startX 开始的X坐标
* @param endX 结束的X坐标
* @param startY 开始的Y坐标
* @param endY 结束的Y坐标
private AnimatorSet createAnimator(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;
* 删除一个item后,其他的item需要自动补齐,这是一个算法问题,如果有不懂的可以私信问我
* @param position
* @param aimPositin
private void animateReorder(int deletePosition, int itemCount)
boolean isForward = itemCount & deleteP
List list = new ArrayList();
if (isForward) {
for (int pos = deleteP pos & itemC pos++) {
View view = getChildAt(pos - getFirstVisiblePosition());
if ((pos + 1) % nColumns == 0) {
list.add(createAnimator(view, -view.getWidth() * (nColumns - 1), 0, view.getHeight(), 0));
list.add(createAnimator(view, view.getWidth(), 0, 0, 0));
for (int pos = deleteP pos & itemC pos--) {
View view = getChildAt(pos - getFirstVisiblePosition());
if ((pos + nColumns) % nColumns == 0) {
list.add(createAnimator(view,view.getWidth() * (nColumns - 1), 0, -view.getHeight(), 0));
list.add(createAnimator(view, -view.getWidth(), 0, 0, 0));
AnimatorSet set = new AnimatorSet();
set.playTogether(list);
set.setInterpolator(new AccelerateDecelerateInterpolator());
set.setDuration(300);
set.addListener(new AnimatorListenerAdapter() {
public void onAnimationStart(Animator animation) {
// TODO Auto-generated method stub
public void onAnimationEnd(Animator animation) {
// TODO Auto-generated method stub
Common.isAnimaEnd =
set.start();
* 方法: createTranslationAnim,同样,这里也是属性动画,大家可以去自己了解
* 描述: TODO
* 参数: @param position 参数: @param aimPosit 参数: @param view 参数: @param
* animView 参数: @return
* 返回: AnimatorSet
* 作者: wedcel
* 时间: 日 下午4:49:23 */ private AnimatorSet createTranslationAnim(int aimPosit, View view, ImageView animView) { int startx = view.getLeft(); int starty = view.getTop(); View aimView = getChildAt(aimPosit); int endx = aimView.getLeft(); int endy = aimView.getTop(); ObjectAnimator animX = ObjectAnimator.ofFloat(animView, &translationX&, startx, endx); ObjectAnimator animY = ObjectAnimator.ofFloat(animView, &translationY&, starty, endy); ObjectAnimator scaleX = ObjectAnimator.ofFloat(animView, &scaleX&, 1f, 0.5f); ObjectAnimator scaleY = ObjectAnimator.ofFloat(animView, &scaleY&, 1f, 0.5f); ObjectAnimator alpaAnim = ObjectAnimator.ofFloat(animView, &alpha&, 1f, 0.0f); AnimatorSet animSetXY = new AnimatorSet(); animSetXY.playTogether(animX,animY,scaleX, scaleY, alpaAnim); return animSetXY; } //这是ViewGroup的onTouchEvent事件,这个事件是需要在onInterceptTouchEvent没有向下分发事件,自己来进行处理 @Override public boolean onTouchEvent(MotionEvent ev) { // TODO Auto-generated method stub if (dragImageView != null && dragPosition != AdapterView.INVALID_POSITION) { // 移动时候的对应x,y位置 int x = (int) ev.getX(); int y = (int) ev.getY(); switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: downX = (int) ev.getX(); windowX = (int) ev.getX(); downY = (int) ev.getY(); windowY = (int) ev.getY(); case MotionEvent.ACTION_MOVE: //进行拖动时改变其位置 onDrag(x, y ,(int) ev.getRawX() , (int) ev.getRawY()); if (!isMoving){ OnMove(x, y); } //如果移动得位置没有item,则跳出 if (pointToPosition(x, y) != AdapterView.INVALID_POSITION){ } case MotionEvent.ACTION_UP: stopDrag(); onDrop(x, y); requestDisallowInterceptTouchEvent(false); default: } } return super.onTouchEvent(ev); } //刷新数据 public void refresh() { stopDrag(); isDrag = DragAdapter mDragAdapter = (DragAdapter) getAdapter(); mDragAdapter.setisDelete(false); mDragAdapter.notifyDataSetChanged(); } /** 在拖动的情况,这里用到了android的窗口机制,大家也可以先去了解一下 */ private void onDrag(int x, int y , int rawx , int rawy) { if (dragImageView != null) { //透明度 windowParams.alpha = 0.6f; // windowParams.x = rawx - itemWidth / 2; // windowParams.y = rawy - itemHeight / 2; //显示坐标 windowParams.x = rawx - win_view_x; windowParams.y = rawy - win_view_y; //对window进行更新 windowManager.updateViewLayout(dragImageView, windowParams); } } /** 在松手下放的情况 */ private void onDrop(int x, int y) { // 根据拖动到的x,y坐标获取拖动位置下方的ITEM对应的POSTION int tempPostion = pointToPosition(x, y); // if (tempPostion != AdapterView.INVALID_POSITION) { dropPosition = tempP DragAdapter mDragAdapter = (DragAdapter) getAdapter(); //显示刚拖动的ITEM mDragAdapter.setShowDropItem(true); //刷新适配器,让对应的ITEM显示 mDragAdapter.notifyDataSetChanged(); // } } /** * 长按点击监听 * @param ev */ public void setOnClickListener(final MotionEvent ev) { setOnItemLongClickListener(new OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterViewparent, View view, int position, long id) { int x = (int) ev.getX();// 长安事件的X位置 int y = (int) ev.getY();// 长安事件的y位置 isDrag = DragAdapter mDragAdapter = (DragAdapter) getAdapter(); mDragAdapter.setisDelete(true); mDragAdapter.notifyDataSetChanged(); startPosition =// 第一次点击的postion dragPosition = //如果是最后一个更多,则不能进行长按 // if (startPosition == getCount() - 1) { // // } ViewGroup dragViewGroup = (ViewGroup) getChildAt(dragPosition - getFirstVisiblePosition()); TextView dragTextView = (TextView)dragViewGroup.findViewById(R.id.name_tv); dragTextView.setSelected(true); dragTextView.setEnabled(false); itemHeight = dragViewGroup.getHeight(); itemWidth = dragViewGroup.getWidth(); itemTotalCount = DragGrid.this.getCount(); int row = itemTotalCount / nC// 算出行数 Remainder = (itemTotalCount % nColumns);// 算出最后一行多余的数量 if (Remainder != 0) { nRows = row + 1; } else { nRows = } // 如果特殊的这个不等于拖动的那个,并且不等于-1 if (dragPosition != AdapterView.INVALID_POSITION) { // 释放的资源使用的绘图缓存。如果你调用buildDrawingCache()手动没有调用setDrawingCacheEnabled(真正的),你应该清理缓存使用这种方法。 win_view_x = windowX - dragViewGroup.getLeft();//VIEW相对自己的X,半斤 win_view_y = windowY - dragViewGroup.getTop();//VIEW相对自己的y,半斤 dragOffsetX = (int) (ev.getRawX() - x);//手指在屏幕的上X位置-手指在控件中的位置就是距离最左边的距离 dragOffsetY = (int) (ev.getRawY() - y);//手指在屏幕的上y位置-手指在控件中的位置就是距离最上边的距离 dragItemView = dragViewG dragViewGroup.destroyDrawingCache(); dragViewGroup.setDrawingCacheEnabled(true); Bitmap dragBitmap = Bitmap.createBitmap(dragViewGroup.getDrawingCache()); mVibrator.vibrate(50);//设置震动时间 startDrag(dragBitmap, (int)ev.getRawX(), (int)ev.getRawY()); hideDropItem(); dragViewGroup.setVisibility(View.INVISIBLE); isMoving = requestDisallowInterceptTouchEvent(true); } } }); } public void startDrag(Bitmap dragBitmap, int x, int y) { stopDrag(); windowParams = new WindowManager.LayoutParams();// 获取WINDOW界面的 //Gravity.TOP|Gravity.LEFT;这个必须加 windowParams.gravity = Gravity.TOP | Gravity.LEFT; // windowParams.x = x - (int)((itemWidth / 2) * dragScale); // windowParams.y = y - (int) ((itemHeight / 2) * dragScale); //得到preview左上角相对于屏幕的坐标 windowParams.x = x - win_view_x; windowParams.y = y - win_view_y; // this.windowParams.x = (x - this.win_view_x + this.viewX);//位置的x值 // this.windowParams.y = (y - this.win_view_y + this.viewY);//位置的y值 //设置拖拽item的宽和高 windowParams.width = (int) (dragScale * dragBitmap.getWidth());// 放大dragScale倍,可以设置拖动后的倍数 windowParams.height = (int) (dragScale * dragBitmap.getHeight());// 放大dragScale倍,可以设置拖动后的倍数 this.windowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; this.windowParams.format = PixelFormat.TRANSLUCENT; this.windowParams.windowAnimations = 0; ImageView iv = new ImageView(getContext()); iv.setImageBitmap(dragBitmap); windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);// &window& windowManager.addView(iv, windowParams); dragImageView = } /** 停止拖动 ,释放并初始化 */ private void stopDrag() { if (dragImageView != null) { windowManager.removeView(dragImageView); dragImageView = } } /** 在ScrollView内,所以要进行计算高度 */ @Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE && 2,MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); } /** 隐藏 放下 的ITEM*/ private void hideDropItem() { ((DragAdapter) getAdapter()).setShowDropItem(false); } /** 获取移动动画 */ public Animation getMoveAnimation(float toXValue, float toYValue) { TranslateAnimation mTranslateAnimation = new TranslateAnimation( Animation.RELATIVE_TO_SELF, 0.0F, Animation.RELATIVE_TO_SELF,toXValue, Animation.RELATIVE_TO_SELF, 0.0F, Animation.RELATIVE_TO_SELF, toYValue);// 当前位置移动到指定位置 mTranslateAnimation.setFillAfter(true);// 设置一个动画效果执行完毕后,View对象保留在终止的位置。 mTranslateAnimation.setDuration(300L); return mTranslateA } /** 移动的时候触发,这里也用到了算法,具体的大家可以研究下*/ public void OnMove(int x, int y) { // 拖动的VIEW下方的POSTION int dPosition = pointToPosition(x, y); // 判断下方的POSTION是否是最开始2个不能拖动的 if (dPosition & getCount() - 1) { if ((dPosition == -1) || (dPosition == dragPosition)){ } dropPosition = dP if (dragPosition != startPosition){ dragPosition = startP } //拖动的=开始拖的,并且 拖动的 不等于放下的 if ((dragPosition == startPosition) || (dragPosition != dropPosition)){ //移需要移动的动ITEM数量 movecount = dropPosition - dragP }else{ //移需要移动的动ITEM数量为0 movecount = 0; } if(movecount == 0){ } int movecount_abs = Math.abs(movecount); if (dPosition != dragPosition) { //dragGroup设置为不可见 ViewGroup dragGroup = (ViewGroup) getChildAt(dragPosition); dragGroup.setVisibility(View.INVISIBLE); float to_x = 1;// 当前下方positon float to_y;// 当前下方右边positon //x_vlaue移动的距离百分比(相对于自己长度的百分比) float x_vlaue = ((float) mHorizontalSpacing / (float) itemWidth) + 1.0f; //y_vlaue移动的距离百分比(相对于自己宽度的百分比) float y_vlaue = ((float) mVerticalSpacing / (float) itemHeight) + 1.0f; Log.d(&x_vlaue&, &x_vlaue = & + x_vlaue); for (int i = 0; i & movecount_ i++) { to_x = x_ to_y = y_ //像左 if (movecount & 0) { // 判断是不是同一行的 holdPosition = dragPosition + i + 1; if (dragPosition / nColumns == holdPosition / nColumns) { to_x = - x_ to_y = 0; } else if (holdPosition % 3 == 0) { to_x = 2 * x_ to_y = - y_ } else { to_x = - x_ to_y = 0; } }else{ //向右,下移到上,右移到左 holdPosition = dragPosition - i - 1; if (dragPosition / nColumns == holdPosition / nColumns) { to_x = x_ to_y = 0; } else if((holdPosition + 1) % 3 == 0){ to_x = -2 * x_ to_y = y_ }else{ to_x = x_ to_y = 0; } } ViewGroup moveViewGroup = (ViewGroup) getChildAt(holdPosition); Animation moveAnimation = getMoveAnimation(to_x, to_y); moveViewGroup.startAnimation(moveAnimation); //如果是最后一个移动的,那么设置他的最后个动画ID为LastAnimationID if (holdPosition == dropPosition) { LastAnimationID = moveAnimation.toString(); } moveAnimation.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub isMoving = } @Override public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationEnd(Animation animation) { // TODO Auto-generated method stub // 如果为最后个动画结束,那执行下面的方法 if (animation.toString().equalsIgnoreCase(LastAnimationID)) { DragAdapter mDragAdapter = (DragAdapter) getAdapter(); mDragAdapter.exchange(startPosition,dropPosition); startPosition = dropP dragPosition = dropP isMoving = } } }); } } } } }
首先我在这里说一下自定义View的分发事件,不了解的可以去先了解一下,对于View因为他没有子View所以他没有onInterceptTouchEvent方法,而ViewGroup有子View所以,他有onInterceptTouchEvent方法,这个方法主要是拦截事件是否继续向下分发,返回true则自己处理,返回false就交给子View处理,getChildAt()用来获取当前item,但是这里要注意的是,他需要减去getFirstVisiblePosition()第一个可见的item的索引,对于上面的几个距离大家可以参考我下面的图
1、dragOffsetX在这里指的是当前拖动的item距离屏幕左边的距离,也就是图中的1号线
2、dragOffsetY在这里指的是当前拖动的item距离屏幕上边的距离,图中的2号线
这里主要就是用的windowManager类,android的窗口机制,要想真正实现拖动我们还要重写onTouchEvent(),在它的ACTION_MOVE中实现拖动操作,完了之后移除镜像,刷新数据,这里需要保存拖动后的顺序到中,具体的我就不说了,大家可以进行Google了解,
接下来我们看下布局文件吧
很简单,没什么说的,然后我们再看下item的布局
大家注意下,我这里是重写了RelativeLayout布局,为了让item是一个正方形,这个布局文件也很简单,大家一看都明白了,不明白的可以私信我
我们再来看一下适配器吧,这里需要在适配器里面做一些操作
package com.roch.water_source_zwb.
import java.util.ArrayL
import java.util.L
import com.lidroid.xutils.DbU
import com.lidroid.xutils.exception.DbE
import com.roch.water_source_zwb.R;
import com.roch.water_source_zwb.app.MyA
import com.roch.water_source_zwb.entity.DragV
import com.roch.water_source_zwb.entity.M
import com.roch.water_source_
import com.roch.water_source_zwb.view.DragG
import android.content.C
import android.os.H
import android.util.L
import android.view.LayoutI
import android.view.V
import android.view.ViewG
import android.view.ViewGroup.LayoutP
import android.view.View.OnClickL
import android.widget.BaseA
import android.widget.ImageV
import android.widget.TextV
public class DragAdapter extends BaseAdapter {
private final static String TAG = &DragAdapter&;
/** 是否显示底部的ITEM */
private boolean isItemShow =
/** 控制的postion */
private int holdP
/** 是否改变 */
private boolean isChanged =
/** 是否可见 */
boolean isVisible =
/** 可以拖动的列表(即用户选择的频道列表) */
public List channelL
/** TextView 频道内容 */
class HolderView
private TextView item_
private ImageView iv_
private ImageView iv_
private boolean isDelete =
/** 要删除的position */
public int remove_position = -1;
private Handler mHandler = new Handler();
private DragG
* 指定隐藏的position
private int hideposition = -1;
public DragAdapter(Context context, List channelList,DragGrid grid) {
this.context =
this.channelList = channelL
this.grid =
public int getCount() {
// TODO Auto-generated method stub
return channelList == null ? 0 : channelList.size();
public DragView getItem(int position) {
// TODO Auto-generated method stub
if (channelList != null && channelList.size() != 0) {
return channelList.get(position);
public long getItemId(int position) {
// TODO Auto-generated method stub
public View getView(final int position, View convertView, ViewGroup parent) {
HolderView holderView =
View view =
if (view == null) {
holderView = new HolderView();
view = LayoutInflater.from(context).inflate(R.layout.gridview_itemview, parent,false);
holderView.iv_icon = (ImageView) view.findViewById(R.id.icon_iv);
holderView.item_text = (TextView) view.findViewById(R.id.name_tv);
holderView.iv_delete = (ImageView) view.findViewById(R.id.delet_iv);
LayoutParams mLayoutParams = holderView.iv_icon.getLayoutParams();
mLayoutParams.width = (int) (Common.Width / 7);
mLayoutParams.height = (int) (Common.Width / 7);
holderView.iv_icon.setLayoutParams(mLayoutParams);
view.setTag(holderView);
holderView = (HolderView)view.getTag();
final DragView iconInfo = getItem(position);
holderView.iv_icon.setImageResource(iconInfo.getResid());
holderView.item_text.setText(iconInfo.getName());
holderView.iv_delete.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mHandler.post(new Runnable() {
public void run() {
// TODO Auto-generated method stub
//判断动画是否结束,没有结束则不能进行下一次的删除
if (!Common.isAnimaEnd) {
notifyDataSetChanged();
grid.deleteInfo(position);
if (position == getCount()-1){
if (convertView == null) {
convertView =
convertView.setEnabled(false);
convertView.setFocusable(false);
convertView.setClickable(false);
DragView channel = getItem(position);
item_text.setText(channel.getName());
if (isChanged && (position == holdPosition) && !isItemShow) {
holderView.item_text.setText(&&);
holderView.item_text.setSelected(true);
holderView.item_text.setEnabled(true);
isChanged =
if (!isVisible && (position == -1 + channelList.size())) {
holderView.item_text.setText(&&);
holderView.item_text.setSelected(true);
holderView.item_text.setEnabled(true);
if(remove_position == position){
deletInfo(position);
if (!isDelete) {
holderView.iv_delete.setVisibility(View.GONE);
if (!iconInfo.getName().equals(&更多&)) {
holderView.iv_delete.setVisibility(View.VISIBLE);
if (hideposition == position) {
view.setVisibility(View.INVISIBLE);
view.setVisibility(View.VISIBLE);
public void setisDelete(boolean isDelete)
this.isDelete = isD
* 删除某个position
* @param position
public void deletInfo(int position)
channelList.remove(position);
hideposition = -1;
notifyDataSetChanged();
/** 添加频道列表 */
public void addItem(DragView channel) {
channelList.add(channel);
notifyDataSetChanged();
/** 拖动变更频道排序,在这里可以将变更后的顺序保存带数据库 */
public void exchange(int dragPostion, int dropPostion) {
holdPosition = dropP
DragView dragItem = getItem(dragPostion);
Log.d(TAG, &startPostion=& + dragPostion + &;endPosition=& + dropPostion);
if (dragPostion & dropPostion) {
channelList.add(dropPostion + 1, dragItem);
channelList.remove(dragPostion);
channelList.add(dropPostion, dragItem);
channelList.remove(dragPostion + 1);
isChanged =
notifyDataSetChanged();
/** 获取频道列表 */
public List getChannnelLst() {
return channelL
/** 设置删除的position */
public void setRemove(int position) {
remove_position =
notifyDataSetChanged();
/** 删除频道列表 */
public void remove() {
channelList.remove(remove_position);
remove_position = -1;
notifyDataSetChanged();
/** 设置频道列表 */
public void setListDate(List list) {
channelList =
/** 获取是否可见 */
public boolean isVisible() {
return isV
/** 设置是否可见 */
public void setVisible(boolean visible) {
isVisible =
/** 显示放下的ITEM */
public void setShowDropItem(boolean show) {
isItemShow =
public void setHidePosition(int position) {
// TODO Auto-generated method stub
this.hideposition =
notifyDataSetChanged();
适配器的注释也写得很明白了,我这里没有添加保存到数据库的代码,大家可以自行添加这里主要的就是exchange()方法,然后我们看下效果图:
Android5.1的模拟器上面,如果大家有什么不懂得,或者对此文章有疑问的欢迎留言讨论
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'

我要回帖

更多关于 卸载手机预装软件 的文章

 

随机推荐