Android 一个比较简陋的动态标题栏

   2016-11-16 0
核心提示:没什么说的,就是一个代码整理。 先来看一下效果图:标题少的:标题多的:因为最近两个项目都有类似效果,所以这里整理了一下代码。实现代码借鉴了 PagerSlidingTabStrip.比较简单,所以这里就直接贴出了主要的实现代码:public class HorizontalView extends

没什么说的,就是一个代码整理。

先来看一下效果图:

标题少的:

标题多的:

因为最近两个项目都有类似效果,所以这里整理了一下代码。实现代码借鉴了 PagerSlidingTabStrip.

比较简单,所以这里就直接贴出了主要的实现代码:

public class HorizontalView extends HorizontalScrollView {

    private LinearLayout container;
    private int tabPadding = 8;
    private int tabTextSize = 16;
    private int tabSelTextSize = 16;
    private int tabTextColor;
    private int count;

    private int screenWidth; // 屏幕宽度
    private int childViewWidth; // 控件宽度
    private LinearLayout.LayoutParams matchParams, weightParmas;

    private List<String> strList;
    private int selPos = 0;
    private Context context;

    public interface onItemClickListener {
        void onClick(int position);
    }

    private onItemClickListener listener;
//    private static final int[] ATTRS = new int[]{
//            android.R.attr.textSize,
//            android.R.attr.textColor
//    };

    public HorizontalView(Context context, AttributeSet attrs) {
        super(context, attrs);
        /**
         *当你想让一个高度值不足scrollview的子控件fillparent的时候,
         * 单独的定义android:layout_height="fill_parent"是不起作用的,
         * 必须加上fillviewport属性,当子控件的高度值大于scrollview的高度时,这个标签就没有任何意义了。
         */
        setFillViewport(true);
        setHorizontalScrollBarEnabled(false);
        this.context = context;

        container = new LinearLayout(getContext());
        container.setOrientation(LinearLayout.HORIZONTAL);
        container.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
        addView(container);
        DisplayMetrics dm = getResources().getDisplayMetrics();
        screenWidth = dm.widthPixels;
        int paddingLeft = getPaddingLeft();
        int paddingRight = getPaddingRight();
        screenWidth = screenWidth - paddingLeft - paddingRight;
        // 把指定单位转换成像素。
        tabPadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, tabPadding, dm);
        tabTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, tabTextSize, dm);
        tabSelTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, tabSelTextSize, dm);

        // get system attrs (android:textSize and android:textColor)
//        TypedArray a = context.obtainStyledAttributes(attrs, ATTRS);
//
//        tabTextSize = a.getDimensionPixelSize(0, tabTextSize);
//        tabTextColor = a.getColor(1, tabTextColor);
//
//        a.recycle();

        matchParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT);
        weightParmas = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT, 1.0f);

    }


    public void setStrList(List<String> list) {
        strList = list;

        if (list == null || list.size() <= 0) {
            throw new IllegalStateException("There is no data in the title list ");
        }

        notifyDataSetChanged();

    }

    public void setItemClickListener(onItemClickListener listener) {
        this.listener = listener;
    }

    public void notifyDataSetChanged() {
        container.removeAllViews();
        count = strList.size();
        childViewWidth = 0;

        for (int i = 0; i < count; i++) {
            addTextTab(i, strList.get(i));
        }

        updateViewStyle();
    }

    public void addTextTab(final int position, String title) {
        final HorizontalViewItem view = new HorizontalViewItem(context);
        view.setFocusable(true);
        view.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (childViewWidth > screenWidth) {
                    int width = view.getWidth();
                    int left = view.getLeft();  // textview 左边位置
                    int tvMargin = screenWidth / 2 - width / 2;    // TextView的目标位置

                    if (left < tvMargin) {
                        scrollTo(0, 0);
                    } else {
                        scrollTo(left - tvMargin, 0);
                    }
                }
                selPos = position;
                updateViewStyle();
                if (listener != null) {
                    listener.onClick(position);
                }
//                Log.i("lfq", "textView scroll x  " + getScrollX() + ",  getleft " + textView.getLeft() + " , getRight " + textView.getRight() + " , textView width " + textView.getWidth() + " , totalWidth : " + childViewWidth);
            }
        });
        view.setPadding(tabPadding, 0, tabPadding, 0);
        view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
//                Log.i("lfq", position + " inside width : " + textView.getWidth());
                childViewWidth += view.getWidth();
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                    getViewTreeObserver().removeGlobalOnLayoutListener(
                            this);
                } else {
                    getViewTreeObserver().removeOnGlobalLayoutListener(
                            this);
                }
            }
        });
        view.setText(title);
//        container.addView(view, position, weightParmas);
        container.addView(view);
    }


    public void updateViewStyle() {
        for (int i = 0; i < count; i++) {
            View v = container.getChildAt(i);
            if (v instanceof HorizontalViewItem) {
                HorizontalViewItem tab = (HorizontalViewItem) v;
                tab.setTextSize(TypedValue.COMPLEX_UNIT_PX, tabTextSize);
                tab.setTypeface(null, Typeface.BOLD);
                tab.setTextColor(getResources().getColor(R.color.white_b0));
                tab.setLineColor(getResources().getColor(R.color.c_ff7a7a));
                // setAllCaps() is only available from API 14, so the upper case is made manually if we are on a
                // pre-ICS-build
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                    tab.setAllCaps(true);
                } else {
                    tab.setText(tab.getText().toString());
                }
                if (selPos == i) {
                    tab.setTextColor(Color.WHITE);
                    tab.setLineColor(Color.WHITE);
                    tab.setTextSize(TypedValue.COMPLEX_UNIT_PX, tabSelTextSize);
                }
            }
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int myWidth = getMeasuredWidth();
        int childWidth = 0;
        for (int i = 0; i < count; i++) {
            childWidth += container.getChildAt(i).getMeasuredWidth();
        }

        if (childWidth > 0 && myWidth > 0) {
            LinearLayout.LayoutParams params;
            if (childWidth <= myWidth) {
                params = weightParmas;
            } else {
                params = matchParams;
            }
            for (int i = 0; i < count; i++) {
                container.getChildAt(i).setLayoutParams(params);
            }
        }

    }
}

HorizontalViewItem 是一个通过布局文件自定义的 View , 就是标题里面所需的一个文本,一条线。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:gravity="center"
              android:orientation="vertical">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tv_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:maxLines="1"
            android:textColor="#b0ffffff"
            android:textSize="14sp"/>

        <TextView
            android:id="@+id/tv_tip"
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:layout_marginTop="1dp"
            android:background="@android:color/white"/>
    </LinearLayout>

</LinearLayout>

代码也就这些,没什么技术含量,便于以后再次使用,所以在这里整理一份。

Demo下载

 
标签: 安卓开发
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • 安卓中通知功能的具体实现
    安卓中通知功能的具体实现
    通知[Notification]是Android中比较有特色的功能,当某个应用程序希望给用户发出一些提示信息,而该应用程序又不在前台运行时,就可以借助通知实现。使用通知的步骤1、需要一个NotificationManager来获得NotificationManager manager = (NotificationManager
    02-05 安卓开发
  • Android view系统分析-setContentView
    Android view系统分析-setContentView
    第一天上班,列了一下今年要学习的东西。主要就是深入学习Android相关的系统源代码,夯实基础。对于学习Android系统源代码,也没什么大概,就从我们平常使用最基础的东西学起,也就是从view这个切入点开始学习Android的源码,在没分析源码之前,我们有的时候
    02-05 安卓开发
  • 如何进行网络视频截图/获取视频的缩略图
    如何进行网络视频截图/获取视频的缩略图
    小编导读:获取视频的缩略图,截图正在播放的视频某一帧,是在音视频开发中,常遇到的问题。本文是主要用于点播中截图视频,同时还可以获取点播视频的缩略图进行显示,留下一个问题,如下图所示, 如果要获取直播中节目视频缩略图,该怎么做呢?(ps:直播是直
  • Android NDK 层发起 HTTP 请求的问题及解决
    Android NDK 层发起 HTTP 请求的问题及解决
    前言新的一年,大家新年快乐~~鸡年大吉!本次给大家带来何老师的最新文章~虽然何老师还在过节,但依然放心不下广大开发者,在此佳节还未结束之际,给大家带来最新的技术分享~ 事件的起因不说了,总之是需要实现一个 NDK 层的网络请求。为了多端适用,还是选择
  • Android插件化(六): OpenAtlasの改写aapt以防止资源ID冲突
    Android插件化(六): OpenAtlasの改写aapt以防
    引言Android应用程序的编译中,负责资源打包的是aapt,如果不对打包后的资源ID进行控制,就会导致插件中的资源ID冲突。所以,我们需要改写aapt的源码,以达到通过某种方式传递资源ID的Package ID,通过aapt打包时获取到这个Package ID并且应用才插件资源的命名
    02-05 安卓开发
  • Android架构(一)MVP架构在Android中的实践
    Android架构(一)MVP架构在Android中的实践
    为什么要重视程序的架构设计 对程序进行架构设计的原因,归根结底是为了 提高生产力 。通过设计是程序模块化,做到模块内部的 高聚合 和模块之间的 低耦合 (如依赖注入就是低耦合的集中体现)。 这样做的好处是使得程序开发过程中,开发人员主需要专注于一点,
    02-05 安卓开发
  • 安卓逆向系列教程 4.2 分析锁机软件
    安卓逆向系列教程 4.2 分析锁机软件
    安卓逆向系列教程 4.2 分析锁机软件 作者: 飞龙 这个教程中我们要分析一个锁机软件。像这种软件都比较简单,完全可以顺着入口看下去,但我这里还是用关键点来定位。首先这个软件的截图是这样,进入这个界面之后,除非退出模拟器,否则没办法回到桌面。上面那
    02-05 安卓开发
  • Android插件化(二):OpenAtlas插件安装过程分析
    Android插件化(二):OpenAtlas插件安装过程分析
    在前一篇博客 Android插件化(一):OpenAtlas架构以及实现原理概要 中,我们对应Android插件化存在的问题,实现原理,以及目前的实现方案进行了简单的叙述。从这篇开始,我们要深入到OpenAtlas的源码中进行插件安装过程的分析。 插件的安装分为3种:宿主启动时立
    02-05 安卓开发
  • [译] Android API 指南
    [译] Android API 指南
    众所周知,Android开发者有中文网站了,API 指南一眼看去最左侧的菜单都是中文,然而点进去内容还是很多是英文,并没有全部翻译,我这里整理了API 指南的目录,便于查看,如果之前还没有通读,现在可以好好看一遍。注意,如果标题带有英文,说明官方还没有翻
  • 使用FileProvider解决file:// URI引起的FileUriExposedException
    使用FileProvider解决file:// URI引起的FileUri
    问题以下是一段简单的代码,它调用系统的相机app来拍摄照片:void takePhoto(String cameraPhotoPath) {File cameraPhoto = new File(cameraPhotoPath);Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);takePhotoIntent.putExtra(Medi
    02-05 安卓开发
点击排行