Android基础第四天

    xiaoxiao2021-12-14  17

    Android基础第四天

    1. 案例:学生信息管理系统

    需求:在输入框中输入姓名,选择性别,点击保存按钮将数据存入数据库,并展示在下方的空白处。(独立参照思路代码敲出来)

    通过该案例可以巩固数据库的创建,数据库的增删改查操作。以及学习到如何动态的将一个textview文本控件添加到Linearlayout容器中。

     

    操作步骤:

    1.        界面布局:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

        xmlns:tools="http://schemas.android.com/tools"

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:orientation="vertical"

        tools:context=".MainActivity">

        <EditText

            android:id="@+id/et_name"

            android:layout_width="match_parent"

            android:layout_height="wrap_content"

            android:hint="请输入学生的姓名" />

     

        <TextView

            android:layout_width="match_parent"

            android:layout_height="wrap_content"

            android:text="请选择学生的性别:" />

     

        <RadioGroup

            android:id="@+id/rg_sex"

            android:layout_width="fill_parent"

            android:layout_height="wrap_content"

            android:orientation="horizontal">

     

            <RadioButton

                android:id="@+id/rb_male"

                android:layout_width="0dip"

                android:layout_height="wrap_content"

                android:layout_weight="1"

                android:checked="true"

                android:text="" />

     

            <RadioButton

                android:id="@+id/rb_female"

                android:layout_width="0dip"

                android:layout_height="wrap_content"

                android:layout_weight="1"

                android:text="" />

        </RadioGroup>

        <Button

            android:layout_width="fill_parent"

            android:layout_height="wrap_content"

            android:onClick="save"

            android:text="保存" />

        <ScrollView

            android:layout_width="fill_parent"

            android:layout_height="fill_parent">

     

            <LinearLayout

                android:id="@+id/ll_result"

                android:layout_width="fill_parent"

                android:layout_height="fill_parent"

                android:orientation="vertical">

            </LinearLayout>

        </ScrollView>

    </LinearLayout>

    注意:最下方的空白处用了一个linearlayout容器来显示添加的学生信息,但是有可能数据太多显示不全,所以包裹了一个ScrollView在外面,可以让里面的信息进行滚动。ScrollView只能有一个子孩子,不能包裹多个。

     

    2.        创建数据库,创建表结构

    表名:student; 字段:姓名name,性别sex

    publicclass StudentDBOpenHelper extends SQLiteOpenHelper {

      public StudentDBOpenHelper(Contextcontext) {

         super(context, "info.db", null, 1);

      }

     

      @Override

      publicvoid onCreate(SQLiteDatabase db) {

         db.execSQL("create table student (_idinteger primary key autoincrement,name varchar(20), sex varchar(6))");

      }

     

      @Override

      publicvoid onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

     

         }

    }

    3.        为了实现业务逻辑和界面的解耦隔离,一般数据库的增删改查都单独创建一个dao的业务逻辑类来实现:

     

    由于操作数据库需要得到SqliteDatabase对象,所以在创建该类的时候,在构造函数中去实例化StudentDBOpenHelper

    /**

     * 学生信息数据库的dao( data access objcet)

     * 增删改查

     */

    publicclass StudentDao {

        private StudentDBOpenHelper helper;

       

        /**

         * 只有一个有参的构造方法,要求必须传入上下文

         * @param context

         */

        public StudentDao(Context context) {

           helper = new StudentDBOpenHelper(context);

        }

        /**

         * 添加一个学生

         * @param name 姓名

         * @param sex 性别,male female

         */

        publicvoid add(String name,String sex){

           SQLiteDatabase  db = helper.getWritableDatabase();

           db.execSQL(5, new Object[]{name,sex});

           db.close();//释放资源

        }

       

        /**

         * 删除一个学生

         * @param name 姓名

         */

        publicvoid delete(String name){

            SQLiteDatabase  db = helper.getWritableDatabase();

           db.execSQL("delete from student wherename=?",new Object[]{name});

           db.close();//释放资源

        }

       

        /**

         * 修改一个学生的性别

         * @param name 姓名

         * @param newsex 新的性别

         */

        publicvoid update(String name,String newsex){

           SQLiteDatabase  db = helper.getWritableDatabase();

           db.execSQL("update student set sex =?where name=?",new Object[]{newsex,name});

           db.close();//释放资源

        }

        /**

         * 查询学生的性别

         * @param name 学生的姓名

         * @return学生性别 null代表学生不存在

         */

        public String find(String name){

           String sex = null;

           SQLiteDatabase  db = helper.getReadableDatabase();

           //结果集游标

           Cursor cursor = db.rawQuery("select sex from studentwhere name=?", new String[]{name});

           boolean result = cursor.moveToNext();

           if(result){

               sex = cursor.getString(0);

           }

           cursor.close();//释放资源

           db.close();

           return sex;

        }

        在MainActivity中初始化控件以及数据库dao业务逻辑类

        @Override

        protectedvoid onCreate(Bundle savedInstanceState){

           super.onCreate(savedInstanceState);

           setContentView(R.layout.activity_main);

           et_name = (EditText) findViewById(R.id.et_name);

           rg_sex = (RadioGroup) findViewById(R.id.rg_sex);

           // 找到界面下方的空白的线性布局

           ll_result = (LinearLayout) findViewById(R.id.ll_result);

           dao = new StudentDao(this);

           refreshData();

        }

     

        publicvoid save(View view) {

           String name = et_name.getText().toString().trim();

           if (TextUtils.isEmpty(name)) {

               Toast.makeText(this, "请输入学生的姓名", 0).show();

               return;

           }

           int id = rg_sex.getCheckedRadioButtonId();

           String sex = "male";

           if (id == R.id.rb_male) {

               //

               sex = "male";

           } else {

               //

               sex = "female";

           }

           dao.add(name, sex);

           Toast.makeText(this, "数据添加成功", 0).show();

           refreshData();

        }

    通过以上4步即可成功的将我们输入的姓名选择的性别信息插入到数据库中,接下来就需要当插入数据成功的时候还得显示在界面的下方,为了方便数据操作,我们最好通过面向对象的思想去实现将一个学生的信息做一个业务bean来操作,所有学生就是一个List集合对象:

    /**

     * 学生的业务bean

     */

    publicclass Student {

        private String name;//姓名

        private String sex;//性别

        public String getName() {

           returnname;

        }

        publicvoid setName(String name) {

           this.name = name;

        }

        public String getSex() {

           returnsex;

        }

        publicvoid setSex(String sex) {

           this.sex = sex;

        }

        @Override

        public String toString() {

           return"Student [name=" + name + ", sex=" + sex + "]";

        }

    }

    4.        在StudentDao中增加一个查询所有学生信息的方法,返回一个List<Student>集合对象,方便在界面操作显示

    /**

         * 获取全部的学生信息

         * @return

         */

        public List<Student> findAll(){

           List<Student> students =new ArrayList<Student>();

           SQLiteDatabase  db = helper.getReadableDatabase();

           Cursor cursor = db.rawQuery("select name, sex fromstudent", null);

           while(cursor.moveToNext()){

               String name =cursor.getString(0);

               String sex =cursor.getString(1);

               Student student = new Student();

               student.setName(name);

               student.setSex(sex);

               students.add(student);

           }

           cursor.close();

           db.close();

           return students;

        }

    }

    5.        在MainActivity中定义一个单独的方法查询所有的学生数据并展示到界面上

        /**

         * 获取数据库的全部记录,刷新显示数据

         */

        privatevoid refreshData() {

           List<Student> students =dao.findAll();

           ll_result.removeAllViews();// 把原来的数据给清除

           for (Student student : students) {

               TextView tv = new TextView(this);

               tv.setText(student.toString());

               ll_result.addView(tv);

           }

        }

    注意:在将textview添加到linearlayout容器中之前,一定要先将linearlayout中原来存在的textview控件清除,否则会造成重复的数据不断显示。

     

    最后在点击保存按钮的save()方法中,当添加成功一条数据时,调用refreshData()方法刷新界面,以及在oncreate方法中调用refreshData()将数据库存在的学生数据显示出来。

    2.ListView

             通过数据库中的学生信息管理系统中的案例让我们熟悉了数据库的创建和使用,以及动态添加一个控件到linearlayout容器中;不过这种方式有一个极大的问题就是:不断的在创建new一个Textview控件添加到linearlayout,会造成如果有100个学生就得new100个textview,如果成千上万那内存开销会巨大导致内存溢出,所以android给我们引入了一个对数据进行列表展示的控件:ListView.

             ListView的特点:

    1、屏幕上可以展示几个条目,ListView就初始化几个,节省内存。

    2、通过使用convertView对创建的视图对象进行复用,ListView 始终保持创建的对象个数为: 屏幕显示的条目的个数+ 1。

    3、ListView 自带ScrollView 的功能,可以实现界面滚动。

    4、ListView 控件的设计遵循MVC 设计模式:mode 数据模型(数据) :要被显示到ListView上的数据集合  view 视图(展示数据) :ListView  controller 控制层(把数据展示到控件上) : 适配器Adapter

     

    Ø  ListView的使用

    1.        布局里引入控件:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

        xmlns:tools="http://schemas.android.com/tools"

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        tools:context=".MainActivity">

     

        <ListView

            android:id="@+id/lv"

            android:layout_width="fill_parent"

            android:layout_height="fill_parent"/>

     

    </RelativeLayout>

    2.        查找控件,设置控制器

    publicclass MainActivity extends Activity {

        // mvc中的view,视图

        private ListView lv;

     

        @Override

        protectedvoid onCreate(Bundle savedInstanceState){

           super.onCreate(savedInstanceState);

           setContentView(R.layout.activity_main);

           // 查找视图

           lv = (ListView) findViewById(R.id.lv);

           // 设置控制器 controller

           lv.setAdapter(new MyAdapter());

        }

     

        // BaseXXX SimpleXXX DefalutXXX

        /**

         * 控制器用来控制listview如何显示

         */

        privateclass MyAdapter extends BaseAdapter {

     

           // 控制listview里面有多少个item

           @Override

           publicint getCount() {

               return 30;

           }

     

           // 返回某个位置显示的view对象。

           @Override

           public View getView(int position, View convertView,ViewGroup parent) {

               TextView tv = new TextView(MainActivity.this);      

               tv.setText("我是文本:" + position);

               tv.setTextSize(24);

               return tv;

           }

     

           @Override

           public Object getItem(int position) {

               returnnull;

           }

     

           @Override

           publiclong getItemId(int position) {

               return 0;

           }

        }

    }

    最后显示的效果即是展示30个textview文本,并且自带滑动的功能:

    Ø  ListView的优化

    上诉的步骤只是最简单的显示出来了一个listview以及里面展示的数据,但是如果我们要显示的数据有一万条,那么在快速往上滚动的过程中就会不断的调用adapter中的getView方法,不断的生成新的Textview控件,消耗内存资源,最后导致内存不足,造成oom内存溢出。

    ListView复用的原理:

    当我们滑动listview的时候,每当一个item看不见的时候,那么那个item就可以被复用起来了,也就是成为了convertView,那个时候convertView就不为null

     

    所谓的复用,其实本质是就是itemview对象没有真正的被垃圾回收器回收掉,而是重新将身上的数据给换掉了,看起来好像是出现了一个新的item而已

     

    对ListView 进行优化的最简单有效的措施就是复用getView 方法中的convertView 对象。convertView来自缓存池,缓存池由ListView 维护,缓存池中的数据来自getView 方法的返回值,也就是说getView 方法的返回值用完后并没有“浪费”,而是被系统放到ListView 的缓存池里了。缓存池的大小=屏幕显示的条目数+1,当滑动屏幕时,被隐藏的项会作为缓存对象,作为getView 的参数传递进来。只需修改此缓存对象的数据,就可以直接使用,而不需要再重新new 一个新的对象,节省了内存,防止内存溢出。

    优化后的代码

        @Override

        public View getView(int position, View convertView,ViewGroup parent) {

               TextView tv = null;

               if (null == convertView) {

                  //如果缓存中没有数据则需要创建一个新的TextView

                  tv = new TextView(MainActivity.this);

               }else{

                  //如果缓存中有数据则直接强转即可

                  tv = (TextView)convertView;

               }

               tv.setText("我是文本:" + position);

               tv.setTextSize(24);

               return tv;

           }     

    打气筒inflate

             现在需要将之前的学生信息管理系统的案例替换成Listview来进行实现,并且条目要更加优化,效果图如下:

            

     

    当我们listview的item条目需要显示比较复杂的布局时,这个时候如果还用代码的方式去实现就不是很方便了,所以android给我们提供了一个方便的API,View对象本身或者任何继承View对象的控件都有一个方法(下面的代码是系统View中的源码)

        /**

         * Inflate a view from an XMLresource.  This convenience method wrapsthe {@link

         * LayoutInflater} class, whichprovides a full range of options for view inflation.

         *

         * @param context The Context object foryour activity or application.

         * @param resource The resource ID toinflate

         * @param root A view group that will bethe parent.  Used to properly inflate the

         * layout_* parameters.

         * @see LayoutInflater

         */

        publicstatic View inflate(Context context, int resource, ViewGroup root) {

            LayoutInflater factory =LayoutInflater.from(context);

            return factory.inflate(resource, root);

     }

    我们把它形象的比喻为打气筒,可以将一个布局文件打气打成一个View对象,方便我们使用。布局里面的所有控件都可以通过这个View对象来进行查找:(以下代码展示了三种方式将一个布局文件转化为Veiw对象)

    @Override

    public View getView(finalint position, View convertView,

                  ViewGroup parent) {//6item

           View view = null;

           if (convertView == null) {

           // 把一个布局xml文件转化成view对象

           /**

            * 第一种方式:

            * 系统控件View自带有inflate方法

            */

           view = View.inflate(MainActivity.this, R.layout.item, null);

           /**

            * 第二种方式实现

            * 参考底层View.inflate()源码的实现:先通过LayoutInfalter 的静态方法from

            * 获取LayoutInflater 对象,然后调用inflate 方法

            */

           LayoutInflater layoutInflater= LayoutInflater.from(MainActivity.this);

           view =layoutInflater.inflate(R.layout.item, null);

           /**

            * 第三种方式实现:

            * 先通过上下文提供的getSystemService 方法获取LayoutInfater 对象

            * 然后调用inflate 方法

            */

           LayoutInflater layoutInflater2= (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);

           view =layoutInflater2.inflate(R.layout.item, null);

           } else {

                  view = convertView;

               }

           // view里面查找孩子控件

           TextView tv_name = (TextView)view.findViewById(R.id.tv_name);

           ImageView iv_sex = (ImageView)view.findViewById(R.id.iv_sex);

              

           Student student = students.get(position);

           String sex = student.getSex();

           if ("male".equals(sex)) {

           iv_sex.setImageResource(R.drawable.nan);

               } else {

                  iv_sex.setImageResource(R.drawable.nv);

               }

               tv_name.setText(student.getName());

               view.findViewById(R.id.iv_delete).setOnClickListener(

                      new OnClickListener() {

                         @Override

                         publicvoid onClick(View v) {

                             Studentstudent = students.get(position);

                             String name= student.getName();

                             // 从数据库删除数据.

                             dao.delete(name);

                             Toast.makeText(MainActivity.this, "数据被删除了", 0)

                                    .show();

                             // 更新ui界面.

                             refreshData();

                         }

                      });

               return view;

           }

     

    Item条目上有一个删除按钮,在上诉代码中给这个按钮注册了点击事件,点击的时候从数据库删除数据,这个时候需要更新UI界面;以及在点击保存按钮的时候添加一条数据库的时候,添加成功后需要刷新界面,那么ListView界面如何刷新呢?

    通知数据适配器刷新数据

             BaseAdapter适配器中有一个方法adapter.notifyDataSetChanged()该方法是通知适配器进行数据刷新,会自己调用adapter中的getCount()和getView()方法进行数据的刷新。

        /**

         * 获取数据库的全部记录,刷新显示数据

         */

        privatevoid refreshData() {

           students = dao.findAll();

           if (adapter == null) {

               //第一次显示数据

               adapter = new MyAdapter();

               lv.setAdapter(adapter);

           }else{

               //通知数据适配器更新数据,而不是new出来新的数据适配器

               adapter.notifyDataSetChanged();

           }

        }

    Ø  ListView 的常见适配器

    除了经常使用到的BaseAdapter 外,系统还提供了几个已经实现好的适配器,都是继承至BaseAdapter

    lv = (ListView) findViewById(R.id.lv);

           String[] objects = new String[]{"Animation","App","content","Media","NFC","OS"};

           /**

            * 第一个参数是:上下文

            * 第二个参数是:布局文件的id,这里使用Android 系统提供的简单布局

            * 第三个参数是:要显示的数据,数组或者List 集合都行

            */

           lv.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, objects));

    ArrayAdapter

    效果为:

    SimpleAdapter

    SimpleAdapter 可以实现比ArrayAdapter复杂一点的布局。使用SimpleAdapter 的数据一般都是HashMap构成的List,List 的每一个对象对应ListView 的每一行。HashMap 的每个键值数据映射到布局文件中对应id 的组件上。因为系统没有对应的布局文件可用,我们可以自己定义一个布局文件。

    比如要实现如下的效果:

     

    代码实现如下:

    lv = (ListView) findViewById(R.id.lv);

           //准备数据

           List<Map<String,Object>> data = new ArrayList<Map<String,Object>>();

           Map<String, Object> map1= new HashMap<String, Object>();

           map1.put("icon", R.drawable.ic_menu_preferences);

           map1.put("name", "功能设置");

           data.add(map1);

           Map<String, Object> map2= new HashMap<String, Object>();

           map2.put("icon", R.drawable.ic_menu_recent_history);

           map2.put("name", "时钟设置");

           data.add(map2);

           Map<String, Object> map3= new HashMap<String, Object>();

           map3.put("icon", R.drawable.ic_menu_refresh);

           map3.put("name", "同步设置");

           data.add(map3);

           Map<String, Object> map4= new HashMap<String, Object>();

           map4.put("icon", R.drawable.ic_menu_report_image);

           map4.put("name", "图片设置");

           data.add(map4);

           /**

            * 第一个参数:上下文

            * 第二个参数:显示的数据

            * 第三个参数:布局文件的资源id

            * 第四个参数:Map 集合中key 的数组

            * 第五个参数:item 布局中ImageView控件的id TextView 的控件的id

            */

           lv.setAdapter(new SimpleAdapter(this, data, R.layout.item, new String[]{"icon","name"}, newint[]{R.id.iv,R.id.tv}));

    3.对话框

    对话框的初始化

    AlertDialog.Builderbuilder = new Builder(当前Activity的上下文);

    对话框设置属性

    builder.setTitle(title);-->设置标题

    builder.setMessage(msg);-->设置提醒信息

    设置对话框按钮

    builder.setPositiveButton(按钮文字,newDialogInterface.OnClickListener());-->最右边的按钮

    builder.setNegativeButton(按钮文字,newDialogInterface.OnClickListener());-->最左边的按钮

    builder.setNeutralButton(按钮文字,new DialogInterface.OnClickListener());-->中间的按钮

    对话框显示

    builder.show();

    对话框样式

    setSingleChoiceItems()-->单选

    setMultiChoiceItems()-->多选

    ProgressDialog-->进度条

    l  确定取消对话框

    代码:

    //builder可以理解成一个构造器,构造对话框所需要的一些数据,最后由dialog来进行显示

           AlertDialog.Builder builder = new Builder(this);

           builder.setTitle("警告:");

           builder.setMessage("若练此功,必先自宫,是否继续?");

           builder.setPositiveButton("确定自宫", new OnClickListener() {

               @Override

               publicvoid onClick(DialogInterface dialog, int which) {

                  Toast.makeText(MainActivity.this, "....", 0).show();

               }

           });

           builder.setNegativeButton("想想再说", new OnClickListener() {

               @Override

               publicvoid onClick(DialogInterface dialog, int which) {

                  Toast.makeText(MainActivity.this, "如不自宫,一定不成功", 0).show();

               }

           });

           AlertDialog dialog = builder.create();

           dialog.setCancelable(false);//设置其他空白区域点击是否可以关闭我们的dialog

           dialog.show();//注意一定要调用show否则显示不了对话框

    l  单选对话框

     

    代码如下:

    AlertDialog.Builder builder = new Builder(this);

           builder.setTitle("请选择您的性别:");

           final String[] items = { "", "", "中性" };

           /**第一个参数为显示的条目数组,第二个参数为默认选中的条目,-1即不选中任何条目*/

           builder.setSingleChoiceItems(items,-1, new OnClickListener() {

               @Override

               publicvoid onClick(DialogInterface dialog, int which) {

                  Toast.makeText(MainActivity.this, "您的性别:" + items[which], 0).show();

               }

           });

           //点击事件如果设置为null则默认点击关闭对话框

           builder.setNegativeButton("取消选择", null);

           builder.show();

    l  对选对话框

    代码如下:

            AlertDialog.Builderbuilder = new Builder(this);

           builder.setTitle("请选择您爱吃的水果");

           final String[] items = new String[] { "黄瓜", "苹果", "香蕉", "菠萝菠萝蜜" };

           //条目的状态数组 true为选中 false为不选中

           finalboolean[] checkedItems = newboolean[] { true, true, false, false };

           builder.setMultiChoiceItems(items,checkedItems,

                  new OnMultiChoiceClickListener() {

                      @Override

                      publicvoid onClick(DialogInterface dialog, int which,

                             boolean isChecked) {

                         Toast.makeText(MainActivity.this,

                                items[which]+ isChecked, 0).show();

                         checkedItems[which]= isChecked;

                      }

                  });

           builder.setNegativeButton("取消选择", null);

           builder.show();正在加载对话框

     

    代码如下:

           final ProgressDialog pd = new ProgressDialog(this);

           pd.setTitle("提醒");

           pd.setMessage("正在加载数据...请稍后");

           pd.show();

           new Thread() {

               publicvoid run() {

                  try {

                      Thread.sleep(3000);

                  } catch (InterruptedException e) {

                      e.printStackTrace();

                  }

                  pd.dismiss();//关闭对话框

               };

           }.start();

    l  进度条对话框

     

    代码如下:

    final ProgressDialog pd = new ProgressDialog(this);

           //进度条的风格为水平进度条

           pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);

           pd.setMax(100);//进度条的最大值

           pd.setTitle("提醒");

           pd.setMessage("正在加载数据...请稍后");

           pd.show();

           new Thread() {

               publicvoid run() {

                  for (int i = 0; i <= 100; i++) {

                      try {

                         Thread.sleep(300);

                      } catch (InterruptedException e) {

                         e.printStackTrace();

                      }

                      pd.setProgress(i);//设置当前进度值

                  }

                  pd.dismiss();

               };

           }.start();

    4.Android下的帧动画

    帧动画:就是由一张一张的图片按照顺序和时间进行一帧一帧的播放。

    帧动画使用的步骤:

    1.        创建帧动画每帧需要的图片, 放到对应的 drawable-xxx 或drawable 目录中

    2.        在drawable 目录下,创建帧动画 xml 文件,根节点选择 animation-list

    <?xml version="1.0"encoding="utf-8"?>

    <animation-list xmlns:android="http://schemas.android.com/apk/res/android"

        android:oneshot="false">

        <item

            android:drawable="@drawable/logo1"

            android:duration="850">

        </item>

        <item

            android:drawable="@drawable/logo2"

            android:duration="850">

        </item>

        <item

            android:drawable="@drawable/logo3"

            android:duration="850">

        </item>

    </animation-list>

    帧动画的自动执行:oneshot  如果为true,表示动画只播放一次停止在最后一帧上,如果设置为false表示动画循环播放。

    3.        设置为 View 的 Background 或者 ImageView 的 src,然后获取到控件的 AnimationDrawable 对象,通过 AnimationDrawable.start() 方法启动动画:

     

    ImageView iv = (ImageView)findViewById(R.id.iv);

           iv.setBackgroundResource(R.drawable.logo);

    AnimationDrawable anim = (AnimationDrawable)iv.getBackground();

           anim.start();//开始播放动画

    5.Android国际化

    文字国际化

    在res文件下创建values--xx文件夹,在里面创建strings.xml文件,在里面写对应的语言

     

    图片国际化

    drawable-xxx里面的资源名字要起一样的,这样系统就能根据当前的语言自动去寻找对应的文件夹资源

     

    6.样式和主题

    配置样式:

    在style文件里设置,如果想继承系统自带的主题或者样式,指定 parent=“需要继承的样式”;如果需要修改继承样式里的某一样,在自定义样式里面重写需要修改的属性即可。

        <style name="text_content_style">

            <item name="android:layout_width">match_parent</item>

            <item name="android:layout_height">wrap_content</item>

            <item name="android:textColor">#0000ff</item>

            <item name="android:textSize">20sp</item>

        </style>

        <style name="text_title_style"parent="@style/text_content_style">

             <item name="android:textSize">25sp</item>

        </style>

       

        <!-- 该方式也可以指定父类为text_content_style,但是不建议 -->

        <style name="text_content_style.sub">

            <item name="android:textSize">28sp</item>

        </style>

    这样做的目的是为了达到复用,代码的简洁,统一修改的便捷。当一个布局界面有大量相同重复的布局属性参数时,就可以使用抽取style的方式来实现,比如:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

        xmlns:tools="http://schemas.android.com/tools"

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:orientation="vertical"

        tools:context=".MainActivity">

       

        <TextView

            style="@style/text_title_style"

            android:text="@string/hello_world"/>

       

        <TextView

            style="@style/text_content_style"

            android:text="@string/hello_world"/>

     

        <TextView

            style="@style/text_content_style.sub"

            android:text="@string/hello_world"/>

     

        <TextView

            style="@style/text_content_style"

            android:text="@string/hello_world"/>

     

        <TextView

            style="@style/text_content_style"

            android:text="@string/hello_world"/>

     

        <TextView

            style="@style/text_content_style"

            android:text="@string/hello_world"/>

     

    </LinearLayout>

    效果为:

     

    设置主题:

    可以通过设置theme属性参数来修改整个应用程序或者单个界面的主题风格:

    在清单文件里面配置 theme="@style:..."

        <application

            android:allowBackup="true"

            android:icon="@drawable/ic_launcher"

            android:label="@string/app_name"

            android:theme="@style/AppTheme"

             >

    指定style为AppTheme则整个应用程序的主题风格即为AppTheme的风格,当然也可以修改AppTheme的风格,将当前主题添加一个没有标题栏的风格:

        <!--Application theme. -->

        <style name="AppTheme"parent="AppBaseTheme">

             <item name="android:windowNoTitle">true</item>

            <!-- All customizations thatare NOT specific to a particular API-level can go here. -->

        </style>

    或者自己定义一个theme:

        <style name="my_app_theme">

              <item name="android:windowNoTitle">true</item>

              <item name="android:background">#440000ff</item>

    </style>

    也可以在代码中设置主题:

    在代码设置 setTheme(ResId) 此方法必须在setContentView之前调用

    publicclass MainActivity extends Activity {

        @Override

        protectedvoid onCreate(Bundle savedInstanceState){

           super.onCreate(savedInstanceState);

           setTheme(R.style.my_app_theme);

           setContentView(R.layout.activity_main);

        }

    }

     

     

     

     

     

    转载请注明原文地址: https://ju.6miu.com/read-972291.html

    最新回复(0)