您的位置:首页 > 其它

今日头条 频道管理(删除、添加、拖动)

2014-10-13 11:54 716 查看
频道管理共分为两部分:

一、频道的删除和添加

二、频道的拖动

一、频道的删除和添加

利用监听来进行动画的执行。

动画:以item本身创建Bitmap, 然后放入顶层ViewGroup 执行动画并监听Animation(动画为TranslateAnimation 移动)

代码:

public class MyActivity extends Activity{

private DragGrid userGridView;
private OtherGridView otherGridView;
private DragGridAdapter adapter;
private ArrayList<String> data1 = null;
private ArrayList<String> data2 = null;
private OtherAdapter otherAdapter;
//1、防止报java.lang.ArrayIndexOutOfBoundsException 异常,用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引
//主要是当连续点击那个还没有移除item的时候, adapter.remove回报这个错
private boolean isMove = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

initView();
initListener();
}

private void initView(){
userGridView = (DragGrid)findViewById(R.id.userGridView);
otherGridView = (OtherGridView) findViewById(R.id.otherGridView);
data1 = new ArrayList<String>();
data2 = new ArrayList<String>();
String[] s = new String[]{"如果当时", "多余的解释", "有何不可", "坏孩子", "清明雨上", "城府", "认错", "内线", "星座书上"};
for(int i = 0;i < s.length;i ++){
data1.add(s[i]);
}
String[] ss = new String[]{"等到烟火清凉", "山水之间", "七夕", "有桃花", "惊鸿一面", "隐隐约约", "宇宙之大", "梧桐灯", "弹指一挥间",
"胡萝卜须", "幻听", "对话老师", "伴虎", "闺蜜", "装糊涂", "play with style", "心疼你的过去", "全球变冷", "亲情式的爱情"};
for(int i = 0;i < ss.length;i ++){
data2.add(ss[i]);
}
adapter = new DragGridAdapter(this, data1);
otherAdapter = new OtherAdapter(this, data2);
userGridView.setAdapter(adapter);
otherGridView.setAdapter(otherAdapter);
}

private void initListener(){
userGridView.setOnItemClickListener(new OnItemClickListener() {

@Override
public void onItemClick(AdapterView<?> parent, View view,
final int position, long id) {
// TODO Auto-generated method stub
if(isMove){
return;
}

if(position > 1){
final ImageView moveImage = getView(view);
if(moveImage != null){
TextView nowTextView = (TextView) view.findViewById(R.id.text_item);
final int[] startCoord = new int[2];
//getLocationInWindow:获取在整个窗口内的绝对坐标
//将view的左上角坐标存入数组中.此坐标是相对当前activity而言.
nowTextView.getLocationInWindow(startCoord);
//setVisible():显示动画要移动的位置
otherAdapter.setVisible(false);
otherAdapter.add(data1.get(position));
//postDelayed():延时50L之后执行
new Handler().postDelayed(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
int[] endCoord = new int[2];
otherGridView.getChildAt(otherGridView.getLastVisiblePosition()).getLocationInWindow(endCoord);
adapter.setRemove(position);
moveAnim(moveImage, startCoord, endCoord, userGridView);
}
}, 50L);
}
}
}
});

otherGridView.setOnItemClickListener(new OnItemClickListener() {

@Override
public void onItemClick(AdapterView<?> parent, View view,
final int position, long id) {
// TODO Auto-generated method stub
if (isMove) {
return;
}

if (position > 1) {
final ImageView moveImage = getView(view);
if (moveImage != null) {
TextView nowTextView = (TextView) view
.findViewById(R.id.text_item);
final int[] startCoord = new int[2];
nowTextView.getLocationInWindow(startCoord);
adapter.setVisible(false);
adapter.add(data2.get(position));
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
int[] endCoord = new int[2];
userGridView.getChildAt(userGridView.getLastVisiblePosition()).getLocationInWindow(endCoord);
otherAdapter.setRemove(position);
moveAnim(moveImage, startCoord, endCoord, otherGridView);
}
}, 50L);
}
}
}
});
}

/* 移动动画*/
private void moveAnim(View view, int[] start, int[] end, final GridView clickGridView){
//getViewGroup、getMoveView :因为Bitmap 不支持Animation动画 所以用控件包含Bitmap 用控件来展示动画
final ViewGroup viewGroup = getViewGroup();
final View moveView = getMoveView(viewGroup, view);

//创建移动动画
TranslateAnimation moveAnimation = new TranslateAnimation(start[0], end[0],
start[1], end[1]);
moveAnimation.setDuration(300L);

AnimationSet moveAnimationSet = new AnimationSet(true);
moveAnimationSet.setFillAfter(false);//动画效果执行完毕后,View对象不保留在终止的位置
moveAnimationSet.addAnimation(moveAnimation);

moveView.startAnimation(moveAnimationSet);

moveAnimationSet.setAnimationListener(new AnimationListener() {

public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub
isMove = true;
}

public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub

}

public void onAnimationEnd(Animation animation) {
// TODO Auto-generated method stub
//删除添加的控件
viewGroup.removeView(moveView);
if(clickGridView instanceof DragGrid){
otherAdapter.setVisible(true);
otherAdapter.notifyDataSetChanged();
adapter.remove();
}else {
adapter.setVisible(true);
adapter.notifyDataSetChanged();
otherAdapter.remove();
}
isMove = false;
}
});

}

/* 把Bitmap添加进ViewGroup*/
private View getMoveView(ViewGroup group, View view){
group.addView(view);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
view.setLayoutParams(params);
return view;
}
/* 获取ViewGroup */
private ViewGroup getViewGroup(){
//getDecorView():decorView是window中的最顶层view
ViewGroup group = (ViewGroup)getWindow().getDecorView();
LinearLayout moveLinearLayout = new LinearLayout(this);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
moveLinearLayout.setLayoutParams(params);
group.addView(moveLinearLayout);
return moveLinearLayout;
}
/* 用来获取绘制的图片*/
private ImageView getView(View view){
view.destroyDrawingCache();
view.setDrawingCacheEnabled(true);
Bitmap cache = Bitmap.createBitmap(view.getDrawingCache());
view.setDrawingCacheEnabled(false);
ImageView iv = new ImageView(this);
iv.setImageBitmap(cache);
return iv;
}

}


二、频道的拖动

思路:重写GridView

通过setOnItemLongClickListener()长时间按住触动 创建窗口 进行拖动

1、创建移动窗口

利用WindowManager WindowManager.LayoutParams 进行窗口创建

2、拖动频道移动

通过TranslateAnimation进行频道移动

public class DragGrid extends GridView {

/** 每个ITEM之间的水平间距 */
private int mHorizontalSpacing = 15;
/** 每个ITEM之间的竖直间距 */
private int mVerticalSpacing = 15;
/** item高 */
private int itemHeight;
/** item宽 */
private int itemWidth;

/** 屏幕上的X */
private int win_view_x;
/** 屏幕上的Y*/
private int win_view_y;

/** window属性*/
private WindowManager.LayoutParams windowParams = null;
/** WindowManager管理器 */
private WindowManager windowManager = null;

/** 拖动的时候放大的倍数 */
private double dragScale = 1.2D;

/** 拖动的时候对应ITEM的VIEW */
private View dragImageView = null;

/** 点击时候的X位置 */
public int downX;
/** 点击时候的Y位置 */
public int downY;
/** 点击时候对应整个界面的X位置 */
public int windowX;
/** 点击时候对应整个界面的Y位置 */
public int windowY;

/** 一行的ITEM数量*/
private int nColumns = 4;

/* 移动时候最后个动画的ID */
private String LastAnimationID;

//长按开始位置(第一次)
private int startPosition;
//长按的位置
private int dragPosition;
//是否移动
private boolean isMove = false;
//移动的次数
private int moveNum = 0;

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);
}
/** 在ScrollView内,所以要进行计算高度 */
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}

private void init(Context context){
//将布局文件中设置的间距dip转为px
mHorizontalSpacing = DataTools.dip2px(context, mHorizontalSpacing);
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
windowX = (int) ev.getX();
windowY = (int) ev.getY();
setOnItemClickListener(ev);
}
return super.onInterceptTouchEvent(ev);
}
/*
有一种方法可以阻止父层的View截获touch事件,就是调用getParent().requestDisallowInterceptTouchEvent(true);方法。
一旦底层View收到touch的action后调用这个方法那么父层View就不会再调用onInterceptTouchEvent了,也无法截获以后的action。
*/
/*
* requestDisallowInterceptTouchEvent():这个方法就是告诉父层不需要调用onInterceptTouchEvent()方法
*
* 在响应touch事件时,会先调用父控件onInterceptTouchEvent()方法,然后在往下传递
* 详细请看博客
*/
@Override
public boolean onTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
int x = (int) ev.getX();
int y = (int) ev.getY();
if (dragImageView != null
&& dragPosition != AdapterView.INVALID_POSITION) {
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
windowX = (int) ev.getX();
windowY = (int) ev.getY();
break;
case MotionEvent.ACTION_MOVE:
onDrag((int) ev.getRawX(), (int) ev.getRawY());
if(!isMove){
onMove(x, y);
}

break;
case MotionEvent.ACTION_UP:
stopDrag();
onDrop(x, y);
requestDisallowInterceptTouchEvent(false);
break;
default:
break;
}
}

return super.onTouchEvent(ev);
}
/* 显示拖动之后位置上的内容 */
private void onDrop(int x, int y){

DragGridAdapter mDragGridAdapter = (DragGridAdapter) getAdapter();
mDragGridAdapter.setShowDropItem(true);

mDragGridAdapter.notifyDataSetChanged();
}
/* 窗口跟随手指进行移动 */
private void onDrag(int rawX, int rawY){
if(dragImageView != null){

windowParams.alpha = 0.6f;

windowParams.x = rawX - win_view_x;
windowParams.y = rawY - win_view_y;

windowManager.updateViewLayout(dragImageView, windowParams);
}
}
private void setOnItemClickListener(final MotionEvent ev){
setOnItemLongClickListener(new OnItemLongClickListener() {

@Override
public boolean onItemLongClick(AdapterView<?> parent, View view,
int position, long id) {
// TODO Auto-generated method stub
startPosition = position;
dragPosition = position;

if(startPosition <= 1){
return false;
}
//getChildAt() 获取的是Grid 中的item
ViewGroup dragViewGroup = (ViewGroup) getChildAt(position);
TextView dragTextView = (TextView) dragViewGroup.findViewById(R.id.text_item);
//setSelected:改变视图的选中状态。视图有选中和未选中两个状态。注意,选择状态不同于焦点。
//典型的选中的视图是象 ListView 和 GridView 这样的 AdapterView 中显示的 内容;选中的内容会显示为高亮
dragTextView.setSelected(true);
dragTextView.setEnabled(false);

itemHeight = dragViewGroup.getHeight();
itemWidth = dragViewGroup.getWidth();

//				System.out.println("dragViewGroup.getHeight()->" + dragViewGroup.getHeight());
//				System.out.println("dragViewGroup.getWidth()->" + dragViewGroup.getWidth());
//				System.out.println("dragTextView.getHeight()->" + dragTextView.getHeight());
//				System.out.println("dragTextView.getWidth()->" + dragTextView.getWidth());

if(dragPosition != AdapterView.INVALID_POSITION){
//现在获取的ev.getX,ev.getY 与 windowX 、windowY 怎么会不一样那 尤其是Y坐标会差距那么大
//getLeft, getRight, getTop, getBottom是相对其父视图的位置

/*event.getRowX():触摸点相对于屏幕原点的x坐标
*event.getX():   触摸点相对于其所在组件原点的x坐标
*/
win_view_x = windowX - dragViewGroup.getLeft();
win_view_y = windowY - dragViewGroup.getTop();
/*
* 在Android中自有获取view中的cache内容,然后将内容转换成bitmap,方法名是:getDrawingCache(),返回结果为Bitmap
* destroyDrawingCache():用来销毁旧的cache
* setDrawingCacheEnabled():用来把cache开启,不然没有办法获取cache
* getDrawingCache():用来获取view中的cache内容,并把获取的内容转换成Bitmap
*/
dragViewGroup.destroyDrawingCache();
dragViewGroup.setDrawingCacheEnabled(true);
Bitmap dragBitmap = Bitmap.createBitmap(dragViewGroup.getDrawingCache());
dragViewGroup.setDrawingCacheEnabled(false);

startDrag(dragBitmap, (int)ev.getRawX(),  (int)ev.getRawY());
hideDropItem();
//					dragViewGroup.setVisibility(View.INVISIBLE);
dragTextView.setBackgroundResource(R.drawable.diji2);
dragTextView.setText("");
isMove = false;
//阻止父层的View截获touch事件
requestDisallowInterceptTouchEvent(true);
return true;
}

return false;
}
});
}

/** 隐藏 放下 的ITEM*/
private void hideDropItem() {
((DragGridAdapter) getAdapter()).setShowDropItem(false);
}

//创建悬浮窗口
private void startDrag(Bitmap bitmap, int rawX, int rawY){
stopDrag();

windowParams = new WindowManager.LayoutParams();
windowParams.gravity = Gravity.TOP | Gravity.LEFT;
/*
* windowParams.x
* 如果忽略gravity属性,那么它表示窗口的绝对X位置。
* 什么是gravity属性呢?简单地说,就是窗口如何停靠。
* 当设置了 Gravity.LEFT 或 Gravity.RIGHT 之后,x值就表示到特定边的距离。
*/
windowParams.x = rawX - win_view_x;
/*
* windowParams.y
* 如果忽略gravity属性,那么它表示窗口的绝对Y位置。
* 当设置了Gravity.TOP 或 Gravity.BOTTOM 之后,y值就表示到特定边的距离。
*/
windowParams.y = rawY - win_view_y;

windowParams.width = (int) (dragScale * bitmap.getWidth());
windowParams.height = (int) (dragScale * bitmap.getHeight());
/*
* FLAG_NOT_FOCUSABLE:不能获得按键输入焦点,所以不能向它发送按键或按钮事件
* FLAG_NOT_TOUCHABLE:不接受触摸屏事件。
* FLAG_KEEP_SCREEN_ON: 当此窗口为用户可见时,保持设备常开,并保持亮度不变
* FLAG_LAYOUT_IN_SCREEN:窗口占满整个屏幕,忽略周围的装饰边框(例如状态栏)。此窗口需考虑到装饰边框的内容
*/
this.windowParams.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
//		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;
//期望的位图格式。默认为不透明.参考android.graphics.PixelFormat。
//还不是很清楚
windowParams.format = PixelFormat.TRANSLUCENT;
//窗口所使用的动画设置。它必须是一个系统资源而不是应用程序资源,因为窗口管理器不能访问应用程序。
// windowParams.windowAnimations = 0;

ImageView iv = new ImageView(getContext());
iv.setImageBitmap(bitmap);

windowManager = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);
windowManager.addView(iv, windowParams);
/* WindowManager是Android中一个重要的服务(Service )。WindowManager Service 是全局的,是唯一的。
* 它将用户的操作,翻译成为指令,发送给呈现在界面上的各个Window。Activity会将顶级的控件注册到 Window Manager 中,
* 当用户真是触碰屏幕或键盘的时候,Window Manager就会通知到,而当控件有一些请求产生,也会经由ViewParent送回到Window Manager中。
* 从而完成整个通信流程。整个Android的窗口机制是基于一个叫做 WindowManager,这个接口可以添加view到屏幕,也可以从屏幕删除view。
* 它面向的对象一端是屏幕,另一端就是View,通过WindowManager的 addView方法创建View,这样产生出来的View根据
* WindowManager.LayoutParams属性不同,效果也就不同了。比如创建 系统顶级窗口,实现悬浮窗口效果!
* WindowManager的方法很简单,基本用到的就三addView,removeView,updateViewLayout。接口,
* 而WindowManager.LayoutParams的属性就多了,非常丰富,具体请查后面介绍
*/
dragImageView = iv;
}
//删除多余窗口
private void stopDrag(){
if(dragImageView != null){
windowManager.removeView(dragImageView);
dragImageView = null;
}
}
//得到动画
private Animation getMoveAnimation(float x, float y){
//Animation.RELATIVE_TO_SELF:相对自己的百分比
//view.width * (百分比 + 1)
//view.height * (百分比 + 1)
TranslateAnimation translateAnimation = new TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0.0F,
Animation.RELATIVE_TO_SELF,x,
Animation.RELATIVE_TO_SELF, 0.0F,
Animation.RELATIVE_TO_SELF, y);// 当前位置移动到指定位置
//请看博客
// translateAnimation.setFillAfter(true);
//延迟
/*
* public void setDuration (long durationMillis)
* 参数durationMillis为动画的持续时间,单位为毫秒(ms)
*/
translateAnimation.setDuration(300L);
return translateAnimation;
}
private void onMove(int x, int y){
final int belowPosition = pointToPosition(x, y);

if(belowPosition <= 1){
return;
}

if(belowPosition == -1 || belowPosition == startPosition){
return;
}

if(dragPosition != startPosition){
dragPosition = startPosition;
}

moveNum = belowPosition - dragPosition;

if(moveNum == 0){
return;
}

ViewGroup group = (ViewGroup) getChildAt(dragPosition);
group.setVisibility(View.INVISIBLE);

float to_x = 1;// 当前下方positon
float to_y;// 当前下方右边positon
//没有理解
//x_vlaue移动的距离百分比(相对于自己长度的百分比)
float x_value = ((float) mHorizontalSpacing / (float) itemWidth) + 1.0f;
//y_vlaue移动的距离百分比(相对于自己宽度的百分比)
float y_value = ((float) mVerticalSpacing / (float) itemHeight) + 1.0f;

int length = Math.abs(moveNum);
int holdPosition;
for(int i = 0;i < length;i ++){

if(moveNum > 0){
holdPosition = dragPosition + i + 1;
if(holdPosition/nColumns == dragPosition/nColumns){
to_x = -x_value;
to_y = 0;
}else if(holdPosition % 4 == 0){
to_x = 3 * x_value;
to_y = -y_value;
}else{
to_x = -x_value;
to_y = 0;
}
} else{
holdPosition = dragPosition  - i - 1;
if(holdPosition/nColumns == dragPosition/nColumns){
to_x = x_value;
to_y = 0;
}else if(holdPosition % 4 == 3){
to_x = - 3 * x_value;
to_y = y_value;
}else{
to_x = x_value;
to_y = 0;
}
}

ViewGroup moveViewGroup = (ViewGroup)getChildAt(holdPosition);
Animation moveAnimation = getMoveAnimation(to_x, to_y);
moveViewGroup.startAnimation(moveAnimation);
if (holdPosition == belowPosition) {
LastAnimationID = moveAnimation.toString();
}
moveAnimation.setAnimationListener(new AnimationListener() {

@Override
public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub
isMove = true;
}

@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)) {
DragGridAdapter mDragAdapter = (DragGridAdapter) getAdapter();
mDragAdapter.exchange(startPosition,belowPosition);
startPosition = belowPosition;
dragPosition = belowPosition;
isMove = false;
}
}
});
}
}

}


代码下载:点击下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐