アコーディオンを作ってみる(一話完結)

度々、いろいろな技術に手を出しつつ、不完全燃焼を繰り返す、当ブログですが、今回は最後までご説明しますね。

アコーディオンはjsでよくあるボタンを押すとその下のコンテンツがスライドダウンしてくるアニメーションです。

このアニメーションは、デフォルトのアニメーションでは、対応できない?(頑張ればスケールとかでも対応可能か?)

と思うので、javaのThreadを利用して、作成してみたいと思います。

きっとandroid2.1くらいから対応できます。

 

最初は構成ですが、ボタンよりも個人的には、LinerLayoutをクリックの対象にする事が多いので

<!-- SET1 -->
 <LinearLayout
 android:id="@+id/btn1"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:background="#ff0000">
 <TextView
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:padding="10dp"
 android:textColor="#ffffff"
 android:text="@string/app_name" />
 </LinearLayout>
 <LinearLayout
 android:id="@+id/content1"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:background="#ffffff">
 
 <TextView
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:padding="10dp"
 android:text="@string/hello" />
 </LinearLayout>

な感じにします。一応@string/helloの中身は結構長いテキストにしておいた方が楽しいです。

ひとつではつまらないので、5個くらいつなげて、main.xmlは

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:orientation="vertical" >
 <ScrollView
 android:layout_width="fill_parent"
 android:layout_height="fill_parent" >
 <LinearLayout
 android:id="@+id/conrainer"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:orientation="vertical" >
 
 
 <!-- SET1 -->
 <LinearLayout
 android:id="@+id/btn1"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:background="#ff0000">
 <TextView
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:padding="10dp"
 android:textColor="#ffffff"
 android:text="@string/app_name" />
 </LinearLayout>
 <LinearLayout
 android:id="@+id/content1"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:background="#ffffff">
 
 <TextView
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:padding="10dp"
 android:text="@string/hello" />
 </LinearLayout>
 
 <!-- SET2 -->
 <LinearLayout
 android:id="@+id/btn2"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:background="#ff0000">
 <TextView
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:padding="10dp"
 android:textColor="#ffffff"
 android:text="@string/app_name" />
 </LinearLayout>
 <LinearLayout
 android:id="@+id/content2"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:background="#ffffff">
 <TextView
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:padding="10dp"
 android:text="@string/hello" />
 </LinearLayout>
 
 <!-- SET3 -->
 <LinearLayout
 android:id="@+id/btn3"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:background="#ff0000">
 <TextView
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:padding="10dp"
 android:textColor="#ffffff"
 android:text="@string/app_name" />
 </LinearLayout>
 <LinearLayout
 android:id="@+id/content3"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:background="#ffffff">
 <TextView
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:padding="10dp"
 android:text="@string/hello" />
 </LinearLayout>
 
 <!-- SET4 -->
 <LinearLayout
 android:id="@+id/btn4"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:background="#ff0000">
 <TextView
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:padding="10dp"
 android:textColor="#ffffff"
 android:text="@string/app_name" />
 </LinearLayout>
 <LinearLayout
 android:id="@+id/content4"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:background="#ffffff">
 <TextView
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:padding="10dp"
 android:text="@string/hello" />
 </LinearLayout>
 
 <!-- SET5 -->
 <LinearLayout
 android:id="@+id/btn5"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:background="#ff0000">
 <TextView
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:padding="10dp"
 android:textColor="#ffffff"
 android:text="@string/app_name" />
 </LinearLayout>
 <LinearLayout
 android:id="@+id/content5"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:background="#ffffff">
 <TextView
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:padding="10dp"
 android:text="@string/hello" />
 </LinearLayout>
 
 </LinearLayout>
 
 </ScrollView>
 
 
 

</LinearLayout>

 

とします。これで、ボタンとコンテンツのセットが5セットのレイアウトができました。

AccordingSetと言うクラスを作成します。

 

package in.andante.accordion;

import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.DecelerateInterpolator;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;

public class AccordionSet {

 private LinearLayout _btn;
 private LinearLayout _content;
 private Handler _handler;
 private float _height;
 private float current = 0.0f;
 private Thread _thread;
 private String _bound = "close";
 private int _startTime;
 private DecelerateInterpolator mInterpolator = new DecelerateInterpolator();
 private int easeTime = 400;
 
 public AccordionSet(LinearLayout btn, LinearLayout content) {
 _btn = btn;
 _content = content;
 _handler = new Handler();
 _height = _content.getHeight();
 mInterpolator = new DecelerateInterpolator();
 _content.setLayoutParams(new LinearLayout.LayoutParams(
 LayoutParams.FILL_PARENT, 0));
 _btn.setOnClickListener(new OnClickListener() {
 @Override
 public void onClick(View v) {
 _startTime = (int)System.currentTimeMillis();
 if (_bound.equals("open")) {
 _bound = "close";
 } else {
 _bound = "open";
 }
 if (_thread == null || !_thread.isAlive()) {
 _thread = null;
 makeThread();
 _thread.start();
 }

 }
 });

 }

 private void makeThread() {
 _thread = new Thread(new Runnable() {
 public void run() {
 while (easeTime > (int)System.currentTimeMillis() - _startTime) {
 int diff = (int)System.currentTimeMillis() - _startTime;
 if (_bound.equals("open")) {
 current = _height * mInterpolator.getInterpolation((float)diff/(float)easeTime);
 } else {
 current = _height-_height * mInterpolator.getInterpolation((float)diff/(float)easeTime);
 }
 threadFunc();
 }
 }
 });
 }

 private void threadFunc() {
 _handler.post(new Runnable() {
 public void run() {
 _content.setLayoutParams(new LinearLayout.LayoutParams(
 LinearLayout.LayoutParams.FILL_PARENT, (int) current));
 }
 });
 try {
 Thread.sleep(1);
 } catch (InterruptedException e) {
 }
 }

 public void deleteAccordion() {
 _btn.setOnClickListener(null);
 _btn = null;
 _content = null;
 }
}

です。一応Threadを使って、繰り返しを行います。前回勉強したイージングの使い方も応用してあります。

Interpolatorの数値のみ利用をする。

 

で上記のクラスですが、注意が必要で、コンテンツに表示する高さを取得する必要があります。

その為、メインのクラスでHandlerを使うか、onWindowFocusChangedを使ってセットをする必要があります。

 

で、更に一度だけ実行すればいいので、いろんな方法があると思うのですが、下記のような形にしています。

 

package in.andante.accordion;

import in.andante.accordion.R.id;
import android.app.Activity;
import android.os.Bundle;
import android.widget.LinearLayout;

public class accActivity extends Activity {


 @Override
 public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.main);
 }

 Boolean _first = true;

 private AccordionSet _as1;
 private AccordionSet _as2;
 private AccordionSet _as3;
 private AccordionSet _as4;
 private AccordionSet _as5;
 
 @Override
 public void onWindowFocusChanged(boolean hasFocus) {
 if (_first) {
 _first = false;
 _as1 = new AccordionSet((LinearLayout)findViewById(id.btn1), (LinearLayout)findViewById(id.content1));
 _as2 = new AccordionSet((LinearLayout)findViewById(id.btn2), (LinearLayout)findViewById(id.content2));
 _as3 = new AccordionSet((LinearLayout)findViewById(id.btn3), (LinearLayout)findViewById(id.content3));
 _as4 = new AccordionSet((LinearLayout)findViewById(id.btn4), (LinearLayout)findViewById(id.content4));
 _as5 = new AccordionSet((LinearLayout)findViewById(id.btn5), (LinearLayout)findViewById(id.content5));
 }
 super.onWindowFocusChanged(hasFocus);
 }
 
 @Override
 protected void onDestroy() {
 if (!_first) {
 _as1.deleteAccordion();
 _as2.deleteAccordion();
 _as3.deleteAccordion();
 _as4.deleteAccordion();
 _as5.deleteAccordion();
 }
 super.onDestroy();
 }
}

これでアコーディオンの実装が完了です。

LinearLayoutの枠だけ守れば中にいろいろ入ると思います!!

 

思ってるより速度も出て、かなりリッチなアプリができると思いますので、是非お試しくださいませ。

前後の記事

前の記事:

次の記事:

関連の記事

コメントの投稿

  • サイト内検索

新作アプリの紹介

関連サイトの紹介

アンドロイドアプリ開発TIPS
きぐるみカメラ
ふらいぱん
アンドロイドのデザイン集
Page top↑