node가 front end처럼 작동할때는 fs에 접근이 불가능하다. 즉 front end에서는 보안문제 방지를 위해 사용자의 컴퓨터 파일 시스템에 접근이 불가능하다. 

.

.

npm canvas를 이용해서 front end쪽에서 이미지를 create 한경우 fs 라이브러리를 사용할수 없기때문에 만들어진 이미지를 저장할수는 없지만 src path를 얻어서 바로 ui에 포함시킬수 있다.

https://stackoverflow.com/a/67231182

canvas.toDataURL()

.

.

민감한 정보는 dot env를 통해 따로 관리힌다

official doc : https://www.npmjs.com/package/dotenv

create-react-app 으로 만들어진 앱의 경우 webpack config 화일은 

The files are located in your node_modules/react-scripts folder 안에 있다.

https://stackoverflow.com/a/48395890

.

.

react checkbox event handle

https://stackoverflow.com/a/51264645

.

.

object를 가지고 있는 useState 업데이트 방법

// To resolve that you need to use object destructing every time
// results will be state = {first: 3, second: 2}
setState(prev => ({...prev, first: 3}))

https://stackoverflow.com/a/71093607

.

.

react와 dot env를 같이 사용하는 경우 주의 사항이 있는데 확인해야 한다

https://medium.com/how-to-react/using-env-file-in-react-js-b2714235e77e

https://youtu.be/8OCEfOKzpAw

react+ chrome extension 개발 세팅설명 매우 좋은 설명 

.

npm install –save react react-dom

npm install –save-dev webpack webpack-cli

npm install –save-dev babel-loader @babel/core @babel/preset-env @babel/preset-react

.

.

아래 과정은 django + django rest framework 세팅 과정

https://vomtom.at/how-to-use-uniswap-v2-as-a-developer/virtual env설치

pip install virtualenv

python3 -m venv venv

venv/Scripts/activate

requirements.txt만들어서 django 와 djangorestframework를 타입

pip install -r requirements.txt를 통해 설치

내용은 아래 그림과 같이 설치할 라이브러리를 파일안에 기입

image

django-admin startproject donkey_ears

django-admin startapp api

python manage.py migrate

python manage.py makemigrations

python manage.py createsuperuser

.

npm install –save react-router-dom

npm install –save semantic-ui-react.

.

.

npm install –save cryptico

.

npm install –save bip39

bip 39을 이용하여 mnemonic phrase를 얻으려 했으나 chrome extension에서는 사용하려면 자꾸 에러 발생 

npm install –save bitcore-mnemonic 

npm install –save url

를 대신 사용

사용법 https://www.npmjs.com/package/bitcore-mnemonic

.

npm install –save ethereum-hdwallet

npm install –save crypto

npm install –save assert

npm install –save crypto-browserify

npm install –save stream

.

.

error solution

설치후에 계속 Module not found: Error: Can’t resolve ‘crypto’ 에러 발생 해결은 아래와 같이 했다.

https://stackoverflow.com/a/67076572

*******************************************************************

react + web3, ethers

기본적으로 react를 사용할때 function , class스타일 두가지로 이용가능하다.

image

react 사용시 import하는 내용

.

클래스 스타일로 이용

image

.

함수형태이용

image

.

image

Web3.providers.HttpProvder를 통해서 만들어진 provider를 ethers에서도 provider로 사용가능할줄 알았는데 약간 다른 형태의 provider였다.

.

react에서 하위 component에게 데이터 전달하는 방법

image
image

.

react 에서 useState사용하는 방법

const [] 에서 첫번째는 state variable 이름이고 다음은 set 함수이름

useState()안은 초기값

image

.

componentDidMount과 같은 역활하는 useEffect

image

.

window.web3에 값이 할당되면 window.ethereum 에도 비슷한 값이 할당된다.

즉 window.ethereum을 통해서도 window.web3를 통해 하던 데이터를 얻을수 있으나 정확하게 같지는 않다.

window.web3안의 eth값이 있지 않은점이 크게 다른점이다. 그래서 window.ethereum.eth는 불가능하다는 이야기다. 

metamask를 이용하는 경우 Web3.providers.HttpProvider()의 작업이 필요하지 않다 metamask안에 자체 provider를 이용한다. 

metamask를 이용하는 경우 자동으로 window.ethereum 값이 설정되어있으므로 이를 이용하면 된다.

.

.

.

.

.

***********************************************************************************

***********************************************************************************

redirect 작업을 위해 useNavigate()를 이용하려고 했지만 react router를 사용해야지만 사용할수 있어서 사용하지 않고 

window.location.href = ’/popup.html?target=CreatePassword’; 와 같은 방법을 사용했다.

https://ncoughlin.com/posts/react-navigation-without-react-router/

.

react router 를 사용하지 못하고 (chrome extension에서는 일반 router기능을 이용할수 없음. 메타메스크의 경우 anchor # 를 이용했다. 아니면 query string을 이용해야 한다.)

.

useState를 통해 주입되는 component 내부에서 useState를 또 사용하는 경우 에러 발생 

avubble 프로젝트의 app.js참고해 볼것

.

jsx에서 collection data type을 iterate 하면서 tag만들어내기 

image

.

image

.

switch를 이용한 경우에 따른 component 삽입

image

.

chrome storage sync 삭제하기

image

.

pass parameters executeScript

image

https://stackoverflow.com/a/68640372

.

opensea get sing asset 

https://docs.opensea.io/reference/retrieving-a-single-asset-testnets

{
 "id": 132352212,
 "num_sales": 0,
 "background_color": null,
 "image_url": “https://i.seadn.io/gae/zNAGqUNWdnYZQDWe9NnswJrQjRAspk8MlwCvRlsdGN6UOPc1Lzc6ZmPliqUMEmyRe1fVyjwm6w-5fr__pfA7hQNC_27RCj5-iLVjNDQ?w=500&auto=format”,
 "image_preview_url": “https://i.seadn.io/gae/zNAGqUNWdnYZQDWe9NnswJrQjRAspk8MlwCvRlsdGN6UOPc1Lzc6ZmPliqUMEmyRe1fVyjwm6w-5fr__pfA7hQNC_27RCj5-iLVjNDQ?w=500&auto=format”,
 "image_thumbnail_url": “https://i.seadn.io/gae/zNAGqUNWdnYZQDWe9NnswJrQjRAspk8MlwCvRlsdGN6UOPc1Lzc6ZmPliqUMEmyRe1fVyjwm6w-5fr__pfA7hQNC_27RCj5-iLVjNDQ?w=500&auto=format”,
 "image_original_url": “https://nftstorage.link/ipfs/bafybeig76mncgmub2f7m7mordkveptk3br4wu6u6j4fhwqznez2ugiskku/0.png”,
 "animation_url": null,
 "animation_original_url": null,
 "name": “Test 0”,
 "description": “Test 0”,
 "external_link": null,
 "asset_contract": {
   "address": “0xcfaf8eb5546fae192916f73126ea2d5991cb2028”,
   "asset_contract_type": “semi-fungible”,
   "created_date": “2022-09-29T09:41:30.559731”,
   "name": “Example Game ERC 1155”,
   "nft_version": null,
   "opensea_version": null,
   "owner": 12540403,
   "schema_name": “ERC1155”,
   "symbol": “”,
   "total_supply": null,
   "description": null,
   "external_link": null,
   "image_url": null,
   "default_to_fiat": false,
   "dev_buyer_fee_basis_points": 0,
   "dev_seller_fee_basis_points": 0,
   "only_proxied_transfers": false,
   "opensea_buyer_fee_basis_points": 0,
   "opensea_seller_fee_basis_points": 250,
   "buyer_fee_basis_points": 0,
   "seller_fee_basis_points": 250,
   "payout_address": null
 },
 "permalink": “https://testnets.opensea.io/assets/goerli/0xcfaf8eb5546fae192916f73126ea2d5991cb2028/0”,
 "collection": {
   "payment_tokens": [
     {
       "id": 1507176,
       "symbol": “ETH”,
       "address": “0x0000000000000000000000000000000000000000”,
       "image_url": “https://openseauserdata.com/files/6f8e2979d428180222796ff4a33ab929.svg”,
       "name": “Ether”,
       "decimals": 18,
       "eth_price": 1,
       "usd_price": 1592.29
     },
     {
       "id": 1507152,
       "symbol": “WETH”,
       "address": “0xb4fbf271143f4fbf7b91a5ded31805e42b2208d6”,
       "image_url": “https://openseauserdata.com/files/accae6b6fb3888cbff27a013729c22dc.svg”,
       "name": “Wrapped Ether”,
       "decimals": 18,
       "eth_price": 1,
       "usd_price": 1593.2
     }
   ],
   "primary_asset_contracts": [
     {
       "address": “0xcfaf8eb5546fae192916f73126ea2d5991cb2028”,
       "asset_contract_type": “semi-fungible”,
       "created_date": “2022-09-29T09:41:30.559731”,
       "name": “Example Game ERC 1155”,
       "nft_version": null,
       "opensea_version": null,
       "owner": 12540403,
       "schema_name": “ERC1155”,
       "symbol": “”,
       "total_supply": null,
       "description": null,
       "external_link": null,
       "image_url": null,
       "default_to_fiat": false,
       "dev_buyer_fee_basis_points": 0,
       "dev_seller_fee_basis_points": 0,
       "only_proxied_transfers": false,
       "opensea_buyer_fee_basis_points": 0,
       "opensea_seller_fee_basis_points": 250,
       "buyer_fee_basis_points": 0,
       "seller_fee_basis_points": 250,
       "payout_address": null
     }
   ],
   "traits": {},
   "stats": {
     "one_hour_volume": 0,
     "one_hour_change": 0,
     "one_hour_sales": 0,
     "one_hour_sales_change": 0,
     "one_hour_average_price": 0,
     "one_hour_difference": 0,
     "six_hour_volume": 0,
     "six_hour_change": 0,
     "six_hour_sales": 0,
     "six_hour_sales_change": 0,
     "six_hour_average_price": 0,
     "six_hour_difference": 0,
     "one_day_volume": 0,
     "one_day_change": 0,
     "one_day_sales": 0,
     "one_day_sales_change": 0,
     "one_day_average_price": 0,
     "one_day_difference": 0,
     "seven_day_volume": 0,
     "seven_day_change": 0,
     "seven_day_sales": 0,
     "seven_day_average_price": 0,
     "seven_day_difference": 0,
     "thirty_day_volume": 0,
     "thirty_day_change": 0,
     "thirty_day_sales": 0,
     "thirty_day_average_price": 0,
     "thirty_day_difference": 0,
     "total_volume": 0,
     "total_sales": 0,
     "total_supply": 1,
     "count": 1,
     "num_owners": 1,
     "average_price": 0,
     "num_reports": 0,
     "market_cap": 0,
     "floor_price": 0
   },
   "banner_image_url": null,
   "chat_url": null,
   "created_date": “2022-09-29T09:41:30.933452+00:00”,
   "default_to_fiat": false,
   "description": null,
   "dev_buyer_fee_basis_points": “0”,
   "dev_seller_fee_basis_points": “0”,
   "discord_url": null,
   "display_data": {
     "card_display_style": “contain”,
     "images": []
   },
   "external_url": null,
   "featured": false,
   "featured_image_url": null,
   "hidden": false,
   "safelist_request_status": “not_requested”,
   "image_url": null,
   "is_subject_to_whitelist": false,
   "large_image_url": null,
   "medium_username": null,
   "name": “Example Game ERC 1155”,
   "only_proxied_transfers": false,
   "opensea_buyer_fee_basis_points": “0”,
   "opensea_seller_fee_basis_points": “250”,
   "payout_address": null,
   "require_email": false,
   "short_description": null,
   "slug": “example-game-erc-1155”,
   "telegram_url": null,
   "twitter_username": null,
   "instagram_username": null,
   "wiki_url": null,
   "is_nsfw": false,
   "fees": {
     "seller_fees": {},
     "opensea_fees": {
       "0x0000a26b00c1f0df003000390027140000faa719": 250
     }
   },
   "is_rarity_enabled": false
 },
 "decimals": null,
 "token_metadata": “https://nftstorage.link/ipfs/bafybeihfcvvlchgu6wogre4ae3jqwigyey3kgb2ur5o3jajv3zsmyve32q/0.json”,
 "is_nsfw": false,
 "owner": {
   "user": null,
   "profile_img_url": “https://storage.googleapis.com/opensea-static/opensea-profile/1.png”,
   "address": “0x0000000000000000000000000000000000000000”,
   "config": “”
 },
 "seaport_sell_orders": null,
 "creator": {
   "user": {
     "username": null
   },
   "profile_img_url": “https://storage.googleapis.com/opensea-static/opensea-profile/2.png”,
   "address": “0x72cebbf26f93cc5913fd87076c59428b794d6786”,
   "config": “”
 },
 "traits": [
   {
     "trait_type": “Base”,
     "value": “Starfish”,
     "display_type": null,
     "max_value": null,
     "trait_count": 0,
     "order": null
   },
   {
     "trait_type": “Eye”,
     "value": “Big”,
     "display_type": null,
     "max_value": null,
     "trait_count": 0,
     "order": null
   }
 ],
 "last_sale": null,
 "top_bid": null,
 "listing_date": null,
 "is_presale": false,
 "supports_wyvern": true,
 "rarity_data": null,
 "transfer_fee": null,
 "transfer_fee_payment_token": null,
 "related_assets": [],
 "orders": null,
 "auctions": [],
 "top_ownerships": [
   {
     "owner": {
       "user": {
         "username": null
       },
       "profile_img_url": “https://storage.googleapis.com/opensea-static/opensea-profile/2.png”,
       "address": “0x72cebbf26f93cc5913fd87076c59428b794d6786”,
       "config": “”
     },
     "quantity": “3”,
     "created_date": “2022-09-29T09:44:15.755541+00:00”
   }
 ],
 "ownership": null,
 "highest_buyer_commitment": null,
 "token_id": “0”
}

.

solidity development

title generator

https://patorjk.com/

.

spdx license

// SPDX-License-Identifier: MIT

.

mumbai test contract 

0x383A22a13D2693ecE63186A594671635a4C163fB

  • controller 이름 바꾸는 방법은 
image

안에서 controller 이름을 클릭후 변경가능

  • (간단하게 canvas의 요소를 controller코드상에서 outlet으로 연결하는 방법)

You’re going to make an outlet for this text field on the PlayerDetailsViewController using the Assistant Editor feature of Xcode. While still in the storyboard, open the Assistant Editor with the button from the toolbar (the one at the top right with two intertwining rings). It should automatically open on PlayerDetailsViewController.swift (if it doesn’t, use the jumpbar in the right hand split window to select PlayerDetailsViewController.swift).

Select the new text field and ctrl-drag(오르쪽클릭은 outlet,왼쪽클릭은 action) to the top of PlayersDetailViewController, just below the class definition. When the popup appears, name the new outlet nameTextField, and click Connect. Xcode will add the property to the PlayersDetailViewController class and connect it in the storyboard:

image

  • static cells: they only work in UITableViewController. Even though Interface Builder will let you add them to a table view inside a regular UIViewController, this won’t work during runtime.

  • (특정 요소를 first responder 로 만드는 방법 )

To avoid this, let a tap anywhere inside the row bring up the keyboard. OpenPlayerDetailsViewController.swift and add the following extension to the end of the file:

// MARK: - UITableViewDelegate
extension PlayerDetailsViewController {

  override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    if indexPath.section == 0 {
      nameTextField.becomeFirstResponder()
    }
  }
}

If the user taps the first cell, the app should activate the text field. There’s only one cell in the section so you only need to test for the section index. Making the text field the first responder will automatically bring up the keyboard.

https://www.raywenderlich.com/160519/storyboards-tutorial-ios-10-getting-started-part-2

  • 예를 들어 segue에 있는 done button을 클릭해서 특정 데이터를 저장하고 modal형태의 창을 닫는 경우 두가지 이벤트를 이용할수 있다. 버튼에 연결되어있는 action과 segue가 닫히기 전에 이벤트를 전달 받는 hook 포인트 prepare 가 있다. 

https://www.raywenderlich.com/160519/storyboards-tutorial-ios-10-getting-started-part-2

  • controller 이름 바꾸는 방법은 
image

안에서 controller 이름을 클릭후 변경가능

  • (간단하게 canvas의 요소를 controller코드상에서 outlet으로 연결하는 방법)

You’re going to make an outlet for this text field on the PlayerDetailsViewController using the Assistant Editor feature of Xcode. While still in the storyboard, open the Assistant Editor with the button from the toolbar (the one at the top right with two intertwining rings). It should automatically open on PlayerDetailsViewController.swift (if it doesn’t, use the jumpbar in the right hand split window to select PlayerDetailsViewController.swift).

Select the new text field and ctrl-drag(오르쪽클릭은 outlet,왼쪽클릭은 action) to the top of PlayersDetailViewController, just below the class definition. When the popup appears, name the new outlet nameTextField, and click Connect. Xcode will add the property to the PlayersDetailViewController class and connect it in the storyboard:

image

  • static cells: they only work in UITableViewController. Even though Interface Builder will let you add them to a table view inside a regular UIViewController, this won’t work during runtime.

  • (특정 요소를 first responder 로 만드는 방법 )

To avoid this, let a tap anywhere inside the row bring up the keyboard. OpenPlayerDetailsViewController.swift and add the following extension to the end of the file:

// MARK: - UITableViewDelegate
extension PlayerDetailsViewController {

  override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    if indexPath.section == 0 {
      nameTextField.becomeFirstResponder()
    }
  }
}

If the user taps the first cell, the app should activate the text field. There’s only one cell in the section so you only need to test for the section index. Making the text field the first responder will automatically bring up the keyboard.

https://www.raywenderlich.com/160519/storyboards-tutorial-ios-10-getting-started-part-2

  • 예를 들어 segue에 있는 done button을 클릭해서 특정 데이터를 저장하고 modal형태의 창을 닫는 경우 두가지 이벤트를 이용할수 있다. 버튼에 연결되어있는 action과 segue가 닫히기 전에 이벤트를 전달 받는 hook 포인트 prepare 가 있다. 

https://www.raywenderlich.com/160519/storyboards-tutorial-ios-10-getting-started-part-2

original source : http://www.androiddocs.com/training/wearables/ui/lists.html

Creating Lists

Lists let users select an item from a set of choices easily on wearable devices.

The Wearable UI Library includes the WearableListView class .

To create a list in your Android Wear apps:

  1. Add a WearableListView element to your activity’s layout definition.
  2. Create a custom layout implementation for your list items.
  3. Use this implementation to create a layout definition file for your list items.
  4. Create an adapter to populate the list.
  5. Assign the adapter to the WearableListView element

Add a List View

<android.support.wearable.view.BoxInsetLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   android:background="@drawable/robot_background"
   android:layout_height="match_parent"
   android:layout_width="match_parent">

   <FrameLayout
       android:id="@+id/frame_layout"
       android:layout_height="match_parent"
       android:layout_width="match_parent"
       app:layout_box="left|bottom|right">

       <android.support.wearable.view.WearableListView
           android:id="@+id/wearable_list"
           android:layout_height="match_parent"
           android:layout_width="match_parent">
       </android.support.wearable.view.WearableListView>
   </FrameLayout>
</android.support.wearable.view.BoxInsetLayout>



Create a Layout Implementation for List Items

This layout also implements the methods in the WearableListView.OnCenterProximityListener interface to change the color of the item’s icon and fade the text in response to events from WearableListView as the user scrolls through the list.

public class WearableListItemLayout extends LinearLayout
            implements WearableListView.OnCenterProximityListener {

   private ImageView mCircle;
   private TextView mName;

   private final float mFadedTextAlpha;
   private final int mFadedCircleColor;
   private final int mChosenCircleColor;

   public WearableListItemLayout(Context context) {
       this(context, null);
   }

   public WearableListItemLayout(Context context, AttributeSet attrs) {
       this(context, attrs, 0);
   }

   public WearableListItemLayout(Context context, AttributeSet attrs,
                                 int defStyle) {
       super(context, attrs, defStyle);

       mFadedTextAlpha = getResources()
                        .getInteger(R.integer.action_text_faded_alpha) / 100f;
       mFadedCircleColor = getResources().getColor(R.color.grey);
       mChosenCircleColor = getResources().getColor(R.color.blue);
   }

   // Get references to the icon and text in the item layout definition
   @Override
   protected void onFinishInflate() {
       super.onFinishInflate();
       // These are defined in the layout file for list items
       // (see next section)
       mCircle = (ImageView) findViewById(R.id.circle);
       mName = (TextView) findViewById(R.id.name);
   }

   @Override
   public void onCenterPosition(boolean animate) {
       mName.setAlpha(1f);
       ((GradientDrawable) mCircle.getDrawable()).setColor(mChosenCircleColor);
   }

   @Override
   public void onNonCenterPosition(boolean animate) {
       ((GradientDrawable) mCircle.getDrawable()).setColor(mFadedCircleColor);
       mName.setAlpha(mFadedTextAlpha);
   }
}



Create a Layout Definition for Items

res/layout/list_item.xml

<com.example.android.support.wearable.notifications.WearableListItemLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:gravity="center_vertical"
   android:layout_width="match_parent"
   android:layout_height="80dp">
   <ImageView
       android:id="@+id/circle"
       android:layout_height="20dp"
       android:layout_margin="16dp"
       android:layout_width="20dp"
       android:src="@drawable/wl_circle"/>
   <TextView
       android:id="@+id/name"
       android:gravity="center_vertical|left"
       android:layout_width="wrap_content"
       android:layout_marginRight="16dp"
       android:layout_height="match_parent"
       android:fontFamily="sans-serif-condensed-light"
       android:lineSpacingExtra="-4sp"
       android:textColor="@color/text_color"
       android:textSize="16sp"/>
</com.example.android.support.wearable.notifications.WearableListItemLayout>



Create an Adapter to Populate the List

private static final class Adapter extends WearableListView.Adapter {
   private String[] mDataset;
   private final Context mContext;
   private final LayoutInflater mInflater;

   // Provide a suitable constructor (depends on the kind of dataset)
   public Adapter(Context context, String[] dataset) {
       mContext = context;
       mInflater = LayoutInflater.from(context);
       mDataset = dataset;
   }

   // Provide a reference to the type of views you're using
   public static class ItemViewHolder extends WearableListView.ViewHolder {
       private TextView textView;
       public ItemViewHolder(View itemView) {
           super(itemView);
           // find the text view within the custom item's layout
           textView = (TextView) itemView.findViewById(R.id.name);
       }
   }

   // Create new views for list items
   // (invoked by the WearableListView's layout manager)
   @Override
   public WearableListView.ViewHolder onCreateViewHolder(ViewGroup parent,
                                                         int viewType) {
       // Inflate our custom layout for list items
       return new ItemViewHolder(mInflater.inflate(R.layout.list_item, null));
   }

   // Replace the contents of a list item
   // Instead of creating new views, the list tries to recycle existing ones
   // (invoked by the WearableListView's layout manager)
   @Override
   public void onBindViewHolder(WearableListView.ViewHolder holder,
                                int position) {
       // retrieve the text view
       ItemViewHolder itemHolder = (ItemViewHolder) holder;
       TextView view = itemHolder.textView;
       // replace text contents
       view.setText(mDataset[position]);
       // replace list item's metadata
       holder.itemView.setTag(position);
   }

   // Return the size of your dataset
   // (invoked by the WearableListView's layout manager)
   @Override
   public int getItemCount() {
       return mDataset.length;
   }
}



Associate the Adapter and Set a Click Listener

public class WearActivity extends Activity
                         implements WearableListView.ClickListener {

   // Sample dataset for the list
   String[] elements = { "List Item 1", "List Item 2", ... };

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.my_list_activity);

       // Get the list component from the layout of the activity
       WearableListView listView =
           (WearableListView) findViewById(R.id.wearable_list);

       // Assign an adapter to the list
       listView.setAdapter(new Adapter(this, elements));

       // Set a click listener
       listView.setClickListener(this);
   }

   // WearableListView click listener
   @Override
   public void onClick(WearableListView.ViewHolder v) {
       Integer tag = (Integer) v.itemView.getTag();
       // use this data to complete some action ...
   }

   @Override
   public void onTopEmptyRegionClick() {
   }
}

original source : http://www.androiddocs.com/training/wearables/ui/lists.html

Creating Lists

Lists let users select an item from a set of choices easily on wearable devices.

The Wearable UI Library includes the WearableListView class .

To create a list in your Android Wear apps:

  1. Add a WearableListView element to your activity’s layout definition.
  2. Create a custom layout implementation for your list items.
  3. Use this implementation to create a layout definition file for your list items.
  4. Create an adapter to populate the list.
  5. Assign the adapter to the WearableListView element

Add a List View

<android.support.wearable.view.BoxInsetLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   android:background="@drawable/robot_background"
   android:layout_height="match_parent"
   android:layout_width="match_parent">

   <FrameLayout
       android:id="@+id/frame_layout"
       android:layout_height="match_parent"
       android:layout_width="match_parent"
       app:layout_box="left|bottom|right">

       <android.support.wearable.view.WearableListView
           android:id="@+id/wearable_list"
           android:layout_height="match_parent"
           android:layout_width="match_parent">
       </android.support.wearable.view.WearableListView>
   </FrameLayout>
</android.support.wearable.view.BoxInsetLayout>



Create a Layout Implementation for List Items

This layout also implements the methods in the WearableListView.OnCenterProximityListener interface to change the color of the item’s icon and fade the text in response to events from WearableListView as the user scrolls through the list.

public class WearableListItemLayout extends LinearLayout
            implements WearableListView.OnCenterProximityListener {

   private ImageView mCircle;
   private TextView mName;

   private final float mFadedTextAlpha;
   private final int mFadedCircleColor;
   private final int mChosenCircleColor;

   public WearableListItemLayout(Context context) {
       this(context, null);
   }

   public WearableListItemLayout(Context context, AttributeSet attrs) {
       this(context, attrs, 0);
   }

   public WearableListItemLayout(Context context, AttributeSet attrs,
                                 int defStyle) {
       super(context, attrs, defStyle);

       mFadedTextAlpha = getResources()
                        .getInteger(R.integer.action_text_faded_alpha) / 100f;
       mFadedCircleColor = getResources().getColor(R.color.grey);
       mChosenCircleColor = getResources().getColor(R.color.blue);
   }

   // Get references to the icon and text in the item layout definition
   @Override
   protected void onFinishInflate() {
       super.onFinishInflate();
       // These are defined in the layout file for list items
       // (see next section)
       mCircle = (ImageView) findViewById(R.id.circle);
       mName = (TextView) findViewById(R.id.name);
   }

   @Override
   public void onCenterPosition(boolean animate) {
       mName.setAlpha(1f);
       ((GradientDrawable) mCircle.getDrawable()).setColor(mChosenCircleColor);
   }

   @Override
   public void onNonCenterPosition(boolean animate) {
       ((GradientDrawable) mCircle.getDrawable()).setColor(mFadedCircleColor);
       mName.setAlpha(mFadedTextAlpha);
   }
}



Create a Layout Definition for Items

res/layout/list_item.xml

<com.example.android.support.wearable.notifications.WearableListItemLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:gravity="center_vertical"
   android:layout_width="match_parent"
   android:layout_height="80dp">
   <ImageView
       android:id="@+id/circle"
       android:layout_height="20dp"
       android:layout_margin="16dp"
       android:layout_width="20dp"
       android:src="@drawable/wl_circle"/>
   <TextView
       android:id="@+id/name"
       android:gravity="center_vertical|left"
       android:layout_width="wrap_content"
       android:layout_marginRight="16dp"
       android:layout_height="match_parent"
       android:fontFamily="sans-serif-condensed-light"
       android:lineSpacingExtra="-4sp"
       android:textColor="@color/text_color"
       android:textSize="16sp"/>
</com.example.android.support.wearable.notifications.WearableListItemLayout>



Create an Adapter to Populate the List

private static final class Adapter extends WearableListView.Adapter {
   private String[] mDataset;
   private final Context mContext;
   private final LayoutInflater mInflater;

   // Provide a suitable constructor (depends on the kind of dataset)
   public Adapter(Context context, String[] dataset) {
       mContext = context;
       mInflater = LayoutInflater.from(context);
       mDataset = dataset;
   }

   // Provide a reference to the type of views you're using
   public static class ItemViewHolder extends WearableListView.ViewHolder {
       private TextView textView;
       public ItemViewHolder(View itemView) {
           super(itemView);
           // find the text view within the custom item's layout
           textView = (TextView) itemView.findViewById(R.id.name);
       }
   }

   // Create new views for list items
   // (invoked by the WearableListView's layout manager)
   @Override
   public WearableListView.ViewHolder onCreateViewHolder(ViewGroup parent,
                                                         int viewType) {
       // Inflate our custom layout for list items
       return new ItemViewHolder(mInflater.inflate(R.layout.list_item, null));
   }

   // Replace the contents of a list item
   // Instead of creating new views, the list tries to recycle existing ones
   // (invoked by the WearableListView's layout manager)
   @Override
   public void onBindViewHolder(WearableListView.ViewHolder holder,
                                int position) {
       // retrieve the text view
       ItemViewHolder itemHolder = (ItemViewHolder) holder;
       TextView view = itemHolder.textView;
       // replace text contents
       view.setText(mDataset[position]);
       // replace list item's metadata
       holder.itemView.setTag(position);
   }

   // Return the size of your dataset
   // (invoked by the WearableListView's layout manager)
   @Override
   public int getItemCount() {
       return mDataset.length;
   }
}



Associate the Adapter and Set a Click Listener

public class WearActivity extends Activity
                         implements WearableListView.ClickListener {

   // Sample dataset for the list
   String[] elements = { "List Item 1", "List Item 2", ... };

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.my_list_activity);

       // Get the list component from the layout of the activity
       WearableListView listView =
           (WearableListView) findViewById(R.id.wearable_list);

       // Assign an adapter to the list
       listView.setAdapter(new Adapter(this, elements));

       // Set a click listener
       listView.setClickListener(this);
   }

   // WearableListView click listener
   @Override
   public void onClick(WearableListView.ViewHolder v) {
       Integer tag = (Integer) v.itemView.getTag();
       // use this data to complete some action ...
   }

   @Override
   public void onTopEmptyRegionClick() {
   }
}