스트리밍 레이아웃 구현

간단하게 흐르는 레이아웃을 실현하고 효과 그림은 다음과 같다1,value 아래의attr 파일
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="FlowView">

        <attr name="pLeft" format="dimension"/>
        <attr name="pRight" format="dimension"/>
        <attr name="pTop" format="dimension"/>
        <attr name="pBottom" format="dimension"/>
        <attr name="hDiver" format="dimension"/>
        <attr name="lDiver" format="dimension"/>
        <attr name="itemLayout" format="reference"/>
        <attr name="addLayout" format="reference"/>

    </declare-styleable>

</resources>

2, 사용할 세 개의 레이아웃 파일 1) 일반 item 옵션의 레이아웃 파일
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/background_item">

    <TextView  android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dip" android:textColor="#FFFFFF" android:text="TextView" />

</RelativeLayout>

2) add 항목의 레이아웃 파일
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/background_add">

    <TextView  android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dip" android:textColor="#FFFFFF" android:text="TextView" />

</RelativeLayout>

3)main 레이아웃 파일
<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res/com.example.flowingdemo"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.example.flowingdemo.view.FlowView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:pLeft="20dip"
        app:pRight="20dip"
        app:pTop="20dip"
        app:pBottom="20dip"
        app:hDiver="20dip"
        app:lDiver="20dip"
        app:itemLayout="@layout/flow_item_layout"
        app:addLayout="@layout/flow_add_layout"
        android:id="@+id/flowview" />

</RelativeLayout>

3, 자동 FlowView, View Group 상속, OnClick 인터페이스 구현
package com.example.flowingdemo.view;

import java.util.ArrayList;
import java.util.List;

import com.example.flowingdemo.R;

import android.content.Context;
import android.content.res.TypedArray;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.RelativeLayout;
import android.widget.TextView;

/* *     match_parent */
public class FlowView extends ViewGroup implements OnClickListener {

    // item
    private int itemLayout = 0;
    // add
    private int addLayout = 0;

    //           
    private int totalWidth = 0, totalHeight = 0;

    //     
    private int hangJiJian = 20;
    //     
    private int lieJianJu = 20;
    //           
    private int leftJianJu = 20, rightJianJu = 20, topJianJu = 20,
            bottomJianJu = 20;

    //       Add  
    private boolean isTianJiaAdd = false;
    //      
    private List<String> list = new ArrayList<String>();

    public FlowView(Context context, AttributeSet attrs, int defStyleAttr,
            int defStyleRes) {
        this(context, attrs);
    }

    public FlowView(Context context, AttributeSet attrs, int defStyleAttr) {
        this(context, attrs);
    }

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

        final TypedArray typedArray = context.obtainStyledAttributes(attrs,
                R.styleable.FlowView);

        itemLayout = typedArray.getResourceId(R.styleable.FlowView_itemLayout,
                R.layout.flow_item_layout);
        addLayout = typedArray.getResourceId(R.styleable.FlowView_addLayout,
                R.layout.flow_add_layout);
        leftJianJu = (int) typedArray.getDimension(R.styleable.FlowView_pLeft,
                (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                        leftJianJu, getResources().getDisplayMetrics()));
        rightJianJu = (int) typedArray.getDimension(
                R.styleable.FlowView_pRight, (int) TypedValue.applyDimension(
                        TypedValue.COMPLEX_UNIT_DIP, rightJianJu,
                        getResources().getDisplayMetrics()));
        topJianJu = (int) typedArray.getDimension(R.styleable.FlowView_pTop,
                (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                        topJianJu, getResources().getDisplayMetrics()));
        bottomJianJu = (int) typedArray.getDimension(
                R.styleable.FlowView_pBottom, (int) TypedValue.applyDimension(
                        TypedValue.COMPLEX_UNIT_DIP, bottomJianJu,
                        getResources().getDisplayMetrics()));
        hangJiJian = (int) typedArray.getDimension(R.styleable.FlowView_hDiver,
                (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                        hangJiJian, getResources().getDisplayMetrics()));
        lieJianJu = (int) typedArray.getDimension(R.styleable.FlowView_lDiver,
                (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                        lieJianJu, getResources().getDisplayMetrics()));

        typedArray.recycle();
    }

    public FlowView(Context context) {
        this(context, null);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        // int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        // int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        totalWidth = widthSize;
        totalHeight = heightSize;

        measureChildren(widthMeasureSpec, heightMeasureSpec);

        setMeasuredDimension(widthSize, heightSize);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int count = getChildCount();

        // x    
        int xp = leftJianJu, yp = topJianJu;

        for (int i = 0; i < count; i++) {
            View childView = getChildAt(i);
            int cw = childView.getMeasuredWidth();
            int ch = childView.getMeasuredHeight();

            int xl = 0, xt = 0, xr = 0, xb = 0;
            if (xp + cw + hangJiJian + rightJianJu >= totalWidth) {
                //       
                yp += ch + lieJianJu;
                xp = leftJianJu;
            }

            if (count - 1 == i && isTianJiaAdd) {
                //      ,  add     add  
                xl = totalWidth - rightJianJu - cw;
                xt = yp;
                xr = xl + cw;
                xb = xt + ch;
            } else {
                //      
                xl = xp;
                xt = yp;
                xr = xl + cw;
                xb = xt + ch;
            }

            xp += cw + hangJiJian;
            childView.layout(xl, xt, xr, xb);
        }
    }

    //        
    public void addView(String message, int type) {
        int layout = 0;
        if (type == 1) {
            //    item
            layout = itemLayout;
        } else if (type == 2) {
            // add           
            if (isTianJiaAdd) {
                return;
            }
            //     
            isTianJiaAdd = true;
            layout = addLayout;
        }
        RelativeLayout relativeLayout = (RelativeLayout) View.inflate(
                getContext(), layout, null);
        TextView textView = (TextView) relativeLayout
                .findViewById(R.id.textView1);
        textView.setLines(1);
        textView.setEllipsize(TextUtils.TruncateAt.END);
        textView.setMaxLines(1);
        textView.setText(message);
        relativeLayout.setOnClickListener(this);

        if (type == 1) {
            relativeLayout.setTag(list.size());
            relativeLayout.setId(123);
        } else {
            relativeLayout.setTag(123);
            relativeLayout.setId(123);
        }

        if (isTianJiaAdd && type == 1) {
            addView(relativeLayout, list.size() - 1);
            list.add(list.size() - 1, message);
        } else {
            addView(relativeLayout);
            list.add(message);
        }

        requestLayout();
    }

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        switch (v.getId()) {
        case 123:
            int position = (Integer) v.getTag();
            if (position == 123) {
                if (onClickFlowView != null) {
                    onClickFlowView.onClickAdd();
                }
            } else {
                if (onClickFlowView != null) {
                    onClickFlowView.onClickItem(position, list.get(position));
                }
            }
            break;

        default:
            break;
        }
    }

    public interface OnClickFlowView {

        public void onClickAdd();

        public void onClickItem(int position, String message);
    }

    private OnClickFlowView onClickFlowView;

    // ----------
    public void setOnClickFlowView(OnClickFlowView onClickFlowView) {
        this.onClickFlowView = onClickFlowView;
    }

    public void setPLeft(int PLeft) {
        this.leftJianJu = PLeft;
        this.requestLayout();
    }

    public void setPRight(int PRight) {
        this.leftJianJu = PRight;
        this.requestLayout();
    }

    public void setPTop(int PTop) {
        this.leftJianJu = PTop;
        this.requestLayout();
    }

    public void setPBottom(int PBottom) {
        this.leftJianJu = PBottom;
        this.requestLayout();
    }

    public void setHDiver(int hDiver) {
        this.leftJianJu = hDiver;
        this.requestLayout();
    }

    public void setLDiver(int lDiver) {
        this.leftJianJu = lDiver;
        this.requestLayout();
    }
}

4, MainActivity의 실현
package com.example.flowingdemo;

import com.example.flowingdemo.view.FlowView;
import com.example.flowingdemo.view.FlowView.OnClickFlowView;

import android.app.Activity;
import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickFlowView {

    private FlowView flowview;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        super.setContentView(R.layout.activity_main);

        flowview = (FlowView) findViewById(R.id.flowview);
        flowview.setOnClickFlowView(this);
        for (int i = 0; i < 10; i++) {
            String s = "";
            for (int j = 0; j < i; j++) {
                s += String.valueOf(j);
            }
            flowview.addView("i->" + s + i, 1);
        }
        //  add  
        flowview.addView("add", 2);
    }

    @Override
    public void onClickAdd() {
        flowview.addView("moren", 1);
    }

    @Override
    public void onClickItem(int position, String message) {
        Toast.makeText(this, "position=" + position + "-------->" + message,
                Toast.LENGTH_SHORT).show();
    }

}

소스 코드 다운로드 주소

좋은 웹페이지 즐겨찾기