"天天背单词"--的设计与实现(二)
来源:互联网 发布:数据采集仪是什么 编辑:程序博客网 时间:2024/06/10 17:32
加上广告之后百度就不让上了,客服说让我在线配置隐藏广告在上架,我可不是那种藏着掖着的人,哈哈,所以只能在云盘下载了
- 下载地址:
https://yunpan.cn/cqt5xp3QAJsSM (提取码:ffaa)
第一大步肯定是需求分析,那么
·这个背单词的软件需要具备的功能:
- 查词
- 每日一句
- 卡片单词,单词本,等级测试,美文欣赏(具体形式后面实现时候再介绍)
- 设置(包括:个人设置,词库下载,缓存清理等)
大概就分这四个模块,所以样式就定成很大众的四个tab页实现
·数据来源及方式,数据库设计,
1.我选择了ICIBA 金山词霸API,因为相对有道等其他api接口,金山提供了单词,词音,每日一句及发音等 很全面.非常符合我们的需求.
2.数据库方面,主要就是记录查询过的单词,和单词测试里学习过的单词,字段都很相似
- 单词,英音标,美音标,英发音,美发音,释义,例句,查询次数,和答错次数.
根据需求删减某系字段即可.
今天主要说明一下ViewPger+Fragment实现主界面Tab的切换效果,先看效果:
基本原理就是ViewPager里面放了四个Fragment,就是这么简单,稍微复杂点就是底下图标的渐变效果.
首先如何在ViewPager里面放了四个Fragment
- xml里声明这个控件等价于一个TextView;
- 出镜成员: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>(); // 渐变图标集合
- 将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);
- 将List放入FragmentPagerAdapter,
mAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) { @Override public int getCount() { return mTabs.size(); } @Override public Fragment getItem(int arg0) { return mTabs.get(arg0); } };
- 最后将FragmentPagerAdapter绑定在ViewPager上 ,
mViewPager.setAdapter(mAdapter); mViewPager.setOffscreenPageLimit(10);//这句话的意思就是再每一个fragment左右各保存5个fragment页面,此参数默认为2,为2时当你滑动到第三个fragment的时候第一个已经被销毁当你滑动回来需要重新加载,数据就没了,所以设置为10,也就是当滑动到第四个依然能保存第一个.
主界面代码:
public class MainActivity extends FragmentActivity implements 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>(); // 渐变图标集合 @Override protected 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的fragment interpretFragment = 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()) { @Override public int getCount() { return mTabs.size(); } @Override public 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);//初始化图标透明度 } @Override public 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); } } @Override public void onPageScrollStateChanged(int arg0) { } @Override public 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); } } @Override public void onPageSelected(int arg0) { switch (arg0) { case 1: interpretFragment.setSearchedPosition(); break; case 3: meFragment.setTvCardCount(); break; } } // 实现查询单词数的更新 @Override public 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.ViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" > </android.support.v4.view.ViewPager> <LinearLayout android:layout_width="match_parent" android:layout_height="60dp" android:background="@drawable/tab_background" android:orientation="horizontal" > <com.qit.iword.TabIcon android: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.TabIcon android: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.TabIcon android: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.TabIcon android: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); } @Override protected 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); } @Override protected 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"; @Override protected Parcelable onSaveInstanceState() { Bundle bundle = new Bundle(); bundle.putParcelable(INSTANCE_STATUS, super.onSaveInstanceState()); bundle.putFloat(STATUS_ALPHA, mAlpha); return bundle; } @Override protected 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查词.
- "天天背单词"--的设计与实现(二)
- "天天背单词"--的设计与实现(一)
- "天天背单词"--的设计与实现(四)
- "天天背单词"--的设计与实现(三)
- 背单词的方法
- 背单词的方法
- 背单词的网站
- 背单词的心得
- 背单词的具体方法
- 一个背单词的软件
- 背单词的坏习惯
- C++ 轻松背单词 设计报告
- 背单词
- 背单词
- 背单词
- 背单词
- 背单词
- 背单词
- argparse load data from file
- 运营地方旅游网站是否还有生存空间?
- png、jpg、gif三种图片格式的区别
- Android 自定义控件需要掌握哪些
- 建站_主机的区别(windows和linux)
- "天天背单词"--的设计与实现(二)
- C# 读取数据表没有主键的问题
- 单例模式Signleton的实现及破坏
- 决定网站命脉的SEO核心关键词选取
- 8个值得关注的SQL-on-Hadoop框架
- dispatch_apply快速迭代
- SVN客户端界面完工+与服务器交互注册登录实现
- 【View】之【SimplePillarsView】可多色可圆角柱状图【demo】
- Jenkins创建slave节点----Linux平台