UI 初步介绍

UI初步介绍

UI界面很重要。

1、如何编写界面

     Android Studio提供可视化编辑器,但不推荐使用,因为屏幕适配性差。

     推荐XML编码方式编写界面。

2、常用控件

     Android提供大量内置控件。

1TextView

    作用:在界面上显示一段文本信息

    代码:

          <TextView

             android:id=”@+id=text_view”

             android:layout_width=”match_parent”

             android:layout_height=”wrap_content”

             android:text=”This is TextView” />

          介绍主要属性:

                android:id给当前控件定义一个唯一标识符,可使用findViewById()来获得该控件实例

                android:layout_widthandroid:layout_height是所有控件必备属性,不然会报错。可选值有:match_parentwrap_contentfill_parentmatch_parentfill_parent相同,推荐match_parent

          不推荐给他们赋固定值,屏幕适配性差。

                 android:text制定显示的内容

                 TextView默认文字内容左上角对齐

                 android:gravity=”center”表示<TextView>里的子项(比如文字内容)对齐方式是居中

                 android:layout_gravity=”center”表示<TextView>在父布局中的对齐方式是居中

                 以上两种属性的可选值基本相同

                 所有gravity属性都可以用”|”来指定多值,”center_vertical|center_horizontal

                 android:textSize=”24sp”指定文字大小,单位是”sp”

                 android:textColor=”#00ff00”指定文字颜色   

     2Button

           <Button

           android:id=”@+id=button”

             android:layout_width=”match_parent”

             android:layout_height=”wrap_content”

             android:text=”Button”

android:textAllCaps=”false” />

             介绍主要属性:

               Android:textAllCaps=”false”,系统会对Button中的所有英文字母自动进行大小写转换,该属性禁用这一默认特性

           Button点击事件注册一个监听器:

               public class MainActivity extends AppCompatActivity {

                       @Override

                       protected void onCreate(Bundle savedInstanceState) {

                           ...

                           Button button = (Button) findViewById(R.id.button);

                           Button.setOnClickListener(new View.OnClickListener() {

                               @Override

                                public void onClick(View v) {

                                  //在此处添加逻辑

                                }

                            });

                        }

                  }

                  onClick()方法是实例化内部接口的同时,实例化匿名对象,基本上Android中监听方法都这么写

            另一种Button点击事件注册监听器方法:

                public class MainActivity extends AppCompatActivity implements View.OnclickListener {

                        //View.OnClickListener为静态内部类,所以继承它时构造方法不需要外部对象的引用,直接当普通类一样

                        @Override

                        protected void onCreate(Bundle savedInstanceState) {

                             ...

                             Button.setOnClickListener(this);

                         }

                         @Override

                         public void onClick(View v) {

                              switch(v.getId()) {

                                 case R.id.button:

                                        //在此处添加逻辑

                                        break;

                                  default:

                                        break;

                               }  

                            }

                          }

                          采用这种写法时,因为MainActivity中所有点击事件的具体逻辑都是通过调用onClick方法来完成的,所以要在onClick方法中对具体的触发View进行判断。而采用匿名实例化内部类的方式,则不需要这么做。 

     3EditText

           介绍主要属性:

               android:hint=”Type something here制定提示性文本,在输入任何内容后自动消失

               android:maxLines指定最大行数,超过文本自动向上滚动

           获取EditText内容的方法:

               获得该EditText的实例然后使用getText()方法,最后toString()转化为字符串

      

     4ImageView

           Android项目的图片资源一般都存放在”drawable”开头的目录下,具体根据分辨率有几个子目录比如:”drawable-xhdpi”            

             介绍主要属性:

                  Android:src=@drawable/img_1”指定一张图片

             ImageView类的一些方法:

                  imageView.setImageResource(R.drawable.img_2)ImageView控件指定图片资源

     5ProgerssBar

           进度条控件

           所有的Android控件都具有android:visibility属性,有三个可选值:visibleinvisiblegone。        visible表示控件可见、invisible表示控件不可见,但仍占据原来位置和大小,即控件透明化、gone表示控件不可见而且不占用任何屏幕控件。

            还可通过代码设置控件的可见性,使用setVisiblity()方法,传入View.VISIVLEView.INVISIBLEGONE三种值

            介绍主要属性:

                style=”?android:attr/progressBarStyleHorizontal”指定不同样式进度条

                android:max=”100”给进度条设置一个最大值

            设置及改变进度条进度方法:

                Int progress = progressBar.getProgress();

                Progress = progress + 10;

                progressBar.setProgress(progress);

     6AlertDialog

           AlertDialog可以在当前界面弹出一个对话,该对话框置顶于多有界面元素智商,能够屏蔽掉其他空间的交互能力,一般用于提示重要内容及警告信息。

           使用方法:

               public class MainActivity extends AppCompatActivity implements View.OnClickListener {

                  ...

                  @Override

                  public void onClick(View v) {

                    switch (v.getId()) {

                      case R.id.button:

                         AlertDialon.Builder dialog = new AlerDialog.Builder(MainActiviyy.this);

                         dialong.setTitle(“This is import”);

                         dialog.setCancelable(“false”);//设置为false,按返回键不能退出,默认为true

                         dialog.setPositiveButton(“OK”, new DialongInterface.OnClickListener() {

                               @Override

                               public void onClick(DialogInterface dialong,int which) {

                                       //具体逻辑或者什么都不写,点击完成后AlertDialog消失

                               }

                          });

                          dialog.setNegativeButton(“Cancel”, new DialogInterface.OnClickListener() {

                                @Override

                                public void onClick(DialogInterface dialong,int which) {

                                      //具体逻辑或者什么都不写,点击完成后AlertDialog消失

                                 }

                           });

                           dialog.show();

                           break;

                         default:

                            break;

                       }

                     }

                   }

                AlertDialog.Builder创建AlertDialog实例

     3ProgressDialog

           ProgressDialog很像但是多了一个进度条,一般用于表示当前操作比较耗时

           使用方法:

               public class MainActivity extends AppCompatActivity implements View.OnClickListener {

                     ...

                     @Override

                     public void onClick(View v) {

                        switch (v.getId()) {

                           case R.id.button:

                              ProgressDialog progressDialog = new ProgressDialog(MainActivity.this);//获得实例的方式与AlertDialog不一样

                              progressDialog.setTitle(“This is ProgressDialog”);

                              progressDialog.setMessage(“Loading...”);

                              progressDialog.setCancelable(true);//如果传入false,一定要在代码中做好控制,数据加载完之后一定要调用PrgoressDialogdissmiss()方法关闭对话框。不然数据加载完ProgressDialog会一直存在。

                              progressDialog.show();

                              break;

                          default:

                             break;

                        }

                    }

                 }

3、四种基本布局

     布局是一种放置很多控件的容器,它可以按照一定的规律调整内部控件的位置

     布局可以嵌套

     Android有四种基本布局

1、线性布局

     所包含控件在线性方向上依次排列

     android:orientation=”vertical”

     anroid:orientation=”horizontal”

     默认为horizontal

    orientation=”horizontal”时子项的layout_width就不能为match_parent,而且layout_gravity只有垂直方向上的对齐方式才有效,因为水平方向上长度不固定,每添加一个控件,水平方向上的长度都会改变,无法指定该方向上的对齐方式。

    orientation=”vertical”时子项的layout_heigth就不能为match_parent,而且layout_gravity只有水平方向上的对齐方式才有效

    介绍主要属性:

        android:layout_weight这个属性允许我们使用比例的方式来指定控件的大小,屏幕适配性非常好。代码如下:

        <LinearLayout ...

           ...>

           <EditText

              ...

              android:layout_width=”0dp”

              android:layout_height=”wrap_content”

              android:layout_weigth=”1”

              .../>

           <Button

              ...

              Android:layout_width=”0dp”

              Android:layout_heigth=”wrap_content”

              Android:layout_weight=”1”

              .../>

                </LinearLayout>

                当指定layout_weigth属性后layout_width属性无效,设置为0dp

                dpAndroid中用于指定控件大小、间距等属性的单位

                系统会把LinearLayout下所有的控件指定的layout_weigth值相加,得到一个总值,然后每个控件所占大小的比例就是用该控件的layout_weight值处以刚才算出的总值。Ps:这个比例是子项相对于母项

                当同级子项中一个为wrap_content或者其他未指定layout_weight时,剩下的子项分配剩下的空间。比如:EditTextlayout_weigth=”1”Buttonlayout_width=”wrap_content”时,Button占据固定空间后剩下的空间全部被EditText占据。这样做,屏幕适配性好。

     2、相对布局

           通过相对定位的方式让控件出现在布局的任意位置

           属性较多

           相对于父布局定位:

               <RelativeLayout

                   ...

                   android:layout_width=”match_parent”

                   android:layout_heigth=”match_parent”>

                   <Button

                      ...

                      android:layout_alignParentLeft=”true”

                      android:layout_alignParenTop=”true”

                      .../>

                   <Button

                      ...

                      android:layout_alignParentRigth=”true”

                      android:layout_alignParentTop=”true”

                      .../>

                   <Button

                      ...

                      android:layout_centerInParent=”true”

                      .../>

                   <Button

                      ...

                      android:layout_alignParentLeft=”true”

                      android:layout_alignParentBottom=”true”

                      .../>

                   <Button

                      ...

                      android:layout_alignParentRight=”true”

                      android:laoyout_alignParentBottom=”true”

                      .../>

             </RelativeLayout>

       相对控件定位:

           <RelativeLayout

               ...

               android:layout_width=”match_parent”

               android:layout_height=”match_parent”>

               <Button

                   ...

                   android:layout_centerInParent=”true”

                   .../>

               <Button

                    ...

                    android:layout_above=”@id/button3”//此时button3的位置一定要先确定!!!!

                    android:layout_toLeftOf=”@id/button3”

                    .../>

               <Button

                    ...

                    android:layout_above=”@id/button3”

                    android:layout_toRightOf=”@id/button3”

                    .../>

               <Button

                    ...

                    android:layout_below=”@id/button3”

                    android:layout_toLeftOf=”id/button3”

                    .../>

               <Button

                    android:layout_below=”@id/button3”

                    android:layout_toRightOf=”@id/button3”

                    .../>

          </RelativeLayout>

        当一个控件去引用另一个控件的id时,该控件一定要定义在引用控件后面!不然会出现找不到id的情况!Ps:如果不这样的话,前一个控件位置都不知道那么后一个位置怎么相对它定位呢?

        介绍属性:

            android:layout_alignLeft表示让一个控件的左边缘和另一个控件的左边缘对齐

            android:layout_alignRight

            android:layout_alignTop

            android:layout_alignBottom        

     3、帧布局

           该布局没有方便的定位方式,所有控件都默认摆放在布局的左上角

           后添加的控件会压在先添加的控件之上

           可以使用layout_gravity来指定控件在布局中的对齐方式(位置)

           该布局定位方式欠缺,应用场景较少

           Android:src=”@mipmap/ic_launcher”引用系统自带图片(安卓图标)

     4、百分比布局

           只有LinearLayout支持layout_weight,RelavtiveFrameLayout都不支持

           Android引入一种全新布局方式来解决此问题-百分比布局

           在百分比布局中不再使用wrap_contentmatch_parent来指定控件大小,而是允许直接指定控件在布局中所占的百分比

            百分比布局只为FrameLayoutRelativeLayout提供功能扩展,提供了PercentFrameLayout

        PercentRelativeLayout这两个全新的布局

            百分比布局不属于系统自带布局,属于新增布局。Android团队将PercentLayout定义在support库中,我们需要在项目(app目录下)的build.gradle中添加PercentLayout库的依赖

            添加依赖:

                dependencies {

                     complie fileTree(dir: ‘libs’, include: [‘*.jar’])

                     complie ‘com.android.support:appcompat-v7:26.0.0-a1pha1’

                     complie ‘com.android.support:percent:26.0.0-a1pha1’

                     testCompile ‘junit:junit:4.12’

                   }//注意percent的版本不能低于appcompat的版本!!!

            修改了build.gradle文件之后,系统会弹出提示,点击Sync Now同步gradle,把新添加的依赖添加到项目中

            布局代码:

               <android.support.percent.PercentFrameLayout

                     xmlns:app=”http://schemas.android.com/apk/res-auto”

                     ...

                     android:layout_width=”match_parent”

                     android:layout_height=”match_parent”>

                     <Button

                          ...

                          android:layout_gravity=”left|top”

                          app:layout_widthPercent=”50%”

                          app:layout_heigthPercent=”50%”/>

                    <Button

                          ...

                          android:layout_gravity=”right|top”

                          app:layout_widthPercent=”50%”

                          app:layout_heightPercent=50%”/>

                    <Button

                          ...

                          android:layout_gravity=”left|bottom”

                          app:layout_widthPercent=”50%”

                          anpp:layout_heightPercent=50%”/>

                    <Button

                          ...

                          android:layout_gravity=”right|bottom”

                          app:layout_widthPercent=”50%”

                          app:layout_heightPercent=50%”/>

              </android.support.percent.PercentFrameLayout>

            由于百分比布局不是内置在系统SDK当中的,所以需要把完整的包路径写出来。然后还必须定义一个app命名空间,这样才能使用百分比布局的自定义属性

            老版本Android Studio内置布局检查机制,认为每一个控件都要指定layout_widthlayout_height才合法。所以上面老版本IDE会报错但是能运行。

4、创建自定义控件

     控件和布局的继承结构:     

                

              所有控件都直接或间接继承自View

              所有布局都直接或间接继承自ViewGroup

              ViewAndroid中最基本的一种UI组件,它可以在屏幕上绘制一块矩形区域,并能相应这块区域的各种事件

              ViewGroup是一种特殊的View,它可以包含很多子View和子ViewGroup,是一个用于放置控件和布局的容器

     1、引入布局

           如果每个活动中都编写一遍同样的布局代码,导致代码大量重复,可以使用引入布局的方式来解决这个问题

           新建title.xml标题布局,代码略

           android:backgroud用于为布局或控件指定一个背景,可以使用颜色或者图片填充

           android:layout_margin指定控件在上下左右方向上偏移的距离

           android:layout_marginLeftandroid:layout_marginTop指定特定方向上偏移距离

           布局引入方法:

                   <LinearLayout

                        ....>

                        <include layout=”@layout/title”/>

                        ...

                     </LinearLayout>

只需要一行<include .../>就可以引入布局

          隐藏系统自带标题栏方法:

               public class MainActivity extends AppCompatActivty {

                     @Override

                     protected void onCreate(Bundle savedInsatnceState) {

                          ...

                          ActionBar actionBar = getSupportActionBar();

                          if(actionBar != null) {

                             actionBar.hide();

                          }

                     }

                }

     2、创建自定义控件

           引入布局的技巧解决了重复编写布局代码的问题,但是如果布局中有一些控件要求能够响应事件,我们还是需要在每个活动中编写相同的逻辑代码,此时最好使用自定义控件来解决代码重复问题

          自定义控件方法:

              新建TitleLayout继承自LinearLayout,让她成为我们自定义的标题栏控件,代码如下:

                  public class TitleLayout extends LinearLayout {//继承Layout是因为Layout的父类使ViewGroupViewGroup是各种控件的容器。

                       public TitleLayout(Context context, AttributeSet attrs) {

                             super(context, attrs);

                             LayoutInflater.from(context).inflate(R.layout.title, this);

                       }

                  }

              LayoutInflater.from(context)构建一个LayoutInflater对象,这里的context是指Activity

              Inflater(R.layout.title, this);动态加载布局,返回布局View实例。

              Inflater两个参数:第一个是资源文件id,第二个是父布局/父控件,这里加入thisTitleLayout父控件,用来容纳之前写好的子布局(标题栏)

              这个地方一定要好好理解,此处,新的控件是父布局,而我们之前写好的title.xml是子布局!所以,thisparent位置。

              Ps:关于LayoutInflater单独讲解。

         自定义控件创建完成

         自定义控件的使用:

             <LinearLayout xlmns:anroid=”http:schemas.android.com/apk/res/android”

                   android:layout_width=”match_parent”

                   android:layout_height=”match_parent”>

                   <com.example.seele.uicustomviews.TitleLayout//添加自定义控件要使用完整类名

                       android:layout_width=”match_parent”

                       android:layout_height=”wrap_content” />

               </LinearLayout>

          TitleLayout类中为标题栏中的按钮注册点击事件,以后每当我们在一个布局中引入TitleLayout时,按钮的点击事件就已经自动实现了,省略大量重复代码。

5、ListView

   1ListView简单用法(最简单的用法)

        Activity_main.xml:

          引入ListView控件

        MainActivity.java:

          Public class Activity extends AppCompatActivity {

              private String[] data = {“apple”,...};

              @Override

              protected void onCreate(Bundle savedInstanceState) {

                  ...

                  ArrayAdapter<String> adapter = new ArrayAdapter<String>(

                        MainActivity.this, android.R.layout.simple_list_item_1, data);

                  ListView listView = (ListView) findViewById(R.id.list_view);

                  listView.setAdapter(adapter);

              }

          }

        通过适配器传递数据给ListView

        Android内置多种适配器,其中ArrayAdapter较方便,支持泛型指定适配数据类型。且有多个构造函数重载。

        这里ArrayAdapter构造函数参数一次传入contextListView子项布局id,适配数据。

        Android.R.layout.simple_list_item_1是内置布局文件。里面只有一个TextView。  

     2、定制ListView界面

           定制实体类Fruit

           自定义ListView子项布局fruit_item.xml

           自定义适配器、覆写getView方法。

           只需要修改fruit_item.xml中内容,就可以定制各种复杂界面。

           自定义适配器:

               public class FruitAdapter extends ArrayAdapter<Fruit> {

                  private int resourceId;

                  public FruitAdapter(Context context, int textViewResourceId, List<Fruit> objects) {

                       super(context, textViewResouceId, objects);

                       resourceId = textViewResourceId;

                  }

                  @Override

                  pubic View getView(int position, View convertView, ViewGroup paretn) {

                      Fruit fruit = getItem(postiont);//getItem方法获得当前项的Fruit实例

                 ①   View view = LayoutInflater.from(getContext).inflate(resourceId, parent, false);

                      ImageView fruitImage = (ImageView) findViewById(R.id.fruit_image);

                      TextView fruitName = (TextView) findViewById(R.id.fruit_name);

                      fruitImage.setImageResource(fruit.getImageId());

                      fruitName.setText(fruit.getName());

                      return view;

                  }

               }

          MainActivit.java中的使用方法与普通ListView相同

     3、提升ListView运行效率!!!

           未经优化的ListView效率很低,主要原因在于布局反复加载,以及反复使用findViewById获得控件实例!

           优化布局反复加载:

               getView中有一个convertView参数,用这个参数对之前加载好的布局进行缓存。

               将上面①行代码更换为如下代码:

                         View view;

                         if(convertView ==  null) {

                                view = LayouInflater.from(getContext()).inflate(resourceId, parent, false);

                         } else {

                                view = convertView;

                         }//当子布局被第一次加载之后convertView就会获得这个View实例,下次就不必再次加载。这个view实例最终会被一个方法add(view)加入进去。

          优化控件实例反复获取:

                虽然不必重复加载布局了,但仍然要反复去获取布局中的控件实例。

                借助ViewHolder来对这部分优化。

                 代码如下:

                      public class FruitAdapter extends ArrayAdapter<Fruit> {

                  private int resourceId;

                  public FruitAdapter(Context context, int textViewResourceId, List<Fruit> objects) {

                       super(context, textViewResouceId, objects);

                       resourceId = textViewResourceId;

                  }

                  @Override

                  pubic View getView(int position, View convertView, ViewGroup paretn) {

                      Fruit fruit = getItem(postiont);//getItem方法获得当前项的Fruit实例

                      View view;

                      ViewHolder viewHolder;

                      if (convertView == null) {

                             view = LayoutInflater.from(getContext()).inflate(resourceId, parent, false);

                             viewHolder = new ViewHolder();

                             viewHolder.fruitImage = (ImageView) view.findViewById(R.id.fruit_image);

                             viewHolder.fruitName = (TextView) view.findViewById(R.id.fruit_name);

                             view.setTag(viewHolder);

                      } else {

                           view = convertView;

                           viewHodler = (ViewHolder) view.getTag();

                      }

                      viewHodler.fruitImage.setImageResource(fruit.getImageId());

                      viewHolder.fruitName.setText(fruit.getName());

                      return view;

                  }

                  class ViewHolder {

                       ImageView fruitImage;

                       TextView fruitName;

               }

              通过内部类ViewHolder对控件实例进行缓存。

              经过以上优化后,效力已经非常不错了。

     4ListView点击事件

          ListView的点击事件只能到达ListView的子项,再深入时较麻烦。

          只为每一个子项注册监听器。当点击ListView每一个子项时,就会回调点击方法。

          代码:

              listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

                 @Override

                 public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

                      Fruit fruit = fruitList.get(position);

                      Toast...show();

                 }

             });//这里只关心一个参数:position

6RecyclerView

1RecyclerView基本用法

     RecyclerView属于新增控件,定义在support库中,需在build.gradle中添加相应依赖库:

         dependencies {

              ...

             compile ‘com.android.support:recyclerview-v7:26.0.0-a1pha1’//版本号不能低于//appcompat版本号,后缀里面第一个是字母l第二个是数字1l

             ...

        }

   添加完之后要点击Sync Now来进行同步。

   activity_main.xml中添加RecyclerView控件。因为是新增控件所以需要完整类名。

   使用与ListView相同的Fruit类以及fruit_item.xml布局

   RecyclerView准备适配器://必须覆写下面三个方法!!!

       public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {

            private List<Fruit> mFruitList;

            static class ViewHolder extends RecyclerView.ViewHolder {

                 ImageView fruitImage;

                 TextView fruitName;

                 public ViewHolder(View view) {

                    super(view);

                     fruitImage = (ImageView) view.findViewById(R.id.fruit_image);

                     fruitName = (TextView) view.findViewById(R.id.fruit_name);

                 }

            }

            public FruitAdapter(List<Fruit> fruitList) {

                  mFruitList = fruitList;

            }

            @Override

             public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

                  View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item, parent, false);

                  ViewHolder holder = new ViewHolder(view);

                  return holder;

             }

            @Override

            public void onBindViewHolder(ViewHolder holder,int position) {

                   Fruit fruit = mFruitList.get(posotion);

                   holder.fruitImage.setImageResource(fruit.getImageId());

                   holder.fruitName.setText(fruit.getName());

            }

            @Override

             public int getItemCount() {

                   return mFruitList.size();

             }

       }

     适配器准备好之后,在MainActivity中使用RecyclerView:

          Public class MainActivity extends AppCompatActivity {

              Private List<Fruit> fruitList = new ArrayList<>();

              @Override

              Protected void onCreate(Bundle savedInstanceState) {

                 Super.onCreate(savedInstanceStae);

                 setContentView(R.layout.activity_main);

                 iniFruits();

                 RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);

                 LinearLayoutManager layoutManager = new LinearLayouManager(this);

                 recyclerView.setLayouManager(layoutManager);//指定RecyclerView的布局方式

                 FruitAdapter adapter = new FruitAdapter(fruitList);

                 recyclerView.setAdapter(adapter);

               }

               Private void iniFruits() {

                  //fruitList添加一些数据

                }

           }

     2、实现横向滚动和瀑布流布局

       横向滚动:

           横向滚动只需要修改LayoutManager

           layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);

           这样LayoutManager的默认纵向排列被改为横行排列

       瀑布流:

           LayouManagerStaggerGridLayoutManager layoutManager = new StaggerGridManager(3, StaggeredGridLayoutManager.VERTICAL);就可实现瀑布流。第一个参数是列数,第二个参数是排列方向。

     3RecyclerView的点击事件

           RecyclerView没有提供类似setOnItemClickListener()这样的注册监听器方法,而是需要给子项具体的View去注册监听事件。

           注册代码如下:

             ViewHolder中实例化fruitView

             

             onCreateViewHolder方法中:

                  final ViewHolder holder = new ViewHolder(View);

                  holder.fruitView.setOnClickListener(new View.OnClickListener() {

                      ....

                  });//fruitView注册监听事件

                  holder.fruitImage.setOnClickListener(new View.OnclickListener() {

                      ...

                 });//fruitImage注册监听事件

             上面分别为最外层布局和ImageView都注册了点击事件,RecyclerView的强大之处也是在这里。当我们点击TextView控件时,最外层布局点击事件就会被触发。

7、编写聊天界面

1、制作Nine-Patch图片

    首先要确保已经为JDK配置了环境变量。

    Android sdk目录下toolsdraw9patch.bat文件,使用它来知足Nine-Patch图片。

    双击draw9patch.bat文件打开,导航栏File-Open 9-patch.png格式图片加载进来。拖动边线,设置图片边缘黑线。上边框和左边框表示要拉伸区域,下边框和右边框表示部分表示内容放置区域。

     导航栏File-Save 9-patch保存图片.9.png

     2、使用到的方法

           msgRecyclerView = (RecyclerView) findViewById(...);

           adapter = new MsgAdapter(...);

           adapter.notifyItemInseted(msgList.size() - 1);//通知适配器有新数据插入。刷新adapter

           msgRecycler.scrollToPosition(msgList.size() - 1);//RecyclerView定位到最后一行

           

 

           

           

           

   

   

 

     

 

            

                  

  

 

     

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值