Android 自定义listview滑到顶部标题固定 轻松实现360软件详情页效果

	mViewPager.setAdapter(mAdapter);

	mViewPager.setCurrentItem(0);

}



private void initViews()

{

	mIndicator = (SimpleViewPagerIndicator) findViewById(R.id.id_stickynavlayout_indicator);

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

	

	/*

	RelativeLayout ll = (RelativeLayout) findViewById(R.id.id_stickynavlayout_topview);

	TextView tv = new TextView(this);

	tv.setText("我的动态添加的");

	tv.setBackgroundColor(0x77ff0000);

	ll.addView(tv, new RelativeLayout.LayoutParams(

			RelativeLayout.LayoutParams.MATCH_PARENT, 600));

	*/

}



@Override

public void setCurrentItem(int page) {

	mViewPager.setCurrentItem(page);

}

}


  



4、Fragment及其布局

--------------



package com.stickynavlistview;

import android.os.Bundle;

import android.support.v4.app.Fragment;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.ArrayAdapter;

import android.widget.ListView;

import java.util.ArrayList;

import java.util.List;

public class TabFragment extends Fragment

{

public static final String TITLE = "title";

private String mTitle = "Defaut Value";

private ListView mListView;

// private TextView mTextView;

private List<String> mDatas = new ArrayList<String>();



@Override

public void onCreate(Bundle savedInstanceState)

{

	super.onCreate(savedInstanceState);

	if (getArguments() != null)

	{

		mTitle = getArguments().getString(TITLE);

	}

}



@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container,

		Bundle savedInstanceState)

{

	View view = inflater.inflate(R.layout.fragment_tab, container, false);

	mListView = (ListView) view

			.findViewById(R.id.id_stickynavlayout_innerscrollview);

	// mTextView = (TextView) view.findViewById(R.id.id_info);

	// mTextView.setText(mTitle);

	for (int i = 0; i < 50; i++)

	{

		mDatas.add(mTitle+" -> " + i);

	}

	mListView.setAdapter(new ArrayAdapter<String>(getActivity(),

			R.layout.item, R.id.id_info, mDatas)

	{

		@Override

		public View getView(int position, View convertView, ViewGroup parent)

		{

			//Log.e("tag", "convertView = " + convertView);

			return super.getView(position, convertView, parent);

		}

	});

	return view;



}



public static TabFragment newInstance(String title)

{

	TabFragment tabFragment = new TabFragment();

	Bundle bundle = new Bundle();

	bundle.putString(TITLE, title);

	tabFragment.setArguments(bundle);

	return tabFragment;

}

}


  

  



最后一步是最重要的,你需要把demo源码中的view包下的SimpleViewPagerIndicator和StickyNavLayout(也就是我们自定义的控件代码拷贝到你的项目中)



下面是 SimpleViewPagerIndicator源码



package com.stickynavlistview.view;

import android.content.Context;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.util.AttributeSet;

import android.util.TypedValue;

import android.view.Gravity;

import android.view.MotionEvent;

import android.view.View;

import android.widget.LinearLayout;

import android.widget.TextView;

import com.stickynavlistview.listenter.ListenerConstans;

public class SimpleViewPagerIndicator extends LinearLayout

{

private static final int COLOR_TEXT_NORMAL = 0xFF000000;

private static final int COLOR_INDICATOR_COLOR = Color.BLACK;



private String[] mTitles;

private int mTabCount;

private int mIndicatorColor = COLOR_INDICATOR_COLOR;

private float mTranslationX;

private Paint mPaint = new Paint();

private int mTabWidth;

private int mTabCutWidth=50;//如果觉得指示线太长,这里可以设置减少长度(这里的值设置最好不要超过100)



public SimpleViewPagerIndicator(Context context)

{

	this(context, null);

}



public SimpleViewPagerIndicator(Context context, AttributeSet attrs)

{

	super(context, attrs);

	mPaint.setColor(mIndicatorColor);

	mPaint.setStrokeWidth(2.0F);//底部指示线的宽度

}



@Override

protected void onSizeChanged(int w, int h, int oldw, int oldh)

{

	super.onSizeChanged(w, h, oldw, oldh);

	mTabWidth =(w / mTabCount) -mTabCutWidth;//指示线的长度

}



public void setTitles(String[] titles)

{

	mTitles = titles;

	mTabCount = titles.length;

	generateTitleView();



}



public void setIndicatorColor(int indicatorColor)

{

	this.mIndicatorColor = indicatorColor;

}



@Override

protected void dispatchDraw(Canvas canvas)

{

	super.dispatchDraw(canvas);

	canvas.save();

	canvas.translate(mTranslationX, getHeight() - 2);

	canvas.drawLine(mTabCutWidth, 0, mTabWidth, 0, mPaint);//(startX, startY, stopX, stopY, paint)

	canvas.restore();

}



public void scroll(int position, float offset)

{

	/**

	 * <pre>

	 *  0-1:position=0 ;1-0:postion=0;

	 * </pre>

	 */

	mTranslationX = getWidth() / mTabCount * (position + offset);

	invalidate();

}





@Override

public boolean dispatchTouchEvent(MotionEvent ev)

{

	return super.dispatchTouchEvent(ev);

}



private void generateTitleView()

{

	if (getChildCount() > 0)

		this.removeAllViews();

	int count = mTitles.length;



	setWeightSum(count);

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

	{

		TextView tv = new TextView(getContext());

		LayoutParams lp = new LayoutParams(0,

				LayoutParams.MATCH_PARENT);

		lp.weight = 1;

		tv.setGravity(Gravity.CENTER);

		tv.setTextColor(COLOR_TEXT_NORMAL);

		tv.setText(mTitles[i]);

		tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);//字体大小

		tv.setLayoutParams(lp);

		final int finalI = i;

		tv.setOnClickListener(new OnClickListener()

		{

			@Override

			public void onClick(View v)

			{

				ListenerConstans.mQunZuPager .setCurrentItem(finalI);

			}

		});

		addView(tv);

	}

}

}


  

下面是 StickyNavLayout源码  

package com.stickynavlistview.view;

import android.content.Context;

import android.support.v4.app.Fragment;

import android.support.v4.app.FragmentPagerAdapter;

import android.support.v4.app.FragmentStatePagerAdapter;

import android.support.v4.view.PagerAdapter;

import android.support.v4.view.ViewPager;

import android.util.AttributeSet;

import android.util.Log;

import android.view.MotionEvent;

import android.view.VelocityTracker;

import android.view.View;

import android.view.ViewConfiguration;

import android.view.ViewGroup;

import android.widget.LinearLayout;

import android.widget.ListView;

import android.widget.OverScroller;

import android.widget.ScrollView;

import com.stickynavlistview.R;

public class StickyNavLayout extends LinearLayout {

private View mTop;

private View mNav;

private ViewPager mViewPager;



private int mTopViewHeight;

private ViewGroup mInnerScrollView;

private boolean isTopHidden = false;



private OverScroller mScroller;

private VelocityTracker mVelocityTracker;

private int mTouchSlop;

private int mMaximumVelocity, mMinimumVelocity;



private float mLastY;

private boolean mDragging;



private boolean isInControl = false;



public StickyNavLayout(Context context, AttributeSet attrs) {

	super(context, attrs);

	setOrientation(LinearLayout.VERTICAL);



	mScroller = new OverScroller(context);

	mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();

	mMaximumVelocity = ViewConfiguration.get(context)

			.getScaledMaximumFlingVelocity();

	mMinimumVelocity = ViewConfiguration.get(context)

			.getScaledMinimumFlingVelocity();



}



@Override

protected void onFinishInflate() {

	super.onFinishInflate();

	mTop = findViewById(R.id.id_stickynavlayout_topview);

	mNav = findViewById(R.id.id_stickynavlayout_indicator);

	View view = findViewById(R.id.id_stickynavlayout_viewpager);

	if (!(view instanceof ViewPager)) {

		throw new RuntimeException(

				"id_stickynavlayout_viewpager show used by ViewPager !");

	}

	mViewPager = (ViewPager) view;

}



@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

	super.onMeasure(widthMeasureSpec, heightMeasureSpec);

	ViewGroup.LayoutParams params = mViewPager.getLayoutParams();

	params.height = getMeasuredHeight() - mNav.getMeasuredHeight();



}



@Override

protected void onSizeChanged(int w, int h, int oldw, int oldh) {

	super.onSizeChanged(w, h, oldw, oldh);

	mTopViewHeight = mTop.getMeasuredHeight();

}



@Override

public boolean dispatchTouchEvent(MotionEvent ev) {

	int action = ev.getAction();

	float y = ev.getY();



	switch (action) {

	case MotionEvent.ACTION_DOWN:

		mLastY = y;

		break;

	case MotionEvent.ACTION_MOVE:

		float dy = y - mLastY;

		getCurrentScrollView();



		if (mInnerScrollView instanceof ScrollView) {

			if (mInnerScrollView.getScrollY() == 0 && isTopHidden && dy > 0

					&& !isInControl) {

				isInControl = true;

				ev.setAction(MotionEvent.ACTION_CANCEL);

				MotionEvent ev2 = MotionEvent.obtain(ev);

				dispatchTouchEvent(ev);

				ev2.setAction(MotionEvent.ACTION_DOWN);

				return dispatchTouchEvent(ev2);

			}

		} else if (mInnerScrollView instanceof ListView) {



			ListView lv = (ListView) mInnerScrollView;

			View c = lv.getChildAt(lv.getFirstVisiblePosition());



			if (!isInControl && c != null && c.getTop() == 0 && isTopHidden

					&& dy > 0) {

				isInControl = true;

				ev.setAction(MotionEvent.ACTION_CANCEL);

				MotionEvent ev2 = MotionEvent.obtain(ev);

				dispatchTouchEvent(ev);

				ev2.setAction(MotionEvent.ACTION_DOWN);

				return dispatchTouchEvent(ev2);

			}

		}

		break;

	}

	return super.dispatchTouchEvent(ev);

}



/**

 *

 */

@Override

public boolean onInterceptTouchEvent(MotionEvent ev) {

	final int action = ev.getAction();

	float y = ev.getY();

	switch (action) {

	case MotionEvent.ACTION_DOWN:

		mLastY = y;

		break;

	case MotionEvent.ACTION_MOVE:

		float dy = y - mLastY;

		getCurrentScrollView();

		if (Math.abs(dy) > mTouchSlop) {

			mDragging = true;

			if (mInnerScrollView instanceof ScrollView) {

				// 如果topView没有隐藏

				// 或sc的scrollY = 0 && topView隐藏 && 下拉,则拦截

				if (!isTopHidden

						|| (mInnerScrollView.getScrollY() == 0

								&& isTopHidden && dy > 0)) {



					initVelocityTrackerIfNotExists();

					mVelocityTracker.addMovement(ev);

					mLastY = y;

					return true;

				}

			} else if (mInnerScrollView instanceof ListView) {



				ListView lv = (ListView) mInnerScrollView;

				View c = lv.getChildAt(lv.getFirstVisiblePosition());

				// 如果topView没有隐藏

				// 或sc的listView在顶部 && topView隐藏 && 下拉,则拦截



				if (!isTopHidden || //

						(c != null //

								&& c.getTop() == 0//

								&& isTopHidden && dy > 0)) {



					initVelocityTrackerIfNotExists();

					mVelocityTracker.addMovement(ev);

					mLastY = y;

					return true;

				}

			}



		}

		break;

	case MotionEvent.ACTION_CANCEL:

	case MotionEvent.ACTION_UP:

		mDragging = false;

		recycleVelocityTracker();

		break;

	}

	return super.onInterceptTouchEvent(ev);

}



private void getCurrentScrollView() {



	int currentItem = mViewPager.getCurrentItem();

	PagerAdapter a = mViewPager.getAdapter();

	if (a instanceof FragmentPagerAdapter) {

		FragmentPagerAdapter fadapter = (FragmentPagerAdapter) a;

		Fragment item = (Fragment) fadapter.instantiateItem(mViewPager,

				currentItem);

		mInnerScrollView = (ViewGroup) (item.getView()

				.findViewById(R.id.id_stickynavlayout_innerscrollview));

	} else if (a instanceof FragmentStatePagerAdapter) {

		FragmentStatePagerAdapter fsAdapter = (FragmentStatePagerAdapter) a;

		Fragment item = (Fragment) fsAdapter.instantiateItem(mViewPager,

				currentItem);

		mInnerScrollView = (ViewGroup) (item.getView()

				.findViewById(R.id.id_stickynavlayout_innerscrollview));

	}



}

最后

整理的这些资料希望对Java开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

image

image

其实面试这一块早在第一个说的25大面试专题就全都有的。以上提及的这些全部的面试+学习的各种笔记资料,我这差不多来回搞了三个多月,收集整理真的很不容易,其中还有很多自己的一些知识总结。正是因为很麻烦,所以对以上这些学习复习资料感兴趣
r = (FragmentPagerAdapter) a;

		Fragment item = (Fragment) fadapter.instantiateItem(mViewPager,

				currentItem);

		mInnerScrollView = (ViewGroup) (item.getView()

				.findViewById(R.id.id_stickynavlayout_innerscrollview));

	} else if (a instanceof FragmentStatePagerAdapter) {

		FragmentStatePagerAdapter fsAdapter = (FragmentStatePagerAdapter) a;

		Fragment item = (Fragment) fsAdapter.instantiateItem(mViewPager,

				currentItem);

		mInnerScrollView = (ViewGroup) (item.getView()

				.findViewById(R.id.id_stickynavlayout_innerscrollview));

	}



}

最后

整理的这些资料希望对Java开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

[外链图片转存中…(img-1ODSY3tB-1719249327644)]

[外链图片转存中…(img-IQ3DIfyi-1719249327645)]

其实面试这一块早在第一个说的25大面试专题就全都有的。以上提及的这些全部的面试+学习的各种笔记资料,我这差不多来回搞了三个多月,收集整理真的很不容易,其中还有很多自己的一些知识总结。正是因为很麻烦,所以对以上这些学习复习资料感兴趣

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值