您的位置:68399皇家赌场 > 集群主机 > Android 轻易实现View自动换行(附源码卡塔尔

Android 轻易实现View自动换行(附源码卡塔尔

发布时间:2020-03-18 06:37编辑:集群主机浏览(165)

    皇家赌场 1Bamboy自动换行

    接纳 Anko 来创设分界面会更为简明、火速。

    5、重写onLayout方法

    上代码截图

    2、Activity的XML构造借使内部放相当多条文的话,可能要套在ScrollView里,以免显示不全

    参考

    1、https://github.com/Kotlin/anko/wiki/Anko-Layouts

    感觉文章能够选用,可以关心一下Wechat公众号【纸上浅谈】

    皇家赌场 2

    Wechat

    此间写图片描述

    在这里个布局文件中,大家第一定义了一个RelativeLayout作为背景构造,然后在这里个布局里定义了三个Button和三个TextView,Button就是标题栏中的重回按键,TextView正是标题栏中的彰显的文字。

    private Button btn_add;private BamAutoLineList bal_list;@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn_add =  findViewById(R.id.btn_add); bal_list = (BamAutoLineList) findViewById(R.id.bal_list); // 点击事件 btn_add.setOnClickListener(new View.OnClickListener() { @Override public void onClick { // 实例化View View item = getLayoutInflater().inflate(R.layout.item, null); // 把View放到控件里去 bal_list.addView; } });}
    

    累计依赖

    Anko 的 Github 仓库是:https://github.com/Kotlin/anko

    在 Github 货仓的 README 上有关什么增加重视已经写的很详细了,把要抬高的选拔性复制粘贴就好了。

    Anko 包罗多少个部分剧情:

    • Anko Commons
      • 轻量级的局地声援类,例如 intent,dialog,logging 等等,其实正是对安卓一些类:Activity、Fragment、Intent 等丰盛扩充函数。
    • Anko Layouts
      • 动态结构用的最首要的库,将广大 Android 的控件 View 调换来了 Anko 加载的方式。
      • 鉴于 Android 还恐怕有此外的控件库,因而 Anko 也对这几个库举行了开展援助,能够筛选足够对应的依赖库。
      • 本来,还能依据要求对自定义 View 举行改换,让它们也扶植 Anko 加载的花样。
    • Anko SQLite
      • 用来 Android SQLite 数据库的询问的库
    • Anko Coroutines
      • 基于 kotlinx.coroutines 协程的一个工具库。

    最后一点了啊,大家在AndroidManifest.xml中必要加上

    效果图

    皇家赌场,就如于Tmall寻觅时的推荐,首先自个儿不清楚天猫的是不是只协理文字,可是自个儿的是别的View都帮助的。看下效果先:

    行使 AnkoComponent 接口成立分界面

    除去直接在 Activity 里面写布局,还足以应用 AnkoComponent 接口创制构造,那样就可以将界面代码和 Activity 的代码抽离了。

    class MyActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
            super.onCreate(savedInstanceState, persistentState)
            MyActivityUI().setContentView(this)
        }
    }
    
    class MyActivityUI : AnkoComponent<MyActivity> {
        override fun createView(ui: AnkoContext<MyActivity>) = with(ui) {
            verticalLayout {
                val name = editText()
                button("Say Hello") {
                    onClick { ctx.toast("Hello, ${name.text}!") }
                }
            }
        }
    }
    

    急需创设我们的分界面类,实现 AnkoComponent 接口,在 createView方法中回到我们的分界面。

    最后在 setContentView 方法中实际上调用的也是 createView 方法,再次来到分界面布局,然后再由地点提到的,Anko 会自动把结构填充到 Activity 中。

    此处运用到了 Kotlin with 的语法糖,使用 with,则赶回的是终极一行的内容,适逢其会 verticalLayout 正是最终一行的故事情节。

    也能够把它转变一下,使用 apply 的语法糖,最终回来的调用该措施的指标,再接着重临该目标的 view 就好了。

    class MyActivityUI : AnkoComponent<MyActivity> {
        override fun createView(ui: AnkoContext<AnkoActivity>) = ui.apply {
            verticalLayout {
                val name = editText()
                button("Say Hello") {
                    onClick { ctx.toast("Hello, ${name.text}!") }
                }
            }
        }.view
    }
    

    皇家赌场 3

    举个例证来讲,标题栏就是个很广泛的重新组合控件,很多分界面包车型地铁底部都会停放贰个标题栏,标题栏上会有个重返开关和标题,点击开关后就足以回到到上二个分界面。那么下边大家就来品尝去落到实处那样叁个标题栏控件。

    假设以为尘少的德姆o还不易的话,能够仿造笔者的Git货仓,种种炫彩效果收入囊中:

    创制轻易构造

    利用 Anko 创制构造很简短:

    class AnkoActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            relativeLayout {
                button("button in center") {
                    textSize = sp(18).toFloat()
                    onClick {
                       longToast("you click button")
                    }
                }.lparams {
                    centerInParent()
                }
            }
        }
    }
    

    成效如下:

    皇家赌场 4

    Anko 创制轻松分界面

    relativeLayout 代码块里大家构建了这两天的分界面,并把它使用到了 Activity 中。

    在那间,并从未行使深谙的 setContentView 方法,那是因为 Anko 会自动将构造分界面 View 设置到 Activity 中。

    relativeLayout代码块就是 Anko 的关键行使办法。

    relativeLayout 作为三个容器,在此中增加了一个 buttonbutton 控件的率先个大括号里设置了它的某本个性和事件,在 lparams 大括号里设置了它在相对于容器的片段参数。

    正是那样轻松的写法达成了界面布局,就像是写 xml 文件一律,只要在父容器里面依照相排版列写好子控件的参数和岗位就好。

    多实施两遍就能够熟谙这种写法,通过 Anko 来成立贰个登入分界面:

        verticalLayout {
                padding = dip(8)
                val account = textView("account") {
                    id = R.id.account_text
                    textSize = sp(12).toFloat()
                    // 设置自己的属性
                }.lparams() {
                    // 设置布局的参数
                }
                var name = editText() // 也可以什么都不设置,使用默认的设置
                textView("password") {
                    id = R.id.password_text
                    onClick {
                        account.setText("change account")
                    }
                }
                var pwd = editText {
                    hint = "input"
                }.lparams(
                        width = dip(100), 
                        height = ViewGroup.LayoutParams.WRAP_CONTENT
                )
                button("login") {
                    onClick {
                        if (name.text.toString().equals("name") 
                            && pwd.text.toString().equals("pwd")) {
                            longToast("login....")
                        } else {
                            longToast("login failed")
                        }
                    }
                }
            }
    

    功用如下:

    皇家赌场 5

    anko_login_ui

     public FlowLayout(Context context) {
            this(context, null);
        }
    
        public FlowLayout(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    

    一、自绘控件

    4、Activity代码

    Fragment 中加载分界面

    在 Fragment 中增多分界面稍有分裂。

    创建 Activity,将 Fragment 增加上来。

    class AnkoFragmentActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            linearLayout {
                id = R.id.fragment_id
                supportFragmentManager.beginTransaction().replace(id, AnkoFragment.newInstance()).commit()
            }
        }
    }
    
    class AnkoFragment : Fragment() {
    
        override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    //        return inflater.inflate(R.layout.fragment_anko, container, false)
            return UI {
                verticalLayout {
                    editText()
                    button("OK")
                }
            }.view
        }
    
        companion object {
            fun newInstance(): AnkoFragment {
                return AnkoFragment()
            }
        }
    }
    

    在 Fragment 的 onCreateView 方法中不在使用 inflater 来加载构造,而是直接运用 UI 函数来落成,再次回到最后的 View 就能够。在那之中 UI 也是对 Fragment 的三个拓宽函数。

    9、selector_btn_item.xml

    2、简单的运动

    条目的XML最外层的Layout,宽高只能是wrap_content,即使你设置成match_parent,或者指定多少dp,都是无效的。连设置margin也都是无效。如果你确实需要限制宽高,那你可以多套一层Layout,在内层Layout设置即可。
    

    Anko 配合 RecyclerView 的使用

    接纳 Anko 来创设三个下拉刷新的 RecyclerView 布局。

    写法还是轻便:

           swipeRefreshLayout {
                setColorSchemeColors(Color.RED, Color.BLUE, Color.GREEN)
                onRefresh {
                    mainHandler.postDelayed(Runnable {
                        isRefreshing = false
                    }, 3000)
                }
                recyclerView {
                    layoutManager = LinearLayoutManager(SampleApp.mContext)
                    setHasFixedSize(true)
                    adapter = Adapter(dataList)
                }
            }
    

    一直在 recyclerView 构造里面安装好相应的 LayoutManager 和 Adapter 就好了。

    并且还能够够在 swipeRefreshLayout 里面管理刷新的事件,在三秒后改进刷新状态,从而甘休刷新就好了。

    源码参照他事他说加以考察 Github 地址:https://github.com/glumes/AndroidKotlinSample

    <?xml version="1.0" encoding="UTF-8"?>
    <resources>
    
        <string-array name="tags">
            <item>美妆</item>
            <item>画板</item>
            <item>漫画</item>
            <item>高科技</item>
            <item>韩国电影</item>
            <item>股票</item>
            <item>美术</item>
            <item>高富帅</item>
            <item>鸿泰安</item>
            <item>运动</item>
            <item>外语</item>
            <item>财经</item>
            <item>大叔</item>
            <item>非主流</item>
            <item>暴走漫画</item>
            <item>心理学</item>
            <item>汉语</item>
            <item>白富美</item>
            <item>自定义</item>
        </string-array>
    
    </resources>
    

    皇家赌场 6

    皇家赌场 7Bamboy自动换行——Tmall

    不足

    Anko 好是好,不过照旧缺乏康健。

    在 XML 中能够设置的控件属性越多,更典型的主宰布局景况,而 Anko 在营造轻巧分界面包车型大巴时候才呈现急速、便捷。

    与此同期 Anko 帮衬的控件有限,加载自定义的控件还得加多额外的代码,在更复杂的行使中应有不太会遍布的选择。

    不容争辩要引进xmlns:custom=”http://schemas.android.com/apk/res-auto”,Android Studio中大家得以行使res-atuo命名空间,就无须在累积自定义View全类名。

    皇家赌场 8

    hi,尘少又来了,这一次为大家带来的,是View可以自行换行的器皿。

    终究今后的结构都是要从 XML 中分析出来,然后再到 LayoutInfalter 里面通过 Constructor.newInstance 反射创设出来的。而 Anko 则是一贯开立 View,用代码创设布局,省去了剖析 XML 的日子。

    五、上边便是有些逻辑代码啦
    1、作者把FlowLayout里面完整的代码贴出来:

    皇家赌场 9

    <ScrollView android:layout_width="match_parent" android:layout_height="match_parent"> <com.bamboy.autowordwrap.BamAutoLineList android: android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="10dp" /></ScrollView>
    

    自定义 View 的加载

    除了这几个之外 Anko 自带以致扶植的控件之外,还能让自定义的 View 也支撑 Anko 的加载形式,在 Anko 的代码块中去改造自定义 View 的设置属性。

    比方,自定义 View ,绘制三个矩形:

    public class RectangleView extends View {
        public int size ;
        public Paint mPaint;
        public RectangleView(Context context) {
            super(context);
            mPaint = new Paint();
            mPaint.setColor(Color.RED);
            mPaint.setAntiAlias(true);
            mPaint.setStrokeWidth(2);
            mPaint.setStyle(Paint.Style.STROKE);
        }
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            setBackgroundColor(Color.BLUE);
            canvas.drawCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2, size, mPaint);
        }
    }
    

    个中,size 变量正是要改成的属性,它决定着圆的半径。

    让自定义 View 匡助 Anko 的加载情势,还必要加上如下的展开函数:

    inline fun ViewManager.rectangleView(init: RectangleView.() -> Unit): RectangleView {
        return ankoView({ RectangleView(it) }, theme = 0, init = init)
    }
    

    由该举办函数来回到大家的 Rectangle View ,至于那其间是什么样落到实处的,临时不做探索,下篇文章再来探究。

    末段就能够像使用任何控件相符来加多到结构中了。

        //加载自定义的 View
            relativeLayout {
                var view = rectangleView {
                    id = R.id.custom_view_id
                    size = 300  // 自定义 View 的属性设置
                }.lparams {
                    width = ViewGroup.LayoutParams.MATCH_PARENT
                    height = dip(200)
                    centerInParent()
                }
    
                button("change size") {
                    onClick {
                        view.size = Random().nextInt(200)   100
                        view.invalidate()
                    }
                }.lparams {
                    below(view)
                    centerHorizontally()
                }
            }
    

    意义如下:

    皇家赌场 10

    anko_custom_view

    点击按键来改革圆的半径大小。

    package com.per.flowlayoutdome;
    
    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.text.TextUtils;
    import android.view.View;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import java.util.ArrayList;
    import java.util.List;
    
    
    public class MainActivity extends Activity {
        private TextView tv_remind;
    
        private FlowLayout tcy_my_label, tcy_hot_label;
        private FlowLayoutAdapter mMyLabelAdapter, mHotLabelAdapter;
        private List<String> MyLabelLists, HotLabelLists;
    
        private static int TAG_REQUESTCODE = 0x101;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            initView();
            initData();
        }
    
        private void initView() {
            tv_remind = (TextView) findViewById(R.id.tv_remind);
            tcy_my_label = (FlowLayout) findViewById(R.id.tcy_my_label);
            tcy_hot_label = (FlowLayout) findViewById(R.id.tcy_hot_label);
        }
    
        private void initData() {
            String[] date = getResources().getStringArray(R.array.tags);
            HotLabelLists = new ArrayList<>();
            for (int i = 0; i < date.length; i  ) {
                HotLabelLists.add(date[i]);
            }
            mHotLabelAdapter = new FlowLayoutAdapter(this, HotLabelLists);
            tcy_hot_label.setAdapter(mHotLabelAdapter);
            tcy_hot_label.setItemClickListener(new TagCloudLayoutItemOnClick(1));
    
            MyLabelLists = new ArrayList<>();
            mMyLabelAdapter = new FlowLayoutAdapter(this, MyLabelLists);
            tcy_my_label.setAdapter(mMyLabelAdapter);
            tcy_my_label.setItemClickListener(new TagCloudLayoutItemOnClick(0));
    
            String labels = String.valueOf(getIntent().getStringExtra("labels"));
            if (!TextUtils.isEmpty(labels) && labels.length() > 0
                    && !labels.equals("null")) {
                String[] temp = labels.split(",");
                for (int i = 0; i < temp.length; i  ) {
                    MyLabelLists.add(temp[i]);
                }
                ChangeMyLabels();
            }
    
        }
    
        /**
         * 刷新我的标签数据
         */
        private void ChangeMyLabels() {
            tv_remind.setVisibility(MyLabelLists.size() > 0 ? View.GONE
                    : View.VISIBLE);
            tcy_my_label.setVisibility(MyLabelLists.size() > 0 ? View.VISIBLE
                    : View.GONE);
            mMyLabelAdapter.notifyDataSetChanged();
        }
    
        /**
         * 标签的点击事件
         *
         * @author lijuan
         */
        class TagCloudLayoutItemOnClick implements FlowLayout.TagItemClickListener {
            int index;
    
            public TagCloudLayoutItemOnClick(int index) {
                this.index = index;
            }
    
            @Override
            public void itemClick(int position) {
                switch (index) {
                    case 0:
                        MyLabelLists.remove(MyLabelLists.get(position));
                        ChangeMyLabels();
                        break;
                    case 1:
                        if (MyLabelLists.size() < 5) {
                            if (HotLabelLists.get(position).equals("自定义")) {
                                startActivityForResult(
                                        new Intent(MainActivity.this,
                                                AddTagActivity.class),
                                        TAG_REQUESTCODE);
                            } else {
                                Boolean isExits = isExist(MyLabelLists,
                                        HotLabelLists.get(position));
                                if (isExits) {
                                    Toast.makeText(MainActivity.this, "此标签已经添加啦", Toast.LENGTH_LONG).show();
                                    return;
                                }
                                MyLabelLists.add(HotLabelLists.get(position));
                                ChangeMyLabels();
                            }
                        } else {
                            Toast.makeText(MainActivity.this, "最多只能添加5个标签", Toast.LENGTH_LONG).show();
                        }
                        break;
                    default:
                        break;
                }
            }
        }
    
        /**
         * 将数组里面的字符串遍历一遍,看是否存在相同标签
         *
         * @param str
         * @param compareStr
         * @return
         */
        public static Boolean isExist(List<String> str, String compareStr) {
            Boolean isExist = false;//默认沒有相同标签
            for (int i = 0; i < str.size(); i  ) {
                if (compareStr.equals(str.get(i))) {
                    isExist = true;
                }
            }
            return isExist;
        }
    
        /**
         * 回传数据
         */
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            if (TAG_REQUESTCODE == requestCode) {
                if (resultCode == AddTagActivity.TAG_RESULTCODE) {
                    String label = data.getStringExtra("tags");
                    MyLabelLists.add(label);
                    ChangeMyLabels();
                }
            }
        }
    }
    

    皇家赌场 11

    <?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:andro android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/btn_padding" android:gravity="center_horizontal" android:orientation="vertical" android:padding="10dp"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/icon" /> <TextView android: android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="条目条目条目" android:textSize="14sp" /></LinearLayout>
    

    上学 Kotlin 应该都或多或少听过 Anko 那几个开源库。

    好了,已经全部写完了,有啥样疑难的,请在底下留言,有不足的还望辅导,感谢各位_

    用线程更改画文字的坐标来贯彻活动

    到此就终止了,尘少平昔的品格,正是那般轻巧。

    咱俩重写了3个布局方法,在上头的构造方法中说过私下认可的构造文件调用的是七个参数的布局方法,所以记得让具有的布局方法调用四个参数的构造方法,然后在三个参数的布局方法中得到自定义属性。

                       4,能够在代码中调用也得以在构造文件中运用

    皇家赌场 12自定义控件

    8、activity_add_tag.xml

    皇家赌场 13

    废话相当的少少,上代码:1、先把自家的自定义控件放到你的花色里

    一开端叁个参数的布局方法和八个参数的构造方法是这么的:

    皇家赌场 14

    本文由68399皇家赌场发布于集群主机,转载请注明出处:Android 轻易实现View自动换行(附源码卡塔尔

    关键词: 68399皇家赌场 简单 源码 换行 纸上浅谈

上一篇:英特尔liJ IDEA导入Android源码

下一篇:没有了