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

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

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

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

  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()) {

            @Override
            public int getCount() {
                return mTabs.size();
            }

            @Override
            public 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 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查词.

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Qi T

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值