Android城市索引含定位和熱門(mén)城市(懸浮塊+右側(cè)字母索引)

一、首先我們想要的效果是:

  • 在城市索引的列表能夠加個(gè)自定義頭部七兜;
  • 有城市索引的字母懸浮塊锯厢;
  • 右側(cè)的字母索引導(dǎo)航酥郭;
  • 仿ios效果的當(dāng)前位置索引提示框

我們先來(lái)看下效果:

這里寫(xiě)圖片描述

下面的代碼可能有點(diǎn)多懂衩,但是效果卻很不錯(cuò)撞叨,請(qǐng)耐心往下看
這里我是用的IndexableLayout控件做的

如果還是有不清楚的,可以去看我的Demo:CityProject

博客地址:點(diǎn)擊這里

二勃痴、如何使用IndexableLayout:

  • 需要加入第三方依賴(lài)庫(kù):
implementation 'me.yokeyword:indexablerecyclerview:1.3.0'
  • 在.xml布局中:
<me.yokeyword.indexablerv.IndexableLayout
        android:id="@+id/indexableLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/white"
        app:indexBar_selectedTextColor="@color/black"  //右側(cè)導(dǎo)航選中時(shí)的顏色
        app:indexBar_textColor="@color/gray1"   //右側(cè)導(dǎo)航字體顏色
        app:indexBar_layout_width="40dp"        //右側(cè)導(dǎo)航的寬度
        app:indexBar_textSize="14sp"         //右側(cè)導(dǎo)航的字體大小
        app:indexBar_textSpace="5dp" />
  • 在Activity中:
    下面注釋寫(xiě)的很清楚了谒所,這里我就不多做說(shuō)明了
public class CityPickerActivity extends AppCompatActivity {
    //IndexableLayout 的適配器
    private ContactAdapter mAdapter;
    //自定義頭部adapter
    private BannerHeaderAdapter mBannerHeaderAdapter;
    //熱門(mén)城市的數(shù)組
    private String[] city = {"東莞","深圳","廣州","溫州","鄭州","金華","佛山","上海","蘇州","杭州","長(zhǎng)沙","中山"};
    private IndexableLayout indexableLayout;
    //熱門(mén)城市的適配器
    private CYBChangeCityGridViewAdapter cybChangeCityGridViewAdapter;
    熱門(mén)城市的集合
    private ArrayList<String> list;
    //返回按鈕
    private ImageView pic_contact_back;
    private Intent intent;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pick_contact);

        initview();
        initAdapter();
        onlisten();
    }

    public void initAdapter(){
        mAdapter = new ContactAdapter(this);        
        indexableLayout.setAdapter(mAdapter);
        //設(shè)置字母提示框?yàn)榉耾s居中
        indexableLayout.setOverlayStyle_Center();
        mAdapter.setDatas(initDatas());
//        indexableLayout.setOverlayStyle_MaterialDesign(Color.RED); 設(shè)置提示框?yàn)榉侣?lián)系人氣泡樣式
        // 全字母排序热康。  排序規(guī)則設(shè)置為:每個(gè)字母都會(huì)進(jìn)行比較排序沛申;速度較慢
        indexableLayout.setCompareMode(IndexableLayout.MODE_FAST);
//        indexableLayout.addHeaderAdapter(new SimpleHeaderAdapter<>(mAdapter, "☆",null, null));

//         構(gòu)造函數(shù)里3個(gè)參數(shù),分別對(duì)應(yīng) (IndexBar的字母索引, IndexTitle, 數(shù)據(jù)源), 不想顯示哪個(gè)就傳null, 數(shù)據(jù)源傳null時(shí),代表add一個(gè)普通的View
//        mMenuHeaderAdapter = new MenuHeaderAdapter("↑", null, initMenuDatas());
//        indexableLayout.addHeaderAdapter(mMenuHeaderAdapter);

        // 這里BannerView只有一個(gè)Item, 添加一個(gè)長(zhǎng)度為1的任意List作為第三個(gè)參數(shù)
        List<String> bannerList = new ArrayList<>();
        bannerList.add("");
        mBannerHeaderAdapter = new BannerHeaderAdapter("↑", null, bannerList);
        indexableLayout.addHeaderAdapter(mBannerHeaderAdapter);
    }

    public void initview(){
        intent = getIntent();
        pic_contact_back = (ImageView) findViewById(R.id.pic_contact_back);
        indexableLayout = (IndexableLayout) findViewById(R.id.indexableLayout);
        indexableLayout.setLayoutManager(new LinearLayoutManager(this));
    }

    public void onlisten(){

        pic_contact_back.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });

        mAdapter.setOnItemContentClickListener(new IndexableAdapter.OnItemContentClickListener<UserEntity>() {
            @Override
            public void onItemClick(View v, int originalPosition, int currentPosition, UserEntity entity) {
                if (originalPosition >= 0) {
                    intent.putExtra("info", entity.getNick());
                    setResult(RESULT_OK, intent);
                    finish();
                } else {
                    ToastUtil.showShort(CityPickerActivity.this, "選中Header/Footer:" + entity.getNick() + "  當(dāng)前位置:" + currentPosition);
                }
            }
        });
    }

    /**
     * 自定義的Banner Header
     */
    class BannerHeaderAdapter extends IndexableHeaderAdapter {
        private static final int TYPE = 1;
        //這里傳的參數(shù)上面注釋有
        public BannerHeaderAdapter(String index, String indexTitle, List datas) {
            super(index, indexTitle, datas);
        }

        @Override
        public int getItemViewType() {
            return TYPE;
        }

        @Override
        public RecyclerView.ViewHolder onCreateContentViewHolder(ViewGroup parent) {
            View view = LayoutInflater.from(CityPickerActivity.this).inflate(R.layout.item_city_header, parent, false);
            VH holder = new VH(view);
            return holder;
        }

        @Override
        public void onBindContentViewHolder(RecyclerView.ViewHolder holder, Object entity) {
            // 數(shù)據(jù)源為null時(shí), 該方法不用實(shí)現(xiàn)
            VH vh = (VH) holder;
            list=new ArrayList<>();
            for(int i = 0; i<city.length; i++){
                list.add(city[i]);
            }
            System.out.println("------------city"+list);
            cybChangeCityGridViewAdapter=new CYBChangeCityGridViewAdapter(CityPickerActivity.this, list);
            // 綁定adpter
            vh.head_home_change_city_gridview.setAdapter(cybChangeCityGridViewAdapter);
            //熱門(mén)城市的item點(diǎn)擊事件
            vh.head_home_change_city_gridview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    intent.putExtra("info", list.get(position));
                    System.out.println("aaaaaayyyyyyyyy"+list.get(position));
                    setResult(RESULT_OK, intent);
                    finish();
                }
            });
            //設(shè)置定位城市的點(diǎn)擊事件
            vh.item_header_city_dw.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    intent.putExtra("bendi", MeNow.city);
                    setResult(RESULT_OK, intent);
                    finish();
                }
            });

        }

        private class VH extends RecyclerView.ViewHolder {
            GridView head_home_change_city_gridview;
            TextView item_header_city_dw;
            public VH(View itemView) {
                super(itemView);
                head_home_change_city_gridview =(QGridView)itemView.findViewById(R.id.item_header_city_gridview);
                item_header_city_dw = (TextView) itemView.findViewById(R.id.item_header_city_dw);
            }
        }
    }

    private List<UserEntity> initDatas() {
        List<UserEntity> list = new ArrayList<>();
        // 初始化數(shù)據(jù),R.array.provinces是城市資源姐军,下面有貼出資源文件代碼
        List<String> contactStrings = Arrays.asList(getResources().getStringArray(R.array.provinces));
        List<String> mobileStrings = Arrays.asList(getResources().getStringArray(R.array.provinces));
        for (int i = 0; i < contactStrings.size(); i++) {
            UserEntity contactEntity = new UserEntity(contactStrings.get(i), mobileStrings.get(i));
            list.add(contactEntity);
        }
        return list;
    }
}

Activity的.xml文件中:

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

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:orientation="horizontal"
        android:background="@color/white"
        android:elevation="3dp"
        >
        <ImageView
            android:id="@+id/pic_contact_back"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:src="@drawable/back"
            android:padding="18dp"
            />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="城市選擇"
            android:layout_gravity="center_vertical"
            android:textColor="@color/black"
            android:textSize="18sp"
            />
    </LinearLayout>

    <me.yokeyword.indexablerv.IndexableLayout
        android:id="@+id/indexableLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/white"
        app:indexBar_selectedTextColor="@color/black"
        app:indexBar_textColor="@color/gray1"
        app:indexBar_layout_width="40dp"
        app:indexBar_textSize="14sp"
        app:indexBar_textSpace="5dp" />

</LinearLayout>

values目錄下的R.arrays.xml城市資源文件:

<?xml version="1.0" encoding="UTF-8"?>
<resources>
    <string-array name="provinces">
        <item>上海</item>
        <item>北京</item>
        <item>杭州</item>
        <item>廣州</item>
        ...
    </string-array>
</resources>

BannerHeaderAdapter其實(shí)就是相當(dāng)于IndexableLayout的頭布局铁材,我這里的定位城市和熱門(mén)城市就是通過(guò)添加這個(gè)頭部(BannerHeaderAdapter的item布局):

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

    <TextView
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:text="定位城市"
        android:gravity="center_vertical"
        android:paddingLeft="15dp"
        android:textSize="@dimen/text_size_18"
        android:textColor="@color/black"
        />
    <TextView
        android:id="@+id/item_header_city_dw"
        android:layout_width="80dp"
        android:layout_height="35dp"
        android:textColor="@color/black"
        android:gravity="center"
        android:layout_marginLeft="15dp"
        android:background="@drawable/sylayout_shop"
        android:text="東莞"/>
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/gray2"
        android:layout_margin="15dp"
        />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:paddingBottom="5dp"
        android:paddingLeft="15dp"
        android:paddingRight="30dp"
        android:orientation="vertical">
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="18sp"
            android:textColor="@color/black"
            android:text="熱門(mén)城市"/>
        <com.wzg.biswang.util.QGridView
            android:id="@+id/item_header_city_gridview"
            android:layout_marginTop="5dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:focusable="true"
            android:focusableInTouchMode="true"
            android:numColumns="3"
            android:stretchMode="columnWidth"
            android:columnWidth="60dp"
            android:verticalSpacing="10dp"
            android:horizontalSpacing="15dp">
        </com.wzg.biswang.util.QGridView>
    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/gray2"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:layout_marginTop="10dp"
        />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:textSize="18sp"
        android:textColor="@color/black"
        android:layout_marginLeft="15dp"
        android:gravity="center_vertical"
        android:text="所有城市"/>
</LinearLayout>

ContactAdapter的適配器也就是IndexableLayout的Adapter,這里必須繼承IndexableAdapter<UserEntity>,你也可以直接把這段代碼復(fù)制下來(lái) :

public class ContactAdapter extends IndexableAdapter<UserEntity> {
    private LayoutInflater mInflater;

    public ContactAdapter(Context context) {
        mInflater = LayoutInflater.from(context);
    }

//設(shè)置懸浮塊的layout
    @Override
    public RecyclerView.ViewHolder onCreateTitleViewHolder(ViewGroup parent) {
        View view = mInflater.inflate(R.layout.item_index_contact, parent, false);
        return new IndexVH(view);
    }
//設(shè)置懸浮塊下面的layout
    @Override
    public RecyclerView.ViewHolder onCreateContentViewHolder(ViewGroup parent) {
        View view = mInflater.inflate(R.layout.item_contact, parent, false);
        return new ContentVH(view);
    }

//設(shè)置懸浮塊的數(shù)據(jù)
    @Override
    public void onBindTitleViewHolder(RecyclerView.ViewHolder holder, String indexTitle) {
        IndexVH vh = (IndexVH) holder;
        vh.tv.setText(indexTitle);
    }

//設(shè)置懸浮塊下面的數(shù)據(jù)
    @Override
    public void onBindContentViewHolder(RecyclerView.ViewHolder holder, UserEntity entity) {
        ContentVH vh = (ContentVH) holder;
        vh.tvName.setText(entity.getNick());
        vh.tvMobile.setText(entity.getMobile());
    }

    private class IndexVH extends RecyclerView.ViewHolder {
        TextView tv;

        public IndexVH(View itemView) {
            super(itemView);
            tv = (TextView) itemView.findViewById(R.id.tv_index);
        }
    }

    private class ContentVH extends RecyclerView.ViewHolder {
        TextView tvName, tvMobile;

        public ContentVH(View itemView) {
            super(itemView);
            tvName = (TextView) itemView.findViewById(R.id.tv_name);
            tvMobile = (TextView) itemView.findViewById(R.id.tv_mobile);
        }
    }
}

懸浮塊的xml文件:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    
    <TextView
        android:id="@+id/tv_index"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#f9f9f9"
        android:paddingBottom="8dp"
        android:paddingLeft="24dp"
        android:paddingTop="8dp"
        android:textColor="@color/gray"
        android:text="A"
        android:textStyle="bold"
        android:textSize="14sp" />

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="0.8dp"
        android:background="#f0f0f0" />
</FrameLayout>

懸浮塊下面的xml文件也就是item布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingBottom="5dp"
    android:background="?attr/selectableItemBackground"
    android:paddingLeft="16dp"
    android:paddingRight="16dp"
    android:paddingTop="5dp">

    <ImageView
        android:visibility="gone"
        android:id="@+id/img_avatar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="16dp"
        android:src="@drawable/bsw_gray" />

    <TextView
        android:id="@+id/tv_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/img_avatar"
        tools:text="張三"
        android:textColor="#373737"
        android:textSize="16sp" />

    <TextView
        android:visibility="gone"
        android:id="@+id/tv_mobile"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/tv_name"
        android:layout_marginTop="12dp"
        android:layout_toRightOf="@id/img_avatar"
        tools:text="18712345678"
        android:textColor="#969696" />

</RelativeLayout>

熱門(mén)城市的GridView奕锌,普通的Adapter類(lèi)我就不用多作解釋了相信大家都能看懂:

public class CYBChangeCityGridViewAdapter extends BaseAdapter{
    private List<String> list;
    private Context context;
    private LayoutInflater inflater;

    public CYBChangeCityGridViewAdapter(Context context,List<String> list){
        this.context=context;
        this.list=list;
        inflater=LayoutInflater.from(context);
    }

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

    @Override public Object getItem(int position) {
        return list.get(position);
    }

    @Override public long getItemId(int position) {
        return position;
    }

    @Override public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder=null;
        if(convertView==null){
            convertView=inflater.inflate(R.layout.item_gridview_cyb_change_city,null);
            viewHolder=new ViewHolder(convertView);
            convertView.setTag(viewHolder);
        }else {
            viewHolder=(ViewHolder)convertView.getTag();
        }
        viewHolder.item_gridview_cyb_change_city_tv.setText(list.get(position));
        return convertView;
    }

    class ViewHolder{
        private TextView item_gridview_cyb_change_city_tv;
        public ViewHolder(View view){
            item_gridview_cyb_change_city_tv=(TextView)view.findViewById(R.id.item_gridview_cyb_change_city_tv);
        }
    }
}

熱門(mén)城市GridView的item布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:descendantFocusability="blocksDescendants"
              android:layout_width="match_parent"
              android:layout_height="40dp">
<TextView
    android:id="@+id/item_gridview_cyb_change_city_tv"
    android:layout_width="match_parent"
    android:layout_height="40dp"
    android:background="@drawable/sylayout_shop"
    android:gravity="center"
    android:paddingTop="2dp"
    android:paddingBottom="2dp"
    android:textSize="13dp"
    android:layout_marginTop="5dp"
    android:text="廣州"/>
</RelativeLayout>

好了著觉,到此就結(jié)束了,趕緊去試試把惊暴!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末饼丘,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子辽话,更是在濱河造成了極大的恐慌肄鸽,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,273評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件油啤,死亡現(xiàn)場(chǎng)離奇詭異典徘,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)益咬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門(mén)逮诲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人幽告,你說(shuō)我怎么就攤上這事梅鹦。” “怎么了冗锁?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,709評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵帘瞭,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我蒿讥,道長(zhǎng)蝶念,這世上最難降的妖魔是什么抛腕? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,520評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮媒殉,結(jié)果婚禮上担敌,老公的妹妹穿的比我還像新娘。我一直安慰自己廷蓉,他們只是感情好全封,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著桃犬,像睡著了一般刹悴。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上攒暇,一...
    開(kāi)封第一講書(shū)人閱讀 52,158評(píng)論 1 308
  • 那天土匀,我揣著相機(jī)與錄音,去河邊找鬼形用。 笑死就轧,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的田度。 我是一名探鬼主播妒御,決...
    沈念sama閱讀 40,755評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼镇饺!你這毒婦竟也來(lái)了乎莉?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,660評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤奸笤,失蹤者是張志新(化名)和其女友劉穎惋啃,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體揭保,經(jīng)...
    沈念sama閱讀 46,203評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡肥橙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了秸侣。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片存筏。...
    茶點(diǎn)故事閱讀 40,427評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖味榛,靈堂內(nèi)的尸體忽然破棺而出椭坚,到底是詐尸還是另有隱情,我是刑警寧澤搏色,帶...
    沈念sama閱讀 36,122評(píng)論 5 349
  • 正文 年R本政府宣布善茎,位于F島的核電站,受9級(jí)特大地震影響频轿,放射性物質(zhì)發(fā)生泄漏垂涯。R本人自食惡果不足惜烁焙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望耕赘。 院中可真熱鬧骄蝇,春花似錦、人聲如沸操骡。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,272評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)册招。三九已至岔激,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間是掰,已是汗流浹背虑鼎。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留冀惭,地道東北人震叙。 一個(gè)月前我還...
    沈念sama閱讀 48,808評(píng)論 3 376
  • 正文 我出身青樓掀鹅,卻偏偏與公主長(zhǎng)得像散休,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子乐尊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評(píng)論 2 359