android高仿网易新闻上下拉刷新,Android之高仿今日头条、网易新闻首页动态改变tab...

前言:

项目需要一个类似今日头条或者网易新闻首页动态改变tab(频道栏目)的功能,进过一番折腾,目前已实现该功能。

先看看效果图:

a2e8895edf78?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

这里写图片描述

思路:

1,关于tab栏目横着滑动功能控件的选择,这里我采用的HorizontalScrollView,每个tab采用动态创建的方式。至于为什么没有选择流行的TabLayout,是因为项目后期需求需要每个tab有一个长按的响应事件,但是TabLayout的长按事件不知道怎么回事,总是无法响应,(有空会去研究)。

2,对栏目进行编辑界面的功能介绍:

①栏目分为当前用户栏目和当前用户没有选择的栏目(更多栏目),采用两个GridView使用,但是整体又是可以上下滑动的,所以两个GridView的外层是一个ScrollView,需要解决嵌套出现的问题。②过拽排序(附有动画效果),当用户在用户栏目长按时,会出现震动,其中的第一个是不允许排序的(不能拖动),更多栏目只有点击事件,当点击时会把当前的tab移动到用户栏目。③编辑界面返回时,需要重新设置首页的tab栏目数据。

3,对栏目进行本地数据存储,记录用户的每次对tab进行的修改。

MainActivity.java代码:

public class MainActivity extends AppCompatActivity {

private ColumnHorizontalScrollView mColumnHorizontalScrollView; // 自定义HorizontalScrollView

private LinearLayout mRadioGroup_content; // 每个标题

private LinearLayout ll_more_columns; // 右边+号的父布局

private ImageView button_more_columns; // 标题右边的+号

private RelativeLayout rl_column; // +号左边的布局:包括HorizontalScrollView和左右阴影部分

public ImageView shade_left; // 左阴影部分

public ImageView shade_right; // 右阴影部分

private int columnSelectIndex = 0; // 当前选中的栏目索引

private int mItemWidth = 0; // Item宽度:每个标题的宽度

private int mScreenWidth = 0; // 屏幕宽度

public final static int CHANNELREQUEST = 1; // 请求码

public final static int CHANNELRESULT = 10; // 返回码

// tab集合:HorizontalScrollView的数据源

private ArrayList userChannelList = new ArrayList();

private ViewPager mViewPager;

private ArrayList fragments = new ArrayList();

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

mScreenWidth = Utils.getWindowsWidth(this);

mItemWidth = mScreenWidth / 7; // 一个Item宽度为屏幕的1/7

initView();

}

private void initView() {

setContentView(R.layout.activity_main);

mColumnHorizontalScrollView = (ColumnHorizontalScrollView) findViewById(R.id.mColumnHorizontalScrollView);

mRadioGroup_content = (LinearLayout) findViewById(R.id.mRadioGroup_content);

ll_more_columns = (LinearLayout) findViewById(R.id.ll_more_columns);

rl_column = (RelativeLayout) findViewById(R.id.rl_column);

button_more_columns = (ImageView) findViewById(R.id.button_more_columns);

shade_left = (ImageView) findViewById(R.id.shade_left);

shade_right = (ImageView) findViewById(R.id.shade_right);

mViewPager = (ViewPager) findViewById(R.id.mViewPager);

// + 号监听

button_more_columns.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

Intent intent_channel = new Intent(getApplicationContext(), ChannelActivity.class);

startActivityForResult(intent_channel, CHANNELREQUEST);

}

});

setChangelView();

}

/**

* 当栏目项发生变化时候调用

*/

private void setChangelView() {

initColumnData();

initTabColumn();

initFragment();

}

/**

* 获取Column栏目 数据

*/

private void initColumnData() {

userChannelList = ((ArrayList) ChannelManage.getManage(AppApplication.getApp()

.getSQLHelper()).getUserChannel());

}

/**

* 初始化Column栏目项

*/

private void initTabColumn() {

mRadioGroup_content.removeAllViews();

int count = userChannelList.size();

mColumnHorizontalScrollView.setParam(this, mScreenWidth, mRadioGroup_content, shade_left,

shade_right, ll_more_columns, rl_column);

for (int i = 0; i < count; i++) {

LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(mItemWidth,

ViewGroup.LayoutParams.WRAP_CONTENT);

params.leftMargin = 5;

params.rightMargin = 5;

TextView columnTextView = new TextView(this);

columnTextView.setGravity(Gravity.CENTER);

columnTextView.setPadding(5, 5, 5, 5);

columnTextView.setId(i);

columnTextView.setText(userChannelList.get(i).getName());

columnTextView.setTextColor(getResources().getColorStateList(R.color.top_category_scroll_text_color_day));

if (columnSelectIndex == i) {

columnTextView.setSelected(true);

}

// 单击监听

columnTextView.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

for (int i = 0; i < mRadioGroup_content.getChildCount(); i++) {

View localView = mRadioGroup_content.getChildAt(i);

if (localView != v) {

localView.setSelected(false);

} else {

localView.setSelected(true);

mViewPager.setCurrentItem(i);

}

}

Toast.makeText(getApplicationContext(), userChannelList.get(v.getId()).getName(), Toast.LENGTH_SHORT).show();

}

});

mRadioGroup_content.addView(columnTextView, i, params);

}

}

/**

* 初始化Fragment

*/

private void initFragment() {

fragments.clear();//清空

int count = userChannelList.size();

for (int i = 0; i < count; i++) {

NewsFragment newfragment = new NewsFragment();

fragments.add(newfragment);

}

NewsFragmentPagerAdapter mAdapetr = new NewsFragmentPagerAdapter(getSupportFragmentManager(), fragments);

mViewPager.setAdapter(mAdapetr);

mViewPager.addOnPageChangeListener(pageListener);

}

/**

* ViewPager切换监听方法

*/

public ViewPager.OnPageChangeListener pageListener = new ViewPager.OnPageChangeListener() {

@Override

public void onPageScrollStateChanged(int arg0) {

}

@Override

public void onPageScrolled(int arg0, float arg1, int arg2) {

}

@Override

public void onPageSelected(int position) {

mViewPager.setCurrentItem(position);

selectTab(position);

}

};

/**

* 选择的Column里面的Tab

*/

private void selectTab(int tab_postion) {

columnSelectIndex = tab_postion;

for (int i = 0; i < mRadioGroup_content.getChildCount(); i++) {

View checkView = mRadioGroup_content.getChildAt(tab_postion);

int k = checkView.getMeasuredWidth();

int l = checkView.getLeft();

int i2 = l + k / 2 - mScreenWidth / 2;

mColumnHorizontalScrollView.smoothScrollTo(i2, 0);

}

//判断是否选中

for (int j = 0; j < mRadioGroup_content.getChildCount(); j++) {

View checkView = mRadioGroup_content.getChildAt(j);

boolean ischeck;

if (j == tab_postion) {

ischeck = true;

} else {

ischeck = false;

}

checkView.setSelected(ischeck);

}

}

@Override

protected void onActivityResult(int requestCode, int resultCode, Intent data) {

switch (requestCode) {

case CHANNELREQUEST:

if (resultCode == CHANNELRESULT) {

setChangelView();

}

break;

default:

break;

}

super.onActivityResult(requestCode, resultCode, data);

}

}

主页是控件和数据初始化工作。可以横向滑动的是自定义的HorizontalScrollView——ColumnHorizontalScrollView,代码如下:

public class ColumnHorizontalScrollView extends HorizontalScrollView {

/**

* 传入整体布局

*/

private View ll_content;

/**

* 传入更多栏目选择布局

*/

private View ll_more;

/**

* 传入拖动栏布局

*/

private View rl_column;

/**

* 左阴影图片

*/

private ImageView leftImage;

/**

* 右阴影图片

*/

private ImageView rightImage;

/**

* 屏幕宽度

*/

private int mScreenWitdh = 0;

/**

* 父类的活动activity

*/

private Activity activity;

public ColumnHorizontalScrollView(Context context) {

super(context);

}

public ColumnHorizontalScrollView(Context context, AttributeSet attrs) {

super(context, attrs);

}

public ColumnHorizontalScrollView(Context context, AttributeSet attrs,

int defStyle) {

super(context, attrs, defStyle);

}

/**

* 在拖动的时候执行

*/

@Override

protected void onScrollChanged(int paramInt1, int paramInt2, int paramInt3, int paramInt4) {

// TODO Auto-generated method stub

super.onScrollChanged(paramInt1, paramInt2, paramInt3, paramInt4);

shade_ShowOrHide();

if (!activity.isFinishing() && ll_content != null && leftImage != null && rightImage != null && ll_more != null && rl_column != null) {

if (ll_content.getWidth() <= mScreenWitdh) {

leftImage.setVisibility(View.GONE);

rightImage.setVisibility(View.GONE);

}

} else {

return;

}

if (paramInt1 == 0) {

leftImage.setVisibility(View.GONE);

rightImage.setVisibility(View.VISIBLE);

return;

}

if (ll_content.getWidth() - paramInt1 + ll_more.getWidth() + rl_column.getLeft() == mScreenWitdh) {

leftImage.setVisibility(View.VISIBLE);

rightImage.setVisibility(View.GONE);

return;

}

leftImage.setVisibility(View.VISIBLE);

rightImage.setVisibility(View.VISIBLE);

}

/**

* 传入父类布局中的资源文件

*/

public void setParam(Activity activity, int mScreenWitdh, View paramView1, ImageView paramView2, ImageView paramView3, View paramView4, View paramView5) {

this.activity = activity;

this.mScreenWitdh = mScreenWitdh;

ll_content = paramView1;

leftImage = paramView2;

rightImage = paramView3;

ll_more = paramView4;

rl_column = paramView5;

}

/**

* 判断左右阴影的显示隐藏效果

*/

public void shade_ShowOrHide() {

if (!activity.isFinishing() && ll_content != null) {

measure(0, 0);

//如果整体宽度小于屏幕宽度的话,那左右阴影都隐藏

if (mScreenWitdh >= getMeasuredWidth()) {

leftImage.setVisibility(View.GONE);

rightImage.setVisibility(View.GONE);

}

} else {

return;

}

//如果滑动在最左边时候,左边阴影隐藏,右边显示

if (getLeft() == 0) {

leftImage.setVisibility(View.GONE);

rightImage.setVisibility(View.VISIBLE);

return;

}

//如果滑动在最右边时候,左边阴影显示,右边隐藏

if (getRight() == getMeasuredWidth() - mScreenWitdh) {

leftImage.setVisibility(View.VISIBLE);

rightImage.setVisibility(View.GONE);

return;

}

//否则,说明在中间位置,左、右阴影都显示

leftImage.setVisibility(View.VISIBLE);

rightImage.setVisibility(View.VISIBLE);

}

}

完成了滑动改变tab索引,左右阴影效果。

用户栏目编辑界面代码

public class ChannelActivity extends GestureDetectorActivity implements AdapterView.OnItemClickListener {

/**

* 用户栏目

*/

private DragGrid userGridView; // GridView

DragAdapter userAdapter; // 适配器

ArrayList userChannelList = new ArrayList();

/**

* 其它栏目

*/

private OtherGridView otherGridView; // GridView

OtherAdapter otherAdapter; // 适配器

ArrayList otherChannelList = new ArrayList(); // 数据源

/**

* 是否在移动,由于是动画结束后才进行的数据更替,设置这个限制为了避免操作太频繁造成的数据错乱。

*/

boolean isMove = false;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.channel);

initView();

initData();

}

/**

* 初始化数据

*/

private void initData() {

userChannelList = ((ArrayList) ChannelManage.getManage(AppApplication.getApp().getSQLHelper()).getUserChannel());

otherChannelList = ((ArrayList) ChannelManage.getManage(AppApplication.getApp().getSQLHelper()).getOtherChannel());

userAdapter = new DragAdapter(this, userChannelList);

userGridView.setAdapter(userAdapter);

otherAdapter = new OtherAdapter(this, otherChannelList);

otherGridView.setAdapter(otherAdapter);

//设置GRIDVIEW的ITEM的点击监听

otherGridView.setOnItemClickListener(this);

userGridView.setOnItemClickListener(this);

}

/**

* 初始化布局

*/

private void initView() {

userGridView = (DragGrid) findViewById(R.id.userGridView);

otherGridView = (OtherGridView) findViewById(R.id.otherGridView);

}

/**

* GRIDVIEW对应的ITEM点击监听接口

*/

@Override

public void onItemClick(AdapterView> parent, final View view, final int position, long id) {

//如果点击的时候,之前动画还没结束,那么就让点击事件无效

if (isMove) {

return;

}

switch (parent.getId()) {

case R.id.userGridView:

//position为 0 的不进行任何操作

if (position != 0) {

final ImageView moveImageView = getView(view);

if (moveImageView != null) {

TextView newTextView = (TextView) view.findViewById(R.id.text_item);

final int[] startLocation = new int[2];

newTextView.getLocationInWindow(startLocation);

final ChannelItem channel = ((DragAdapter) parent.getAdapter()).getItem(position);

otherAdapter.setVisible(false);

//添加到最后一个

otherAdapter.addItem(channel);

new Handler().postDelayed(new Runnable() {

public void run() {

try {

int[] endLocation = new int[2];

//获取终点的坐标

otherGridView.getChildAt(otherGridView.getLastVisiblePosition()).getLocationInWindow(endLocation);

MoveAnim(moveImageView, startLocation, endLocation, channel, userGridView);

userAdapter.setRemove(position);

} catch (Exception localException) {

}

}

}, 50L);

}

}

break;

case R.id.otherGridView:

// 其它GridView

final ImageView moveImageView = getView(view);

if (moveImageView != null) {

TextView newTextView = (TextView) view.findViewById(R.id.text_item);

final int[] startLocation = new int[2];

newTextView.getLocationInWindow(startLocation);

final ChannelItem channel = ((OtherAdapter) parent.getAdapter()).getItem(position);

userAdapter.setVisible(false);

//添加到最后一个

userAdapter.addItem(channel);

new Handler().postDelayed(new Runnable() {

public void run() {

try {

int[] endLocation = new int[2];

//获取终点的坐标

userGridView.getChildAt(userGridView.getLastVisiblePosition()).getLocationInWindow(endLocation);

MoveAnim(moveImageView, startLocation, endLocation, channel, otherGridView);

otherAdapter.setRemove(position);

} catch (Exception localException) {

}

}

}, 50L);

}

break;

default:

break;

}

}

/**

* 点击ITEM移动动画

*

* @param moveView

* @param startLocation

* @param endLocation

* @param moveChannel

* @param clickGridView

*/

private void MoveAnim(View moveView, int[] startLocation, int[] endLocation, final ChannelItem moveChannel,

final GridView clickGridView) {

int[] initLocation = new int[2];

//获取传递过来的VIEW的坐标

moveView.getLocationInWindow(initLocation);

//得到要移动的VIEW,并放入对应的容器中

final ViewGroup moveViewGroup = getMoveViewGroup();

final View mMoveView = getMoveView(moveViewGroup, moveView, initLocation);

//创建移动动画

TranslateAnimation moveAnimation = new TranslateAnimation(

startLocation[0], endLocation[0], startLocation[1],

endLocation[1]);

moveAnimation.setDuration(300L);

//动画配置

AnimationSet moveAnimationSet = new AnimationSet(true);

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

moveAnimationSet.addAnimation(moveAnimation);

mMoveView.startAnimation(moveAnimationSet);

moveAnimationSet.setAnimationListener(new Animation.AnimationListener() {

@Override

public void onAnimationStart(Animation animation) {

isMove = true;

}

@Override

public void onAnimationRepeat(Animation animation) {

}

@Override

public void onAnimationEnd(Animation animation) {

moveViewGroup.removeView(mMoveView);

// instanceof 方法判断2边实例是不是一样,判断点击的是DragGrid还是OtherGridView

if (clickGridView instanceof DragGrid) {

otherAdapter.setVisible(true);

otherAdapter.notifyDataSetChanged();

userAdapter.remove();

} else {

userAdapter.setVisible(true);

userAdapter.notifyDataSetChanged();

otherAdapter.remove();

}

isMove = false;

}

});

}

/**

* 获取移动的VIEW,放入对应ViewGroup布局容器

*

* @param viewGroup

* @param view

* @param initLocation

* @return

*/

private View getMoveView(ViewGroup viewGroup, View view, int[] initLocation) {

int x = initLocation[0];

int y = initLocation[1];

viewGroup.addView(view);

LinearLayout.LayoutParams mLayoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);

mLayoutParams.leftMargin = x;

mLayoutParams.topMargin = y;

view.setLayoutParams(mLayoutParams);

return view;

}

/**

* 创建移动的ITEM对应的ViewGroup布局容器

*/

private ViewGroup getMoveViewGroup() {

ViewGroup moveViewGroup = (ViewGroup) getWindow().getDecorView();

LinearLayout moveLinearLayout = new LinearLayout(this);

moveLinearLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));

moveViewGroup.addView(moveLinearLayout);

return moveLinearLayout;

}

/**

* 获取点击的Item的对应View,

*

* @param view

* @return

*/

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;

}

/**

* 退出时候保存选择后数据库的设置

*/

private void saveChannel() {

ChannelManage.getManage(AppApplication.getApp().getSQLHelper()).deleteAllChannel();

ChannelManage.getManage(AppApplication.getApp().getSQLHelper()).saveUserChannel(userAdapter.getChannnelLst());

ChannelManage.getManage(AppApplication.getApp().getSQLHelper()).saveOtherChannel(otherAdapter.getChannnelLst());

}

@Override

public void onBackPressed() {

saveChannel();

if (userAdapter.isListChanged()) {

Intent intent = new Intent(getApplicationContext(), MainActivity.class);

setResult(MainActivity.CHANNELRESULT, intent);

finish();

} else {

super.onBackPressed();

}

}

}

实现了拖动和添加动画,排序功能。

剩下的就是适配器和本地数据存储代码,再不贴出来了。完整代码已上传至github,关注公众号“code小生”查看原文,以及项目地址。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值