英语学习app开发笔记


最近在写一款英语学习的软件,现在按照功能实现的流程,把每个功能的实现方法整理出来,便于之后的修改。

按钮界面跳转功能

主界面代码

        button1=(Button) findViewById(com.example.grt.AviationEnglish.R.id.button1);
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(Pilot.this,section_one.class);
                startActivity(intent);
            }
        });

class section_one

public class section_one extends AppCompatActivity {
    Button button5;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_section_one);
    
        button5=(Button) findViewById(R.id.button5);
        button5.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(section_one.this,letter_spell.class);
                startActivity(intent);
            }
        });
    }
}

activity_section_one.xml

数据库实现存储功能

使用了litepal 1.6.1。
LitePal是一款开源的Android数据库框架,采用对象关系映射(ORM)模式,将常用的数据库功能进行封装,可以不用写一行SQL语句就可以完成创建表、增删改查的操作。并且很轻量级,jar包不到100k,几乎零配置。
在build.grade中添加

implementation files('libs/litepal-1.6.1-src.jar')
import android.database.sqlite.SQLiteDatabase;
import org.litepal.crud.DataSupport;
import org.litepal.tablemanager.Connector;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;

创建数据库中的词条类。具有词条类就可以按照词条的类别将数据存入数据库中。

package com.example.grt.English;

import org.litepal.crud.DataSupport;

public class english extends DataSupport{
    private String entry;
    private String word;
    private int audio;

    public english(String entry,String word,int audio) {
        this.entry=entry;
        this.word=word;
        this.audio=audio;
    }

    public String getEntry() {
        return entry;
    }

    public void setEntry(String entry) {
        this.entry = entry;
    }

    public String getWord() {
        return word;
    }

    public void setWord(String word) {
        this.word = word;
    }

    public String getText() {
        return "  "+entry+"  "+word;
    }

    public int getAudio() {
        return audio;
    }

    public void setAudio(int audio) {
        this.audio = audio;
    }
}

从raw中读取文件

将词条以一定格式按照文本文件的格式存入raw文件夹中。
主界面代码

            Resources res=this.getResources();
            InputStream in=null;
            BufferedReader br =null;
            in=res.openRawResource(com.example.grt.English.R.raw.database);
            String str;
            br =new BufferedReader(new InputStreamReader(in,"GBK"));
            int times=0;
            while ((str=br.readLine())!=null){
            }

将文件内容存入数据库

逐行读取文本文件,单词与释义被"-"符号分割,每行一个词条。

try {
            SQLiteDatabase english = Connector.getDatabase();
            List<pilot_english> newsList=new ArrayList<>();
            Resources res=this.getResources();
            InputStream in=null;
            BufferedReader br =null;
            in=res.openRawResource(com.example.grt.AviationEnglish.R.raw.database);
            String str;
            br =new BufferedReader(new InputStreamReader(in,"GBK"));
            int times=0;
            while ((str=br.readLine())!=null){
                String[] tmp=str.split("-");
                newsList.add(new english(tmp[0],tmp[1],audio[times]));
                times=times+1;
                if(times%100==0){
                    DataSupport.saveAll(newsList);
                    newsList.clear();
                }
            }
            DataSupport.saveAll(newsList);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

适配器Adapter

Adapter是用来帮助填出数据的中间桥梁,简单点说:将各种数据以合适的形式显示在View中给用户看。Adapter有很多的接口,抽象类,子类可以使用。是一个可以仔细研究的内容。
由于搜索后的词条需要在listview中被显示出来,因此需要用到Adapter的知识点。

import android.widget.ArrayAdapter;
public class EntryAdapter extends ArrayAdapter {
    private final int resourceId;
    Context context;

    public EntryAdapter(Context context, int textViewResourceId, List<pilot_english> objects) {
        super(context, textViewResourceId, objects);
        this.context=context;
        resourceId = textViewResourceId;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final english english_entry = (pilot_english) getItem(position); // 获取当前项的实例
        View view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);//实例化一个对象
        TextView list_item = (TextView) view.findViewById(R.id.entry_name);//获取该布局内的文本视图
        list_item.setText(english_entry.getText());//为文本视图设置文本内容
        return view;
    }
}

未搜索时将部分项目显示在界面上

如同文曲星一样的电子辞典,在键入关键字前,listview上从第一个词条向下显示。

public class search extends AppCompatActivity{
    private static List<english> entry_pool = new ArrayList<english>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search);
        final ListView lisT=(ListView) findViewById(R.id.listview1);
        for(int i=1;i<16;i++){
            english entry=DataSupport.find(english.class, i);
            entry_pool.add(entry);
        }
        EntryAdapter adapter=new EntryAdapter(search.this,R.layout.list_item,entry_pool);
        ListView listview=(ListView)findViewById(R.id.listview1);
        listview.setAdapter(adapter);
    }
}

搜索栏使用

搜索栏为SearchView 类别,目前使用其onQueryTextSubmit()与onQueryTextChange()两个函数。

        SearchView searchBar=(SearchView) findViewById(R.id.search);
        final ListView lisT=(ListView) findViewById(R.id.listview1);
        searchBar.setSubmitButtonEnabled(true);
        searchBar.setBackgroundColor(Color.parseColor("#88d47c"));
        searchBar.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            // 当点击搜索按钮时触发该方法
            @Override
            public boolean onQueryTextSubmit(String query) {
            }
            // 当搜索内容改变时触发该方法
            @Override
            public boolean onQueryTextChange(String newText) {
                return true;
            }
        });

搜索并将结果显示在listview中

无论是onQueryTextSubmit(String query) 函数还是onQueryTextChange(String newText)函数,都会传入参数query 或是 newText,其实就是搜索栏中键入的内容。根据搜索栏中键入的内容,需要和数据库中的词条逐一进行比对。键入内容可能和单词相匹配,也有可能和词条相匹配,这样就需要把键入的字符串与它们做匹配。使用的代码为:

List<pilot_english> all=DataSupport.findAll(english.class);
for(int i=1;i<num;i++){                       
    if(all.get(i).getEntry().contains(query)||all.get(i).getWord().contains(query)){
        entry_pool.add(all.get(i));
        }

主要使用字符串的contains()函数进行匹配。
SearchView函数

        SearchView searchBar=(SearchView) findViewById(R.id.search);
        final ListView lisT=(ListView) findViewById(R.id.listview1);
        searchBar.setSubmitButtonEnabled(true);
        searchBar.setBackgroundColor(Color.parseColor("#88d47c"));

        listview.setAdapter(adapter);
        searchBar.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            // 当点击搜索按钮时触发该方法
            @Override
            public boolean onQueryTextSubmit(String query) {
                entry_pool.clear();
                int num=DataSupport.count(english.class);
                List<pilot_english> all=DataSupport.findAll(english.class);
                for(int i=1;i<num;i++){
                    if(all.get(i).getEntry().contains(query)||all.get(i).getWord().contains(query)){
                        entry_pool.add(all.get(i));
                    }
                }
                EntryAdapter adapter=new EntryAdapter(search.this,R.layout.list_item,entry_pool);
                ListView listview=(ListView)findViewById(R.id.listview1);
                listview.setAdapter(adapter);
                return true;
            }

            // 当搜索内容改变时触发该方法
            @Override
            public boolean onQueryTextChange(String newText) {
                entry_pool.clear();
                int num=DataSupport.count(english.class);
                List<pilot_english> all=DataSupport.findAll(english.class);
                for(int i=1;i<num;i++){if(all.get(i).getEntry().contains(newText)||all.get(i).getWord().contains(newText)){
                        entry_pool.add(all.get(i));
                    }
                }
                EntryAdapter adapter=new EntryAdapter(search.this,R.layout.list_item,entry_pool);
                ListView listview=(ListView)findViewById(R.id.listview1);
                listview.setAdapter(adapter);
                return true;
            }
        });

搜索功能目前稍慢,可以尝试通过检索首字母的方式加快搜索速度

listview添加点击方法

通常点击listview中的词条,应该跳转到该词条对应的界面。可以在搜索界面对应的class类中添加如下代码,以实现点击相应功能。

ListView listview=(ListView)findViewById(R.id.listview1);
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                String item = ((TextView)view).getText().toString();
                Toast.makeText(search.this,"item=",Toast.LENGTH_LONG).show();
                System.out.println("===OnItemClick(AdapterView<?> parent="+parent+",View view="+view+",int position="+position+",long id ="+id+")====");
            }
        });

音频播放功能 listview内部按钮点击事件

listview中每一条list包含了一个imagebutton,想设置点击imagebutton时的函数,需要在 Adapter类的getview中设置点击事件。这里通过ViewHolder中的button变量获取到view中imagebutton对应的ID,然后对其设置OnClickListener。

    public class ViewHolder {
        public ImageButton button;
        public int audio;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final ViewHolder holder = new ViewHolder();
        final pilot_english english_entry = (pilot_english) getItem(position); // 获取当前项的Fruit实例
        View view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);//实例化一个对象
        TextView list_item = (TextView) view.findViewById(R.id.entry_name);//获取该布局内的文本视图
        list_item.setText(english_entry.getText());//为文本视图设置文本内容
        holder.button=(ImageButton) view.findViewById(R.id.imageButton);
        holder.audio=english_entry.getAudio();
        view.setTag(holder);
        View.OnClickListener listener=new View.OnClickListener(){
            @Override
            public void onClick(View v)
            {
                MediaPlayer mp =MediaPlayer.create(context,holder.audio);
                mp.start();
            }
        };
        holder.button.setOnClickListener(listener);
        return view;
    }

界面背景图

界面设置纯色的方法:
在对应界面xml文件内设置 android:background

使用主流图片加载库Glide
有时背景需要加载图片时,容易因为图片在解析的过程中被弄的极大,导致内存溢出,导致不同机型上可能出现闪退的情况。Glide是主流的加载库之一,作为一个被google推荐的开源库,它有着跟随页面周期、支持gif和webp、支持多种数据源等特点,是一个值得进一步学习的图片加载库。
其使用简便,只需添加对应jar后加入如下代码。
在build.gradle

implementation files('libs/glide-3.7.0.jar')
import com.bumptech.glide.Glide;
int resource = com.example.grt.AviationEnglish.R.drawable.back_two;
ImageView imageView = (ImageView) findViewById(com.example.grt.AviationEnglish.R.id.imageView1);
imageView.setScaleType(ImageView.ScaleType. CENTER_CROP);
Glide.with(this).load(resource).into(imageView);
  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值