メモ:gruntが動作しない

[root@rhel76 ~]# grunt
/usr/lib/node_modules/grunt-cli/node_modules/micromatch/index.js:44
let isMatch = picomatch(String(patterns[i]), { ...options, onResult }, true);
^^^

SyntaxError: Unexpected token ...
at createScript (vm.js:56:10)
at Object.runInThisContext (vm.js:97:10)
at Module._compile (module.js:549:28)
at Object.Module._extensions..js (module.js:586:10)
at Module.load (module.js:494:32)
at tryModuleLoad (module.js:453:12)
at Function.Module._load (module.js:445:3)
at Module.require (module.js:504:17)
at require (internal/module.js:20:19)
at Object.<anonymous> (/usr/lib/node_modules/grunt-cli/node_modules/findup-sync/index.js:12:10)


アンサー:
Nodeのバージョンが古いと推測します。
Spread syntax(...)はNode 8.6.0以降でサポートされている比較的新しい構文です。
このリンクで説明されている手順のいずれかに従ってNodeのバージョンをアップデートしてみてください。

nodeの最新実行環境を使えば良い

teratail.com

Dockerコンテナ node実行環境 web向け

Dockerfileを用意

#--------------------------------------------------------------------------
# image setup
#--------------------------------------------------------------------------
FROM node:latest

#--------------------------------------------------------------------------
# install grunt-cli
#--------------------------------------------------------------------------
RUN npm install -g grunt-cli

#--------------------------------------------------------------------------
# install sass
#--------------------------------------------------------------------------
RUN npm install -g sass

#--------------------------------------------------------------------------
# set the working directory
#--------------------------------------------------------------------------
WORKDIR /var/www

コンテナイメージをビルド

docker build -t mynode .

bashで起動

docker run -it --rm -v `pwd`:/var/www mynode bash

Android 12 Beta 1

Android 12 Beta 1 - Google Japan Blog

Beta1 には注目すべき点がいくつもあります。まず、「Material You」というデザイン言語を採用し、Android 史上最大の変更が行われた UI です。さらに、おおよその位置情報を提供する設定など、ぜひ試していただきたい新しいプライバシー機能や、アプリとユーザーが高性能なデバイスを確認できる「パフォーマンス クラス」という新しい基準も導入しています。

  • Material You
  • 再設計されたウィジェット
  • 動的なカラー API
  • ストレッチ オーバースクロール
  • よりスムーズな音声の遷移
  • 通知トランポリンの制限
  • パフォーマンス クラス
  • アプリの休止状態(ハイバネーション
  • 近くのデバイスを探す権限
  • おおよその位置

ViewPager2, TabLayoutを用いてタブ付きスワイプビューを作成。そのタブを無限ループさせる。

ViewPager2, TabLayoutを用いてタブ付きスワイプビューを作成する。さらにそのタブ,スワイプを無限ループできるようにする。
参考にしたのはこれら

もちろんkotlinで実装します。バージョンは1.4.21
主要な登場クラスはViewPager2, TabLayout, FragmentStateAdapter, Fragment

仕組みとしては、表示したいものが10ページあるとしたら、

[10][1][2][3][4][5][6][7][8][9][10][1]

つまりは実際のページ数に+2して、両端に実際の最後のページと最初のページをくっつけるということ。

FragmentStateAdapter側の実装

private val REAL_PAGE_SIZE = 10

class CollectionAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {

    override fun getItemCount(): Int = REAL_PAGE_SIZE + 2

    fun getRealCount() = REAL_PAGE_SIZE

    fun getRealPosition(position: Int): Int {
        return when (position) {
            0 -> getRealCount() - 1
            getRealCount() + 1 -> 0
            else -> position - 1
        }
    }

    // Return a NEW fragment instance in createFragmt
    override fun createFragment(position: Int): Fragment {
        val i = getRealPosition(position)
        return ItemFragment.newInstance("$i")
    }
}

ViewPager2,TabLayout側の実装

class BlankFragment : Fragment() {

    private var _binding: FragmentBlankBinding? = null
    private val binding get() = _binding!!

    private lateinit var collectionAdapter: CollectionAdapter
    private lateinit var viewPager: ViewPager2

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentBlankBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        collectionAdapter = CollectionAdapter(this)
        viewPager = binding.pager
        viewPager.apply {
            adapter = collectionAdapter

            registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {

                private var realPosition = -1

                override fun onPageScrollStateChanged(state: Int) {
                    if (state == ViewPager2.SCROLL_STATE_IDLE && realPosition >= 0) {
                        viewPager.setCurrentItem(realPosition, false)
                        realPosition = -1
                    }
                }

                override fun onPageSelected(position: Int) {
                    when (position) {
                        0 -> realPosition = collectionAdapter.getRealCount()
                        collectionAdapter.getRealCount() + 1 -> realPosition = 1
                        else -> {
                        }
                    }
                }
            })
            setCurrentItem(1, false)
        }

        val tabLayout = binding.tabLayout
        tabLayout.tabMode = TabLayout.MODE_SCROLLABLE
        TabLayoutMediator(tabLayout, viewPager) { tab, position ->
            val i = collectionAdapter.getRealPosition(position)
            tab.text = "PAGE ${(i + 1)}"
        }.attach()

    }

    companion object {
        ...
    }
}

ViewPager2を持つFragmentのxml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".BlankFragment">

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

</LinearLayout>

このリポジトリ GitHub - ochim/extend-affirmationsで使っています。

以上

2018年09月02日のツイート

2018年09月01日のツイート