2013年12月18日水曜日

ActionBarを使ってみる(SearchViewを配置する Android 2.2以上)

Google Mapなどを利用していると上部に検索ボックスがあり、
そこに検索した結果の位置に地図が反映される機能が欲しい!!ということで、
さっそく試してみました(ΦωΦ)フフフ…

せっかくなのでActionBarの中に表示する方法でやりたいと思います。

やり方としては、SearchViewを使うパターンと、EditTexgを使うパターンがあるそうですが、
今回はSearchViewを使うパターンで試したいと思います。

SearchViewはAPI Levele 11(Android 3.0)以上から利用可能らしいです(´;ω;`)ウッ…
ただ、support libraryを使えば2.2系以上でも動作させる事も可能みたいです。

ActionBarにアクションアイテム(オプションメニューのアイコンなどのこと)の代わりに表示するビューやウィジェットの事を、
アクションビューと呼ぶそうです。

アクションアイテムにアクションビューを指定する場合には、2つの方法があります。
・android:actionLayout属性を使う(layoutのxmlを指定する)
・android:actionViewClass属性を使う(Viewを継承するクラスを指定する)
この2つを利用する場合には、android:showAsAction属性に「collapseActionView」を指定すると、
アクションアイテムをタップすると格納されている、アクションビューが表示されるようになる。

指定しなかった場合には、デフォルトでアクションビューがアクションアイテムに表示されます。

ハマった所といえば、
ActionBarに表示するメニューの定義XMLで
名前空間を指定しないといけない点です:(;゙゚'ω゚'):

API Level 11未満で利用したい場合には、
次の名前空間を記述して、それを利用しないとエラーになってしまいます(´;ω;`)ブワッ
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:myapp="http://schemas.android.com/apk/res-auto" >
SearchViewではサジェスト機能などもあるそうですが、
とりあえず今回はシンプルな構成でやりたいと思います( ´∀`)bグッ!

■AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.seachview1"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="18" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.seachview1.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
■res/values/strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
 
    <string name="app_name">SearchViewWithActionBarCompat</string>
    <string name="action_settings">Settings</string>
    <string name="hello_world">Hello world!</string>
    <string name="action_search">Search</string>
    <string name="search_hint">Search Places</string>
    <string name="search_label">Search Label</string>
    <string name="search_settings">Search Places</string>
 
</resources>
■res/values/styles.xml
<resources>

    <!--
        Base application theme, dependent on API level. This theme is replaced
        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
    -->
    <style name="AppBaseTheme" parent="Theme.AppCompat.Light">
        <!--
            Theme customizations available in newer API levels can go in
            res/values-vXX/styles.xml, while customizations related to
            backward-compatibility can go here.
        -->
    </style>

    <!-- Application theme. -->
    <style name="AppTheme" parent="AppBaseTheme">
        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
    </style>

</resources>
■res/menu/main.xml

ActionBarに表示する、メニューの設定になります。

SearchViewはAPI Level 11から利用できるもので、
showAsAction 属性も API Level 11 から導入されたため、
それ以下のバージョンで利用する場合には、
名前空間として 「http://schemas.android.com/apk/res-auto」 を指定する必要があるそうです。

また、actionViewClassでsupport libraryのSearchViewを指定します。
※Viewを継承するクラスの完全修飾名を指定する。
actionViewClassでViewを指定した場合には、showAsActionに「collapseActionView」を利用する事も検討する。 これを設定すると、メニューをクリックした時にactionViewClassに設定したViewが表示される
設定されていない場合には、ActionBarの中に指定されたViewが表示された状態になる

showAsActionの条件が複数ある場合にはパイプでつなげる事。
always|collapseActionView

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:myapp="http://schemas.android.com/apk/res-auto" >

    <item
        android:id="@+id/action_search"
        android:orderInCategory="100"
        android:title="@string/action_search"
        myapp:actionViewClass="android.support.v7.widget.SearchView"
        myapp:showAsAction="always"/>
    <item
        android:id="@+id/action_settings"
        android:orderInCategory="100"
        myapp:showAsAction="ifRoom"
        android:title="@string/action_settings"/>

</menu>
■activity_main.xml

メインのレイアウトにはTextViewのみ配置します。
<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="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

</RelativeLayout>

■MainActivity.java

アクションビューを取得するには、onCreateOptionsMenuでgetActionViewを利用する。

今回は利用していませんが、android:showAsAction属性に「collapseActionView」を指定している状態で、
クラスに「CollapsibleActionView」を実装すると、
アクションビューが展開、または格納された時のコールバックメソッドをで通知を受けれるようになる。

package com.example.seachview1;

import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.SearchView;
import android.support.v7.widget.SearchView.OnCloseListener;
import android.support.v4.view.MenuItemCompat;
import android.text.TextUtils;
import android.util.Log;
import android.app.Activity;
import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.provider.SearchRecentSuggestions;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MenuInflater;
import android.view.View;
import android.view.View.OnFocusChangeListener;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends ActionBarActivity {

 private static final String TAG = "MainActivity";
 private static TextView mTextView = null;

 // SearchVIewのリスナー
 private final SearchView.OnQueryTextListener mOnQueryTextListener = new SearchView.OnQueryTextListener() {
  /*
   * 文字に変更があったら(1文字ずつ呼ばれる)
   * 
   * @see android.support.v7.widget.SearchView.OnQueryTextListener#
   * onQueryTextChange(java.lang.String)
   */
  @Override
  public boolean onQueryTextChange(String newText) {

   Log.d(TAG, "onQueryTextChange "
     + (TextUtils.isEmpty(newText) ? "" : "Query so far: "
       + newText));

   return true;
  }

  /*
   * 文字入力を確定した場合
   * 
   * @see android.support.v7.widget.SearchView.OnQueryTextListener#
   * onQueryTextSubmit(java.lang.String)
   */
  @Override
  public boolean onQueryTextSubmit(String query) {

   Log.d(TAG, "onQueryTextSubmit Searching for: " + query);

   // 入力された文字を設定する
   mTextView.setText(query);

   return true;
  }
 };

 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  //
  mTextView = (TextView) findViewById(R.id.text);

 }

 /*
  * メニューの作成
  * 
  * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
  */
 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.main, menu);

  // menu定義のitemのidがaction_searchのものを取得する
  MenuItem searchItem = menu.findItem(R.id.action_search);

  // SearchViewを取得する
  final SearchView searchView = (SearchView) MenuItemCompat
    .getActionView(searchItem);

  // 虫メガネのアイコンを表示するか
  searchView.setIconifiedByDefault(true);

  // Submitボタンを表示するか
  searchView.setSubmitButtonEnabled(false);

  // SearchViewに何も入力していない時のテキストを設定
  searchView.setQueryHint("検索文字を入力して下さい。");

  // リスナーを登録する
  searchView.setOnQueryTextListener(mOnQueryTextListener);

  return super.onCreateOptionsMenu(menu);
 }

}
実行結果は次のようになります。

 文字を入力すると、TextViewにもその結果が反映されます。


以上です(`・ω・´)ゞビシッ!!

参考URL

0 件のコメント:

コメントを投稿