天天背单词--的设计与实现(二)

2023-11-03 21:10
文章标签 实现 设计 天天 背单词

本文主要是介绍天天背单词--的设计与实现(二),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

加上广告之后百度就不让上了,客服说让我在线配置隐藏广告在上架,我可不是那种藏着掖着的人,哈哈,所以只能在云盘下载了

  • 下载地址:
    https://yunpan.cn/cqt5xp3QAJsSM (提取码:ffaa)

第一大步肯定是需求分析,那么

·这个背单词的软件需要具备的功能:

  1. 查词
  2. 每日一句
  3. 卡片单词,单词本,等级测试,美文欣赏(具体形式后面实现时候再介绍)
  4. 设置(包括:个人设置,词库下载,缓存清理等)

大概就分这四个模块,所以样式就定成很大众的四个tab页实现

·数据来源及方式,数据库设计,
1.我选择了ICIBA 金山词霸API,因为相对有道等其他api接口,金山提供了单词,词音,每日一句及发音等 很全面.非常符合我们的需求.
2.数据库方面,主要就是记录查询过的单词,和单词测试里学习过的单词,字段都很相似

  • 单词,英音标,美音标,英发音,美发音,释义,例句,查询次数,和答错次数.

根据需求删减某系字段即可.

今天主要说明一下ViewPger+Fragment实现主界面Tab的切换效果,先看效果:
这里写图片描述

基本原理就是ViewPager里面放了四个Fragment,就是这么简单,稍微复杂点就是底下图标的渐变效果.

首先如何在ViewPager里面放了四个Fragment

  1. xml里声明这个控件等价于一个TextView;
  2. 出镜成员:ViewPager Fragment List FragmentPagerAdapter
 private ViewPager mViewPager; // 主界面fragment容器private List<Fragment> mTabs = new ArrayList<Fragment>(); // fragment集合private FragmentPagerAdapter mAdapter; // 适配器private List<TabIcon> mTabIndicators = new ArrayList<TabIcon>(); // 渐变图标集合
  1. 将Fragment放入List中,
    //添加四个tab的fragment mTabs = new ArrayList<Fragment>(); 自己建的Fragment fragment1 = new 自己建的Fragment();mTabs.add(fragment1);自己建的Fragment fragment2 = new 自己建的Fragment();mTabs.add(fragment2);自己建的Fragment fragment3 = new 自己建的Fragment();mTabs.add(fragment3);自己建的Fragment fragment4 = new 自己建的Fragment();mTabs.add(fragment4);
  1. 将List放入FragmentPagerAdapter,
    mAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {@Overridepublic int getCount() {return mTabs.size();}@Overridepublic Fragment getItem(int arg0) {return mTabs.get(arg0);}};
  1. 最后将FragmentPagerAdapter绑定在ViewPager上 ,
    mViewPager.setAdapter(mAdapter);mViewPager.setOffscreenPageLimit(10);//这句话的意思就是再每一个fragment左右各保存5个fragment页面,此参数默认为2,为2时当你滑动到第三个fragment的时候第一个已经被销毁当你滑动回来需要重新加载,数据就没了,所以设置为10,也就是当滑动到第四个依然能保存第一个.

主界面代码:

public class MainActivity extends FragmentActivityimplements OnClickListener, OnPageChangeListener, IAtSettingFragment {private ViewPager mViewPager; // 主界面fragment容器private List<Fragment> mTabs = new ArrayList<Fragment>(); // fragment集合private FragmentPagerAdapter mAdapter; // 适配器private List<TabIcon> mTabIndicators = new ArrayList<TabIcon>(); // 渐变图标集合@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();initDatas();mViewPager.setAdapter(mAdapter);mViewPager.setOffscreenPageLimit(10);initEvent();}/*** 初始化事件和服务*/@SuppressWarnings("deprecation")private void initEvent() {mViewPager.setOnPageChangeListener(this);Intent intent = new Intent(this, NotifyReviewService.class);startService(intent);}InterpretFragment interpretFragment;DailyFragment tabFragment;ReciteFragment reciteFragment;MeFragment meFragment;/*** 初始化数据(界面 词库)*/private void initDatas() {// 导入词库new WriteToSD(this);//添加四个tab的fragmentinterpretFragment = new InterpretFragment();mTabs.add(interpretFragment);tabFragment = new DailyFragment();mTabs.add(tabFragment);reciteFragment = new ReciteFragment();mTabs.add(reciteFragment);meFragment = new MeFragment();mTabs.add(meFragment);mAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {@Overridepublic int getCount() {return mTabs.size();}@Overridepublic Fragment getItem(int arg0) {return mTabs.get(arg0);}};}/*** 找控件和绑定监听器*/private void initView() {mViewPager = (ViewPager) findViewById(R.id.viewPager);TabIcon one = (TabIcon) findViewById(R.id.tab_one);mTabIndicators.add(one);TabIcon two = (TabIcon) findViewById(R.id.tab_two);mTabIndicators.add(two);TabIcon three = (TabIcon) findViewById(R.id.tab_three);mTabIndicators.add(three);TabIcon four = (TabIcon) findViewById(R.id.tab_four);mTabIndicators.add(four);one.setOnClickListener(this);two.setOnClickListener(this);three.setOnClickListener(this);four.setOnClickListener(this);one.setIconAlpha(1.0f);//初始化图标透明度}@Overridepublic void onClick(View v) {resetOtherTabs();switch (v.getId()) {case R.id.tab_one:mTabIndicators.get(0).setIconAlpha(1.0f);mViewPager.setCurrentItem(0, false);break;case R.id.tab_two:mTabIndicators.get(1).setIconAlpha(1.0f);mViewPager.setCurrentItem(1, false);break;case R.id.tab_three:mTabIndicators.get(2).setIconAlpha(1.0f);mViewPager.setCurrentItem(2, false);break;case R.id.tab_four:mTabIndicators.get(3).setIconAlpha(1.0f);mViewPager.setCurrentItem(3, false);break;}}/*** 重制其他Tab的颜色*/private void resetOtherTabs() {for (int i = 0; i < mTabIndicators.size(); i++) {mTabIndicators.get(i).setIconAlpha(0);}}@Overridepublic void onPageScrollStateChanged(int arg0) {}@Overridepublic void onPageScrolled(int arg0, float arg1, int arg2) {if (arg1 > 0) {TabIcon left = mTabIndicators.get(arg0);TabIcon right = mTabIndicators.get(arg0 + 1);left.setIconAlpha(1 - arg1);right.setIconAlpha(arg1);}}@Overridepublic void onPageSelected(int arg0) {switch (arg0) {case 1:interpretFragment.setSearchedPosition();break;case 3:meFragment.setTvCardCount();break;}}// 实现查询单词数的更新@Overridepublic void onQuery(String szContent) {meFragment.setTvQueryCount();}}

主界面XML代码

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"xmlns:qit="http://schemas.android.com/apk/res/com.qit.iword"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><android.support.v4.view.ViewPagerandroid:id="@+id/viewPager"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1" ></android.support.v4.view.ViewPager><LinearLayoutandroid:layout_width="match_parent"android:layout_height="60dp"android:background="@drawable/tab_background"android:orientation="horizontal" ><com.qit.iword.TabIconandroid:id="@+id/tab_one"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:padding="5dp"qit:tab_color="#FD805B"qit:tab_icon="@drawable/tab_intercept"qit:tab_text="翻译"qit:tab_text_size="12sp" /><com.qit.iword.TabIconandroid:id="@+id/tab_two"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:padding="5dp"qit:tab_color="#FD805B"qit:tab_icon="@drawable/tab_daily"qit:tab_text="每句"qit:tab_text_size="12sp" /><com.qit.iword.TabIconandroid:id="@+id/tab_three"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:padding="5dp"qit:tab_color="#FD805B"qit:tab_icon="@drawable/tab_recite"qit:tab_text="发现"qit:tab_text_size="12sp" /><com.qit.iword.TabIconandroid:id="@+id/tab_four"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:padding="5dp"qit:tab_color="#FD805B"qit:tab_icon="@drawable/tab_me"qit:tab_text="我的"qit:tab_text_size="12sp" /></LinearLayout></LinearLayout>

tab_bg样式(新建drawable>tab_bg.xml)

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" ><stroke
        android:width="1.5dp"android:color="#eee" /><solid android:color="#f7f7f7" /></shape>

命名空间(values>attr.xml)

    <attr name="tab_icon" format="reference"></attr><attr name="tab_color" format="color"></attr><attr name="tab_text" format="string"></attr><attr name="tab_text_size" format="dimension"></attr><declare-styleable name="TabIcon"><attr name="tab_icon"></attr><attr name="tab_color"></attr><attr name="tab_text"></attr><attr name="tab_text_size"></attr></declare-styleable>

图标渐变效果参考Hyman老师的文章

http://blog.csdn.net/lmj623565791/article/details/41087219

其实底部效果无非就是这张图
这里写图片描述

讲解一下:如同上图,现在我们假设有两张图片Src和Dst,当我们把两张图拼在一起的时候会有后面13种情况,拿我们要用到的DstIn举例,”重合部分显示Dst”就会出现那个样式,同理可得其他.

那么就很好理解了 我底下放一个有颜色的控件,上面放一张透明背景的图标,当样式为DstIn时,两方重合部分显示颜色,就得到前面此效果了,至于渐变无非就是透明度随移动而变化.

书写TabIcon类来自定义这种View

public class TabIcon extends View {private int mColor = 0xff45c01a;private Bitmap mIconBitmap;private String mText = "iWord";private int mTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 12,getResources().getDisplayMetrics());private Canvas mCanvas;private Bitmap mBitmap;private Paint mPaint;private float mAlpha;private Rect mIconRect;private Rect mTextBound;private Paint mTextPaint;public TabIcon(Context context) {this(context, null);}public TabIcon(Context context, AttributeSet attrs) {this(context, attrs, 0);}/*** 获取自定义属性的值* * @param context* @param attrs* @param defStyleAttr*/public TabIcon(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TabIcon);int n = a.getIndexCount();for (int i = 0; i < n; i++) {int attr = a.getIndex(i);switch (attr) {case R.styleable.TabIcon_tab_icon:BitmapDrawable drawable = (BitmapDrawable) a.getDrawable(attr);mIconBitmap = drawable.getBitmap();break;case R.styleable.TabIcon_tab_color:mColor = a.getColor(attr, mColor);break;case R.styleable.TabIcon_tab_text:mText = a.getString(attr);break;case R.styleable.TabIcon_tab_text_size:mTextSize = (int) a.getDimension(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 12,getResources().getDisplayMetrics()));break;}}a.recycle();mTextBound = new Rect();mTextPaint = new Paint();mTextPaint.setTextSize(mTextSize);mTextPaint.setColor(0xff555555);mTextPaint.getTextBounds(mText, 0, mText.length(), mTextBound);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int iconWidth = Math.min(getMeasuredWidth() - getPaddingLeft() - getPaddingRight(),getMeasuredHeight() - getPaddingTop() - getPaddingBottom() - mTextBound.height());int left = getMeasuredWidth() / 2 - iconWidth / 2;int top = getMeasuredHeight() / 2 - (mTextBound.height() + iconWidth) / 2;mIconRect = new Rect(left, top, left + iconWidth, top + iconWidth);}@Overrideprotected void onDraw(Canvas canvas) {canvas.drawBitmap(mIconBitmap, null, mIconRect, null);int alpha = (int) Math.ceil(255 * mAlpha);setupTargetBitmap(alpha);drawSourceText(canvas, alpha);drawTargetText(canvas, alpha);canvas.drawBitmap(mBitmap, 0, 0, null);}/*** 绘制变色文本* * @param canvas* @param alpha*/private void drawTargetText(Canvas canvas, int alpha) {mTextPaint.setColor(mColor);mTextPaint.setAlpha(alpha);int x = getMeasuredWidth() / 2 - mTextBound.width() / 2;int y = mIconRect.bottom + mTextBound.height();canvas.drawText(mText, x, y, mTextPaint);}/*** 绘制文本* * @param canvas* @param alpha*/private void drawSourceText(Canvas canvas, int alpha) {mTextPaint.setColor(0xff333333);mTextPaint.setAlpha(255 - alpha);int x = getMeasuredWidth() / 2 - mTextBound.width() / 2;int y = mIconRect.bottom + mTextBound.height();canvas.drawText(mText, x, y, mTextPaint);}/*** 绘制可变色Icon* * @param alpha*/private void setupTargetBitmap(int alpha) {mBitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Config.ARGB_8888);mCanvas = new Canvas(mBitmap);mPaint = new Paint();mPaint.setColor(mColor);mPaint.setAntiAlias(true);mPaint.setDither(true);mPaint.setAlpha(alpha);mCanvas.drawRect(mIconRect, mPaint);mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));mPaint.setAlpha(255);mCanvas.drawBitmap(mIconBitmap, null, mIconRect, mPaint);}public void setIconAlpha(float alpha) {this.mAlpha = alpha;invalidateView();}/*** 重绘*/private void invalidateView() {if (Looper.getMainLooper() == Looper.myLooper()) {invalidate();} else {postInvalidate();}}private static final String INSTANCE_STATUS = "instance_status";private static final String STATUS_ALPHA = "status_alpha";@Overrideprotected Parcelable onSaveInstanceState() {Bundle bundle = new Bundle();bundle.putParcelable(INSTANCE_STATUS, super.onSaveInstanceState());bundle.putFloat(STATUS_ALPHA, mAlpha);return bundle;}@Overrideprotected void onRestoreInstanceState(Parcelable state) {if(state instanceof Bundle){Bundle bundle = (Bundle) state;mAlpha = bundle.getFloat(STATUS_ALPHA);super.onRestoreInstanceState(bundle.getParcelable(INSTANCE_STATUS));return;}super.onRestoreInstanceState(state);}}

再说一遍,颜色渐变代码属于完全抄袭完全,呵呵哒…

好主界面tab的UI就完成了,下一篇实现第一个fragment查词.

这篇关于天天背单词--的设计与实现(二)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/340889

相关文章

SpringBoot3实现Gzip压缩优化的技术指南

《SpringBoot3实现Gzip压缩优化的技术指南》随着Web应用的用户量和数据量增加,网络带宽和页面加载速度逐渐成为瓶颈,为了减少数据传输量,提高用户体验,我们可以使用Gzip压缩HTTP响应,... 目录1、简述2、配置2.1 添加依赖2.2 配置 Gzip 压缩3、服务端应用4、前端应用4.1 N

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

使用Python实现快速搭建本地HTTP服务器

《使用Python实现快速搭建本地HTTP服务器》:本文主要介绍如何使用Python快速搭建本地HTTP服务器,轻松实现一键HTTP文件共享,同时结合二维码技术,让访问更简单,感兴趣的小伙伴可以了... 目录1. 概述2. 快速搭建 HTTP 文件共享服务2.1 核心思路2.2 代码实现2.3 代码解读3.

MySQL双主搭建+keepalived高可用的实现

《MySQL双主搭建+keepalived高可用的实现》本文主要介绍了MySQL双主搭建+keepalived高可用的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、测试环境准备二、主从搭建1.创建复制用户2.创建复制关系3.开启复制,确认复制是否成功4.同

Java实现文件图片的预览和下载功能

《Java实现文件图片的预览和下载功能》这篇文章主要为大家详细介绍了如何使用Java实现文件图片的预览和下载功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... Java实现文件(图片)的预览和下载 @ApiOperation("访问文件") @GetMapping("

使用Sentinel自定义返回和实现区分来源方式

《使用Sentinel自定义返回和实现区分来源方式》:本文主要介绍使用Sentinel自定义返回和实现区分来源方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Sentinel自定义返回和实现区分来源1. 自定义错误返回2. 实现区分来源总结Sentinel自定

Java实现时间与字符串互相转换详解

《Java实现时间与字符串互相转换详解》这篇文章主要为大家详细介绍了Java中实现时间与字符串互相转换的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、日期格式化为字符串(一)使用预定义格式(二)自定义格式二、字符串解析为日期(一)解析ISO格式字符串(二)解析自定义

opencv图像处理之指纹验证的实现

《opencv图像处理之指纹验证的实现》本文主要介绍了opencv图像处理之指纹验证的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录一、简介二、具体案例实现1. 图像显示函数2. 指纹验证函数3. 主函数4、运行结果三、总结一、