自定義控件 - 流式布局(FlowLayout)

效果圖

流式布局.gif
流式布局.gif

item 布局文件kingoit_flow_layout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_vertical"
    android:paddingBottom="@dimen/margin5"
    android:paddingEnd="@dimen/margin5"
    android:paddingRight="@dimen/margin10"
    tools:ignore="RtlSymmetry">

    <TextView
        android:id="@+id/value"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ellipsize="end"
        android:gravity="center"
        android:lines="1"
        android:paddingBottom="2dp"
        android:paddingTop="2dp"
        android:textColor="#000000"
        android:textSize="16sp"/>

    <ImageView
        android:id="@+id/delete"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/value"
        android:layout_alignEnd="@id/value"
        android:layout_alignRight="@id/value"
        android:layout_alignTop="@+id/value"
        android:layout_marginEnd="-2dp"
        android:layout_marginRight="-2dp"
        android:src="@drawable/cancel"
        android:tint="@color/colorDialogContent"
        android:visibility="gone"/>

</RelativeLayout>

設(shè)置屬性 res\values\attrs.xml

    <!--KingoitFlowLayout 恶耽,流式布局屬性設(shè)置-->
    <declare-styleable name="KingoitFlowLayout">
        <attr name="flowLayoutRadius" format="dimension"/>
        <attr name="flowLayoutTextColor" format="color"/>
        <attr name="flowLayoutTextColorSelector" format="color"/>
        <attr name="flowLayoutTextSize" format="dimension"/>
        <attr name="flowLayoutLineColor" format="color"/>
        <attr name="flowLayoutLineWidth" format="dimension"/>
        <attr name="flowLayoutBackgroundColor" format="color"/>
        <attr name="flowLayoutBackgroundColorSelector" format="color"/>
        <attr name="flowLayoutDeleteBtnColor" format="color"/>
    </declare-styleable>

控件實現(xiàn) KingoitFlowLayout

/**
 * kingoit,流式布局
 * 20180815-修復(fù)不可滑動問題
 * @author zuo
 * @date 2018/7/16 11:48
 */
public class KingoitFlowLayout extends ViewGroup {
    //記錄每個View的位置
    private List<ChildPos> mChildPos = new ArrayList<ChildPos>();
    private float textSize;
    private int textColor;
    private int textColorSelector;
    private float shapeRadius;
    private int shapeLineColor;
    private int shapeBackgroundColor;
    private int shapeBackgroundColorSelector;
    private float shapeLineWidth;
    private int deleteBtnColor;
    /**
     * 是否是可刪除模式
     */
    private boolean isDeleteMode;
    /**
     * 記錄所有選中著的詞
     */
    private List<String> mAllSelectedWords = new ArrayList<>();

    private class ChildPos {
        int left, top, right, bottom;

        public ChildPos(int left, int top, int right, int bottom) {
            this.left = left;
            this.top = top;
            this.right = right;
            this.bottom = bottom;
        }
    }

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

    public KingoitFlowLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
        initAttributes(context, attrs);
    }

    /**
     * 最終調(diào)用這個構(gòu)造方法
     *
     * @param context  上下文
     * @param attrs    xml屬性集合
     * @param defStyle Theme中定義的style
     */
    public KingoitFlowLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    /**
     * 流式布局屬性設(shè)置
     *
     * @param context
     * @param attrs
     */
    @SuppressLint("ResourceAsColor")
    private void initAttributes(Context context, AttributeSet attrs) {
        @SuppressLint("Recycle")
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.KingoitFlowLayout);
        textSize = typedArray.getDimension(R.styleable.KingoitFlowLayout_flowLayoutTextSize, 16);
        textColor = typedArray.getColor(R.styleable.KingoitFlowLayout_flowLayoutTextColor, Color.parseColor("#FF4081"));
        textColorSelector = typedArray.getResourceId(R.styleable.KingoitFlowLayout_flowLayoutTextColorSelector, 0);
        shapeRadius = typedArray.getDimension(R.styleable.KingoitFlowLayout_flowLayoutRadius, 40f);
        shapeLineColor = typedArray.getColor(R.styleable.KingoitFlowLayout_flowLayoutLineColor, Color.parseColor("#ADADAD"));
        shapeBackgroundColor = typedArray.getColor(R.styleable.KingoitFlowLayout_flowLayoutBackgroundColor, Color.parseColor("#c5cae9"));
        shapeBackgroundColorSelector = typedArray.getResourceId(R.styleable.KingoitFlowLayout_flowLayoutBackgroundColorSelector, 0);
        shapeLineWidth = typedArray.getDimension(R.styleable.KingoitFlowLayout_flowLayoutLineWidth, 4f);
        deleteBtnColor = typedArray.getColor(R.styleable.KingoitFlowLayout_flowLayoutDeleteBtnColor, Color.GRAY);
    }

    /**
     * 測量寬度和高度
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //獲取流式布局的寬度和模式
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        //獲取流式布局的高度和模式
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        //使用wrap_content的流式布局的最終寬度和高度
        int width = 0, height = 0;
        //記錄每一行的寬度和高度
        int lineWidth = 0, lineHeight = 0;
        //得到內(nèi)部元素的個數(shù)
        int count = getChildCount();
        mChildPos.clear();
        for (int i = 0; i < count; i++) {
            //獲取對應(yīng)索引的view
            View child = getChildAt(i);
            //測量子view的寬和高
            measureChild(child, widthMeasureSpec, heightMeasureSpec);
            MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
            //子view占據(jù)的寬度
            int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
            //子view占據(jù)的高度
            int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
            //換行
            if (lineWidth + childWidth > widthSize - getPaddingLeft() - getPaddingRight()) {
                //取最大的行寬為流式布局寬度
                width = Math.max(width, lineWidth);
                //疊加行高得到流式布局高度
                height += lineHeight;
                //重置行寬度為第一個View的寬度
                lineWidth = childWidth;
                //重置行高度為第一個View的高度
                lineHeight = childHeight;
                //記錄位置
                mChildPos.add(new ChildPos(
                        getPaddingLeft() + lp.leftMargin,
                        getPaddingTop() + height + lp.topMargin,
                        getPaddingLeft() + childWidth - lp.rightMargin,
                        getPaddingTop() + height + childHeight - lp.bottomMargin));
            } else {  //不換行
                //記錄位置
                mChildPos.add(new ChildPos(
                        getPaddingLeft() + lineWidth + lp.leftMargin,
                        getPaddingTop() + height + lp.topMargin,
                        getPaddingLeft() + lineWidth + childWidth - lp.rightMargin,
                        getPaddingTop() + height + childHeight - lp.bottomMargin));
                //疊加子View寬度得到新行寬度
                lineWidth += childWidth;
                //取當(dāng)前行子View最大高度作為行高度
                lineHeight = Math.max(lineHeight, childHeight);
            }
            //最后一個控件
            if (i == count - 1) {
                width = Math.max(lineWidth, width);
                height += lineHeight;
            }
        }
        // 得到最終的寬高
        // 寬度:如果是AT_MOST模式密任,則使用我們計算得到的寬度值,否則遵循測量值
        // 高度:只要布局中內(nèi)容的高度大于測量高度偷俭,就使用內(nèi)容高度(無視測量模式)浪讳;否則才使用測量高度
        int flowLayoutWidth = widthMode == MeasureSpec.AT_MOST ? width + getPaddingLeft() + getPaddingRight() : widthSize;
        int flowLayoutHeight = heightMode == MeasureSpec.AT_MOST ? height + getPaddingTop() + getPaddingBottom() : heightSize;
        //真實高度
        realHeight = height + getPaddingTop() + getPaddingBottom();
        //測量高度
        measuredHeight = heightSize;
        if (heightMode == MeasureSpec.EXACTLY) {
            realHeight = Math.max(measuredHeight, realHeight);
        }
        scrollable = realHeight > measuredHeight;
        // 設(shè)置最終的寬高
        setMeasuredDimension(flowLayoutWidth, flowLayoutHeight);
    }

    /**
     * 讓ViewGroup能夠支持margin屬性
     */
    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MarginLayoutParams(getContext(), attrs);
    }

    /**
     * 設(shè)置每個View的位置
     */
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int count = getChildCount();
        for (int i = 0; i < count; i++) {
            View child = getChildAt(i);
            ChildPos pos = mChildPos.get(i);
            //設(shè)置View的左邊、上邊涌萤、右邊底邊位置
            child.layout(pos.left, pos.top, pos.right, pos.bottom);
        }
    }

    public void addItemView(LayoutInflater inflater, String tvName) {
        //加載 ItemView并設(shè)置名稱淹遵,并設(shè)置名稱
        View view = inflater.inflate(R.layout.kingoit_flow_layout, this, false);
        ImageView delete = view.findViewById(R.id.delete);
        if (isDeleteMode) {
            delete.setVisibility(VISIBLE);
        } else {
            delete.setVisibility(GONE);
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            delete.setImageTintList(ColorStateList.valueOf(deleteBtnColor));
        }
        TextView textView = view.findViewById(R.id.value);
        textView.setTextSize(textSize / getContext().getResources().getDisplayMetrics().scaledDensity);
        if (textColorSelector != 0) {
            ColorStateList csl = getResources().getColorStateList(textColorSelector);
            textView.setTextColor(csl);
        } else {
            textView.setTextColor(textColor);
        }
        textView.setPadding(20, 4, 20, 4);
        textView.setText(tvName);
        //動態(tài)設(shè)置shape
        GradientDrawable drawable = new GradientDrawable();
        drawable.setCornerRadius(shapeRadius);
        drawable.setStroke((int) shapeLineWidth, shapeLineColor);
        if (shapeBackgroundColorSelector != 0) {
            ColorStateList csl = getResources().getColorStateList(shapeBackgroundColorSelector);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                drawable.setColor(csl);
            }
        } else {
            drawable.setColor(shapeBackgroundColor);
        }
        textView.setBackgroundDrawable(drawable);

        //把 ItemView加入流式布局
        this.addView(view);
    }


    public boolean isDeleteMode() {
        return isDeleteMode;
    }

    public void setDeleteMode(boolean deleteMode) {
        isDeleteMode = deleteMode;
    }

    //---20180815---修復(fù)不可滑動bug----start----
    private boolean scrollable; // 是否可以滾動
    private int measuredHeight; // 測量得到的高度
    private int realHeight; // 整個流式布局控件的實際高度
    private int scrolledHeight = 0; // 已經(jīng)滾動過的高度
    private int startY; // 本次滑動開始的Y坐標(biāo)位置
    private int offsetY; // 本次滑動的偏移量
    private boolean pointerDown; // 在ACTION_MOVE中,視第一次觸發(fā)為手指按下负溪,從第二次觸發(fā)開始計入正式滑動

    /**
     * 滾動事件的處理透揣,當(dāng)布局可以滾動(內(nèi)容高度大于測量高度)時,對手勢操作進行處理
     */
    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // 只有當(dāng)布局可以滾動的時候(內(nèi)容高度大于測量高度的時候)川抡,且處于攔截模式辐真,才會對手勢操作進行處理
        if (scrollable && isInterceptedTouch) {
            int currY = (int) event.getY();
            switch (event.getAction()) {
                // 因為ACTION_DOWN手勢可能是為了點擊布局中的某個子元素,因此在onInterceptTouchEvent()方法中沒有攔截這個手勢
                // 因此崖堤,在這個事件中不能獲取到startY侍咱,也因此才將startY的獲取移動到第一次滾動的時候進行
                case MotionEvent.ACTION_DOWN:
                    break;
                // 當(dāng)?shù)谝淮斡|發(fā)ACTION_MOVE事件時,視為手指按下密幔;以后的ACTION_MOVE事件才視為滾動事件
                case MotionEvent.ACTION_MOVE:
                    // 用pointerDown標(biāo)志位只是手指是否已經(jīng)按下
                    if (!pointerDown) {
                        startY = currY;
                        pointerDown = true;
                    } else {
                        offsetY = startY - currY; // 下滑大于0
                        // 布局中的內(nèi)容跟隨手指的滾動而滾動
                        // 用scrolledHeight記錄以前的滾動事件中滾動過的高度(因為不一定每一次滾動都是從布局的最頂端開始的)
                        this.scrollTo(0, scrolledHeight + offsetY);
                    }
                    break;
                // 手指抬起時楔脯,更新scrolledHeight的值;
                // 如果滾動過界(滾動到高于布局最頂端或低于布局最低端的時候)胯甩,設(shè)置滾動回到布局的邊界處
                case MotionEvent.ACTION_UP:
                    scrolledHeight += offsetY;
                    if (scrolledHeight + offsetY < 0) {
                        this.scrollTo(0, 0);
                        scrolledHeight = 0;
                    } else if (scrolledHeight + offsetY + measuredHeight > realHeight) {
                        this.scrollTo(0, realHeight - measuredHeight);
                        scrolledHeight = realHeight - measuredHeight;
                    }
                    // 手指抬起后別忘了重置這個標(biāo)志位
                    pointerDown = false;
                    break;
                default:
                    break;
            }
        }
        return super.onTouchEvent(event);
    }

    /**
     * 事件攔截昧廷,當(dāng)手指按下或抬起的時候不進行攔截(因為可能這個操作只是點擊了布局中的某個子元素)堪嫂;
     * 當(dāng)手指移動的時候,才將事件攔截麸粮;
     * 因增加最小滑動距離防止點擊時誤觸滑動
     */
    private boolean isInterceptedTouch;
    private int startYY = 0;
    private boolean pointerDownY;
    private int minDistance = 10;

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean intercepted = false;
        int currY = (int) ev.getY();
        int offsetY = 0;
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                pointerDownY = true;
                intercepted = false;
                break;
            case MotionEvent.ACTION_MOVE:
                if (pointerDownY) {
                    startYY = currY;
                } else {
                    offsetY = currY - startYY;
                }
                pointerDownY = false;
                intercepted = Math.abs(offsetY) > minDistance;
                break;
            case MotionEvent.ACTION_UP:
                // 手指抬起后別忘了重置這個標(biāo)志位
                intercepted = false;
                break;
            default:
                break;
        }
        isInterceptedTouch = intercepted;
        return intercepted;
    }

    //---20180815---修復(fù)不可滑動bug----end----

    /**
     * 流式布局顯示
     * Toast.makeText(FlowLayoutActivity.this, keywords, Toast.LENGTH_SHORT).show();
     *
     * @param list
     */
    public void showTag(final List<String> list, final ItemClickListener listener) {
        removeAllViews();
        for (int i = 0; i < list.size(); i++) {
            final String keywords = list.get(i);
            addItemView(LayoutInflater.from(getContext()), keywords);
            final int finalI = i;
            getChildAt(i).setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (isDeleteMode()) {
                        list.remove(keywords);
                        showTag(list, listener);
                    } else {
                        View child = getChildAt(finalI);
                        child.setSelected(!child.isSelected());
                        if (child.isSelected()) {
                            mAllSelectedWords.add(list.get(finalI));
                        } else {
                            mAllSelectedWords.remove(list.get(finalI));
                        }
                        listener.onClick(keywords, mAllSelectedWords);
                    }
                }
            });
        }
    }

    public interface ItemClickListener {
        /**
         * item 點擊事件
         *
         * @param currentSelectedkeywords
         * @param allSelectedKeywords
         */
        void onClick(String currentSelectedkeywords, List<String> allSelectedKeywords);
    }
}

控件使用

    <com.kingoit.list.flowLayout.KingoitFlowLayout
        android:id="@+id/kingoit_flow_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="12dp"
        app:flowLayoutBackgroundColor="@color/light_blue_700"
        app:flowLayoutBackgroundColorSelector="@drawable/selector_flowlayout_item_bg"
        app:flowLayoutDeleteBtnColor="@color/colorPrimary"
        app:flowLayoutLineColor="@color/transation"
        app:flowLayoutLineWidth="1dp"
        app:flowLayoutRadius="50dp"
        app:flowLayoutTextColor="@color/light_blue_50"
        app:flowLayoutTextColorSelector="@drawable/selector_flowlayout_item_text_color"
        app:flowLayoutTextSize="16sp"/>
  • java代碼
/**
 * 流式布局使用示例代碼
 * @author zuo
 * @date 2018/8/15 9:39
 */
public class FlowTestActivity extends Activity implements KingoitFlowLayout.ItemClickListener {
    private KingoitFlowLayout flowLayout;
    private KingoitHeadView headView;
    private List<String> list = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_flow_test);
        headView = findViewById(R.id.head_view);
        flowLayout = findViewById(R.id.kingoit_flow_layout);
        initData();
        initView();
    }

    private void initData() {
        for (int i = 0; i < 10; i++) {
            list.add("戰(zhàn)爭女神");
            list.add("蒙多");
            list.add("德瑪西亞皇子");
            list.add("殤之木乃伊");
            list.add("狂戰(zhàn)士");
            list.add("布里茨克拉克");
            list.add("冰晶鳳凰 艾尼維亞");
            list.add("德邦總管");
            list.add("野獸之靈 烏迪爾 (德魯伊)");
            list.add("賽恩");
            list.add("詭術(shù)妖姬");
            list.add("永恒夢魘");
        }
    }

    private void initView() {
        headView.getHeadRightImg().setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                flowLayout.setDeleteMode(!flowLayout.isDeleteMode());
                flowLayout.showTag(list, FlowTestActivity.this);
            }
        });
        flowLayout.showTag(list, FlowTestActivity.this);
    }


    @Override
    public void onClick(String currentSelectedkeywords, List<String> allSelectedKeywords) {
        Toast.makeText(FlowTestActivity.this, currentSelectedkeywords, Toast.LENGTH_SHORT).show();
    }
}
  • 樣式代碼
  • selector_flowlayout_item_bg
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/light_blue_50" android:state_pressed="true" />
    <item android:color="@color/colorWhite" android:state_selected="true" />
    <item android:color="@color/light_blue_700" />
</selector>
  • selector_flowlayout_item_text_color
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/light_blue_700" android:state_pressed="true" />
    <item android:color="@color/light_blue_700" android:state_selected="true" />
    <item android:color="@color/light_blue_50" />
</selector>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末溉苛,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子弄诲,更是在濱河造成了極大的恐慌愚战,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件齐遵,死亡現(xiàn)場離奇詭異寂玲,居然都是意外死亡,警方通過查閱死者的電腦和手機梗摇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門拓哟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人伶授,你說我怎么就攤上這事断序。” “怎么了糜烹?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵违诗,是天一觀的道長。 經(jīng)常有香客問我疮蹦,道長诸迟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任愕乎,我火速辦了婚禮阵苇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘感论。我一直安慰自己绅项,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布比肄。 她就那樣靜靜地躺著趁怔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪薪前。 梳的紋絲不亂的頭發(fā)上润努,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天,我揣著相機與錄音示括,去河邊找鬼铺浇。 笑死,一個胖子當(dāng)著我的面吹牛垛膝,可吹牛的內(nèi)容都是我干的鳍侣。 我是一名探鬼主播丁稀,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼倚聚!你這毒婦竟也來了线衫?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤惑折,失蹤者是張志新(化名)和其女友劉穎授账,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體惨驶,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡白热,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了粗卜。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片屋确。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖续扔,靈堂內(nèi)的尸體忽然破棺而出攻臀,到底是詐尸還是另有隱情,我是刑警寧澤纱昧,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布刨啸,位于F島的核電站,受9級特大地震影響砌些,放射性物質(zhì)發(fā)生泄漏呜投。R本人自食惡果不足惜加匈,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一存璃、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧雕拼,春花似錦纵东、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至辑甜,卻和暖如春衰絮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背磷醋。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工猫牡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人邓线。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓淌友,卻偏偏與公主長得像煌恢,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子震庭,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容

  • mean to add the formatted="false" attribute?.[ 46% 47325/...
    ProZoom閱讀 2,696評論 0 3
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,077評論 25 707
  • 生活需要感動瑰抵。 之前和我的一個好朋友說有的時候別人對我太好了我會有恐懼感 害怕自己所做的拖不起他們的期望 她安慰我...
    舟自橫歡閱讀 148評論 0 0
  • 學(xué)習(xí)演說的108條理由 1.突破自己 2.增加自信心 3.訓(xùn)練自己的能力 4.增加影響力 5.贈加人脈 6.倍增財...
    倩華老師逆向思維分享師閱讀 2,327評論 0 0
  • 人生需要更多地經(jīng)歷,也許我們并不知道自己每一步的行動器联,會給自己帶來怎樣的改變二汛,但是我們知道如果不去做,自己就會感到...
    好聽的暖陽閱讀 164評論 7 9