在activity中我们一般使用这三个方法 initUI() initListener() initData().
//initView() Button bt=(Button) findViewById(R.id.bt); //initListener 这个监听器 一般用于监听其他的事件,不用于监听按钮 bt.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { } }); //initData(); bt.setText("xxxxx"); //processClick(); //这个类主要用于接收 控件的监听器 比如按钮之内的,用你的activity去实现监听器 //后就用这个方法去实现方法。
项目的一些规范用法:
一般我们在写项目的时候,会去定义一个BaseActivity。用这个Activity作为抽象基类,
然后暴露一些抽象方法,这样你在要写的Activity去继承这个基类的Activity,这样你只需要去重写他的抽象方法就可以了。
我们一般会写一个基类专门的包 com.xxx.xxx.base
package com.chen.textttt.base; import android.app.Activity; import android.os.Bundle; public abstract class BaseActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initView(); initListener(); initData(); } public abstract void initView(); public abstract void initListener(); public abstract void initData();
//这个步骤可以避免强转。直接调用这个方法即可 public <T> T findView(int id) { @SuppressWarnings("unchecked") T view = (T) findViewById(id); return view; } }
然后我们会使用activity去继承这个类 然后实现方法,这样的好处在于你就不需要在你的Activity里面写很长的方法。在onCreate里面。
这里注意一点:就是我们的setContenView();方法要写在initView()里面,不写在BaseActivity里面的原因就是因为,每一个Acitivity都应该又自己决定自己的布局。
public class MainActivity extends BaseActivity { private Button bt; public void initView() { setContentView(R.layout.activity_main); bt = (Button) findViewById(R.id.bt); } public void initListener() { bt.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { } }); } public void initData() { bt.setText("xxxxx"); } }
这里我们一般不用initListener 去实现监听方法。一般用是这样去实现的。
我们先在BaseActivity里面去实现点击事件的监听。
然后去实现onclick方法。因为我们的点击事件的方法是给其他继承它的类实现的。
所以我们需要提供一个抽象方法,然后在点击的时候实现这个方法。这样继承baseactivcity的Activity只需要实现这个方法就可以实现点击事件了。
public class MainActivity extends BaseActivity { private Button bt; public void initView() { setContentView(R.layout.activity_main); bt = (Button) findViewById(R.id.bt); } public void initListener() { //这里就是因为你继承了BaseActivity所以相当于已经实现了 这个监听器。所以直接传递当前类的对象即可 bt.setOnClickListener(this); } public void initData() { bt.setText("xxxxx"); } @Override public void progressClick(View v) { //这里就是处理当前监听的事件的内容 switch (v.getId()) { case value: break; default: break; } } }
public abstract class BaseActivity extends Activity implements OnClickListener { public abstract void processClick(View v); @Override public void onClick(View v) { progressClick(v); } }
————————————————————————————————————
ViewPager 的介绍:
中间是一个ViewPager:由于是扩展包中的类所以我们在xml中定义的时候需要全包名
ViewPager是android扩展包v4包中的类,这个类可以让用户左右切换当前的view。
1)ViewPager类直接继承了ViewGroup类(相当于Layout),所有它是一个容器类,可以在其中添加其他的view类。
2)ViewPager类需要一个PagerAdapter适配器类给它提供数据。
3)ViewPager经常和Fragment一起使用,并且提供了专门的FragmentPagerAdapter和FragmentStatePagerAdapter类供Fragment中的ViewPager使用。
<android.support.v4.view.ViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="match_parent" > </android.support.v4.view.ViewPager>
小知识:如何查看扩展包中的类的源码
首先找到你的sdk位置,然后找到extras,然后找到android,然后找到support\v4\src
复制地址C:\Users\xx\AppData\Local\Android\sdk\extras\android\support\v4\src
然后在libs里面创建一个文件,名字为: android-support-v4.jar.properties
然后在这个文件里面写入
src=C:\\Users\\CC\\AppData\\Local\\Android\\sdk\\extras\\android\\support\\v4\\src
这里注意需要把斜杠写成转义字符。然后重启即可。
你就可以去扩展包里面找你想要查看的类 双击即可。
————————————————————————
选项卡栏的布局设计:
这里绿色和蓝色是线性布局 最外面是相对布局。
<RelativeLayout android:layout_width="match_parent" android:layout_height="60dp" android:background="#292B28" > <View android:layout_width="60dp" android:layout_height="4dp" android:layout_alignParentBottom="true" android:background="#CE0000" /> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:orientation="vertical" > <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/img_conversation" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="会话" android:textColor="#FFFFFF" android:textSize="14sp" /> </LinearLayout>这里只是一个例子,我们需要注意这个红线我们只能在 代码中动态的去设置他的宽。
————————————————————————————————
定义Fragment基类&FragmentPagerAdapter:
我们先在initView()中找到ViewPage控件。
由于我们的ViewPage控件控制的是三个Fragment所以,我们和activity一样,先定义一个基类的Fragment.
public abstract class BaseFragment extends Fragment implements OnClickListener{ //返回一个view对象 这个对象会作为fragment显示的内容 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { //注意这里我们不能直接去实现fragment显示的内容,因为这是一个基类 //所以我们需要暴露一个抽象方法出去 return initView(inflater, container, savedInstanceState); } //跟Fragment关联的Activity被创建的时候调用 @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); //因为我们需要在activity创建的时候才去调用这两个方法 initListener(); initData(); } public abstract View initView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState); public abstract void initListener(); public abstract void initData(); public abstract void processClick(View v); @Override public void onClick(View v) { processClick(v); } }
由于ViewPage需要显示数据 他和ListView一样 需要一个Adapter.
pageAdapter:给viewpage设置一个View对象不适合Fragment。
所以我们一般使用FragmentPageAdapter: 这个就是给viewpage设置一个Fragment.
public class MainAdapter extends FragmentPagerAdapter { List<Fragment> fragments; public MainAdapter(FragmentManager fm, List<Fragment> fragments) { super(fm); this.fragments = fragments; } @Override public Fragment getItem(int position) { return fragments.get(position); } @Override public int getCount() { return fragments.size(); } }
————————————————————————————————————
ViewPager显示三个Fragment:
首先我们需要创建三个Fragment继承我们前面写的BaseFragment;
public class ConversionFragment extends BaseFragment { @Override public View initView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_conversation, null); return view; } @Override public void initListener() { } @Override public void initData() { } @Override public void processClick(View v) { } }
创建好三个Fragment 之后我们要去定义三个布局文件来给Fragment作为显示。
设置好之后我们就可以在activity里面给ViewPage设置他的adapter
public class MainActivity extends BaseActivity { private ViewPager viewPager; private List<Fragment> fragments; public void initView() { setContentView(R.layout.activity_main); viewPager = (ViewPager) findViewById(R.id.viewPager); } public void initListener() { } public void initData() { fragments = new ArrayList<Fragment>(); ConversionFragment fragment1 = new ConversionFragment(); GroupFragment fragment2 = new GroupFragment(); SearchFragment fragment3 = new SearchFragment(); fragments.add(fragment1); fragments.add(fragment2); fragments.add(fragment3); //这里由于我们使用的Fragment是V4包下面的所以,我们要获取FragmentManager //就需要我们的BaseActivity继承FragmentActivity才可以。 //然后通过getSupportFragmentManager()去获得FragmentManager MainAdapter adapter = new MainAdapter(getSupportFragmentManager(), fragments); viewPager.setAdapter(adapter); } @Override public void progressClick(View v) { } }
__________________________________________________________
改变选项卡的文字大小和颜色:
我们需要修改这些属性,需要在viewPage改变的时候去修改,所以我们先给他一个监听器。
addOnPageChangeListener();
将这个方法写在 initListener()里面,这是因为只有这一个activity才使用它,所以不需要再BaseActivity里面定义方法。
public void initListener() { viewPager.addOnPageChangeListener(new OnPageChangeListener() { //当界面切换完成的时候调用。返回当前界面的索引。索引是从0开始 @Override public void onPageSelected(int position) { textColorAndScale(); } //当你移动的时候就可以调用这个方法 @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } //当用户开始拖动的时候调用 @Override public void onPageScrollStateChanged(int state) { } }); }
protected void textColorAndScale() { int item = viewPager.getCurrentItem(); tv_conversation.setTextColor(item == 0 ? Color.WHITE : Color.BLACK); tv_group.setTextColor(item == 1 ? Color.WHITE : Color.BLACK); tv_search.setTextColor(item == 2 ? Color.WHITE : Color.BLACK); switch (item) { case 0: ObjectAnimator.ofFloat(tv_conversation, "scaleY", 1, 1.2f).start(); ObjectAnimator.ofFloat(tv_conversation, "scaleX", 1, 1.2f).start(); break; case 1: ObjectAnimator.ofFloat(tv_group, "scaleY", 1, 1.2f).start(); ObjectAnimator.ofFloat(tv_group, "scaleX", 1, 1.2f).start(); break; case 2: ObjectAnimator.ofFloat(tv_search, "scaleY", 1, 1.2f).start(); ObjectAnimator.ofFloat(tv_search, "scaleX", 1, 1.2f).start(); break; } }
点击选项卡切换:
viewPage.的监听器里面 的:
onPageSelected(int position)方法不仅在界面切换时会调用,在你的索引改变的时候也会调用。
所以我们只需要在点击三个绿色布局的时候调用监听器,然后点击事件的时候去设置
viewPage的当前界面的索引即可
@Override public void progressClick(View v) { switch (v.getId()) { case R.id.ll_tab_conversation: viewPager.setCurrentItem(0); break; case R.id.ll_tab_group: viewPager.setCurrentItem(1); break; case R.id.ll_tab_search: viewPager.setCurrentItem(2); break; }
——————————————————————————————————————
选项卡的红线移动;
我们先在initView()里面找到控件。
然后在 initData();里面去写一个方法setIndicationline();
private void setIndicationline() { int width = getWindowManager().getDefaultDisplay().getWidth();//通过这API获取屏幕宽度 tab_indication_red.getLayoutParams().width=width/3;//通过这个API设置控件的宽度 }
然后我们要去动态的改变红线和我们的移动屏幕一起变换。
//viewpager界面切换时会触发 viewPager.setOnPageChangeListener(new OnPageChangeListener() { //切换完成后调用,传入的参数是切换后的界面的索引 @Override public void onPageSelected(int position) { textLightAndScale(); } //滑动过程不断调用 //如果滑动过程中出现两个界面,position是前一个的索引 @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { System.out.println(positionOffsetPixels); //计算红线位移的距离 int distance = positionOffsetPixels / 3; //持续时间为0,立刻生效,因为红线的移动需要与用户滑动同步 ViewPropertyAnimator.animate(v_indicate_line).translationX(distance + position * v_indicate_line.getWidth()).setDuration(0); } @Override public void onPageScrollStateChanged(int state) { // TODO Auto-generated method stub } });
不一样。
第一个方法中position是当你的界面移动完成的时候才会变。
第二个方法中的position是当你的界面只要你一移动就会变,根据你的移动方向变,
比如你向右移动那么你一移动,就会变成你移动方向界面的索引。
这个方法ViewPropertyAnimator.animate(v_indicate_line).translationX(distance + position * v_indicate_line.getWidth()).setDuration(0);
是在nineoldandroids-2.4.0.jar 库文件中的方法。
这个方法是可以兼容9以下的API,所以我们可以使用这个方法,
onPageScrolled()这个方法中的positionOffsetPixels这个参数的意思就是动态获取你的
移动的像素,当移动结束后就会变成0,你向右移动会增大,向左移会变小。
只要你移动就会获取你的像素。
我们为了给红线动态的和屏幕移动一起变化,所以我们需要用到这个参数。
distance=positionOffsetPixels/3;
因为positionOffsetPixels就是获取你一个界面移动到另外一个界面的像素。
相当于你手机屏幕的宽度。
当时positionOffsetPixels这个参数 停止移动后会变成0,也就是说你移动过后红线还是会变成他的初始值。
所以我们应该动态的给红线添加初始值。
distance+ position * 控件id.getwidth();
因为你每次移动相当于下一个界面的索引*控件的宽度作为初始值。
但是有一个小问题,当你移动到最右边的时候。你向左移,但是distance 还是正数。
按道理下一个初始值应该还是会变大,但是没有变大。
原因就是因为position只要你一移动 ,它就会变,也就是说你向左一移动,马上就会变小。
所以才会导致我们的红线还能变回去。