在这篇博客里有链接 高仿猫眼电影app源码下载地址
先看布局文件吧
fragment_movie_rank_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:dandy="http://schemas.android.com/apk/res/com.demo.dandy"
android:layout_width="match_parent"
android:layout_height="@dimen/title_height"
android:background="@color/background_bg1"
android:paddingLeft="@dimen/inner_padding_size"
android:paddingRight="@dimen/out_padding_size" >
<com.dandy.weights.TitleTabBar
android:id="@+id/movie_topBar"
android:layout_width="@dimen/top_title_bar_sum_width"
android:layout_height="@dimen/top_title_bar_height"
android:layout_centerInParent="true"
dandy:titleSourceId="@array/movie_title" />
</RelativeLayout>
接下来看数组字体arrays.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="movie_title">
<item >热映</item>
<item >待映</item>
<item >榜单</item>
</string-array>
</resources>
自定义属性attrs.xml
<declare-styleable name="TopTitleBar">
<attr name="titleSourceId" format="reference"/>
</declare-styleable>
TitleTabBar
package com.dandy.weights;
import com.demo.dandy.R;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.view.View.OnClickListener;
/**
* 整体思路是:
* 总体是个贞布局
* 1、第一层最底层铺设一个图片
* 2、第二层是那个滑动的白色背景的图片
* 接下来上面覆盖装3个textView的线性布局-背景透明
*
*/
public class TitleTabBar extends FrameLayout implements OnClickListener{
//热映,待映,榜单字体
private int titleSourceId;
//控件的高度,总体宽度,每个选项的宽度,选项数量
private int itemHeight,itemWidth,sumWidth,count;
private String [] titles;
private int currentSelectIndex = 0;
private int whiteColor,redColor;
private TitleTabClickListener mListener;
/**
* 构造函数
*/
private Context mContext;
private Resources mResources;
public TitleTabBar(Context context) {
this(context, null);
}
public TitleTabBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public TitleTabBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.mContext = context;
this.mResources = mContext.getResources();
init(attrs);
}
/**
* 初始化自定义属性
* @param attrs
*/
private void init(AttributeSet attrs){
//未选中的白色字体
this.whiteColor = mResources.getColor(R.color.textcolor_white_a);
//选中时的红色字体
this.redColor = mResources.getColor(R.color.textcolor_red_d);
//高度
this.itemHeight = mResources.getDimensionPixelSize(R.dimen.top_title_bar_height);
//总体宽度
this.sumWidth = mResources.getDimensionPixelSize(R.dimen.top_title_bar_sum_width);
TypedArray ta = mContext.obtainStyledAttributes(attrs,R.styleable.TopTitleBar);
titleSourceId = ta.getResourceId(R.styleable.TopTitleBar_titleSourceId, -1);
ta.recycle();
if(titleSourceId != -1){
titles = mResources.getStringArray(titleSourceId);
//获取数量--热映、待映、榜单
this.count = titles.length;
//获取每个选项的宽度
this.itemWidth = sumWidth / count;
}
/**设置底部的默认图片背景,半透明,圆角,暗红色,宽高属性*/
ImageView back = new ImageView(mContext);
back.setAlpha(0.5f);
back.setBackgroundResource(R.drawable.shape_grey_back);
this.addView(back, new LayoutParams(sumWidth, itemHeight));
//顺序不能变,先添加白色textView块,在添加3个textView文本视图控件
addBar();
addTitle();
}
/**
* 添加每一个选项
*/
private ImageView tabBar;
private void addBar(){
tabBar = new ImageView(mContext);
//宽度高度
LayoutParams params = new LayoutParams(itemWidth, itemHeight);
//背景白色填充
tabBar.setBackgroundResource(R.drawable.shape_white_back);
//设置宽高参数
tabBar.setLayoutParams(params);
//进行添加
this.addView(tabBar);
}
/**
* 存放热映、待映、榜单三个TextView的线性布局
*/
private void addTitle(){
LinearLayout content = new LinearLayout(mContext);
//透明
content.setBackgroundColor(mResources.getColor(R.color.transparent));
this.addView(content, new LayoutParams(sumWidth, itemHeight));
//依次添加3个TextView控件
for(int i = 0;i<count;i++){
//水平依次添加3个textView控件
content.addView(singleTitle(i));
}
}
//存放3个textView的集合容器
private SparseArray<TextView> titleArray = new SparseArray<TextView>();
private TextView singleTitle(int index){
TextView title = new TextView(mContext);
if(index == currentSelectIndex){
title.setTextColor(redColor);
}else{
title.setTextColor(whiteColor);
}
//设置字体大小
title.setTextSize(TypedValue.COMPLEX_UNIT_PX,mResources.getDimensionPixelSize(R.dimen.title_text_size));
//点击事件
title.setOnClickListener(this);
//设置索引
title.setTag(index);
//设置选项名称
title.setText(titles[index]);
//设置每一个选项的宽高
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(itemWidth, itemHeight);
//设置权重
title.setGravity(Gravity.CENTER);
//设置宽度高度
title.setLayoutParams(params);
titleArray.put(index, title);
return title;
}
@Override
public void onClick(View v) {
if(v instanceof TextView){
setTitleState((Integer) v.getTag());
if(mListener != null){
mListener.callback(currentSelectIndex);
}
}
}
/**
*设置标题栏点击效果
*@param selectedIndex:被点击的标题下标
*/
public void setTitleState(int selectedIndex){
TextView last = titleArray.get(currentSelectIndex);
if(last != null){
last.setTextColor(whiteColor);
last.setAlpha(1.0f);
}
currentSelectIndex = selectedIndex;
TextView title = titleArray.get(currentSelectIndex);
if(title != null){
title.setTextColor(redColor);
title.setAlpha(1.0f);
}
}
public void scrollBar(float startX,float endX,int duration){
ObjectAnimator oa = ObjectAnimator.ofFloat(tabBar, "x", startX,endX);
oa.setDuration(duration);
oa.start();
}
/**
*标题点击回调
*/
public interface TitleTabClickListener{
void callback(int index);
}
public void setTitleTabClickListener(TitleTabClickListener listener){
this.mListener = listener;
}
public String[] getTitles(){
return titles;
}
public int getTitleCount(){
return count;
}
public float getItemWidth(){
return itemWidth;
}
public ImageView getTabBar(){
return tabBar;
}
public View getSelectedTitleView(int index){
return titleArray.get(index);
}
public void setTitleAlpha(int index,float alpha){
titleArray.get(index).setAlpha(alpha);
}
}
接下来看布局的代码吧---那个继承的BaseFragment代码不贴了,上篇博客有
MovieFragment
package com.demo.dandy.fragments;
import java.util.ArrayList;
import java.util.List;
import android.support.v4.app.FragmentManager;
import android.support.v4.view.ViewPager;
import android.view.ViewGroup;
import com.dandy.adapter.DandyFragmentPagerAdapter;
import com.dandy.interfaces.DandyPagerChangeListener;
import com.dandy.weights.TitleTabBar;
import com.dandy.weights.TitleTabBar.TitleTabClickListener;
import com.dandy.weights.baseWeights.BaseFragment;
import com.demo.dandy.R;
import com.demo.dandy.fragments.movie.HotFragment;
import com.demo.dandy.fragments.movie.RankFragment;
import com.demo.dandy.fragments.movie.WaitFragment;
public class MovieFragment extends BaseFragment implements TitleTabClickListener{
private FragmentManager manager;
private TitleTabBar titleTabBar;
private ViewPager contentPager;
private DandyFragmentPagerAdapter mAdapter;
@Override
public void setContentView(ViewGroup container) {
//加载电影界面的布局文件
rootView = mInflater.inflate(R.layout.fragment_movie_layout, container,false);
//获取fragment管理器
manager = this.getFragmentManager();
}
@Override
public void initView() {
//热映、待映、榜单
titleTabBar = (TitleTabBar) rootView.findViewById(R.id.movie_topBar);
titleTabBar.setTitleTabClickListener(this);
//热映、待映、榜单对应的ViewPager
contentPager = (ViewPager) rootView.findViewById(R.id.contentPager);
/**
* 设置页面改变监听--去改变titleTabBar
*/
contentPager.setOnPageChangeListener(new DandyPagerChangeListener(contentPager,titleTabBar){
@Override
public void focusedFragment(int selectPosition, int lastPosition) {
super.focusedFragment(selectPosition, lastPosition);
titleTabBar.setTitleState(selectPosition);
}
});
}
//初始化数据-fragment集合
private List<BaseFragment> fragments = new ArrayList<BaseFragment>();
@Override
public void bindData() {
//初始化fragments--添加3个fragment页面即可
fragments.add(new HotFragment());
fragments.add(new WaitFragment());
fragments.add(new RankFragment());
//创建适配器
mAdapter = new DandyFragmentPagerAdapter(manager, fragments);
//设置适配器
contentPager.setAdapter(mAdapter);
//默认定位到第一张图片
contentPager.setCurrentItem(0);
//只加载3张图片
contentPager.setOffscreenPageLimit(3);
}
/**
* 实现TitleTabClickListener的方法回调
*/
@Override
public void callback(int index) {
contentPager.setCurrentItem(index);
}
}
上面的布局代码中设置到
contentPager.setOnPageChangeListener(new DandyPagerChangeListener(contentPager,titleTabBar){
@Override
public void focusedFragment(int selectPosition, int lastPosition) {
super.focusedFragment(selectPosition, lastPosition);
titleTabBar.setTitleState(selectPosition);
}
});
跟着鼠标点过去,是自定义的页面监听
BaseOnPageChangeListener
package com.dandy.interfaces;
import com.dandy.weights.TitleTabBar;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.widget.ImageView;
public abstract class BaseOnPageChangeListener implements OnPageChangeListener {
public boolean isDragging;
public float endPosition;
public float beginPosition;
public int lastFragmentIndex;
public int currentFragmentIndex;
private float lastOffset = 0;
private int lastValue = 0;
private boolean right = false;
private boolean left = false;
//viewPager
public ViewPager pager;
//头部的滑动块
public TitleTabBar titleTabBar;
// 白色底部的TextView控件
public ImageView mBar;
// 获取每个TextView的宽度
public float itemWidth;
public BaseOnPageChangeListener(ViewPager pager, TitleTabBar tabBar) {
this.pager = pager;
this.titleTabBar = tabBar;
this.mBar = tabBar.getTabBar();
this.itemWidth = titleTabBar.getItemWidth();
}
@Override
public void onPageScrollStateChanged(int state) {
if (state == ViewPager.SCROLL_STATE_DRAGGING) {
// 正在拖动页面时执行此处
isDragging = true;
} else if (state == ViewPager.SCROLL_STATE_SETTLING) {
//默示滑动完毕了
isDragging = false;
//滑动完毕后,将白色背景的TextView的endPosition作为最新的beginPosition
beginPosition = endPosition;
if (pager.getCurrentItem() == currentFragmentIndex) {
//如果停留在本页面
endPosition = titleTabBar.getSelectedTitleView(
currentFragmentIndex).getX();
moveNextFalse();
}
} else if (state == ViewPager.SCROLL_STATE_IDLE) {
// 未拖动页面时执行此处
isDragging = false;
right = left = false;
lastOffset = 0;
}
}
/**
* positionOffset
* 假如0界面滑动到1界面时候--值从0-1变动
* 假如1界面滑动到0界面时候--值从1-0变动
* positionOffsetPixels偏移的距离--同上原理
*/
@Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
//如果正在移动
if (isDragging) {
if (lastValue > positionOffsetPixels) {// 手指向右滑动,新值比旧值小
if (right) {// 上次滑动方向是否是右
endPosition = beginPosition - itemWidth
* (Math.abs(lastOffset - (1 - positionOffset)));
} else if (left) {
endPosition = beginPosition - itemWidth
* (Math.abs(positionOffset - lastOffset));
}
right = true;
left = false;
} else if (lastValue < positionOffsetPixels) {// 手指向左滑动,新的值比旧值大
if (left) {// 上次滑动方向是否是左
endPosition = beginPosition + itemWidth
* (Math.abs(lastOffset - positionOffset));
} else if (right) {
endPosition = beginPosition + itemWidth
* (Math.abs(1 - lastOffset - positionOffset));
}
right = false;
left = true;
} else {// 两边
endPosition = beginPosition;
right = left = false;
}
moveing();
}
//如果手指是向右滑动,页面向左
if (right) {
lastOffset = 1 - positionOffset;
}
//如果向左边滑动,页面向右
if (left) {
lastOffset = positionOffset;
}
//移动过程中,会时刻产生新的偏移量,那么就将lastValue实时更新为最新的偏移量
lastValue = positionOffsetPixels;
beginPosition = endPosition;
}
// 此方法是页面跳转完后得到调用,arg0是你当前选中的页面的Position
@Override
public void onPageSelected(int position) {
lastFragmentIndex = currentFragmentIndex;
beginPosition = endPosition;
//将滑动到的页面的索引值赋值给最新的当前的fragment索引值
currentFragmentIndex = position;
//获取最新的选项的偏移量
endPosition = titleTabBar.getSelectedTitleView(position).getX();
//进入到下一个页面
moveNextTrue();
}
public abstract void moveNextFalse();// 未进入下一个页面
public abstract void moveing();// 滑动中
public abstract void moveNextTrue();// 进入下一个页面
}
DandyPagerChangeListener
package com.dandy.interfaces;
import com.dandy.weights.TitleTabBar;
import android.app.Activity;
import android.support.v4.view.ViewPager;
public class DandyPagerChangeListener extends BaseOnPageChangeListener{
public DandyPagerChangeListener(ViewPager pager,TitleTabBar tabBar) {
super(pager, tabBar);
}
@Override
public void moveNextFalse() {
titleTabBar.scrollBar(beginPosition, endPosition, 100);
}
@Override
public void moveing() {
titleTabBar.scrollBar(beginPosition, endPosition, 0);
}
@Override
public void moveNextTrue() {
focusedFragment(currentFragmentIndex,lastFragmentIndex);
titleTabBar.scrollBar(beginPosition, endPosition, 200);
}
public void focusedFragment(int selectPosition,int lastPosition){};
}