Android自定义ViewGroup,内容过长时可设置"..."截断

一、效果

二、实现

1.自定义View

public class FeatureGroupView extends ViewGroup{
    //itemSpaceVertical为列与列之间的间距
    private int itemSpaceVertical, itemSpaceHorizontal, maxLineNum;
    private int paddingTop, paddingBottom, paddingLeft, paddingRight;
    private int moreTextColor, moreTextSize;
    private TextView moreTextView;

    public FeatureGroupView(Context context) {
        super(context);
    }

    public FeatureGroupView(Context context, AttributeSet attrs) {
        super(context, attrs);

        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.FixedWidthViewGroup);//自定义样式,名字为FixedWidthViewGroup

        itemSpaceVertical = (int) typedArray.getDimension(R.styleable.FixedWidthViewGroup_itemSpaceVertical, 0);
        itemSpaceHorizontal = (int) typedArray.getDimension(R.styleable.FixedWidthViewGroup_itemSpaceHorizontal, 0);
        maxLineNum =  typedArray.getInt(R.styleable.FixedWidthViewGroup_maxLineNum, Integer.MAX_VALUE);
        moreTextColor = typedArray.getColor(R.styleable.FixedWidthViewGroup_moreTextColor, -1);
        moreTextSize = typedArray.getInt(R.styleable.FixedWidthViewGroup_moreTextSize, -1);
        paddingTop = getPaddingTop();
        paddingBottom = getPaddingBottom();
        paddingLeft = getPaddingLeft();
        paddingRight = getPaddingRight();

        typedArray.recycle();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
        final int count = getChildCount();
        int parentWidth = MeasureSpec.getSize(widthMeasureSpec) - paddingRight;
        if(maxLineNum != Integer.MAX_VALUE){
            moreTextView = createMore();
            moreTextView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
            parentWidth = parentWidth - (itemSpaceVertical + moreTextView.getMeasuredWidth());

        }

        int lengthY = paddingTop;
        int lengthX = paddingLeft;
        int lineNum = 0;
        for(int i = 0; i < count; i++){
            final View child = getChildAt(i);
            if(child.getVisibility() == GONE){
                continue;
            }
            child.measure(MeasureSpec.UNSPECIFIED,MeasureSpec.UNSPECIFIED);
            int width = child.getMeasuredWidth();
            int height = child.getMeasuredHeight();

            if(lengthY <= paddingTop){
                lengthY += height;
            }
            if(i == 0){
                lengthX += width;
            }else{
                lengthX += width + itemSpaceVertical;
            }
            if(lengthX > parentWidth){
                lineNum++;
                if(lineNum >= maxLineNum){
                    //如果超过规定的最大行数 标记上一行最后一个为结束项
                    if(i - 1 >= 0){
                        LayoutData layoutData = (LayoutData) getChildAt(i - 1).getTag();
                        if (layoutData != null) {
                            layoutData.isEnd = true;
                        }
                    }
                    break;
                }

                lengthX = paddingLeft + width;
                lengthY = lengthY + height + itemSpaceHorizontal;
            }
            child.setTag(new LayoutData(lengthX, lengthY));
        }
        setMeasuredDimension(widthMeasureSpec, MeasureSpec.makeMeasureSpec( lengthY + paddingBottom, MeasureSpec.UNSPECIFIED));
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        for (int i = 0; i < getChildCount(); i++) {
            final View child = this.getChildAt(i);
            if (child.getVisibility() == GONE) {
                continue;
            }
            if(child.getTag() == null){
                break;
            }
            LayoutData layoutData = (LayoutData) child.getTag();
            if (layoutData != null) {
                int left = layoutData.x - child.getMeasuredWidth();
                int top = layoutData.y  - child.getMeasuredHeight();
                child.layout(left, top, layoutData.x,layoutData.y);
                if(layoutData.isEnd && moreTextView!= null){
                    addView(moreTextView);
                    moreTextView.layout(child.getRight() + itemSpaceVertical , child.getBottom() - moreTextView.getMeasuredHeight() ,
                            child.getRight()+ itemSpaceVertical + moreTextView.getMeasuredWidth(), child.getBottom());
                }
            }
        }
    }
   //简单起见,这里用了TextView,并设置内容为"..."
    private TextView createMore(){
        TextView more = new TextView(getContext());
        more.setText("...");
        more.setGravity(Gravity.CENTER);
        if(moreTextColor != -1){
            more.setTextColor(moreTextColor);
        }
        if(moreTextSize != -1){
            more.setTextSize(moreTextSize);
        }
        return more;
    }

    private class LayoutData{
        int x;
        int y;
        boolean isEnd;

        public LayoutData(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }
}

2.自定义R.styleable.FixedWidthViewGroup样式

res/values/attrs.xml文件的<resources>标签下增加内容:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    ...
    ...
    <declare-styleable name="FixedWidthViewGroup">
        <attr name="itemSpaceVertical" format="dimension" />
        <attr name="itemSpaceHorizontal" format="dimension" />
        <attr name="maxLineNum" format="integer" />
        <attr name="moreTextColor" format="color" />
        <attr name="moreTextSize" format="integer" />
    </declare-styleable>
</resources>

3.每个item的布局,

item_feature.xml:

<?xml version="1.0" encoding="utf-8"?>
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginRight="3dp"
    android:gravity="center"
    android:paddingBottom="1dp"
    android:paddingLeft="3dp"
    android:paddingRight="3dp"
    android:paddingTop="1dp"
    android:singleLine="true"
    android:textColor="#80b2bf"
    android:textSize="11sp"
    android:background="@drawable/feature_item_bg"/>

4.res/drawable/feature_item_bg.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item>
        <shape android:shape="rectangle">
            <stroke android:width="1dp" android:color="#80b2bf" />
            <solid android:color="@android:color/transparent" />
            <corners android:radius="2dp" />
        </shape>
    </item>

</selector>

5.Activity的布局文件

activity_freture_group.xml:

<ScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:background="#FFEEDD">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:showDividers="middle"
        android:dividerPadding="20dp">

        <view.FeatureGroupView
            android:id="@+id/features1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:padding="10dp"
            android:orientation="horizontal"
            android:background="#d0d0d0"

            app:itemSpaceVertical="10dp"
            app:maxLineNum="1"
            app:moreTextColor="#80b2bf"
            app:moreTextSize="12"
            />
        <view.FeatureGroupView
            android:id="@+id/features2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:background="#d0d0d0"
            android:orientation="horizontal"

            app:itemSpaceVertical="4dp"
            app:itemSpaceHorizontal="4dp"
            app:maxLineNum="2"
            app:moreTextColor="#80b2bf"
            app:moreTextSize="12"
            />
        <view.FeatureGroupView
            android:id="@+id/features3"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:orientation="horizontal"
            android:paddingLeft="10dp"
            android:background="#d0d0d0"

            app:itemSpaceVertical="4dp"
            app:moreTextColor="#80b2bf"
            app:moreTextSize="12"
            />

        <view.FeatureGroupView
            android:id="@+id/features4"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:orientation="horizontal"
            android:background="#d0d0d0"
            android:padding="10dp"

            app:itemSpaceVertical="4dp"
            app:itemSpaceHorizontal="2dp"
            app:maxLineNum="2"
            app:moreTextColor="#80b2bf"
            app:moreTextSize="12"
            />
    </LinearLayout>
</ScrollView>

说明:

xmlns:app="http://schemas.android.com/apk/res-auto" , 加上这一句便可以使用<declare-styleable>中自定义的样式,app为命名空间,可以写成其他名字。
app:itemSpaceVertical="10dp" 
, 使用自定义样式中的属性,"app"为"xmlns:app=..."中的"app"

6.Activity代码

public class FeatureGroupActivity extends Activity {

    private FeatureGroupView featureGroupView1;
    private FeatureGroupView featureGroupView2;
    private FeatureGroupView featureGroupView3;
    private FeatureGroupView featureGroupView4;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_freture_group);
        featureGroupView1 = (FeatureGroupView)findViewById(R.id.features1);
        featureGroupView2 = (FeatureGroupView)findViewById(R.id.features2);
        featureGroupView3 = (FeatureGroupView)findViewById(R.id.features3);
        featureGroupView4 = (FeatureGroupView)findViewById(R.id.features4);

        addFeatures(featureGroupView1);
        addFeatures(featureGroupView2);
        addFeatures(featureGroupView3);
        addFeatures(featureGroupView4);
    }

    private void addFeatures(ViewGroup viewGroup){
        for(String str: getFeatures()){
            TextView feature = (TextView) getLayoutInflater().inflate(R.layout.item_feature, null);
            feature.setText(str);
            viewGroup.addView(feature);
        }
    }

    private List<String> getFeatures(){
        List<String> list = new ArrayList<>();
        list.add("北京");
        list.add("上海");
        list.add("广东");
        list.add("四川");
        list.add("威海");
        list.add("大连");
        list.add("青岛");
        list.add("浙江");
        list.add("海口");
        list.add("西安");
        list.add("山东");
        list.add("济南");
        list.add("河北");
        list.add("石家庄");
        list.add("香港");
        list.add("西藏");
        list.add("新疆");
        list.add("重庆");
        list.add("秦皇岛");
        list.add("保定");
        list.add("太原");
        list.add("天津");
        list.add("黑龙江");
        list.add("哈尔滨");
        return list;
    }
}
时间: 2024-10-24 07:36:20

Android自定义ViewGroup,内容过长时可设置"..."截断的相关文章

Android 自定义ViewGroup之实现FlowLayout-标签流容器

本篇文章讲的是Android 自定义ViewGroup之实现标签流式布局-FlowLayout,开发中我们会经常需要实现类似于热门标签等自动换行的流式布局的功能,网上也有很多这样的FlowLayout,但不影响我对其的学习.和往常一样,主要还是想总结一下自定义ViewGroup的开发过程以及一些需要注意的地方. 按照惯例,我们先来看看效果图 一.写代码之前,有几个是问题是我们先要弄清楚的: 1.什么是ViewGroup:从名字上来看,它可以被翻译为控件组,言外之意是ViewGroup内部包含了许

Android 自定义ViewGroup手把手教你实现ArcMenu

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/37567907 逛eoe发现这样的UI效果,感觉很不错,后来知道github上有这么个开源项目~~~~当然本篇不是教你如何使用这个开源项目,而是教你如何自己通过自定义ViewGroup写这样的效果,自定义ViewGroup也是我的痛楚,嘿嘿,希望以此可以抛砖引玉~~ 效果图: 1.实现思路 通过效果图,会有几个问题: a.动画效果如何实现 可以看出动画是从顶点外外发射的,可能有人

Android 自定义ViewGroup 实战篇 -&gt; 实现FlowLayout

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38352503 ,本文出自[张鸿洋的博客] 1.概述 上一篇已经基本给大家介绍了如何自定义ViewGroup,如果你还不了解,请查看:Android 手把手教您自定ViewGroup ,本篇将使用上篇介绍的方法,给大家带来一个实例:实现FlowLayout,何为FlowLayout,如果对Java的Swing比较熟悉的话一定不会陌生,就是控件根据ViewGroup的宽,自动的往右

android自定义viewgroup实现等分格子布局

先上效果图: 实现这样的效果: 一般的思路就是,直接写布局文件,用LinearLayout 嵌套多层子LinearLayout,然后根据权重layout_weight可以达到上面的效果 还有就是利用gridview了,但是这里的需求就是不能上下滑动,使用gridview的时候还要计算布局的高度,否则内容超出下滑: 开始我是用的第一种,直接在布局文件实现了,但是后来发现代码太多太恶心哦,所以我继承viewGroup,重写两个关键的方法:onLayout(),onMeasure() 我的大致思路:

Android自定义ViewGroup (选择照片或者拍照)

教你搞定Android自定义ViewGroup http://www.jianshu.com/p/138b98095778 字数1794 阅读7030 评论8 喜欢37 上一篇我们介绍了Android中自定义View的知识,并实现了一个类似Google彩虹进度条的自定义View,今天我们将进一步学习如何去自定义一个ViewGroup. ViewGroup 我们知道ViewGroup就是View的容器类,我们经常用的LinearLayout,RelativeLayout等都是ViewGroup的子

Android中TextView内容过长加省略号

      textview中有个内容过长加省略号的属性,即ellipsize,用法如下: 在xml中 Android:ellipsize = "end"   省略号在结尾 android:ellipsize = "start" 省略号在开头 android:ellipsize = "middle"     省略号在中间 android:ellipsize = "marquee"  跑马灯 最好加一个约束android:sin

【Android自定义ViewGroup】不一样的轮子,巧用类变量解决冲突,像IOS那样简单的使用侧滑删除,一个控件搞定Android item侧滑删除菜单。

================================================================================== [1 序言] 侧滑删除的轮子网上有很多,最初在github上看过一个,还是ListView时代,那是一个自定义ListView 实现侧滑删除的,当初就觉得这种做法不是最佳,万一我项目里又同时有自定义ListView的需求,会增加复杂度. 写这篇文章之前又通过毒度搜了一下,排名前几的CSDN文章,都是通过自定义ListVIew和Vie

[Android] 自定义ViewGroup最佳入门实践

对自定义view还不是很了解的码友可以先看自定义View入门这篇文章,本文主要对自定义ViewGroup的过程的梳理,废话不多说. 1.View 绘制流程 ViewGroup也是继承于View,下面看看绘制过程中依次会调用哪些函数. 说明: measure()和onMeasure() 在View.Java源码中: public final void measure(int widthMeasureSpec,int heightMeasureSpec){ ... onMeasure ... } p

Android 自定义ViewGroup,实现侧方位滑动菜单

侧方位滑动菜单 1.现在adnroid流行的应用当中很多都是用的侧方位滑动菜单如图: 将菜单显示在左边,内容页面显示在右边,通过滑动或则按钮点击来隐藏和显示菜单. 2.首先对ViewGroup进行个了解: View是ViewGroup的父类,ViewGroup具有View的所有特性,ViewGroup主要用用来充当View的容器,将其中的View作为自己孩子, 并对其进行管理,当然孩子也是可以是ViewGroup类型. View类一般用于绘图操作,重写他的onDraw方法,但它不可以包含其他组件