自定义控件(21)---自定义控件之高仿猫眼小项目(3)

在这篇博客里有链接   高仿猫眼电影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){};
	
}



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值