移动周分享-第43期

tablayout方法setupWithViewPager()坑 - 吴明

  • tallayout平常使用setupWithViewPager()
1
2
3
4
ViewPager viewPager=(ViewPager)findViewById(R.id.view_pager);
TabLayout tabContainView = (TabLayout) findViewById(R.id.pick_school_category_contain);
viewPager.setAdatper(new FragmentStatePagerAdapter(FragmentManager,fragments));
tabContainView. setupWithViewPager(viewPager);
  • 查看setupWithViewPager()方法源码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public void setupWithViewPager(@NonNull ViewPager viewPager) {
final PagerAdapter adapter = viewPager.getAdapter();
if (adapter == null) {
throw new IllegalArgumentException("ViewPager does not have a PagerAdapter set");
}

// First we'll add Tabs, using the adapter's page titles
setTabsFromPagerAdapter(adapter);

// Now we'll add our page change listener to the ViewPager
viewPager.addOnPageChangeListener(new TabLayoutOnPageChangeListener(this));

// Now we'll add a tab selected listener to set ViewPager's current item
setOnTabSelectedListener(new ViewPagerOnTabSelectedListener(viewPager));

// Make sure we reflect the currently set ViewPager item
if (adapter.getCount() > 0) {
final int curItem = viewPager.getCurrentItem();
if (getSelectedTabPosition() != curItem) {
selectTab(getTabAt(curItem));
}
}
}
  • 就会发现这里有三个坑

    • setTabsFromPagerAdapter

      1
      2
      3
      4
      5
      6
      public void setTabsFromPagerAdapter(@NonNull PagerAdapter adapter) {
      removeAllTabs();
      for (int i = 0, count = adapter.getCount(); i < count; i++) {
      addTab(newTab().setText(adapter.getPageTitle(i)));
      }
      }

      removeAllTabs()这个就是说把前面所有tablayout添加的view都删掉。也就是说在之前不管怎么处理view都被干掉。然后设置为PagerAdapter返回的title

    • setOnTabSelectedListener(new ViewPagerOnTabSelectedListener(viewPager));

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      public static class ViewPagerOnTabSelectedListener implements TabLayout.OnTabSelectedListener {
      private final ViewPager mViewPager;

      public ViewPagerOnTabSelectedListener(ViewPager viewPager) {
      mViewPager = viewPager;
      }

      @Override
      public void onTabSelected(TabLayout.Tab tab) {
      mViewPager.setCurrentItem(tab.getPosition());
      }

      @Override
      public void onTabUnselected(TabLayout.Tab tab) {
      // No-op
      }

      @Override
      public void onTabReselected(TabLayout.Tab tab) {
      // No-op
      }
      }

      这里主要不算不算太坑,最主要的是设置了点击tablayot默认是viewpager是滚动的,自己可以设置这个时间监听。重写他的方法

    • selectTab(getTabAt(curItem));

      1
      2
      3
      4
      5
      6
      if (adapter.getCount() > 0) {
      final int curItem = viewPager.getCurrentItem();
      if (getSelectedTabPosition() != curItem) {
      selectTab(getTabAt(curItem));
      }
      }

      这里最主要是第一次默认选中第一个。相对应一些viewpager第一次就选中的不是第一个,这个就是一个很大的一个问题就是相当于viewpager点击了两次。

    • 分享这个坑主要是给大家提前填。以后还是不能偷懒就为了省代码而忘了看封装的方法的代码是不是有问题。

Chrome Custom Tabs 标签优点 - 王进

  • Chrome自定义标签页(Custom Tabs)将允许应用预加载,从而将网页的加载时间直接减半。

它的速度比WebView更快,预加载的效果甚至好于Chrome本身。

  • 持良好的用户体验,并且让用户感觉这个自定义 Tab 就是您应用的一部分。

  • 使用方法比WebView 简单,只需要一行代码,和直接调用系统浏览器显示网页没啥区别

  • 有大量自定义属性,改善用户体验

使用方法

需要导入Custom Tabs 的支持包:

compile ‘com.android.support:customtabs:23.1.0’

最简单的使用方式是只需要使用 CustomTabsIntent.Builder 对象来设置一些常用自定义选项,然后调用 CustomTabsIntent.launchUrl(Activity context, Uri url)) 函数即可。当然在具体使用过程中,您还需要判断用户手机是否支持 Custom Tabs。

配置属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 CustomTabsIntent.Builder intentBuilder = new CustomTabsIntent.Builder();

// 修改 ActionBar 的颜色
intentBuilder.setToolbarColor(Color.RED);

// 添加一个分享按钮
String shareLabel = "分享";
Bitmap icon = BitmapFactory.decodeResource(getResources(), android.R.drawable.ic_menu_share);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, BlankActivity.class), 0);
intentBuilder.setActionButton(icon, shareLabel, pendingIntent);

//添加Menu 按钮
intentBuilder.addMenuItem("打开", pendingIntent);

//是否显示网页标题
intentBuilder.setShowTitle(true);

//隐藏网页Bar
intentBuilder.enableUrlBarHiding();

//自定义关闭 Custom tabs 的图标
intentBuilder.setCloseButtonIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher));

//自定义 Activity 转场 动画
intentBuilder.setStartAnimations(this, R.anim.slide_in_right, R.anim.slide_out_left);
intentBuilder.setExitAnimations(this, android.R.anim.slide_in_left, android.R.anim.slide_out_right);

CustomTabsIntent customTabsIntent = intentBuilder.build();
// customTabsIntent.launchUrl(this, Uri.parse("http://www.51offer.com/"));

Android NDK 入门 - 杨俊构

什么是NDK?

  • NDK是一系列工具的集合

NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk。这些工具对开发者的帮助是巨大的。
NDK集成了交叉编译器,并提供了相应的mk文件隔离CPU、平台、ABI等差异,开发人员只需要简单修改mk文件(指出“哪些文件需要编译”、“编译特性要求”等),就可以创建出so。
NDK可以自动地将so和Java应用一起打包,极大地减轻了开发人员的打包工作。

  • NDK提供了一份稳定、功能有限的API头文件声

Google明确声明该API是稳定的,在后续所有版本中都稳定支持当前发布的API。从该版本的NDK中看出,这些API支持的功能非常有限,包含有:C标准库(libc)、标准数学库(libm)、压缩库(libz)、Log库(liblog)。

为什么使用NDK

  1. 代码的保护。由于apk的java层代码很容易被反编译,而C/C++库反汇难度较大。
  2. 可以方便地使用现存的开源库。大部分现存的开源库都是用C/C++代码编写的。
  3. 提高程序的执行效率。将要求高性能的应用逻辑使用C开发,从而提高应用程序的执行效率。
  4. 便于移植。用C/C++写得库可以方便在其他的嵌入式平台上再次使用

如何使用NDK

  • Android JNI 原理

    Android上层的Application和ApplicationFramework都是使用Java编写,底层包括系统和使用众多的LIiraries都是C/C++编写的。所以上层Java要调用底层的C/C++函数库必须通过Java的JNI来实现。

  • Android studio NDK 开发

  1. 解压NDK开发工具集
  2. 打开android studio,新建Android工程
  3. 点击:File ->ProjectStructure:如图:
  4. 在 local.properties 文件中设置ndk的路径
  5. 在 gradle.properties 添加”android.useDeprecatedNdk=true”
  6. 在 build.gradle 添加NDK 的配置
  7. 添加JAVA 接口类文件
1
2
3
4
5
6
7
8
package com.example.jungou.jnitest;
// Created by jungou on 2016/1/28 0028.
public class JniApi {
static {
System.loadLibrary("jesonlib");
}
private native String getTitle();
}
  1. 添加jni文件夹
  2. JAVA 接口类使用Alt+回车 自动修正,自动实现C代码
1
2
3
4
5
6
#include <jni.h>
JNIEXPORT jstring JNICALL
Java_com_example_jungou_jnitest_JniApi_getTitle(JNIEnv *env, jobject instance) {

// TODO
return (*env)->NewStringUTF(env, "hello tile");
}
  1. 完成接口调用,测试完成

demo地址