android 打造炫酷导航栏(仿UC头条)
来源:互联网 发布:ntoskrnl 占用80端口 编辑:程序博客网 时间:2024/05/15 10:41
年后开始上班甚是清闲,所以想捣鼓一些东西。在翻阅大神杰作Android 教你打造炫酷的ViewPagerIndicator 不仅仅是高仿MIUI 的时候看到下面有一条评论说,如果导航栏能滑动就更好了。我就想我可以去改一下就可以。然后又想感觉有点像UC的头条的界面。于是就往里面加东西,调试写代码。弄了两天有点效果了,写出来看看了。
项目下载地址:http://download.csdn.net/detail/qq_16064871/9434291
1、先看效果
用咔咔大师录屏的gif效果,有点失真。
这是第一个版本的效果。因为我不断往里面加东西,所以有几个版本了。
2、这个版本基本代码
实现思路就是自定义绘制了。主要有两层,第一层是ViewPagerIndicator。主要负责导航栏的三角形指示器的绘制,以及页面滑动的回调,控制。当然这里需要android.support.v4.view.ViewPager这东西配合使用。
第二层是,导航栏的滑动效果,以及最左、最右有 反弹的效果。这个效果我是从以前一篇博文改动到了这里来。链接:android 滚动条下拉反弹的效果(类似微信朋友圈)。这里效果是垂直,改为横向就行了。还有这两层同时使用需要处理就是滑动不要冲突就可以了。
xml布局代码:
<com.ucnew.view.BounceScrollView android:id="@+id/id_scrollview" android:layout_width="0dp" android:layout_height="45dp" android:layout_weight="1" android:focusableInTouchMode="false" android:scrollbars="none" > <com.ucnew.view.ViewPagerIndicator android:id="@+id/id_indicator" android:layout_width="match_parent" android:layout_height="45dp" android:orientation="horizontal" mmsx:item_count="4" > </com.ucnew.view.ViewPagerIndicator> </com.ucnew.view.BounceScrollView>
3、自定义view的java代码
ViewPagerIndicator
package com.ucnew.view;import java.util.List;import com.ucnew.activity.R;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.CornerPathEffect;import android.graphics.Paint;import android.graphics.Paint.Style;import android.graphics.Path;import android.support.v4.view.ViewPager;import android.support.v4.view.ViewPager.OnPageChangeListener;import android.util.AttributeSet;import android.util.DisplayMetrics;import android.util.TypedValue;import android.view.Gravity;import android.view.View;import android.view.WindowManager;import android.widget.LinearLayout;import android.widget.TextView;public class ViewPagerIndicator extends LinearLayout{//绘制三角形的画笔private Paint mPaint; //path构成一个三角形private Path mPath;//三角形的宽度private int mTriangleWidth;// 三角形的高度private int mTriangleHeight; //三角形的宽度为单个Tab的1/6private static final float RADIO_TRIANGEL = 1.0f / 6;// 三角形的最大宽度private final int DIMENSION_TRIANGEL_WIDTH = (int) (getScreenWidth() / 3 * RADIO_TRIANGEL);//初始时,三角形指示器的偏移量private int mInitTranslationX; // 手指滑动时的偏移量private float mTranslationX; // tab数量private int mTabVisibleCount; // tab上的内容private List<String> mTabTitles; // 与之绑定的ViewPagerpublic ViewPager mViewPager; // 标题正常时的颜色private static final int COLOR_TEXT_NORMAL = 0x77FFFFFF; //标题选中时的颜色private static final int COLOR_TEXT_HIGHLIGHTCOLOR = 0xFFFFFFFF;public ViewPagerIndicator(Context context){this(context, null);}public ViewPagerIndicator(Context context, AttributeSet attrs){super(context, attrs);// 获得自定义属性,tab的数量TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.ViewPagerIndicator);mTabVisibleCount = a.getInt(R.styleable.ViewPagerIndicator_item_count,4);if (mTabVisibleCount < 0)mTabVisibleCount = 4;a.recycle();// 初始化画笔mPaint = new Paint();mPaint.setAntiAlias(true);mPaint.setColor(Color.parseColor("#ffffffff"));mPaint.setStyle(Style.FILL);mPaint.setPathEffect(new CornerPathEffect(3));}//绘制指示器@Overrideprotected void dispatchDraw(Canvas canvas){canvas.save();// 画笔平移到正确的位置canvas.translate(mInitTranslationX + mTranslationX, getHeight() + 1);canvas.drawPath(mPath, mPaint);canvas.restore();super.dispatchDraw(canvas);} //初始化三角形的宽度@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh){super.onSizeChanged(w, h, oldw, oldh);mTriangleWidth = (int) (w / mTabVisibleCount * RADIO_TRIANGEL);// 1/6 of// widthmTriangleWidth = Math.min(DIMENSION_TRIANGEL_WIDTH, mTriangleWidth);// 初始化三角形initTriangle();// 初始时的偏移量mInitTranslationX = getScreenWidth() / mTabVisibleCount / 2 - mTriangleWidth / 2;} //设置可见的tab的数量public void setVisibleTabCount(int count){this.mTabVisibleCount = count;} //设置tab的标题内容 可选,生成textview加入布局,灵活处理public void setTabItemTitles(List<String> datas){// 如果传入的list有值,则移除布局文件中设置的viewif (datas != null && datas.size() > 0){this.removeAllViews();this.mTabTitles = datas;for (String title : mTabTitles){// 添加viewaddView(generateTextView(title));}// 设置item的click事件setItemClickEvent();}}//根据标题生成我们的TextViewprivate TextView generateTextView(String text){TextView tv = new TextView(getContext());LinearLayout.LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);lp.width = getScreenWidth() / mTabVisibleCount;tv.setGravity(Gravity.CENTER);tv.setTextColor(COLOR_TEXT_NORMAL);tv.setText(text);tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);tv.setLayoutParams(lp);return tv;}//对外的ViewPager的回调接口public interface PageChangeListener{public void onPageScrolled(int position, float positionOffset,int positionOffsetPixels);public void onPageSelected(int position);public void onPageScrollStateChanged(int state);}// 对外的ViewPager的回调接口private PageChangeListener onPageChangeListener;// 对外的ViewPager的回调接口的设置public void setOnPageChangeListener(PageChangeListener pageChangeListener){this.onPageChangeListener = pageChangeListener;}// 设置关联的ViewPager,以及传入 BounceScrollView,进行设置滚动public void setViewPager(ViewPager mViewPager, final BounceScrollView scrollView, int pos){this.mViewPager = mViewPager;mViewPager.setOnPageChangeListener(new OnPageChangeListener(){@Overridepublic void onPageSelected(int position){// 设置字体颜色高亮resetTextViewColor();highLightTextView(position);// 回调if (onPageChangeListener != null){onPageChangeListener.onPageSelected(position);}}@Overridepublic void onPageScrolled(int position, float positionOffset,int positionOffsetPixels){// 滚动scroll(scrollView,position, positionOffset);// 回调if (onPageChangeListener != null){onPageChangeListener.onPageScrolled(position,positionOffset, positionOffsetPixels);}}@Overridepublic void onPageScrollStateChanged(int state){// 回调if (onPageChangeListener != null){onPageChangeListener.onPageScrollStateChanged(state);}}});// 设置当前页mViewPager.setCurrentItem(pos);// 高亮highLightTextView(pos);}//高亮文本protected void highLightTextView(int position){View view = getChildAt(position);if (view instanceof TextView){((TextView) view).setTextColor(COLOR_TEXT_HIGHLIGHTCOLOR);}}//重置文本颜色private void resetTextViewColor(){for (int i = 0; i < getChildCount(); i++){View view = getChildAt(i);if (view instanceof TextView){((TextView) view).setTextColor(COLOR_TEXT_NORMAL);}}}// 设置点击事件public void setItemClickEvent(){int cCount = getChildCount();for (int i = 0; i < cCount; i++){final int j = i;View view = getChildAt(i);view.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v){mViewPager.setCurrentItem(j);}});}}// 初始化三角形指示器private void initTriangle(){mPath = new Path();mTriangleHeight = (int) (mTriangleWidth / 2 / Math.sqrt(2));mPath.moveTo(0, 0);mPath.lineTo(mTriangleWidth, 0);mPath.lineTo(mTriangleWidth / 2, -mTriangleHeight);mPath.close();}//指示器跟随手指滚动,以及容器滚动public void scroll(BounceScrollView scrollView,int position, float offset){// 不断改变偏移量,invalidatemTranslationX = getScreenWidth() / mTabVisibleCount * (position + offset);int tabWidth = getScreenWidth() / mTabVisibleCount;// 容器滚动,当移动到倒数最后一个的时候,开始滚动if (offset > 0 && position >= (mTabVisibleCount - 1) && getChildCount() > mTabVisibleCount){if (mTabVisibleCount != 1){//下面注释掉,是滚动ViewPagerIndicator这个LinearLayout//this.scrollTo((position - (mTabVisibleCount - 1)) * tabWidth + (int) (tabWidth * offset), 0);//只滚动滚动条,禁止滚动lineayoutscrollView.setScrolledTo((position - (mTabVisibleCount - 1)) * tabWidth + (int) (tabWidth * offset), 0);} else// 为count为1时 的特殊处理{this.scrollTo(position * tabWidth + (int) (tabWidth * offset), 0);//scrollView.setScrolledTo(position * tabWidth + (int) (tabWidth * offset), 0);}}//处理特殊情况else if (offset > 0 && position <= mTabVisibleCount - 1) {scrollView.setScrolledTo(0, 0);}invalidate();}//设置布局中view的一些必要属性;如果设置了setTabTitles,布局中view则无效@Overrideprotected void onFinishInflate(){super.onFinishInflate();int cCount = getChildCount();if (cCount == 0)return;for (int i = 0; i < cCount; i++){View view = getChildAt(i);LinearLayout.LayoutParams lp = (LayoutParams) view.getLayoutParams();lp.weight = 0;lp.width = getScreenWidth() / mTabVisibleCount;view.setLayoutParams(lp);}// 设置点击事件setItemClickEvent();}//获得屏幕的宽度public int getScreenWidth(){WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);DisplayMetrics outMetrics = new DisplayMetrics();wm.getDefaultDisplay().getMetrics(outMetrics);return outMetrics.widthPixels ;}}
BounceScrollView
package com.ucnew.view;import android.content.Context;import android.graphics.Rect;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.view.animation.TranslateAnimation;import android.widget.HorizontalScrollView;/** * ScrollView反弹效果的实现 */public class BounceScrollView extends HorizontalScrollView {// 孩子Viewprivate View inner; // 点击时x坐标private float x;// 矩形(这里只是个形式,只是用于判断是否需要动画private Rect normal = new Rect(); // 是否开始计算private boolean isCount = false;private RotatImageView mRotatImageView;public BounceScrollView(Context context, AttributeSet attrs) {super(context, attrs);}/*** * 根据 XML 生成视图工作完成.该函数在生成视图的最后调用,在所有子视图添加完之后. 即使子类覆盖了 onFinishInflate * 方法,也应该调用父类的方法,使该方法得以执行. */@Overrideprotected void onFinishInflate() {if (getChildCount() > 0) {inner = getChildAt(0);}}//手动需要设置滚动位置public void setScrolledTo(int position, float positionOffset) {this.scrollTo(position,(int) positionOffset);} //监听touch@Overridepublic boolean onTouchEvent(MotionEvent ev) {if (inner != null) {commOnTouchEvent(ev);}return super.onTouchEvent(ev);}//触摸事件public void commOnTouchEvent(MotionEvent ev) {int action = ev.getAction();switch (action) {case MotionEvent.ACTION_DOWN:break;case MotionEvent.ACTION_UP:// 手指松开.if (isNeedAnimation()) {animation();isCount = false;}break;/*** * 排除出第一次移动计算,因为第一次无法得知y坐标, 在MotionEvent.ACTION_DOWN中获取不到, * 因为此时是MyScrollView的touch事件传递到到了LIstView的孩子item上面.所以从第二次计算开始. * 然而我们也要进行初始化,就是第一次移动的时候让滑动距离归0. 之后记录准确了就正常执行. */case MotionEvent.ACTION_MOVE:final float preX = x;// 按下时的y坐标float nowX = ev.getX();// 时时y坐标int deltaX = (int) (preX - nowX);// 滑动距离if (!isCount) {deltaX = 0; // 在这里要归0.}x = nowX;// 当滚动到最上或者最下时就不会再滚动,这时移动布局if (isNeedMove()) {// 初始化头部矩形if (normal.isEmpty()) {// 保存正常的布局位置normal.set(inner.getLeft(), inner.getTop(),inner.getRight(), inner.getBottom());}// 移动布局inner.layout(inner.getLeft() - deltaX / 4, inner.getTop(),inner.getRight() - deltaX / 4, inner.getBottom());//图片加号旋转,如果不需要这个直接删了就行if (mRotatImageView != null) {mRotatImageView.setRotationLeft();}}isCount = true;break;default:break;}}//回缩动画public void animation() {// 开启移动动画TranslateAnimation ta = new TranslateAnimation(0, 0, inner.getTop(),normal.top);ta.setDuration(200);inner.startAnimation(ta);// 设置回到正常的布局位置inner.layout(normal.left, normal.top, normal.right, normal.bottom);normal.setEmpty();}//设置图片加号旋转public void setRotatImageView(RotatImageView rotatImageView){this.mRotatImageView = rotatImageView;}// 是否需要开启动画public boolean isNeedAnimation() {return !normal.isEmpty();}/*** * 是否需要移动布局 inner.getMeasuredHeight():获取的是控件的总高度 * getHeight():获取的是屏幕的高度 */public boolean isNeedMove() {int offset = inner.getMeasuredWidth() - getWidth();int scrollX = getScrollX();// 0是顶部反弹//是底部反弹加上 if (scrollX == 0 || scrollX == offset) {return true;}return false;}}
都有很详细的注释,以及测试需要说明。
那么就直接看下一个版本。
4、看下一个版本效果
多了一个图标,这个图标可以用来监听,等等。
我后面捣鼓加了一个旋转动画,动画效果可能不是很好。但也可以看看。
5、xml代码
有一些自定义属性以及效果的代码就不贴,感兴趣下载源码。看不懂的,看我前几篇文章,自定义控件使用。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:mmsx="http://schemas.android.com/apk/res/com.ucnew.activity" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#ffffffff" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#8000bf5f" > <com.ucnew.view.BounceScrollView android:id="@+id/id_scrollview" android:layout_width="0dp" android:layout_height="45dp" android:layout_weight="1" android:focusableInTouchMode="false" android:scrollbars="none" > <com.ucnew.view.ViewPagerIndicator android:id="@+id/id_indicator" android:layout_width="match_parent" android:layout_height="45dp" android:orientation="horizontal" mmsx:item_count="4" > </com.ucnew.view.ViewPagerIndicator> </com.ucnew.view.BounceScrollView> <com.ucnew.view.RotatImageView android:id="@+id/id_rotat_imageView" android:layout_width="50dp" android:layout_height="wrap_content" android:paddingLeft="30dp" android:layout_gravity="center" mmsx:src="@drawable/add" > </com.ucnew.view.RotatImageView> </LinearLayout> <android.support.v4.view.ViewPager android:id="@+id/id_vp" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" > </android.support.v4.view.ViewPager></LinearLayout>
6、增加以及这里主要主要需要改的代码。
ViewPagerIndicator类的这个函数
//获得屏幕的宽度public int getScreenWidth(){WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);DisplayMetrics outMetrics = new DisplayMetrics();wm.getDefaultDisplay().getMetrics(outMetrics);//获取是整个屏幕的宽度,我试过自定义宽度测量宽度,不行。因为本身还没内容,是后面添加的。所以需要后面加东西//需要这里减去宽度就行。其中这里减去120就是60dp的宽度return outMetrics.widthPixels -100;}
还有一个图片的旋转类RotatImageView
package com.ucnew.view;import com.ucnew.activity.R;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Matrix;import android.graphics.Paint;import android.graphics.PaintFlagsDrawFilter;import android.util.AttributeSet;import android.util.Log;import android.view.View;public class RotatImageView extends View {private Paint paint = null; // 画笔private Bitmap mbitmap = null; // 图片位图private Bitmap bitmapDisplay = null;private Matrix matrix = null;private int mWidth = 0; // 图片的宽度private int mHeight = 0; // 图片的高度private float fAngle = 180.0f; // 图片旋转private PaintFlagsDrawFilter mDrawFilter; public RotatImageView(Context context) {super(context);}public RotatImageView(Context context, AttributeSet attrs){this(context, attrs, 0);}/** * 初始化一些自定义的参数 * * @param context * @param attrs * @param defStyle */public RotatImageView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);TypedArray a = context.getTheme().obtainStyledAttributes(attrs,R.styleable.RotatImageView, defStyle, 0);int n = a.getIndexCount();for (int i = 0; i < n; i++) {int attr = a.getIndex(i);switch (attr) {// 原始图片,在布局里面获取case R.styleable.RotatImageView_src:mbitmap = BitmapFactory.decodeResource(getResources(),a.getResourceId(attr, 0));bitmapDisplay = mbitmap;break;}}a.recycle(); mDrawFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG);paint = new Paint();paint.setFlags(Paint.ANTI_ALIAS_FLAG);matrix = new Matrix();}/** * 计算控件的高度和宽度 */@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){// 设置宽度int specMode = MeasureSpec.getMode(widthMeasureSpec);int specSize = MeasureSpec.getSize(widthMeasureSpec);//match_parent或者设置的精确值获取//MeasureSpec.EXACTLYif (specMode == MeasureSpec.EXACTLY){mWidth = specSize;} else{// 由图片决定的宽//getPaddingLeft(),getPaddingRight()这两个值是控件属性的向内偏移的距离值,所以的一起计算//区别于layout_marginLeft,两个控件的左间距值设置int desireByImg = getPaddingLeft() + getPaddingRight()+ mbitmap.getWidth();// wrap_contentif (specMode == MeasureSpec.AT_MOST){//所以最小的值,宽度的话是左右内偏移距离之和mWidth = Math.min(desireByImg, specSize);} elsemWidth = desireByImg;}// 设置高度,部分解释同上specMode = MeasureSpec.getMode(heightMeasureSpec);specSize = MeasureSpec.getSize(heightMeasureSpec);//match_parent或者设置的精确值获取//MeasureSpec.EXACTLYif (specMode == MeasureSpec.EXACTLY){mHeight = specSize;} else{int desire = getPaddingTop() + getPaddingBottom()+ mbitmap.getHeight();// wrap_contentif (specMode == MeasureSpec.AT_MOST){mHeight = Math.min(desire, specSize);} elsemHeight = desire;}//计算好的宽度以及高度是值,设置进去setMeasuredDimension(mWidth, mHeight);}// 向左旋转public void setRotationLeft() {fAngle = fAngle - 20;setAngle();}// 向右旋转public void setRotationRight() {fAngle = fAngle + 20;setAngle();}private boolean isRoate = false;// 设置旋转比例private void setAngle() {Log.i("Show", String.valueOf(fAngle));isRoate = true;//设置图片的旋转中心,即绕(X,Y)这点进行中心旋转 要旋转的角度matrix.preRotate(fAngle, (float)mbitmap.getWidth()/2, (float)mbitmap.getHeight()/2); invalidate();}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//消除锯齿, 图片旋转后的锯齿消除不成功,实在不行图片边缘加一些白色像素点canvas.setDrawFilter(mDrawFilter); if (isRoate) {canvas.drawBitmap(bitmapDisplay, matrix, paint);isRoate = false;}else {canvas.drawBitmap(bitmapDisplay, 0, 0, paint);}}}
activity调用以及初始化这些自定义控件
package com.ucnew.activity;import java.util.ArrayList;import java.util.Arrays;import java.util.List;import com.ucnew.activity.R;import com.ucnew.fragment.VpSimpleFragment;import com.ucnew.view.BounceScrollView;import com.ucnew.view.RotatImageView;import com.ucnew.view.ViewPagerIndicator;import android.os.Bundle;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentActivity;import android.support.v4.app.FragmentPagerAdapter;import android.support.v4.view.ViewPager;import android.view.Window;public class MainActivity extends FragmentActivity{private List<Fragment> mTabContents = new ArrayList<Fragment>();private FragmentPagerAdapter mAdapter;private ViewPager mViewPager;private List<String> mDatas = Arrays.asList("页面1", "页面2", "页面3", "页面4","页面5", "页面6", "页面7", "页面8", "页面9");private ViewPagerIndicator mIndicator;private BounceScrollView mScrollView;private RotatImageView mRotatImageView;@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.vp_indicator);initView();initDatas();//设置Tab上的标题mIndicator.setTabItemTitles(mDatas);mViewPager.setAdapter(mAdapter);//设置关联的ViewPagermIndicator.setViewPager(mViewPager,mScrollView,0);//设置关联的图片旋转,根据需要设置,效果不是很好mScrollView.setRotatImageView(mRotatImageView);}private void initDatas(){for (String data : mDatas){VpSimpleFragment fragment = VpSimpleFragment.newInstance(data);mTabContents.add(fragment);}mAdapter = new FragmentPagerAdapter(getSupportFragmentManager()){@Overridepublic int getCount(){return mTabContents.size();}@Overridepublic Fragment getItem(int position){return mTabContents.get(position);}};}private void initView(){mScrollView = (BounceScrollView) findViewById(R.id.id_scrollview);mViewPager = (ViewPager) findViewById(R.id.id_vp);mIndicator = (ViewPagerIndicator) findViewById(R.id.id_indicator);mRotatImageView = (RotatImageView)findViewById(R.id.id_rotat_imageView);}}
还有部分代码没贴。自已下载查看吧。
7、最后效果图
录屏不是很清晰,来一张截图,够清晰的
项目下载地址:http://download.csdn.net/detail/qq_16064871/9434291
用到知识
Android 教你打造炫酷的ViewPagerIndicator 不仅仅是高仿MIUI
android 滚动条下拉反弹的效果(类似微信朋友圈)
android 自定义控件以及自定义view学习(随机验证码生成)
android 自定义控件属性(TypedArray以及attrs解释)
android 自定义图片合集(自定义控件)
android 自定义图片合集(自定义控件)
- android 打造炫酷导航栏(仿UC头条)
- Android之仿今日头条顶部导航栏效果
- Android之仿今日头条顶部导航栏效果
- Android之仿今日头条顶部导航栏效果
- Android之仿今日头条顶部导航栏效果
- 纯jq仿今日头条导航栏
- 仿今日头条顶部导航效果
- 仿UC头条首页-html+css+纯JS
- Android-导航栏特效-新闻类APP(仿iOS版网易新闻今日头条的文字渐变缩放特效)
- Android-导航栏特效-新闻类APP(仿iOS版网易新闻今日头条的文字渐变缩放特效)
- Android-导航栏特效-新闻类APP(仿iOS版网易新闻今日头条的文字渐变缩放特效)
- Android源码解析-仿今日头条PagerSlidingTabStrip滑动页面导航效果
- android-自定义View-PagerIndicatorView(仿UC浏览区主界面导航)
- (android高仿系列)今日头条 --新闻阅读器
- Android ViewPagerIndicator仿今日头条标题栏效果(一)
- Android ViewPagerIndicator仿今日头条标题栏效果(二)
- 自定义View之仿今日头条颜色渐变指示器导航栏
- 仿科技头条导航下面透明三角
- 使用ContentProvider读取系统联系人信息
- 进制转换[PAT]
- CodeForces NO.549A Face Detection
- MySQL主从复制原理
- CSAPP 3e Attack lab
- android 打造炫酷导航栏(仿UC头条)
- 归并排序
- 常浏览的博客和网站
- 最值得你所关注的10个C语言开源项目
- linux常用命令2(转载)
- Java关键字final、static使用总结
- Lena Söderberg误入学术圈
- 2014年值得关注的9 个开源项目
- STL-vector的实现