3、UI就是脸面,目标:开发一套符合自己审美观的科幻UI

3.2常见控件的使用

3.2.1TextView

3.2.2Button

    <Button
        android:id="@+id/button_on"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button"
        android:textAllCaps="false"/>

textAllCaps属性,系统会对Button中所有英文字母转换为大写,false会显示原来的字符

3.2.3EditText

    <EditText
        android:id="@+id/edittext_on"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="This is EditText"
        android:maxLines="3"/>

hint属性会给输入框一个提示性文本,当输入时就会消失

maxLines属性会限制显示最多行数 

        edittext_on = (EditText)findViewById(R.id.edittext_on);
        String edittext = edittext_on.getText().toString();

将EditText中输入内容取出转化为字符串

3.2.4ImageView

布局文件中:

    <ImageView
        android:id="@+id/imageview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_launcher"/>

 src引用图片

代码中:

设置为另一张图片

image.setImageResource(R.mipmap.ic_launcher_round);

3.2.5ProgressBar

用于界面上先是一个进度条,使用比较简单:

    <ProgressBar
        android:id="@+id/progress_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        style="@style/Base.Widget.AppCompat.ProgressBar.Horizontal"/>

 

3.2.6AlertDialog

AlertDialog是在当前界面弹出一个对话框,置顶于所有界面元素之上,一般用于警告会非常重要的内容:

AlertDialog.Builder dialog = new AlertDialog.Builder(NormalActivity.this);
                dialog.setTitle("关机");
                dialog.setMessage("您确定要关机吗?");
                dialog.setCancelable(false);
                dialog.setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Toast.makeText(NormalActivity.this,"本机将在3秒后关机",Toast.LENGTH_SHORT).show();
                    }
                });
                dialog.setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Toast.makeText(NormalActivity.this,"取消",Toast.LENGTH_SHORT).show();
                    }
                });
                dialog.show();
dialog.setCancelable(false);

setCancelable属性值为true时,点击AlertDialog以外区域时AlertDialog会被dismiss掉,setPositiveButton()是对话框设置确定按钮点击事件,setNegativeButton()是对话框设置取消按钮点击事件,show()是将对话框显示出来。

3.2.7ProgressDialog

与AlertDialog类似,弹出的是一个进度条,一般用于耗时操作;

                ProgressDialog progress =new ProgressDialog(NormalActivity.this);
                progress.setTitle("稍等");
                progress.setMessage("等待");
                progress.setCancelable(true);
                progress.show();

如果setCancelable传入false,表示不能被取消,一定要控制,当数据加载完毕后,调用其dismiss()关闭。

3.5.2ListView

定制的ListView的界面

首先定义一个实体类,作ListView的适配器的适配类型:

public class Fruit {
    private String name;
    private int imageid;

    public Fruit(String name , int imageid){
        this.name = name;
        this.imageid = imageid;
    }

    public String getName() {
        return name;
    }

    public int getImageid() {
        return imageid;
    }
}

然后指定ListView子项的自定义布局,在layout中新建fruit_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="wrap_content">
    <ImageView
        android:id="@+id/item_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_launcher"/>
    <TextView
        android:id="@+id/item_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        android:text="名字"
        android:layout_gravity="center_vertical"/>

</LinearLayout>

接下来创建自定义适配器,继承自ArrayAdapter,泛型指定为Furit类,新建FuritAdapter:

package co.example.hanwei.listviewtest;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;

/**
 * Created by hanwei on 2018/8/10 0010.
 */

public class FruitAdapter extends ArrayAdapter<Fruit>{

    private int resourceid;
    public FruitAdapter(Context context, int textviewResourceId, List<Fruit> Objects){/*重写的父类的一个构造函数*/
        super(context,textviewResourceId,Objects);/*三个参数分别代表:上下文,ListView子项布局的id,和数据*/
        resourceid = textviewResourceId;
    }

    @Override
    public View getView(int position,  View convertView,  ViewGroup parent) {/*重写gteView(),这个方法在没个子项被滚动到屏幕时候调用*/
        Fruit fruit = getItem(position);/*首先调用getItem()得到当前实例的Fruit实例*/
        View view = LayoutInflater.from(getContext()).inflate(resourceid,parent,false);/*用LyoutInFlater来为这个子项加载我们传入的布局*/
        ImageView fruit_image_id = (ImageView) view.findViewById(R.id.item_image);   /*其中三个参数:ListView子项布局的id,当前视图的父级视图,*/
        TextView fruit_name_id = (TextView) view.findViewById(R.id.item_name);       /*雕鹰view获取ImageView和TextView的实例*/
        fruit_image_id.setImageResource(fruit.getImageid());                          /*调用setImageResource和setText来设置显示的图片和文字*/
        fruit_name_id.setText(fruit.getName());                                       /*最后将布局返回*/
        return view;

    }
}

下面修改MainActivity中的代码:

package co.example.hanwei.listviewtest;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ListView;

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

public class MainActivity extends AppCompatActivity {
    private List<Fruit> furitlist = new ArrayList<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initFruit();/*初始化所有水果数据*/
        FruitAdapter adapter = new FruitAdapter(MainActivity.this,R.layout.fruit_item,furitlist);/*创建FruitAdapter适配器对象,传入上下文,自定义布局,要显示的数据*/
        ListView fruit_listview = (ListView)findViewById(R.id.fruit_listview);
        fruit_listview.setAdapter(adapter);/*将adapter作为适配器传递给ListView*/
    }
    public void initFruit(){
        for(int i = 0;i < 10 ;i ++){
            Fruit banana = new Fruit("Banana",R.mipmap.ic_launcher);/*在Fruit类的构造函数中将对应的水果名字和对应说过图片的id传入*/
            furitlist.add(banana);                                   /*将创建好的对象添加到水果列表中*/
            Fruit apple = new Fruit("apple",R.mipmap.ic_launcher);
            furitlist.add(apple);
            Fruit orange = new Fruit("orange",R.mipmap.ic_launcher);
            furitlist.add(orange);
            Fruit pear = new Fruit("pear",R.mipmap.ic_launcher);
            furitlist.add(pear);
            Fruit cherry = new Fruit("cherry",R.mipmap.ic_launcher);
            furitlist.add(cherry);
        }
    }
}

定制比较简单。

3.5.3提升ListView的运行效率

ListView运行效率很低,我们用一些方法来提高:getView()中有一个ConverView参数,用于将之前加载好的布局进行缓存,以后便可以复用。

每次还会调用View的findViewById()来获取一次控件的实例,借助ViewHolder进行优化。

package com.example.administrator.listviewtest;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;

/**
 * Created by Administrator on 2018/8/12.
 */

public class FruitAdapter extends ArrayAdapter<Fruit>{
    private  int resourceid;
    public FruitAdapter(Context context , int textviewResourceId , List<Fruit> Objects){
        super(context,textviewResourceId,Objects);
        resourceid = textviewResourceId;
    }


    @Override
    public View getView(int position,  View convertView, ViewGroup parent) {/*每次都将布局重新加载一遍*/
        Fruit fruit = getItem(position);/*convertView用于将之前加载好的布局进行缓存,可以进行重用*/
        View view;
        ViewHolder viewHolder;
        if(convertView == null){
            view = LayoutInflater.from(getContext()).inflate(resourceid,parent,false);
            viewHolder = new ViewHolder();
            viewHolder.fruit_iamge_id = (ImageView) view.findViewById(R.id.item_image);
            viewHolder.fruit_name_id = (TextView) view.findViewById(R.id.item_name);
            view.setTag(viewHolder);/*将viewHolder存储在view中*/
        }else{
            view = convertView;
            viewHolder = (ViewHolder) view.getTag();/*当ViewHolder不为空的时候调用getTeg()重新获取ViewHolder,这样,所有的控件实例都缓存在了ViewHolder中*/
        }
        viewHolder.fruit_iamge_id.setImageResource(fruit.getImageid());
        viewHolder.fruit_name_id.setText(fruit.getName());
        return view;
    }
    class ViewHolder{/*新增一个内部类用于对控件进行缓存,当convertView为空时候,创建一个ViewHolder对象,将控件实例存放在ViewHolder里*/
        ImageView fruit_iamge_id;/**/
        TextView fruit_name_id;
    }
}

3.5.4ListView的点击事件

        fruit_list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override/*四个参数分别代表:parent识别是哪个ListView,view当前listview的item的view的布局,用这个view,获取里面空间的id后操作控件,position当前item在listview中适配器里的位置,id是当前item在listview里的第几行的位置*/
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Fruit fruit = fruitList.get(position);/*通过position判断用户点击的是哪个子项*/
                Toast.makeText(MainActivity.this,fruit.getName(),Toast.LENGTH_LONG).show();
            }
        });

3.6RecyclerView滚动控件

使用RecyclerView需要在app/build.gradle中添加依赖库:

compile 'com.android.support:recyclerview-v7:25.3.1'
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.3.1'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    compile 'com.android.support:recyclerview-v7:25.3.1'
    testCompile 'junit:junit:4.12'
}

点击Sync Now进行同步

准备适配器:

package co.example.hanwei.listviewtest;

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;

/**
 * Created by hanwei on 2018/8/10 0010.
 */

public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder>{
    private List<Fruit> mFruitList;
    /*
    * 首先定义一个内部类ViewHolder继承自RecyclerView.ViewHolder
    * ViewHolder的构造函数传入一个View的一个参数,通常就是RecyclerView子项的最外层布局
    * 然后就可以通过findViewById获取布局中的图片和名字的实例
    * */
    static class ViewHolder extends RecyclerView.ViewHolder{
        ImageView fruit_image_id;
        TextView fruit_name_id;
        public ViewHolder(View itemView) {
            super(itemView);
            fruit_image_id = (ImageView)itemView.findViewById(R.id.item_image);
            fruit_name_id = (TextView)itemView.findViewById(R.id.item_name);
        }
    }
    /*
    * 构造函数,用故意把要展示的数据源传进来,赋值给一个全局变量mFruitList
    * */
    public FruitAdapter(List<Fruit> fruitList){
        mFruitList = fruitList;
    }
    /**
     * 因为FruitAdapter是继承自RecyclerView.Adapter
     *那么必须重写onCreateViewHolder(),onBindViewHolder(),getItemCount()
     */
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {/*在这里将布局加载进来,创建一个ViewHolder实例*/
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item,parent,false);
        ViewHolder holder = new ViewHolder(view);/*并把加载进来的布局传入到构造函数中*/
        return holder;/*最后将ViewHolder的实例返回*/
    }
    /*
    *onBindViewHolder是用于对RecyclceView子项数据进行赋值的,
    * 会在每个子项滚入屏幕内执行,通过position参数得到当前Fruit实例
    * 再将数据设置到ViewHolder的ImageView和TextView中
    */
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Fruit fruit = mFruitList.get(position);
        holder.fruit_image_id.setImageResource(fruit.getImageid());
        holder.fruit_name_id.setText(fruit.getName());
    }
    /*
    *告诉RecyclerView一共有多少子项
    */
    @Override
    public int getItemCount() {
        return mFruitList.size();
    }
}

控件布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="co.example.hanwei.listviewtest.MainActivity">

<android.support.v7.widget.RecyclerView
    android:id="@+id/fruit_receclerview"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

</android.support.v7.widget.RecyclerView>

</LinearLayout>

MainActivity.java修改:

package co.example.hanwei.listviewtest;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

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


public class MainActivity extends AppCompatActivity {
    private List<Fruit> furitlist = new ArrayList<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initFruit();/*初始化所有水果数据*/
        RecyclerView fruit_recyclerview = (RecyclerView)findViewById(R.id.fruit_receclerview);
        /*LinearLayoutManager:线性布局管理器*/
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        /*将他设置到RecyclerView中,LinearLayoutManager用于指定RecyclerView的布局方式,LinearLayoutManager是线性布局的意思,可以实现ListView类似的效果*/
        fruit_recyclerview.setLayoutManager(layoutManager);
        /*接下来创建FruitAdapter实例,将furitlist水果数据传入到FruitAdapter的构造函数中*/
        FruitAdapter adapter = new FruitAdapter(furitlist);
        fruit_recyclerview.setAdapter(adapter);/*将adapter作为适配器传递给RecyclerView*/
    }
    public void initFruit(){
        for(int i = 0;i < 30 ;i ++){
            Fruit banana = new Fruit("Banana",R.mipmap.ic_launcher);/*在Fruit类的构造函数中将对应的水果名字和对应说过图片的id传入*/
            furitlist.add(banana);                                   /*将创建好的对象添加到水果列表中*/
            Fruit apple = new Fruit("apple",R.mipmap.ic_launcher);
            furitlist.add(apple);
            Fruit orange = new Fruit("orange",R.mipmap.ic_launcher);
            furitlist.add(orange);
            Fruit pear = new Fruit("pear",R.mipmap.ic_launcher);
            furitlist.add(pear);
            Fruit cherry = new Fruit("cherry",R.mipmap.ic_launcher);
            furitlist.add(cherry);
        }
    }
}

实现了类似ListView的效果。

3.6.2实现横向滚动和瀑布流布局

记者如一行代码,来设置布局的排列方向,HORIZONTAL表示让布局横向排列

layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initFruit();/*初始化所有水果数据*/
        RecyclerView fruit_recyclerview = (RecyclerView)findViewById(R.id.fruit_receclerview);
        /*LinearLayoutManager:线性布局管理器*/
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        /*将他设置到RecyclerView中,LinearLayoutManager用于指定RecyclerView的布局方式,LinearLayoutManager是线性布局的意思,可以实现ListView类似的效果*/
        fruit_recyclerview.setLayoutManager(layoutManager);
        /*接下来创建FruitAdapter实例,将furitlist水果数据传入到FruitAdapter的构造函数中*/
        FruitAdapter adapter = new FruitAdapter(furitlist);
        fruit_recyclerview.setAdapter(adapter);/*将adapter作为适配器传递给ListView*/
    }

自定义布局修改为:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="100dp"
              android:layout_height="wrap_content"
              android:orientation="vertical">
    <ImageView
        android:id="@+id/item_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_launcher"
        android:layout_gravity="center_horizontal"/>
    <TextView
        android:id="@+id/item_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="名字"
        android:layout_gravity="center_horizontal"/>

</LinearLayout>

RecyclerView能做到横向滚动,是因为布局排列交给了LayoutManager,其中制订了一套可扩展的布局排列接口,子类只要按照接口的规范来实现,就能定制出不同排列方式的布局,RecyclerView给我们提供了StaggeredGridLayoutManager和GridLayoutManager,我们试一下StaggeredGridLayoutManager:

修改item布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:layout_margin="5dp"
              android:orientation="vertical">
       <! -- 这里做了几处小的调整,首先将 Linear Layout的宽度由100dp改成了 match parent,因为
        瀑布流布局的宽度应该是根据布局的列数来自动适配的,而不是一个固定值。另外我们使用了
        layout margin属性来让子项之间互留一点间距,这样就不至于所有子项都紧贴在一些。还有
        就是将 Text view的对齐属性改成了居左对齐,因为待会我们会将文字的长度变长,如果还是居
        中显示就会感觉怪怪的-->
    <ImageView
        android:id="@+id/item_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_launcher"
        android:layout_gravity="center_horizontal"/>
    <TextView
        android:id="@+id/item_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="名字"
        android:layout_gravity="left"/>

</LinearLayout>

代码中修改:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initFruit();/*初始化所有水果数据*/
        RecyclerView fruit_recyclerview = (RecyclerView)findViewById(R.id.fruit_receclerview);
        /*在onCreate()实现瀑布流布局StaggeredGridLayoutManager构造函数接受两个参数,第一个指定布局的列数,指定布局的排列方向,传入StaggeredGridLayoutManager.VERTICAL会纵向排列*/
        StaggeredGridLayoutManager layoutManager= new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL);
        /*LinearLayoutManager:线性布局管理器*/
        /*LinearLayoutManager layoutManager = new LinearLayoutManager(this);*/
        /*layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);*/
        /*将他设置到RecyclerView中,LinearLayoutManager用于指定RecyclerView的布局方式,LinearLayoutManager是线性布局的意思,可以实现ListView类似的效果*/
        fruit_recyclerview.setLayoutManager(layoutManager);
        /*接下来创建FruitAdapter实例,将furitlist水果数据传入到FruitAdapter的构造函数中*/
        FruitAdapter adapter = new FruitAdapter(furitlist);
        fruit_recyclerview.setAdapter(adapter);/*将adapter作为适配器传递给ListView*/
    }

具体效果:

 

 

3.6.3 RecyclerView的点击事件

RecyclerView直接摒弃了子项点击事件的监听器,所有的点击事件都由具体的Ⅴiew去注册。在FruitAdapter中修改。

我们先是修改了 ViewHolder,在 Viewholder中添加了 fruitier变量来保存子项最外层布局的实例:

static class ViewHolder extends RecyclerView.ViewHolder{
        ImageView fruit_image_id;
        TextView fruit_name_id;
        /*用于保存子项最外层布局实例*/
        View fruitview;
        public ViewHolder(View itemView) {
            super(itemView);
            fruitview = itemView;
            fruit_image_id = (ImageView)itemView.findViewById(R.id.item_image);
            fruit_name_id = (TextView)itemView.findViewById(R.id.item_name);
        }
    }

在onCreateViewHolder中注册点击事件:

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {/*在这里将布局加载进来,创建一个ViewHolder实例*/
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item,parent,false);
        final ViewHolder holder = new ViewHolder(view);/*并把加载进来的布局传入到构造函数中*/
        holder.fruitview.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /*获取实例中点击item在adapter中的position(位置)*/
                int position = holder.getAdapterPosition();
                /*通过position(位置)拿到相应的实例*/
                Fruit fruit = mFruitList.get(position);
                Toast.makeText(v.getContext(),"你点击了"+fruit.getName(),Toast.LENGTH_SHORT).show();
            }
        });
        holder.fruit_image_id.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = holder.getAdapterPosition();
                Fruit fruit = mFruitList.get(position);
                Toast.makeText(v.getContext(),"你点击了图片"+fruit.getImageid(),Toast.LENGTH_SHORT).show();
            }
        });
        return holder;/*最后将ViewHolder的实例返回*/
    }

 

展开阅读全文

没有更多推荐了,返回首页