转载请注明出处
http://blog.csdn.net/oddshou/article/details/73467589
更新:
仿腾讯新闻频道定制界面效果2
这个效果一直想做,最近项目无事决定着手实现
先看原效果图
那么我们的目标就是实现这样一个效果。目前分析大致有件事情要做:
1、添加或者移除频道动画(添加或移除都需要跨越中间栏目分类)
2、拖拽频道动画
先来分析拖拽动画,这个看似复杂,其实并不难。长按之后布局不变,底部位置出现一个占位空白频道。同时,我们需要调整位置的频道变成抓取状态。移动时,底部布局动态变化直至放下抓取(松手)所选频道移动到占位位置。这个过程可以分成两个部分
底部运动:那么移动的效果实际就是根据鼠标(暂时这么描述)的位置决定占位符(底部占位控件)的下一个位置,并移动到那个位置
顶部运动(抓取控件的运动)根据手势移动,并提供位置坐标
接下来分析添加或者移除频道动画
移除上边(已选频道)这里不需要做什么处理,只需要简单移除就好。同时执行移除动画(后面控件填充空位),那么下边(推荐频道这里)执行添加动画,起始位置为上边移除的位置。
添加 因为添加都是添加在末尾,所以动画也很简单。下边移除,上边添加。添加执行动画,起始位置在移除的地方。
当然以上两块的动画还需要注意动画的执行顺序。
下面开始第一步控制生成布局
图片:
代码
public class GridLayoutAnimation extends Activity {
LinearLayout rootLayout;
static final String [] CHANNELS_CHOOSED = {"要闻", "视频","广东","娱乐","体育",
"要闻2", "视频2","广东2","娱乐2","体育2",
"要闻3", "视频3","广东3","娱乐3","体育3",
"要闻4", "视频4","广东4","娱乐4","体育4",
};
static final String [] CHANNELS_UNCHOOSED = {"宠物", "纪录片","文化","动漫","股票",
"宠物2", "纪录片2","文化2","动漫2","股票2",
"宠物3", "纪录片3","文化3","动漫3","股票3",
"宠物4", "纪录片4","文化4","动漫4","股票4",
};
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_container);
rootLayout = (LinearLayout) findViewById(R.id.container);
createPage();
}
protected void createPage(){
//1.titile 已选频道
TextView chooseTitle = new TextView(this);
chooseTitle.setWidth(200);
chooseTitle.setHeight(100);
chooseTitle.setText("已选频道");
rootLayout.addView(chooseTitle, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
//2.buttons 已选频道
GridLayout gridLayoutChoosed = new GridLayout(this);
gridLayoutChoosed.setColumnCount(4);
gridLayoutChoosed.setLayoutTransition(new LayoutTransition());
for (String title: CHANNELS_CHOOSED
) {
Button btn = new Button(this);
btn.setText(title);
btn.setWidth(180);
gridLayoutChoosed.addView(btn);
}
rootLayout.addView(gridLayoutChoosed);
//3.title 推荐频道
TextView unChoosedTitle = new TextView(this);
unChoosedTitle.setWidth(200);
unChoosedTitle.setHeight(100);
unChoosedTitle.setText("未选频道");
rootLayout.addView(unChoosedTitle, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
//4.buttons 推荐频道
GridLayout gridLayoutUnChoosed = new GridLayout(this);
gridLayoutUnChoosed.setColumnCount(4);
gridLayoutUnChoosed.setLayoutTransition(new LayoutTransition());
for (String title: CHANNELS_UNCHOOSED
) {
Button btn = new Button(this);
btn.setWidth(180);
btn.setText(title);
gridLayoutUnChoosed.addView(btn);
}
rootLayout.addView(gridLayoutUnChoosed);
}
到目前还只是简单的搭建工作,还没有实现什么功能。不过前端工作就是这样,开到界面写起代码来就会越来越幸福有离成功越来越近的感觉。
相信代码应该能看懂,createPage()
添加一些需要的控件。
接下来实现添加和移除的动画。
用上图的效果对比腾讯新闻的话,流畅度不够。还有一个很重要的转移动画没有完成,拖拽也没有完成。
完成这一步的话,需要的工作也讲下:上下两块用的是gridLayout,通过setLayoutTransition
方法设置基本动画效果,包括移除,添加,以及其他item的换行效果。
算了代码就不贴了,后续完成后一并贴上。
对比发现使用setLayoutTransition
动画过程中还可以继续操作,而腾讯新闻却不可以,表示他用的是纯动画而系统这种方式不是。
试过关闭这个动画,速度很快。想了一下,后面的移动动画和拖拽都是要自己实现的,干脆还是自己实现吧。
第二天项目停滞,之前考虑用TranslationLayout 没能解决问题,不过意外发现了一些东西,这里一并记录一下
https://stackoverflow.com/questions/20973089/android-add-view-with-expand-animation-without-blinking
https://github.com/andkulikov/Transitions-Everywhere
以上两个链接一个是系统自动实现动画效果的api,要求api 19我这里就先不考虑了。另一个是第三方库,api要求不高,这里暂时不用了,日后有需要再研究。关键字TransitionManager.beginDelayedTransition
Transitions-Everywhere
第三天:第一个大的效果已经完成
这里说明一下:差距还在于按钮点击效果上,通过手机拍摄慢动作可以发现点击过程中有短暂的白块,认为应该是btn点击背景色导致,这里暂时不去处理。到目前的代码也贴一下不是很多。
public class GridLayoutAnimation extends Activity implements View.OnLongClickListener, View.OnClickListener {
private static final String TAG = "GridLayoutAnimation";
LinearLayout rootLayout;
static final String[] CHANNELS_CHOOSED = {"要闻", "视频", "广东", "娱乐", "体育",
"要闻2", "视频2", "广东2", "娱乐2", "体育2",
"要闻3", "视频3", "广东3", "娱乐3", "体育3",
"要闻4", "视频4", "广东4", "娱乐4", "体育4",
};
static final String[] CHANNELS_UNCHOOSED = {"宠物", "纪录片", "文化", "动漫", "股票",
"宠物2", "纪录片2", "文化2", "动漫2", "股票2",
"宠物3", "纪录片3", "文化3", "动漫3", "股票3",
"宠物4", "纪录片4", "文化4", "动漫4", "股票4",
};
private GridLayout gridLayoutUnChoosed;
private GridLayout gridLayoutChoosed;
private ArrayList<BtnData> groupDataChoosed;
private ArrayList<BtnData> groupDataUnChoosed;
private LayoutTransition mTransitionerTop;
private LayoutTransition mTransitionerBottom;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_container);
rootLayout = (LinearLayout) findViewById(R.id.container);
createPage();
}
protected void createPage() {
//尝试过设置同一个LayoutTransition,发现会有错乱,大概是因为
//动画是两块的,同步执行会有问题。
mTransitionerTop = new LayoutTransition();
mTransitionerBottom = new LayoutTransition();
setupCustomAnimations();
//1.titile 已选频道
TextView chooseTitle = new TextView(this);
chooseTitle.setWidth(200);
chooseTitle.setHeight(100);
chooseTitle.setText("已选频道");
rootLayout.addView(chooseTitle, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
//2.buttons 已选频道
gridLayoutChoosed = new GridLayout(this);
gridLayoutChoosed.setColumnCount(4);
gridLayoutChoosed.setLayoutTransition(mTransitionerTop);
groupDataChoosed = new ArrayList<BtnData>();
createBtns(CHANNELS_CHOOSED, gridLayoutChoosed, groupDataChoosed);
rootLayout.addView(gridLayoutChoosed);
//3.title 推荐频道
TextView unChoosedTitle = new TextView(this);
unChoosedTitle.setWidth(200);
unChoosedTitle.setHeight(100);
unChoosedTitle.setText("未选频道");
rootLayout.addView(unChoosedTitle, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
//4.buttons 推荐频道
gridLayoutUnChoosed = new GridLayout(this);
gridLayoutUnChoosed.setColumnCount(4);
gridLayoutUnChoosed.setLayoutTransition(mTransitionerBottom);
groupDataUnChoosed = new ArrayList<BtnData>();
createBtns(CHANNELS_UNCHOOSED, gridLayoutUnChoosed, groupDataUnChoosed);
rootLayout.addView(gridLayoutUnChoosed);
}
private LayoutTransition.TransitionListener mTransitionListner = new LayoutTransition.TransitionListener() {
int[] locationSrc = new int[2];
@Override
public void startTransition(LayoutTransition transition, ViewGroup container, View view, int transitionType) {
if (transitionType == LayoutTransition.DISAPPEARING) {
view.getLocationInWindow(locationSrc);
} else if (transitionType == LayoutTransition.APPEARING) {
int[] locationDst = new int[2];
if (transition == mTransitionerTop) {
//由下到上
getLocation(locationDst);
} else if (transition == mTransitionerBottom) {
//由上到下
View dstView = gridLayoutUnChoosed.getChildAt(0);
dstView.getLocationInWindow(locationDst); //这里获取得到0,0,改用其他方式获取
}else {
return;
}
PropertyValuesHolder pvhTransX =
PropertyValuesHolder.ofFloat("translationX", locationSrc[0] - locationDst[0], 0f);
PropertyValuesHolder pvhTransY =
PropertyValuesHolder.ofFloat("translationY", locationSrc[1] - locationDst[1], 0f);
final ObjectAnimator animIn = ObjectAnimator.ofPropertyValuesHolder(
this, pvhTransX, pvhTransY).
setDuration(transition.getDuration(LayoutTransition.APPEARING));
transition.setAnimator(LayoutTransition.APPEARING, animIn);
}
}
@Override
public void endTransition(LayoutTransition transition, ViewGroup container, View view, int transitionType) {
}
private void getLocation(int[] location) {
//1.计算新增控件行列
int childCount = gridLayoutChoosed.getChildCount();
int columnCount = gridLayoutChoosed.getColumnCount();
int row = (int)Math.ceil(( childCount + 1.0 )/columnCount + 0.5);
int column = (childCount + 1) % columnCount;
if (column > 1) {
View columnBefor = gridLayoutChoosed.getChildAt(childCount - 1);
columnBefor.getLocationInWindow(location);
location[0] += columnBefor.getWidth(); //这里理论上还需要加上一些margin left,right
}else {
//这里认为已选频道大于1
View columnAbove = gridLayoutChoosed.getChildAt(childCount - columnCount);
columnAbove.getLocationInWindow(location);
location[1] += columnAbove.getHeight(); //同样这里也是不准确的
}
}
};
private void setupCustomAnimations() {
//把延时去掉,速度瞬间提升
// mTransitionerTop.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 0);
// mTransitionerTop.setStartDelay(LayoutTransition.APPEARING, 0);
mTransitionerTop.addTransitionListener(mTransitionListner);
mTransitionerTop.setAnimator(LayoutTransition.DISAPPEARING, null);
mTransitionerTop.setAnimator(LayoutTransition.APPEARING, null);
mTransitionerTop.setInterpolator(LayoutTransition.APPEARING, new LinearInterpolator());
mTransitionerTop.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 0);
mTransitionerTop.setStartDelay(LayoutTransition.APPEARING, 0);
// mTransitionerBottom.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 0);
// mTransitionerBottom.setStartDelay(LayoutTransition.APPEARING, 0);
mTransitionerBottom.addTransitionListener(mTransitionListner);
mTransitionerBottom.setAnimator(LayoutTransition.DISAPPEARING, null);
mTransitionerBottom.setAnimator(LayoutTransition.APPEARING, null);
mTransitionerBottom.setInterpolator(LayoutTransition.APPEARING, new LinearInterpolator());
mTransitionerBottom.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 0);
mTransitionerBottom.setStartDelay(LayoutTransition.APPEARING, 0);
}
protected void createBtns(String[] titles, ViewGroup rootView, ArrayList<BtnData> groupList) {
for (int i = 0; i < titles.length; i++) {
Button btn = new Button(this);
btn.setOnLongClickListener(this);
btn.setOnClickListener(this);
btn.setWidth(180);
btn.setText(titles[i]);
BtnData btnData = new BtnData(i, titles[i], titles == CHANNELS_CHOOSED);
btn.setTag(btnData);
groupList.add(btnData);
rootView.addView(btn);
}
}
@Override
public boolean onLongClick(View v) {
return false;
}
@Override
public void onClick(View v) {
//已选频道点击移动到未选频道
//未选频道点击移动到已选频道
BtnData tag = (BtnData) v.getTag();
if (tag.choosed) {
gridLayoutChoosed.removeView(v);
//这里如果不添加新的btn 会有问题,原因似乎是原btn有一些坐标属性
//导致添加到新的父控件计算位置有误
Button btn = getButton(tag);
gridLayoutUnChoosed.addView(btn, 0);
tag.choosed = false;
if (groupDataChoosed.contains(tag)) {
groupDataChoosed.remove(tag);
}
if (!groupDataUnChoosed.contains(tag)) {
groupDataUnChoosed.add(tag);
}
} else {
gridLayoutUnChoosed.removeView(v);
Button btn = getButton(tag);
gridLayoutChoosed.addView(btn);
tag.choosed = true;
if (!groupDataChoosed.contains(tag)) {
groupDataChoosed.add(tag);
}
if (groupDataUnChoosed.contains(tag)) {
groupDataUnChoosed.remove(tag);
}
}
}
@NonNull
private Button getButton(BtnData tag) {
Button btn = new Button(this);
btn.setOnLongClickListener(this);
btn.setOnClickListener(this);
btn.setWidth(180);
btn.setText(tag.title);
btn.setTag(tag);
return btn;
}
public class BtnData {
int id;
String title;
boolean choosed;
public BtnData(int id, String title, boolean choosed) {
this.id = id;
this.title = title;
this.choosed = choosed;
}
}
}
接下来需要实现拖拽的效果
兴高采烈发现view.startDragAndDrop 却不能用,api level 24,我只能另寻他处了。
备注一些吧,感觉很强大。
http://www.jcodecraeer.com/a/anzhuokaifa/developer/2013/0311/1003.html
第三天基本把第二个效果做完了,先上图
效果基本上完成了,还有一个释放回弹和占位效果。做这个效果三天了,要达到比较完美的效果仍然需要下一些功夫,就当是个思路吧。
补充说明一下,依然使用了startDrag。
最后代码
package com.oddshou.testall.animation;
import android.animation.LayoutTransition;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.app.Activity;
import android.content.ClipData;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.DragEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.widget.Button;
import android.widget.GridLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.oddshou.testall.Logger;
import com.oddshou.testall.R;
import java.util.ArrayList;
/**
* Created by oddshou on 2017/6/19.
*/
public class GridLayoutAnimation extends Activity implements View.OnLongClickListener,
View.OnClickListener, View.OnDragListener {
private static final String TAG = "GridLayoutAnimation";
LinearLayout rootLayout;
static final String[] CHANNELS_CHOOSED = {"要闻", "视频", "广东", "娱乐", "体育",
"要闻2", "视频2", "广东2", "娱乐2", "体育2",
"要闻3", "视频3", "广东3", "娱乐3", "体育3",
"要闻4", "视频4", "广东4", "娱乐4", "体育4",
};
static final String[] CHANNELS_UNCHOOSED = {"宠物", "纪录片", "文化", "动漫", "股票",
"宠物2", "纪录片2", "文化2", "动漫2", "股票2",
"宠物3", "纪录片3", "文化3", "动漫3", "股票3",
"宠物4", "纪录片4", "文化4", "动漫4", "股票4",
};
private GridLayout gridLayoutUnChoosed;
private GridLayout gridLayoutChoosed;
private ArrayList<BtnData> groupDataChoosed;
private ArrayList<BtnData> groupDataUnChoosed;
private LayoutTransition mTransitionerTop;
private LayoutTransition mTransitionerBottom;
//内部调换位置
private boolean choosedChange;
private int choosedChangeId;
private View moveView;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_container);
rootLayout = (LinearLayout) findViewById(R.id.container);
createPage();
}
protected void createPage() {
//尝试过设置同一个LayoutTransition,发现会有错乱,大概是因为
//动画是两块的,同步执行会有问题。
mTransitionerTop = new LayoutTransition();
mTransitionerBottom = new LayoutTransition();
setupCustomAnimations();
//1.titile 已选频道
TextView chooseTitle = new TextView(this);
chooseTitle.setWidth(200);
chooseTitle.setHeight(100);
chooseTitle.setText("已选频道");
rootLayout.addView(chooseTitle, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
//2.buttons 已选频道
gridLayoutChoosed = new GridLayout(this);
gridLayoutChoosed.setColumnCount(4);
gridLayoutChoosed.setLayoutTransition(mTransitionerTop);
groupDataChoosed = new ArrayList<BtnData>();
createBtns(CHANNELS_CHOOSED, gridLayoutChoosed, groupDataChoosed);
rootLayout.addView(gridLayoutChoosed);
//3.title 推荐频道
TextView unChoosedTitle = new TextView(this);
unChoosedTitle.setWidth(200);
unChoosedTitle.setHeight(100);
unChoosedTitle.setText("未选频道");
rootLayout.addView(unChoosedTitle, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
//4.buttons 推荐频道
gridLayoutUnChoosed = new GridLayout(this);
gridLayoutUnChoosed.setColumnCount(4);
gridLayoutUnChoosed.setLayoutTransition(mTransitionerBottom);
groupDataUnChoosed = new ArrayList<BtnData>();
createBtns(CHANNELS_UNCHOOSED, gridLayoutUnChoosed, groupDataUnChoosed);
rootLayout.addView(gridLayoutUnChoosed);
}
private LayoutTransition.TransitionListener mTransitionListner = new LayoutTransition.TransitionListener() {
int[] locationSrc = new int[2];
@Override
public void startTransition(LayoutTransition transition, ViewGroup container, View view, int transitionType) {
if (transitionType == LayoutTransition.DISAPPEARING) {
view.getLocationInWindow(locationSrc);
} else if (transitionType == LayoutTransition.APPEARING) {
//点击.由上到下 终点为下面第一个。
//由下到上,终点为上面最后一个。
int[] locationDst = new int[2];
if (!choosedChange) {
if (transition == mTransitionerTop) {
//由下到上
getLocation(locationDst);
} else if (transition == mTransitionerBottom) {
//由上到下
View dstView = gridLayoutUnChoosed.getChildAt(0);
dstView.getLocationInWindow(locationDst); //这里获取得到0,0,改用其他方式获取
}else {
return;
}
}else {
View dstView = gridLayoutChoosed.getChildAt(choosedChangeId);
dstView.getLocationInWindow(locationDst); //这里获取得到0,0,改用其他方式获取
choosedChange = false;
}
PropertyValuesHolder pvhTransX =
PropertyValuesHolder.ofFloat("translationX", locationSrc[0] - locationDst[0], 0f);
PropertyValuesHolder pvhTransY =
PropertyValuesHolder.ofFloat("translationY", locationSrc[1] - locationDst[1], 0f);
final ObjectAnimator animIn = ObjectAnimator.ofPropertyValuesHolder(
this, pvhTransX, pvhTransY).
setDuration(transition.getDuration(LayoutTransition.APPEARING));
transition.setAnimator(LayoutTransition.APPEARING, animIn);
}
}
@Override
public void endTransition(LayoutTransition transition, ViewGroup container, View view, int transitionType) {
}
private void getLocation(int[] location) {
//1.计算新增控件行列
int childCount = gridLayoutChoosed.getChildCount();
int columnCount = gridLayoutChoosed.getColumnCount();
int row = (int)Math.ceil(( childCount + 1.0 )/columnCount + 0.5);
int column = (childCount + 1) % columnCount;
if (column > 1) {
View columnBefor = gridLayoutChoosed.getChildAt(childCount - 1);
columnBefor.getLocationInWindow(location);
location[0] += columnBefor.getWidth(); //这里理论上还需要加上一些margin left,right
}else {
//这里认为已选频道大于1
View columnAbove = gridLayoutChoosed.getChildAt(childCount - columnCount);
columnAbove.getLocationInWindow(location);
location[1] += columnAbove.getHeight(); //同样这里也是不准确的
}
}
};
private void setupCustomAnimations() {
//把延时去掉,速度瞬间提升
// mTransitionerTop.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 0);
// mTransitionerTop.setStartDelay(LayoutTransition.APPEARING, 0);
mTransitionerTop.addTransitionListener(mTransitionListner);
mTransitionerTop.setAnimator(LayoutTransition.DISAPPEARING, null);
mTransitionerTop.setAnimator(LayoutTransition.APPEARING, null);
mTransitionerTop.setInterpolator(LayoutTransition.APPEARING, new LinearInterpolator());
mTransitionerTop.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 0);
mTransitionerTop.setStartDelay(LayoutTransition.APPEARING, 0);
// mTransitionerBottom.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 0);
// mTransitionerBottom.setStartDelay(LayoutTransition.APPEARING, 0);
mTransitionerBottom.addTransitionListener(mTransitionListner);
mTransitionerBottom.setAnimator(LayoutTransition.DISAPPEARING, null);
mTransitionerBottom.setAnimator(LayoutTransition.APPEARING, null);
mTransitionerBottom.setInterpolator(LayoutTransition.APPEARING, new LinearInterpolator());
mTransitionerBottom.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 0);
mTransitionerBottom.setStartDelay(LayoutTransition.APPEARING, 0);
}
protected void createBtns(String[] titles, ViewGroup rootView, ArrayList<BtnData> groupList) {
for (int i = 0; i < titles.length; i++) {
Button btn = new Button(this);
btn.setOnLongClickListener(this);
btn.setOnClickListener(this);
btn.setOnDragListener(this);
btn.setWidth(180);
btn.setText(titles[i]);
BtnData btnData = new BtnData(i, titles[i], titles == CHANNELS_CHOOSED);
btn.setTag(btnData);
groupList.add(btnData);
rootView.addView(btn);
}
}
@Override
public boolean onLongClick(View v) {
// v.startDragAndDrop() api level 24,好吧算我输
ClipData dragData = ClipData.newPlainText("clipdata", "clipString");
// View.DragShadowBuilder dragShadowBuilder = new View.DragShadowBuilder(v);
View.DragShadowBuilder dragShadowBuilder = new MyShadow(v);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
v.startDragAndDrop(dragData, dragShadowBuilder, null, 0);
}else {
v.startDrag(dragData, dragShadowBuilder, null, 0);
}
// v.setEnabled(false);
moveView = v;
return false;
}
@Override
public boolean onDrag(View v, DragEvent event) {
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
//开始拖动,所有监听控件都会收到
return !(v == moveView);
case DragEvent.ACTION_DRAG_ENTERED:
Logger.i(TAG, "onDrag: " + event.getAction() + " " + ((BtnData)v.getTag()).title , "oddshou");
//进入目标区域,执行变换
BtnData tag = (BtnData) v.getTag();
if (tag.choosed) {
int k = -1; //终点
int j = -1; //起点
for (int i = 0; i < gridLayoutChoosed.getChildCount(); i++) {
View child = gridLayoutChoosed.getChildAt(i);
if (child == v) {
k = i;
}
if (child == moveView) {
j = i;
}
if (k >= 0 && j >= 0) {
break;
}
}
choosedChange = true;
choosedChangeId = k > j ? k-1 : k;
//如果起点小于终点,计算终点坐标时减1,大于终点不减
gridLayoutChoosed.removeView(moveView);
moveView.setLayoutParams(new GridLayout.LayoutParams());
gridLayoutChoosed.addView(moveView, k);
}
return false;
case DragEvent.ACTION_DRAG_LOCATION:
Logger.i(TAG, "onDrag: " + event.getAction(), "oddshou");
return true;
case DragEvent.ACTION_DRAG_EXITED:
//移除目标区域
Logger.i(TAG, "onDrag: " + event.getAction() + " " + ((BtnData)v.getTag()).title, "oddshou");
return true;
case DragEvent.ACTION_DROP:
Logger.i(TAG, "onDrag: " + event.getAction() + " " + ((BtnData)v.getTag()).title, "oddshou");
//目标区域放下
BtnData tag2 = (BtnData) v.getTag();
if (tag2.choosed) {
//还原到终点位置
}else {
//进入下方第一个位置
}
return true;
case DragEvent.ACTION_DRAG_ENDED:
// if (moveView == v) {
// moveView.setEnabled(true);
// }
return true;
}
return false;
}
@Override
public void onClick(View v) {
//已选频道点击移动到未选频道
//未选频道点击移动到已选频道
BtnData tag = (BtnData) v.getTag();
if (tag.choosed) {
gridLayoutChoosed.removeView(v);
//这里如果不添加新的btn 会有问题,原因似乎是原btn有一些坐标属性
//导致添加到新的父控件计算位置有误
v.setLayoutParams(new GridLayout.LayoutParams());
gridLayoutUnChoosed.addView(v, 0);
tag.choosed = false;
if (groupDataChoosed.contains(tag)) {
groupDataChoosed.remove(tag);
}
if (!groupDataUnChoosed.contains(tag)) {
groupDataUnChoosed.add(tag);
}
} else {
gridLayoutUnChoosed.removeView(v);
v.setLayoutParams(new GridLayout.LayoutParams());
gridLayoutChoosed.addView(v);
tag.choosed = true;
if (!groupDataChoosed.contains(tag)) {
groupDataChoosed.add(tag);
}
if (groupDataUnChoosed.contains(tag)) {
groupDataUnChoosed.remove(tag);
}
}
}
@NonNull
private Button getButton(BtnData tag) {
Button btn = new Button(this);
btn.setOnLongClickListener(this);
btn.setOnClickListener(this);
btn.setWidth(180);
btn.setText(tag.title);
btn.setTag(tag);
return btn;
}
public class BtnData {
int id;
String title;
boolean choosed;
public BtnData(int id, String title, boolean choosed) {
this.id = id;
this.title = title;
this.choosed = choosed;
}
}
/**
* 要达到完成的效果还需要仔细斟酌shader效果,
* 目前我遇到的问题就是始终有透明度,
*/
public class MyShadow extends View.DragShadowBuilder {
private View viewSrc;
public MyShadow(View view) {
super(view);
this.viewSrc = view;
}
@Override
public void onDrawShadow(Canvas canvas) {
canvas.drawColor(Color.RED);
// super.onDrawShadow(canvas);
viewSrc.draw(canvas);
}
}
}
xml代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/container"
android:background="@android:color/white"
android:clipChildren="false">
</LinearLayout>
好了,先就这样。有需要再完善。希望上传的一些图片能正常播放
2017.6.21
oddshou