반응형
블로그 이미지
개발자로서 현장에서 일하면서 새로 접하는 기술들이나 알게된 정보 등을 정리하기 위한 블로그입니다. 운 좋게 미국에서 큰 회사들의 프로젝트에서 컬설턴트로 일하고 있어서 새로운 기술들을 접할 기회가 많이 있습니다. 미국의 IT 프로젝트에서 사용되는 툴들에 대해 많은 분들과 정보를 공유하고 싶습니다.
솔웅

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리

[Worklight] 첫번째 앱 HelloWorklight

2014. 9. 15. 01:14 | Posted by 솔웅


반응형

Worklight로 첫번째 앱을 만들었습니다.


http://www.ibm.com/developerworks/mobile/worklight/getting-started.html#GS_hello 에 있는 Creating your first hybrid Worklight application 이라는 문서를 따라 했어요.




이클립스는 이렇게 생겼는데요. 프로젝트 제목에서 오른쪽 마우스를 누르면 아래와 같이 됩니다.




여기서 Open Worklight Console을 선택하면 이 Hybrid 앱이 브라우저에 표시 되요.




이 Console 페이지에서 Preview as Common Resources를 선택하면 해당 앱이 실행됩니다.


만드는 방법은 그냥 Worklight Project를 만들면 되요.

자세한 내용은  Creating your first hybrid Worklight application 문서에 있으니까 참조하시구요.


이 글에는 나중에 앱을 만들일 있으면 참조할 내용들만 정리해 둘 겁니다.



1. Worklight Project 생성 -> 프로젝트 이름 넣고 Hybrid Application 선택 후 Next

2. 앱 이름 Type -> JavaScript framework을 선택할 수 있음 -> Finish


이렇게 하면 됩니다.




Worklight Project는 이렇게 세 부분으로 돼 있습니다.

첫번째로 개발 과정이나 배포단계에서 사용할 Reference들이 있는 부분

그리고 앱에서 사용하는 소스코드들과 adapter들 즉 실제 개발을 위한 소스코드들이 위치하는 부분

마지막으로 서버 customization components들이 있습니다.

 common 이라는 폴더는 default 환경을 말합니다. 여기에 각 환경별로 공유되는 모든 resource들이 들어가게 됩니다.


apps라는 폴더를 오른쪽 클릭해서 New > Worklight environment를 선택하시면




이와 같이 선택할 수 있는 여러 환경들이 보여집니다.

개발하고 싶은 환경을 선택하실 수 있습니다.


Common 환경에는 아래와 같은 주요 파일들이 있습니다.

index.html - main HTML file, css : main.css, images : common 환경에서 사용하는 이미지, js - initOption.js : 앱의 초기화 단계에서 사용하는 자바스크립트, main.js : main 자바스크립트, messages.js : 앱 메세지를 가지고 있는 JSON 객체. translation등에 이용될 수 있음.


legal 폴더는 모든 legal에 관련된 문서들이 있습니다. 라이센스나 뭐 배포 금지 허용 여부 뭐 그런것들이요.


application-descriptor.xml 파일은 이 어플리케이션의 메타데이터가 있습니다.


build-settings.xml 파일에는 minification and concatenation 에 대한 정보가 있습니다.


bin 폴더에는 remote Worklight Server에 deploy 할 때 사용될 수 있는 .wlapp, .wladapter 등이 있습니다.


세번째는 서버와 관련된 부분인데요.


externalServerLibraries폴더에는 external service server에 있는 라이브러리들이 있습니다.


server 폴더에는 서버쪽에서 해당 프로젝트를 customization할 수 있는 파일들이 들어 있습니다.


우선 conf 폴더에는

authenticationConfig.xml, default.keystore, login.html, SMSConfig.xml 등등이 있습니다.

java 폴더에는 앱을 빌드하고 난 후 Worklight 서버에 컴파일되고 deploy될 자바 클래스들이 있구요.

lib 폴더에는 서버에 deploy 될 JAR 파일들이 있습니다.


services 폴더에는 back-end services와 관련된 내용들이 있습니다.


Creating your first hybrid Worklight application 문서를 보면 더 자세한 내용들이 나옵니다.



그것들까지 다 정리할 수 는 없겠네요. 혹시 나중에 필요하면 정리하는 걸로 하고...

이 문서 마지막에 퀴즈가 있는데 그거나 복사해 넣어 둬야겠어요.




디폴터 앱 구조는 single HTML과 여러 CSS 그리고 JS 파일들이고


custom server-side Java 클래스들과 서버에서 사용되는 Properties 그리고 서버쪽 자바 코드가 포함된 JAR 파일들이 Worklight Project의 server-side 컴포넌트에 추가 될 수 있답니다.

서버 퍼포먼스를 테스트하기 위한 JMeter 어플리케이선은 이 프로젝트에 추가하지 않구요.


어플리케이션이 사용할 URL을 명시하는 곳은 application-descriptor.xml 입니다.


일단 첫번째 앱을 만들면서 Worklight Project의 기본 구조에 대해서 공부했습니다.


반응형

'WEB_APP > IBM Worklight' 카테고리의 다른 글

IBM Weblight 개요 및 설치하기  (0) 2014.08.26

IBM Weblight 개요 및 설치하기

2014. 8. 26. 15:12 | Posted by 솔웅


반응형

IBM Worklight Foundation


Develop, test, secure and manage mobile apps


IBM® Worklight® Foundation 은 여러분의 비지니스를 mobile device들로 확장하는데 도움을 드립니다. 이 제품은 개방적이고 여러 platform에서 빌드 하고 테스트하고 실행할 수 있고 native, hybrid, mobile web app 등을 관리할 수 있도록 해 줍니다. IBM Worklight Foundation 은 앱 개발과 유지 보수 비용을 절감하고 time-to-market 을 개선하고 모바일 앱에 대한 운영과 보안 부분을 개선하는데 도움을 드립니다.

IBM Worklight Foundation 은 아래 다섯가지로 구성돼 있습니다.

IBM Worklight Studio는 코드 재사용을 극대화하고 신속한 개발을 도와주는 native와 hybrid 개발에 대한 leading tool들을 제공합니다.

IBM Worklight Server는 mobile-optimized middleware로 어플리케이션과 back-end system 그리고 cloud-based service들 사이의 gateway 역할을 합니다.

IBM Worklight Device Runtime Components는 runtime client API (application program interfaces)로 보안과 운용 그리고 유용성(사용성) 개선을 위해 디자인 되었습니다.

IBM Worklight Application Center는 완성된 (production-ready) 모바일 앱을 배포하는 것을 관리하는 enterprise app store 를 셋업할 수 었도록 도와 줍니다.

IBM Worklight Console 은 administrative GUI 로 서버, adapters, 어플리케이션 그리고 push servies에 대한 실시간 운영 통게 분석을 제공함 으로서 모바일 앱의 관리와 모니터 그리고 instrument에 도움을 주기 위해 디자인 되었습니다.




IBM Worklight로 다음과 같은 일을 할 수 있습니다. :

   - 하나로 통일되고 공유되는 code base로 다양한 모바일 운영환경과 다양한 device들을 지원합니다.
   - Worklight 개발자들을 위해 command line interpreter로 선호하는 개발 툴을 활용할 수 있도록 합니다.
   - IBM BlueMix 모바일 서비스를 포함해 enterprise data, applications 그리고 cloud service들과 함께 연결되고 동기화 됩니다.
   - device, application, data 그리고 network 단에서 mobile 보안을 강화시켜 줍니다.

   - 하나의 central interface로부터 모바일 앱 포트폴리오를 관리합니다.




Download: IBM Worklight Developer Edition

IBM Worklight Developer Edition은 Eclipse IDE를 위한 self-contained, easy-to-install plugin 입니다. IBM Worklight Enterprise and Consumer Editions 은 각각의 개발 환경과 서버 콤포넌트들로 구성돼 있고 Developer Edition 은 그것들을 묶어서 데이터베이스나 어플리케이선 서버를 따로 인스톨하지 않고 한번에 Eclips용으로 다운로드 할 수 있도록 해 줍니다.

일단 인스톨이 되면 쉽고 빠르게 mobile web, hybrid 그리고 native 앱들을 iOS, 안드로이드, 블랙베리, Windows® Phone 등을 포함한 여러 모바일 플랫폼에서 동작하도록 할 수 있습니다. 이러한 앱 개발을 위해 HTML5, CSS3, JavaScript, Apache Cordova 그리고 jQuery, Sencha Touch, Dojo Mobile 같은 많이 사용되는 자바스크립트 프레임워크들을 사용할 수 있습니다.



Install Worklight Studio - 링크 클릭 후 worklight Studio 탭 선택

Worklight Studio 는 Eclipse plugin으로 신속하게 빌드하고 실행시키고 mobile web, hybrid, native 앱들을 관리할 수 있도록 해 줍니다.

    1. Java EE Developer를 위한 Eclipse IDE를 준비하세요.
    Juno SR2 (4.2.2), Kepler SR1 (4.3.1), Kepler SR2 (4.3.2), or Luna R (4.4).
    이전 버전의 이클립스를 가지고 있다면 Juno, Kepler, Luna 로 업데이트 한 후 아래 과정을 실행하시기 바랍니다.
    
    2.V6.1 이전의 Worklight Developer Edition을 가지고 있다면 그 프로그램을 Uninstall 하세요.
    이전 버전의 Worklight Developer Edition에서 Worklight Studio V6.2 로 업그레이드 할 수 없습니다.
    
    3. 이클립스를 실행후 Help > Eclipse Marketplace를 선택하세요.
      
    4.Find field에 Worklight을 입력한 후 Go를 클릭하세요.
    
    5.IBM Worklight Studio Install 버튼을 클릭하세요.
    
    6.IBM Worklight Studio와 다른 모든 기능들이 이미 선택돼 있을 겁니다. 확인 후 Next를 클릭하세요.
        항상 IBM Worklight Studio를 선택해야 합니다.
        IBM Dojo Mobile Tools 와 IBM jQuery Mobile Tools 들은 선택사항입니다. 필요하시면 선택하세요.
        
    7. license term들을 확인 후 accept 하세요. 그리고 installation을 시작하려면 Finish를 클릭하시면 됩니다.
    
    8. installation을 완료하기 위해 prompt들을 따라 진행하시기 바랍니다.
    
    9. 만약 여러분의 Eclipse workbench 에 IBM Rational Team Concert™ V4.0 Eclipse Client 가 이미 인스톨 되어 있다면, Worklight Studio를 시작하기 전에 이클립스 environment를 clean 하셔야 합니다.
    
    10. 이제 Worklignt 를 시작하세요. 


Get Start 링크 : http://www.ibm.com/developerworks/mobile/worklight/getting-started.html


====================================================================


이번에 join 한 프로젝트에서 하이브리드 모바일 앱을 만드는데 거기서 이 IBM Worklight를 사용합니다.

이 프로젝트에 제 업무의 25%만 사용해서 매뉴얼 테스팅만 하기 때문에 이 툴을 알아야 될 필요는 없지만..

관심있는 Cross-Platform Mobile App Development 툴이라 한번 공부해 보려구요.


다음 글서 부터는 Get Start 링크에 있는 사용법을 따라 해 본 후 정리해서 올릴 계획입니다.

반응형

'WEB_APP > IBM Worklight' 카테고리의 다른 글

[Worklight] 첫번째 앱 HelloWorklight  (0) 2014.09.15

[CookBook] Fragments 이해하기 -10-

2013. 10. 2. 12:08 | Posted by 솔웅


반응형

Setting user's Preferences with PreferenceFragment


PreferenceFragment는 유저가 어플리케이션을 configure하고 personalize할 수 있도록 하는 fragment 입니다. 이 PreferenceFragment는 여러개의 preference view들을 가질 수 있습니다. 애플리케이션의 preference를 쉽게 세팅할 수 있도록 도와주기 위해서이죠. PreferenceFragments에는 아래와 같은 preference view 들이 있습니다.



PreferenceScreen : preference screen을 정의하기 위해 사용되는 XML의 root element.

CheckBoxPreference : check되면 true를 안되면 false를 return 하는 간단한 check box를 표시한다.

ListPreference : 사용자가 선택할 수 있는 radio button들의 리스트를 표시한다.

EditTextPreference : 사용자가 텍스트를 입력할 수 있는 EditText dialog를 표시한다.

RingtonePreference : ringtone을 가리키는 radio button을 표시한다.

PreferenceCategory : 카테고리 내의 관계된 preference들을 grouping 한다.

Preference : Button 처럼 사용하는 custom preference



어떻게 어플리케이션 preference들이 세팅되는지 이해하기 위해 PrefFragmentApp이라는 안드로이드 프로젝트를 일단 만들어 보죠. pPreferenceFragment에서 preference view들을 표시하는 방법에는 두가지가 있습니다. XML 파일을 이용하는 방법과 code를 이용하는 방법이 있습니다. 우리는 XML을 이용하는 방법을 시도해 보겠습니다. 그러니까 먼저 res 폴더 밑에 xml 이라는 폴더를 먼저 만드셔야 합니다. 이 res/xml 이라는 폴더 밑에 preference.xml 이라는 XML 파일을 추가하시면 됩니다. 이 xml 에는 어플리케이션의 configure를 위해 유저에게 표시될 preference view들이 선언돼 있습니다. 이 preference view들 중 유저가 선택한 옵션들은 어플리케이션 내에 계속 유지될 겁니다.






preference.xml



<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
    <PreferenceCategory android:title="Category 1">
        <CheckBoxPreference
            android:title="Newsletter"
            android:defaultValue="false"
            android:key="Newskey"  />
        <EditTextPreference android:key="Namekey"
            android:title="Enter your name: "
            android:dialogTitle="Enter your name" >
        </EditTextPreference>
    </PreferenceCategory>
    <PreferenceCategory android:title="Category 2">
        <RingtonePreference android:showDefault="true"
            android:key="Audio" android:title="Select sound"
            android:ringtoneType="notification" >
        </RingtonePreference>
        <ListPreference android:title="Products List "
            android:key="products_list"
            android:entries="@array/products"
            android:entryValues="@array/prodselected"
            android:dialogTitle="Choose a product" >
        </ListPreference>
    </PreferenceCategory>
    <Preference
        android:title="Submit"
        android:key="submitPref" />
</PreferenceScreen>



이 PreferenceScreen 안에는 두개의 PreferenceCategory가 있는게 보이실 겁니다. Category 1에는 CheckboxPreference, EditTextPreference 이렇게 두개의 preference view가 있습니다. Category 2에는 RingtonePreference, ListPreference 이렇게 있구요. 모든 preference view는 android:key 값을 가져야 합니다. 일정의 id이죠. android:title 속성은 preference view의 초기값을 할당하기 위해 사용됩니다. 그리고 android:defaultValue 속성은 preference view에 디폴트 값을 할당할 때 사용되구요.



CheckBoxPreference는 UI element로서 check box를 표시합니다. 여기에는 Boolean 형식으로 값이 저장되구요. 체크박스가 선택되면 true값이 선택되지 않으면 false 값이 저장됩니다.  android:default 속성을 사용해서 디폴트 값을 false로 설정했습니다.



EditTextPreference 는 android:key 속성에 Namekey 라고 정해져 있습니다. 그리고 android:title에는 Enter your name : 이 지정돼 있구요. 이 EditTextPreference 가 선택되면 title이 Enter your name 이라는 dialog가 뜰 겁니다. 사용자가 정보를 입력하고 OK 버튼을 클릭하면 입력된 정보가 preference store에 저장됩니다.



RingtonePreference는 ringtone 리스트가 있는 dialog box를 보여줄 겁니다. 그리고 사용자가 default ringtone이나 silent mode를 선택할 수 있도록 합니다. 여기에 android:key 속성에는 Audio라고 설정이 돼 있습니다. 그리고 title은 Select sound라고 돼 있죠. android:ringtoneType은 display 될 ringtone 리스트를 정합니다. 여기에 들어갈 수 있는 값은 ringtone, notification, alarm 그리고 all 이 들어갈 수 있습니다.



ListPreference 에는 radio 버튼 형식으로 preference들의 세트를 dialog box 에 보여 줍니다. 사용자가 그 중 하나를 선택할 수 있는 거죠. 이 dialog box의 title은 Choose a product 가 될 겁니다. android:key 속성에는 product_list가 대입 됐구요. android:endtries 속성은 preference들의 리스트를 보여주기 위해 ListPreference에 product라는 이름의 배열이 할당됐습니다. 이 배열에 있는 값들이 ListPreference를 통해서 표시되는 radio button들의 아이템이 될 겁니다. android:entryValues 속성은 prodselected라고 하는 다른 배열을 정의하는데요. product 배열에 정의된 요소들의 값을 잡아두고 있기 위해서 세팅됐습니다. android:entryValues 속성은 사용자가 선택한 radio button에 해당되는 값들을 저장하는 배열입니다.



<Preference> element는 PreferenceFragment에 Submit Button을 표시합니다. 이 Submit button은 여기서 android:key 속성에 해당되는 값이 submitPref로 돼 있습니다. 자바코드에서 이 값을 갖고 콘트롤 할 겁니다.



이제 strings.xml에 두개의 배열을 정의할 겁니다. 하나는 ListPreference의 radio button에 표시될 텍스트들이구요 다른 하나는 첫번째 배열과 대응하는 값들 입니다. 이 xml은 res/values 폴더 안에 있게 됩니다.



strings.xml



<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">PrefFragmentApp</string>
    <string name="menu_settings">Settings</string>
    <string-array name="products">
        <item>Camera</item>
        <item>Laptop</item>
        <item>Watch</item>
        <item>Smartphone</item>
        <item>Television</item>
    </string-array>
    <string-array name="prodselected">
        <item>You have selected Camera</item>
        <item>You have selected Laptop</item>
        <item>You have selected Watch</item>
        <item>You have selected Smartphone</item>
        <item>You have selected Television</item>  
    </string-array>
</resources>


products 배열에 있는 element들은 ListPreference에 보이는 radio buttons 옆에 표시될 텍스트 들입니다. prodselected 배열은 위 products 배열중에서 선택된 것들에 대한 return 값들이 들어 있습니다.



preference.xml에 있는 이 preference view들을 load 하기 위한 자바클래스가 필요 합니다. 아래 그 샘플 코드가 있습니다.



PrefFragActivity.java



public class PrefFragActivity extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getFragmentManager().beginTransaction().replace(android.R.id.content, new PrefsFragment()).commit();
    }

    public static class PrefsFragment extends PreferenceFragment  {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(R.xml.preferences);
            Preference submitPref = (Preference) findPreference("submitPref");
            submitPref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
                public boolean onPreferenceClick(Preference preference) {
                    getActivity().finish();
                    return true;
                }
            });
        }
    }
}



PreferenceFragment를 사용하기 위해 자바 클래스에서 PreferenceFragment를 extends 합니다. addPreferencesFromResource() 메소드는 XML 파일(preferences.xml)에 있는 PreferenceFragment에 있는 preference view를 load하기 위해 호출됩니다. preferences.xml에서 <Preference) element를 사용해 정의된 Submit 버튼은 submitPref라는 Preference 객체를 통해서 접근되고 매핑이 됩니다. 이것의 콜백 메소드인 onPreferenceClick()은 submitPref 객체가 클릭됐을 떄 실행됩니다. 이 onPreferenceClick() 메소드는 이 activity를 finish() 하고 선택된 preferences에 필요한 action을 하기 위해 PreferenceFragActivity.java로 돌아 갑니다. 이 PrefFragmentAppActivity자바 activity 파일을 통해 텍스트뷰에 유저가 선택한 preference를 표시할 겁니다.



이 PreferenceFragment에 보여지는 preference view들로부터 선택된 옵션을 표시하기 위해 4개의 텍스트뷰가 정의되어야 합니다. 아래 그 layout xml 파일이 있습니다.



activity_pref_fragment_app.xml



<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/newsletter"
        android:textSize="@dimen/text_size"        
        android:textStyle="bold" />
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/name"
        android:textSize="@dimen/text_size"
        android:textStyle="bold" />
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/ringtone"
        android:textSize="@dimen/text_size"
        android:textStyle="bold" />
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/product"
        android:textSize="@dimen/text_size"
        android:textStyle="bold" />
</LinearLayout>



위 layout xml 파일을 보면 4개의 텍스트뷰가 있고 각각 id 는 각각 newsletter, name, ringtone, product 입니다. 이 텍스트뷰는 LinearLayout 안에서 아래 위로 배치됩니다. newsletter 텍스트뷰에는 CheckBoxPreference의 체크박스에 유저가 체크했는지 여부가 표시될 겁니다. name 텍스트뷰는 EditTextPreference에 유저가 입력한 이름이 표시될것이고 ringtone 텍스트뷰는 유저가 선택한 RingtonePreference의 ringtone이 표시될 겁니다. product 텍스트뷰에는 ListPreference에서 유저가 선택한 product가 표시됩니다.



PreferenceFragment를 표시하고 사용자가 선택한 preference들을 보여주기위해 아래와 같은 자바파일을 만듭니다.



PrefFragmentAppActivity.java



public class PrefFragmentAppActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pref_fragment_app);
        startActivity(new Intent(this, PrefFragActivity.class));
    }

    @Override
    public void onResume() {
        super.onResume();
        SharedPreferences prefs=PreferenceManager.getDefaultSharedPreferences(this);
        TextView newsletter=(TextView)findViewById(R.id.newsletter);
        TextView name=(TextView)findViewById(R.id.name);
        TextView ringtone=(TextView)findViewById(R.id.ringtone);
        TextView product=(TextView)findViewById(R.id.product);
        if(Boolean.valueOf(prefs.getBoolean("Newskey", false)))
            newsletter.setText("You have selected Newsletter");
        else
            newsletter.setText("");
        ringtone.setText("The ringtone selected is "+prefs.getString("Audio", "Silent"));
        name.setText("The name entered is "+prefs.getString("Namekey",""));
        String selectedProduct = prefs.getString("products_list", "Camera");
        product.setText(selectedProduct);
    }
}



이 PreferenceFragment를 표시하기 위해 PrefFragActivity 클래스가 시작됩니다. PreferenceFragment에서 사용자가 선택한 preferences를 보여주기 위해 activity_pref_fragment_app.xml 인 layout 파일에 텍스트 뷰들이 정의돼 있습니다. 이 preference 뷰들에서 선택된 옵션을 찾기 위해  prefs로 명명된 SharedPreferences 객체를 생성했습니다. getInt(), getString(), getBoolean() 메소드를 통해 이 SharedPreferences 객체로부터 그 값들을 수집합니다.



CheckBoxPreference의 값을 읽기 위해서는 getBoolean() 메소드를 사용하고 CheckBoxPreference의 key를 전달해서 값을 받습니다. 이 Newskey라는 key가 SharedPreference 인스턴스의 getBoolean()메소드를 통해 전달 됐을 때 이 CheckBoxPreference는 true나 false 를 return 할 겁니다.


그리고 EditTextPreference는 SharedPreference 인스턴스의 getString()메소드로 Namekey라는 key를 전달합니다. 디폴트는 empty string 입니다. RingtonePreference와 ListPreference도 Audio와 product_list라는 key 값을 SharedPreference인스턴스의 getString() 메소드를 통해서 전달합니다. preference view들에서 사용자에 의해 선택된 preference들은 택스트뷰들을 통해 표시됩니다. ringtone의 디폴트값은 Silent 이고 product는 Camera 입니다.



이 PrefFragActivity.java 를 안드로이드에 보이도록 하려면 아래 코드를 AndroidManifest.xml에 추가하셔야 합니다.



<activity android:name=".PrefFragActivity" android:label="@string/app_name" />



Summary
 
 이 챕터에서는 fragments의 사용법과 다른 화면 크기에 맞게 어플리케이션을 적용하는 방법에 대해 다뤘습니다. fragment life cycle과 runtime시 동적으로 이 fragment를 추가하는 방법도 다뤘습니다. 그리고 fragment들 사이에 데이터를 전달하고 받는 방법도 배웠습니다. 그리고 ListFragment, DialogFragment 그리고 PreferenceFragment에 대해서도 배웠습니다.


반응형

[CookBook] Fragments 이해하기 -9-

2013. 10. 1. 21:11 | Posted by 솔웅


반응형

Displaying Dialog Through DialogFragment



안드로이드에서는 dialogs가 비동기적입니다. 동기적인 dialogs들은 이 dialog가 실행되는 동안 activity가 suspends 됩니다. 유저가 이 dialog를 사용하고 있는 동안에는 다른 것들이 올 수 없습니다. 비동기적인 dialogs들은 유저가 dialog를 사용하고 있는 동안에도 activity의 작업은 계속 됩니다. 이 activity는 콜백 메소드를 implement 함으로서 dialog와 함께 유저의 접근을 허용할 수 있습니다. 안드로이드의 dialogs는 자연스럽습니다. dialog가 open 돼 있는 동안 유저는 어플리케이션의 다른 부분에 접근할 수 없습니다. dialog를 비동기적으로 호출하는 방법의 잇점은 코딩을 줄일 뿐만 아니라 code를 통해서 이 dialog를 dismiss 할 수 있는 기능이 제공 된다는 것입니다.



DialogFragment base class를 extends 함으로서 DialogFragment를 사용하실 수 있습니다. 이 DialogFragment base 클래스는 Fragment 클래스에서 파생된 것입니다. 이 DialogFragment를 구현하기 위해 DialogFragmentApp이라는 프로젝트를 만들겠습니다. 여기에는 두개의 fragments들이 있을 건데요. 하나는 DialogFragment를 보여줄거고 다른 하나는 텍스트뷰를 보여줄 겁니다. DialogFragment와 유저의 상호작용은 두번째 fragment에 있는 텍스트뷰를 통해서 이뤄질 겁니다. DialogFragment에 있는 selected button은 두번째 fragment의 텍스트뷰를 통해서 display 됩니다.




이 DialogFragment를 만들기 전에 우선 텍스트뷰를 가지고 있는 fragment의 UI를 정의하겠습니다.


fragment2.xml



<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <TextView 
        android:id="@+id/selectedopt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Select Open Dialog Button"
        android:textSize="@dimen/text_size"
        android:textStyle="bold" />
</LinearLayout>



LinearLayout 안에 id 가 selectedopt인 한개의 TextView 가 있습니다. 여기에 할당된 텍스트는 Select Open Dialog Button이네요. 볼드체이고 사이즈는 dimension resource의 text_size를 갖다가 사용합니다.
이 UI를 load 할 자바 클래스를 만들어 보죠.



Fragment2Activity.java



public class Fragment2Activity extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment2, container, false);
    }
}



아주 간단합니다. Fragment base 클래스를 extends 했고 onCreateView() 메소드 안에는 방금 만들었던 fragment2.xml 의 UI를 로드하기 위해 LayoutInflater를 사용했습니다.



이 fragment를 사용할 layout xml파일을 만들겠습니다.



activity_dialog_fragment_app.xml



<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >
    <fragment
        android:name="com.androidtablet.dialogfragmentapp.Fragment2Activity"
        android:id="@+id/fragment2"
        android:layout_weight="0"
        android:layout_width="wrap_content"
        android:layout_height="match_parent" />
    <Button
        android:id="@+id/dialog_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Open Dialog"
        android:textSize="@dimen/text_size" />
</LinearLayout>


Button 이 있습니다. 이 버튼을 클릭하면 DialogFragment가 나타나도록 할 겁니다. fragment와 button 이 LinearLayout 안에 배치해 있습니다. Fragment는 id 가 fragment2 이고 Button 은 id 가 dialog_button 입니다. Caption은 Open Dialog로 돼 있네요. 이 Caption은 dimention resource에서 text_size로 정의된 텍스트 크기를 가질 거구요.



이제 DialogFragment를 보여줄 코드를 작성할 차례입니다. DialogFragment를 보이기 위해서 자바 클래스는 DialogFragment 클래스를 extend 해야 합니다.



Fragment1Avtivity.java



public class Fragment1Activity extends DialogFragment{
    static Fragment1Activity newInstance(String title) {
        Fragment1Activity fragment = new Fragment1Activity();
        Bundle args = new Bundle();
        args.putString("title", title);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {   
        String title = getArguments().getString("title");
        Dialog diag = new AlertDialog.Builder(getActivity())
        .setIcon(R.drawable.ic_launcher)
        .setTitle(title)
        .setPositiveButton("OK", new DialogInterface.
            OnClickListener() {
            public void onClick(DialogInterface dialog, int
                whichButton) {
                ((DialogFragmentAppActivity) getActivity()).PositiveButton();
            }
        })
        .setNegativeButton("Cancel", new DialogInterface.
            OnClickListener() {
            public void onClick(DialogInterface dialog, int
                whichButton) {
                ((DialogFragmentAppActivity) getActivity()).NegativeButton();
            }
        }).create();
 
        return diag;
    }
}



보시다시피 DialogFragment를 생성하기 위해 이 자바 클래스는 DialogFragment 클래스를 extends 했습니다.
newInstance() 메소드는 이 fragment의 new instance를 생성합니다. 이 DialogFragment의 제목이 파라미터로 전달 됩니다. 이 파라미터는 Bundle 에 저장되고 fragment에 세팅 됩니다. (setArguments().



DialogFragment의 view hierarchy를 생성하기 위해 onCreateDialog() 메소드를 오버라이드 합니다. 그리고 title을 만들기 위한 Bundle 객체가 파라미터로 전달 됩니다. 이 onCreateDialog() 메소드 안에서 이 Dialog를 생성하기 위해 AlertDialog.Builder()를 사용하시는 것을 보실 수 있을 겁니다. 여기에 아이콘을 세팅하고 타이틀을 세팅하고 OK 버튼과 Cancel 버튼을 생성합니다.
이 OK와 Cancel 버튼에는 각각 onClickListener()를 달구요. OK를 클릭하면 PositiviButton() 메소드가 호출 디고 Cancel 버튼을 클릭하면 NegativeButton()이 호출 됩니다.



마지막에 이 메소드에서는 이 AlertDialog를 return 하구요.



이제 이 DialogFragment를 invoke 시킬 자바 액티비티 파일을 만들어야 합니다. 이 java activity file에는 OK와 Cancel을 눌렀을 때 실행되어야 할 PositiveButton()과 NegativeButton()메소드들이 구현되어야 하구요.



DialogFragmentAppActivity.java



public class DialogFragmentAppActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dialog_fragment_app);
        Button dialogButton = (Button)findViewById(R.id.dialog_button);
        dialogButton.setOnClickListener(new Button.OnClickListener(){
            @Override
            public void onClick(View arg0) {
                Fragment1Activity dialogFragment =
                    Fragment1Activity.newInstance( "Continue Processing?");
                dialogFragment.show(getFragmentManager(),  "Dialog Fragment Example");
            }
        });
    }

    public void PositiveButton() {
        TextView selectedOpt = (TextView)findViewById(R.id.selectedopt);
        selectedOpt.setText("You have selected OK button");
    }

    public void NegativeButton() {
        TextView selectedOpt = (TextView) findViewById(R.id.selectedopt);
        selectedOpt.setText("You have selected Cancel button");   
    }
}


onCreate() 메소드를 보시면 아까 만들었던 activity_dialog_fragment_app.xml 의 UI를 view로 set 하고 그 안의 Button에 대한 객체를 만듭니다. 그리고 이 버튼에 리스너를 달아서 클릭하면 Fragment1Activity.java 의 newInstance() 메소드를 호출합니다. 이때 타이틀이 될 Continue Processing?이라는 텍스트가 파라미터로 전달 되구요.
이 DialogFragment는 show() 메소드를 호출함으로서 visible 하게 됩니다. 이 show() 메소드는 이 fragment를 주어진 FragmentManager에 추가하게 되죠.
이 코드에는 아까 말했듯이 PositiveButton()과 NegativeButton() 메소드가 구현되었습니다. OK와 Cancel 버튼이 눌렸을 때 호출될 메소드 들입니다. 이 두 메소드에서는 모두 selectedopt라는 id를 가진 텍스트뷰의 객체를 만들고 여기에 text를 세팅하고 있습니다.



이 앱을 실행하고 Open Dialog 라는 버튼을 누르면 AlertDialog가 뜹니다. 여기서 OK를 누르면 이 Dialog 가 사라지고 왼쪽의 텍스트뷰에 You have selected OK Button이 쓰여지고 Cancel을 누르면 You have selected Cancel button 이 출력됩니다.



이 Dialog box는 사용자에게 중요한 메세지를 alert 하거나 사용자로부터 어떤 feedback을 받을 때 사용합니다.

반응형

Sencha Touch 1.x 관련 메모

2013. 10. 1. 11:35 | Posted by 솔웅


반응형

* 앱 시작하기


Ext.setup({
    tabletStartupScreen: 'tablet_startup.png',
    phoneStartupScreen: 'phone_startup.png',
    icon: 'icon.png',
    glossOnIcon: false,
    statusBarStyle: 'default',
 
onReady: function(){
new Ext.Panel(
{
    fullscreen: true,
    html: 'Hello Sencha Touch'
}
);
}
});



new Ext.Application({
launch: function() {
new Ext.Panel(
{
fullscreen: true,
html: ‘Hello Sencha Touch’
}
);
}
});


MVC - Ext.Application




* Theme : Sass (Ruby) - CSS를 프로그래밍하듯이 작성할 수 있음
  Sass 내장함수 : http://sass-lang.com/docs/yardoc/Sass/Script/Functions.html
  > sass filename.scss filename.css
  > css2sass filename.css filename.scss
  > sass -style compressed filename.scss filename.css



* Compass : Sass 를 좀 더 편리하게 개발할 수 있도록 함 http://compass-style.org/



* 설치
  - Ruby 설치 http://www.ruby-lang.org/ko/downloads/
  - Sass & Compass 설치
    > gem install haml
    > gem install compass


* config.rb : 컴파일 옵션



* resources/themes/stylesheets/sencha-touch/default/_variables.scss
  $base-color : 앱의 기본 색상 정의
  $base-gradient : ‘matte’, ‘glossy’, ‘flat’, ‘bevel’, ‘recessed’ etc.
  > compass compile sencha-touch.scss
  > compass -watch



* Ext.Panel



Ext.setup({
onReady: function(){
new Ext.Panel({          Panel 객체 생성, <dev>요소로 DOM에 추가 됨
fullscreen: true,        전체 화면
style: "...",          CSS 지정
layout: { ... },         레이아웃 정보
items: [ { ... }, { ... }, ... ],         UI 아이템들 지정
dockedItems: [ { ... }, { ... }, ... ]         도킹 아이템 지정. Panel의 상하좌우에 밀착된 아이템
});
}
});



* dockedItems


dockedItems: [
{
dock: "top",
style: "background-color:red;",
html: "DockItem-Top"
},
{
dock: "left",
style: "background-color:gray;",
html: "DockItem-Left"
},
{
dock: "bottom",
style: "background-color:yellow;",
html: "DockItem-Bottom"
},
{
dock: "right",
style: "background-color:green;",
html: "DockItem-Right"
}
}



* layout


layout: {
type: 'vbox',
align: 'stretch',
pack: 'center'
},



* items : 객체 생성


items:[
new Ext.Button({ text: ‘button1’ })
]



* Ext.TabPanel


Ext.setup({
onReady: function(){
var item1 = {
title: 'Tab1',
style: "background-color: red;",
html: 'Item1'
};
var item2 = {
title: 'Tab2',
style: "background-color: gray;",
html: 'Item2'
};
var item3 = {
title: 'Tab3',
style: "background-color: yellow;",
html: 'Item3'
};
var panel = new Ext.TabPanel({
fullscreen: true,
ui: 'dark',
tabBarDock: 'top',
cardSwitchAnimation: 'slide',
items: [item1,item2,item3]
});
}
});



* Ext.Carousel


Ext.setup({
onReady: function(){
var item1 = {
style: "background-color:red;",
html: 'Item1'
};
var item2 = {
style: "background-color:gray;",
html: 'Item2'
};
var item3 = {
style: "background-color:yellow;",
html: 'Item3'
};
var panel = new Ext.Carousel({
fullscreen: true,
ui: 'dark',
indicator: true,
direction: 'horizontal',
items: [item1,item2,item3]
});
}
});


* Multi Carousel


Ext.setup({
onReady: function(){
var item1 = {
style: "background-color:red;",
html: 'Item1'
};
var item2 = {
style: "background-color:gray;",
html: 'Item2'
};
var item3 = {
style: "background-color:yellow;",
html: 'Item3'
};
var topCarousel = new Ext.Carousel({
items: [item1,item2,item3]
});
var middleCarousel = new Ext.Carousel({
items: [item1,item2,item3]
});
var bottomCarousel = new Ext.Carousel({
items: [item1,item2,item3]
});
var panel = new Ext.Panel({
fullscreen: true,
layout:{
type: 'vbox',
align: 'stretch'
},
defaults: {flex: 1},
items: [topCarousel, middleCarousel, bottomCarousel]
});
}
});



* Ext.Toolbar


Ext.setup({
onReady: function(){
var panel = new Ext.Panel({
fullscreen: true,
dockedItems: [{
xtype: 'toolbar',
dock: 'top',
title: 'My Toolbar',
defaults: {
xtype: 'button'
},
items: [
{ ui: 'decline-round', text:'decline-round' }
]
}]
});
}
});



* Ext.Button


Ext.setup({
onReady: function(){
new Ext.Panel({
fullscreen: true,
layout: {
type: 'vbox',
align: 'start'
},
defaults: {
layout: { type: 'hbox' },
flex:1,
defaults: {
xtype: 'button'
}
},
items:[
{items: [
{ ui: 'normal', text:'Normal',
handler: function() {
Ext.Msg.alert('Message', 'Hi~~', Ext.emptyFn);
}
},
{ui: 'round', text:'Round'},
{ui: 'small', text:'Small'}
]},
{items: [
{ui: 'decline', text:'Drastic'},
{ui: 'decline-round', text:'Round'},
{ui: 'decline-small', text:'Small'}
]},
{items: [
{ui: 'confirm', text:'Confirm'},
{ui: 'confirm-round', text:'Round'},
{ui: 'confirm-small', text:'Small'}
]},
{items: [
{ui: 'action', text:'Action'},
{ui: 'action-round', text:'Round'},
{ui: 'action-small', text:'Small'}
]},
{items: [
{ui: 'back', text:'back'},
{ui: 'Forward', text:'Forward'}
]}
]
});
}
});



* SegmentedButton


Ext.setup({
onReady: function(){
var segmentedButton = [{
xtype: 'segmentedbutton',
allowMultiple: false,
allowDepress: false,
items: [
{ text: 'Toggle 1' },
{ text: 'Toggle 2', pressed : true },
{ text: 'Toggle 3' }
],
listeners : {
toggle : function(container, button, active){
Ext.Msg.alert('Tap', button.text + " : " + (active ? 'on' : 'off'), Ext.emptyFn);
}
}
}];
new Ext.Panel({
fullscreen: true,
dockedItems:{
xtype: 'toolbar',
ui: 'light',
items: [segmentedButton]
}
});
}
});



* iconCls


Ext.setup({
onReady: function(){
var item1 = { title: 'info', iconCls: 'info', badgeText:'2',};
var item2 = { title: 'favorites', iconCls: 'favorites' };
var item3 = { title: 'settings', iconCls: 'settings' };
var item4 = { title: 'bookmarks', iconCls: 'bookmarks' };
var item5 = { title: 'download', iconCls: 'download' };
var item6 = { title: 'more', iconCls: 'more' };
var item7 = { title: 'search', iconCls: 'search' };
var item8 = { title: 'team', iconCls: 'team' };
var item9 = { title: 'time', iconCls: 'time' };
var item10 = { title: 'user', iconCls: 'user' };
var item11 = { title: 'action', iconCls: 'action' };
var item12 = { title: 'add', iconCls: 'add' };
var item13 = { title: 'arrow_up', iconCls: 'arrow_up' };
var item14 = { title: 'arrow_right', iconCls: 'arrow_right' };
var item15 = { title: 'arrow_down', iconCls: 'arrow_down' };
var item16 = { title: 'arrow_left', iconCls: 'arrow_left' };
var item17 = { title: 'compose', iconCls: 'compose' };
var item18 = { title: 'delete', iconCls: 'delete' };
var item19 = { title: 'refresh', iconCls: 'refresh' };
var item20 = { title: 'reply', iconCls: 'reply' };
var item21 = { title: 'star', iconCls: 'star' };
var item22 = { title: 'trash', iconCls: 'trash' };
var panel = new Ext.TabPanel({
fullscreen: true,
ui: 'light',
cardSwitchAnimation: 'slide',
tabBar: {
dock: 'bottom',
scroll: 'horizontal'
},
items:
[
item1,item2,item3,item4,item5,item6,item7,item8,item9,item10,
item11,item12,item13,item14,item15,item16,item17,item18,item19,item20,
item21,item22
]
});
}
});



* Overlay : HTML과 스크립트 모두 작업해야 함

* Ext.List

* Ext.MessageBox : Alert, Confirm, Prompt


* Ext.is
  width: Ext.is.Phone ? 260 : 400,
  height: Ext.is.Phone ? 220 : 400


* contentEl : html을 사용해서 레이아웃 구성



********************** 이상 UI 와 관련해서 ************************

* Ajax

* Ext.Template : HTML 태그 모형


var myTpl = new Ext.Template([
'<div>',
'<span> <b>{name}</b> is {value} </span>',
'</div>'
]);
Ext.setup({
onReady: function(){
var panel = new Ext.Panel({
fullscreen:true,
tpl: myTpl
});
panel.update(
{
name: "Sencha Touch",
value: "The First HTML5 Mobile Web App Framework"
}
);
}
});



* Ext.XTemplate : 배열 형태의 데이터를 쉽게 다룰 수 있음



* Ajax 호출 : Ext.Ajax
    • url: Ajax 통신 대상이 되는 원격지의 URL
    • timeout: 네트워크 통신이 항상 안정적이지는 않다. 따라서 적절한 타임아웃 설정이 필요하다. Ajax 통신 과정에서 타임아웃 시간을 초과하면 더는 기다리지 않고 실패로 처리하는 것이 좋다. 이 속성에 타임아웃 값을 밀리초 단위로 지정한다. 기본값은 30,000밀리초(약 30초)다.
    • success 함수: Ajax 통신이 성공하면 실행되는 함수
    • failure 함수: Ajax 통신이 실패하면 실행되는 함수
    • callback 함수: 성공/실패와 상관없이 Ajax 통신이 완료되면 실행되는 함수



* JSONP : 크로스도메인 접근을 가능하도록 함
 <script type=’text/javascript’ src=’http://anotherDomain/server.js’></script>



Ext.util.JSONP.callback(
{
"name": "Sencha Touch",
"value": "The First HTML5 Mobile Web App Framework"
}
)



Ext.util.JSONP.request({ .......



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



* Data package



* Ext.data.Proxy
  - ServerProxy : 원격지 서버에서 데이터 로딩
  - ClientProxy : 로컬 저장소로부터 데이터 로딩



* Ext.data.Reader : proxy로 얻어온 데이터 해석하고 데이터 모델 객체로 생성함
  - JsonReader
  - XmlReader

 

* Ext.data.Store : 데이터의 연산을 수행할 수 있도록 함
  - inline Data


var store = new Ext.data.Store({
data: [
{firstName: 'Julio', lastName: 'Benesh'},
{firstName: 'Julio', lastName: 'Minich'},
{firstName: 'Tania', lastName: 'Ricco'},
………
]


  - External Data


var store = new Ext.data.Store({
proxy: {
type: 'ajax',
url : 'server.html',
reader: {
type: 'json',
root: 'users'
}
}
});



* DataView : Store에 저장된 데이터를 UI에 표현하기 위한 컴포넌트 객체 (Ext.List가 이 클래스를 상속함)



* Ext.Template : 데이터의 레이아웃을 결정할 때 사용 (XTemplate)



* 원격지 서버의 리소스 호출 : Mode, Store, Proxy, Reader 이용
  - JsonReader 사용
  - XmlReader 사용



* 데이터 정렬과 필터링
  - Store 객체의 sort()와 filter() 함수


jsonStore.sort(‘firstName’,’DESC’); //firstName을 기준으로 내림차순 정렬
jsonStore.filter(‘firstName’, ‘JM’);. //firstName 값이 ‘JM’인 것만 조회



* Ext.data.ClientProxy 클래스를 상속받은 객체를 통해 로컬 자원에 액세스할 수 있음
  - Memory
  - Web Storage : HTML5에서 추가된 클라이언트 측 저장소
    : LocalStorage (영구저장소)
    : SessionStorage (임시저장소)
  - ClientProxy, WebStorageProxy 상속받아 LocalStorageProxy 객체나 SessionStorageProxy 객체 이용



* Ext.NestedList : 리스트를 계층 구조로 표현할 수 있음 : 타이틀바의 제목이나 뒤로가기 버튼이 자동으로 생성 됨



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


* Event
  - handler 를 이용한 버튼 탭 이벤트 처리


new Ext.Button({
text: 'MyButton',
handler: function(btn, event){
Ext.Msg.alert('Title', btn.text, Ext.emptyFn);
}
})
 

  - onItemDisclosure 속성을 이용한 리스트 탭 이벤트 처리



new Ext.List({
itemTpl : '{firstName} {lastName}',
store: store,
onItemDisclosure: function(record, btn, index) {
Ext.Msg.alert('Message', record.get('firstName'), Ext.emptyFn);
}
}


* 표준 이벤트 처리
  - listeners를 이용한 인라인 이벤트 처리


new Ext.Button({
text: 'MyButton',
listeners: {
tap: function(btn, event){ console.log(event.type); },
click: {
element: 'el',
fn: function(event){ console.log(event.type); }
}
}
})



  - 0n() 함수를 이용한 이벤트 처리


btn.on({
'tap' : {
fn: function(event){ console.log('tap')},
delay: 2000
},
'click' : {
element: 'el',
fn: function(event){ console.log('click')},
}
});



* 리스트의 itemtap, itemswipe 이벤트



* Touch Event
  - 탭(Tap) 관련 이벤트 : tap, singletap , doubletap, taphold, tapcancel
  - 터치(Touch) 관련 이벤트 : touchstart, touchend, touchmove, touchdown
  - 스윕(Swipe) 이벤트 : swipe
  - 핀치(Pinch) 관련 이벤트 : pinch, pinchstart, pinchend
  - 드래그(Drag) 및 스크롤(Scroll) 관련 이벤트 : drag, dragstart, dragend, scroll, scrollstart, scrollend



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



* Media 지원 : HTML5에 추가된 Video, Audio 사용. Ext.Video, Ext.Audio



* Ext.Media
  - autoPause  : 미디어가 비활성화(deactivate)될 때 자동으로 일시정지할지 결정한다(기본값: true).
  - autoResume : 미디어가 활성화(activate)될 때 자동으로 재생할지 결정한다(기본값: false)
  - enableControls : 미디어 재생을 제어하는 컨트롤 바의 표시 여부를 결정한다(기본값: true).
  - url : 미디어 소스를 지정한다
  - play() : 미디어를 재생한다.
  - pause() : 미디어 재생을 일지정지한다.
  - toggle() : 미디어 재생과 일시정지를 번갈아 처리하는 토글 기능을 제공한다.



* Ext.Video


Ext.setup({
onReady: function() {
var pnl = new Ext.Panel({
fullscreen: true,
layout: {
type: 'vbox',
pack: 'center'
},
items: [{
xtype: 'video',
url: 'space.mp4',
loop: true,
width: 500,
height: 400,
posterUrl: 'Screenshot.png'
}]
})
}
});



* Ext.Audio


Ext.setup({
onReady: function() {
var pnl = new Ext.Panel({
fullscreen: true,
layout: {
type: 'vbox',
pack: 'center'
},
items: [{
xtype: 'audio',
url: 'crash.mp3',
loop: true
}]
})
}
});



반응형

[CookBook] Fragments 이해하기 -8-

2013. 9. 30. 22:43 | Posted by 솔웅


반응형

Displaying Options Using ListFragment



ListFragment는 이미 만들어진 리스트뷰를 가지고 있는 fragment 입니다. 리스트 뷰에 들어갈 내용들(data source)는 array나 cursor가 될 수 있습니다. 이 ListFragments를 이해하기 위해서 리스트뷰와 텍스트뷰를 포함하고 있는 어플리케이션을 만들어 보겠습니다. 리스트 뷰에는 아이템들이 들어갈 것이고 이 아이템을 선택하면 텍스트 뷰에 표시되도록 만들 겁니다. 이 앱에서 리스트뷰는 ListFragment를 통해서 표시됩니다. 이 새로운 프로젝트의 이름은 ListFragmentApp으로 하겠습니다. 우선 텍스트뷰를 표시할 fragment부터 만들겠습니다. fragment2.xml 이라는 layout xml을 res/layout 폴더에 만들겠습니다.


fragment2.xml



<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <TextView 
        android:id="@+id/selectedopt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Please select a product"
       android:textSize="@dimen/text_size"
       android:textStyle="bold"  />
 </LinearLayout>




id가 selectedopt라는 텍스트뷰가 LinearLayout 안에 정의돼 있습니다. 일단 Please select a product라는 문자가 세팅돼 있습니다. 이 텍스트는 볼드체이고 size는 dimension resource에서 지정된 text_size를 사용합니다. 이 텍스트 뷰는 자바 코드에서 리스트뷰에서 선택된 아이템의 값을 표시하도록 만들어질 겁니다.



device의 화면크기에 맞게 리스트뷰의 아이템들이 표시되도록 하기 위해서 list_item.xml 파일을 res/layout 폴더 밑에 만들어 넣겠습니다.



list_item.xml



<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="6dp"
      android:textSize="@dimen/text_size"
      android:textStyle="bold" />
     


보시면 리스트뷰에 있는 아이템들은 6dp 의 패딩을 갖게 돼 있습니다. 그리고 텍스트는 bold 체이고 크기는 dimension resource에 있는 text_size를 갖다가 사용합니다.


fragment2.xml로 부터 fragment의 UI를 load 하기 위해 자바 클래스를 만들겠습니다.



Fragment2Activity.java

    


public class Fragment2Activity extends Fragment {
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment2, container, false);
    }

    public void dispOption(String msg){
        TextView selectedOpt = (TextView) getActivity().findViewById(R.id.selectedopt);
        selectedOpt.setText("You have selected "+msg);  
    }
}

 


이 클래스는 Fragment base 클래스를 extends 했습니다. onCreateView() 메소드를 오버라이드 해 fragment2.xml에서 정의한 텍스트 뷰 UI를 inflate 하기 위해 LayoutInflater를 그 안에서 사용했습니다.

 

이제 리스트뷰를 만들기 위해서 ListFragment를 사용할 겁니다. 이 ListFragment는 리스트뷰를 갖고 있습니다. 그러니까 이 fragment를 위해서 따로 UI를 정의할 필요는 없습니다. ListFragment 클래스를 extends한 자바클래스에서 동적으로 추가하시면 됩니다. 이 자바 클래스 안에서 리스트뷰에 들어갈 아이템들을 동적으로 할당할 겁니다. 그리고 리스트뷰에서 선택된 아이템을 Fragment2의 텍스트 뷰로 전달해서 화면에 표시하도록 할 거구요.
 
 

Fragment1Activity.java
 
 

public class Fragment1Activity extends ListFragment {
    String[] products={"Camera", "Laptop", "Watch",  "Smartphone", "Television"};

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ArrayAdapter<String> arrayAdpt = new ArrayAdapter  <String>(getActivity(),R.layout.list_item, products);
        setListAdapter(arrayAdpt);
    }

    @Override
    public void onListItemClick(ListView l, View v, int  position, long id) {
        Fragment2Activity frag = (Fragment2Activity) getFragmentManager().findFragmentById(R.id.fragment2);
        frag.dispOption(((TextView) v).getText().toString());                         
    }
}



보시다 시피 ListFragment를 extends 했습니다. 리스트뷰를 사용할 거기 때문이죠. 이 리스트뷰에 아이템을 표시하기 위해서 아이템들이 들어있는 products라는 배열을 만들었습니다. 그리고 onCreate() 메소드를 보시죠. 여기서는 ArrayAdapter를 만들어서 list_item.xml 을 할당해 주고 위에서 만든 products 배열도 할당해 줬습니다. 그리고 setListAdapter()메소드를 사용해서 이 ArrayAdapter를 세팅했구요. 이러면 이 ListView에 이 값들이 세팅이 되서 화면에 아이템으로 뿌려질 수 있습니다.



그리고 onListItemClick() 리스너를 사용했죠. 해당 아이템일 클릭되면 실행될 콜백 메소드 입니다. 여기서는 Fragment2Activity 클래스를 초기화한 frag라는 객체를 만들어서 이 frag의 disOption()이라는 메소드를 호출하도록 코딩을 했습니다 코딩할 때 텍스트뷰의 텍스트를 전달하고 있구요.



이제 이 두개의 fragment들을 함께 화면에 표시하도록 해야 합니다.
우선 layout xml을 만듭니다.


activity_list_fragment_app.xml



<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >
    <fragment
        android:name="com.androidtablet.listfragmentapp.Fragment1Activity"
        android:id="@+id/fragment1"
        android:layout_weight="1"
        android:layout_width="wrap_content"
        android:layout_height="match_parent" />
    <fragment
        android:name="com.androidtablet.listfragmentapp.Fragment2Activity"
        android:id="@+id/fragment2"
        android:layout_weight="0"
        android:layout_width="wrap_content"
        android:layout_height="match_parent" />
</LinearLayout>


여기에는 저 위에 만들었던 두개의 fragment가 들어있습니다. 이 두 fragment들을 추가하기 위해 <fragment> element를 사용했죠. android:name 이라는 속성에는 각각 fragment의 클래스 이름이 들어가 있습니다.
이제 이 layout xml을 load 할 자바 클래스를 만들겠습니다. 이 자바 클래스에는 특별히 코딩을 할 필요는 없습니다.



ListFragmentAppActivity.java



public class ListFragmentAppActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_list_fragment_app);
    }
}



이렇게 하면 예제가 완성됐습니다.

반응형

[CookBook] Fragments 이해하기 -7-

2013. 9. 30. 08:47 | Posted by 솔웅


반응형

Implementing Communication Between Fragments



fragment들 사이에서 데이터를 전달할 수 있도록 하기 위해 Fragment 클래스에서는 두개의 메소드를 제공하고 있습니다. 바로 setArguments() 와 getArguments() 인데요. setArguments() 메소드는 fragment의 Bundle을 저장합니다. getArguments() 메소드는 이 전달된 정보를 얻기 위해 Bundle을 retrieve 하죠.



아래 코드는 fragment1에서 fragment2로 정보를 전달합니다. frag2_container는 layout xml 에서 지정한 fragment container의 ID 입니다.



#1 Fragment2Activity fragment2 = new Fragment2Activity();
#2 Bundle args = new Bundle();
#3 String message = "Message from Fragment1";
#4    if(null==fragmentManager.findFragmentByTag(TAG2)){
#5        Fragment2Activity fragment2 = new Fragment2Activity();
#6      args.putString("msg", message);
#7      fragment2.setArguments(args);
#8      fragmentTransaction.replace(R.id.frag2_container,fragment2);
#9        String tag = null;
#10        fragmentTransaction.addToBackStack(tag);
#11        fragmentTransaction.commit();
#12 }



#1에 있는 Fragment2Activity는 fragment2의 자바 클래스를 말합니다. fragment2라는 자바 클래스 인스턴스를 생성했습니다.
#2에서는 args라고 하는 Bundle 객체를 생성했습니다.
#3에서는 message라고 하는 String 객체를 생성했죠. 이 메세지는 fragment2에 전달 될 겁니다.
#4번에서는 TAG2라는 fragment가 있는지 여부를 체크합니다. TAG2는 fragment2를 말하는 거니까 fragment2가 있는지 여부를 체크하는 겁니다.
#5번은 Fragment2Activity 자바클래스의 인스턴스를 만들고 #6번에서는 args 번들에 3번에서 정의했던 메세지를 세팅합니다.
#7에서는 fragment2에 이 Bundle 을 세팅하구요.
#8번과 #9번에서는 이전의 fragment를 navigating하는 부분이구요.



이 activity stack은 이전의 activity들을 계속 track 합니다. Back 버튼을 누르면 activity stack에 있는 activity가 pop up 되서 그 activity 가 화면에 보여지게 됩니다. 다른 말로 이 activity stack은 Back 버튼을 누르면 이전 화면으로 돌아갈 수 있도록 만드는 거죠.



fragment도 이러한 개념을 사용합니다. back stack에 FragmentTransaction을 추가하려면 commit() 하기 전에 FragmentTransaction의 addToBackStack() 메소드를 호출해야 합니다.



위 코드에서 보면 처음에는 xml에 있는 fragment가 화면에 보였다가 두번째 fragment로 replace됐습니다. 그리고 이전 fragment는 BackStack에 넣구요. 그래서 Back 버튼을 누르면 이전의 FragmentTransaction이 돌아와서 이전의 fragment가 화면에 보여질 겁니다.



Bundle을 통해서 위에 setArguments()메세지를 통해 세팅된 정보를 어떻게 다음 fragment에서 이 메세지를 받고 display하는지에 대해서도 궁금할 겁니다. 그 답은 Bundle을 사용해서 fragment에서 메세지를 받는 것은 getArgument() 메소드를 사용한다 입니다.
아래에 샘플 코드가 있습니다.



String messageReceived = "";
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    ViewGroup container, Bundle savedInstanceState) {
        Bundle bundle = getArguments();
        if(bundle != null) {
            messageReceived = bundle.getString("msg");
        }
    }
}


fragment끼리의 communication을 이해하기 위해 FragmentsByCodeApp 어플리케이션에서 fragment1에서 fragment 2로 메세지를 보내는 것을 구현하겠습니다. 이를 위해 FragmentsByCodeAppActivity.java 의 코드를 수정합니다.



public class FragmentsByCodeAppActivity extends Activity implements OnOptionSelectedListener {
    private static final String TAG1 = "1";
    private static final String TAG2 = "2";
   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fragments_by_code_app);
        FragmentManager fragmentManager = getFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        if(null==fragmentManager.findFragmentByTag(TAG1)){
            Fragment1Activity fragment1 = new Fragment1Activity();
            fragmentTransaction.add(R.id.frag1_container, fragment1, TAG1); 
        }
        Bundle args = new Bundle();
        String message="Message from Fragment 1";  

        if(null==fragmentManager.findFragmentByTag(TAG2)){
            Fragment2Activity fragment2 = new Fragment2Activity();
            args.putString("msg", message);
            fragment2.setArguments(args);

            fragmentTransaction.add(R.id.frag2_container, fragment2, TAG2); 
        }
        fragmentTransaction.commit();
        }

    public void onOptionSelected(String msg){
        Fragment2Activity frag2 = (Fragment2Activity) getFragmentManager().findFragmentById(R.id.frag2_container);
        frag2.dispOption(msg);             
    }
}



우선 Bundle 인스턴스인 args를 생성했습니다. 이 args 객체에 message라는 String 객체를 put 했구요. 그리고 이 Bundle을 fragment2에 넣었습니다. 그 다음에 fragment2에서는 이 Bundle 을 getArguments() 메소드를 이용해서 이 정보를 받습니다. 그 받는 부분을 한번 보겠습니다.



public class Fragment2Activity extends Fragment {
    TextView selectedOpt;
    String messageReceived="";


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View vw= inflater.inflate(R.layout.fragment2,  container, false);
           Bundle bundle=getArguments(); 
           if(bundle !=null) {
               messageReceived = bundle.getString("msg");
               selectedOpt = (TextView) vw.findViewById(R.id.selectedopt);
               selectedOpt.setText(messageReceived);
           }
           return vw;     

    }

    public void dispOption(String msg){
        TextView selectedOpt = (TextView) getActivity().findViewById(R.id.selectedopt);
        selectedOpt.setText("You have selected "+msg);  
    }
}


이렇게 getArguments()를 사용해서 해당 정보를 받습니다. 이렇게 받은 정보는 TextView에 뿌려질 거구요.



이 어플리케이션을 실행하면 아래와 같은 화면을 볼 수 있습니다.






Fragment base 클래스 이외에도 fragment는 다른 몇개의 Fragment 클래스의 subclass들을 extend 할 수 있습니다. DialogFragment, ListFragment, PreferenceFragment들이 그것입니다.

반응형

[CookBook] Fragments 이해하기 -6-

2013. 9. 29. 22:47 | Posted by 솔웅


반응형

Fragment1Activity.java



public class Fragment1Activity extends Fragment {
    OnOptionSelectedListener  myListener;
    @Override
    public View onCreateView(LayoutInflater inflater,
        ViewGroup container, Bundle savedInstanceState) {
        Context c = getActivity().getApplicationContext();
        View vw = inflater.inflate(R.layout.fragment1, container, false);
        String[] products={"Camera", "Laptop", "Watch", "Smartphone", "Television"};
        ListView productsList = (ListView) vw.findViewById(R.id.products_list);
        ArrayAdapter<String> arrayAdpt= new ArrayAdapter <String>(c, R.layout.list_item, products);
        productsList.setAdapter(arrayAdpt);
        productsList.setOnItemClickListener(new OnItemClickListener(){
            @Override
            public void onItemClick(AdapterView<?> parent, View v, int position, long id){
                myListener.onOptionSelected(((TextView) v).getText().toString());  
            }
        });
        return vw;
    }
   
    public interface OnOptionSelectedListener {
        public void onOptionSelected(String message);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            myListener = (OnOptionSelectedListener) activity;
        } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString() + " must implement OnItemClickListener");
        }
    } 
}




이 Fragment1Activity 클래스는 Fragment 클래스를 extends 했습니다. onCreateView() 메소드 안에서는 LayoutInflater 객체가 fragment1.xml 에서 정의된 ListView를 inflate하기 위해 사용됐습니다. 이 리스트 뷰는 product_list라는 id를 가진 xml 내의 listview 를 가져와서 productsList 라는 객체에 넣었습니다. 그리고 ArrayAdapter 를 사용해서 list_item.xml 을 이용해서 각 아이템들을 세팅하고 구체적인 아이템 내용은 products 배열에서 가져오고 있습니다. 그리고 이 Adapter를 productsList에 세팅합니다. 그리고 productsList 에 onItemClickListener를 달아서 리스트뷰 내의 아이템이 선택되면 어떤 일을 하도록 정의합니다. setOnItemClickListener 안에는 inItemClick()이라는 콜백 메소드가 있는데요. 아이템이 클릭되면 이 메소드가 자동으로 호출됩니다. 여기서는 아이템이 클릭되면 onOptionSelected() interface를 호출하네요. 그 인터페이스 안에는 onOptionSelected() 메소드가 선언돼 있구요. 이 fragment와 연관된 activity는 OnOptionSelectedListener 인터페이스를 implements 했을 겁니다. 그리고 이 인터페이스의 body인 onOptionSelected() 메소드를 구현했을 거구요. 그러니까 여기서 아이템이 클릭되면 구체적인 동작은 이 OnOptionSelectedListener 인터페이스를 implements 한 activity에서 구현됩니다.



이제 만들어야 할 파일은 Fragment2Activity.java인데요. 여기서는 아래 두가지 일을 해야 합니다.

- fragment2.xml 에서 UI를 load 합니다.
- 유저가 선택한 제품을 출력할 dispOption 메소드를 정의 해야 합니다.



이 두가지 일을 하기 위해서 아래와 같이 코딩을 합니다.



Fragment2Activity.java



public class Fragment2Activity extends Fragment {
    TextView selectedOpt;
    String messageReceived="";

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View vw= inflater.inflate(R.layout.fragment2,  container, false);
           Bundle bundle=getArguments(); 
           if(bundle !=null) {
               messageReceived = bundle.getString("msg");
               selectedOpt = (TextView) vw.findViewById(R.id.selectedopt);
               selectedOpt.setText(messageReceived);
           }
           return vw;     
    }

    public void dispOption(String msg){
        TextView selectedOpt = (TextView) getActivity().findViewById(R.id.selectedopt);
        selectedOpt.setText("You have selected "+msg);  
    }
}


여기서도 fragment를 생성하기 위해 Fragment 클래스를 extends 했습니다. 그리고 onCreateView() 메소드를 오버라이드 해서 그 안에서 LayoutInflater 객체를 이용해 fragment2.xml 안에 정의된 TextView를 inflate 했습니다. 리스트뷰에서 선택된 제품 이름은 dispOption() 메소드로 전달되서 이 TextView 를 통해 화면에 뿌려질 겁니다.



이제 맨 처음 만든 activity_fragments_by_code_app.xml 을 불러와서 사용할 java 파일을 만들 차례입니다.
이 xml layout에 정의된 frag1_container와 frag2_container로 id가 정의된 LinearLayout 에 위에서 만든 fragment들을 배치시켜야겠죠.
소스 내용은 아래와 같습니다.



FragmentsByCodeAppActivity.java



public class FragmentsByCodeAppActivity extends Activity implements OnOptionSelectedListener {
    private static final String TAG1 = "1";
    private static final String TAG2 = "2";
   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fragments_by_code_app);
        FragmentManager fragmentManager = getFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        if(null==fragmentManager.findFragmentByTag(TAG1)){
            Fragment1Activity fragment1 = new Fragment1Activity();
            fragmentTransaction.add(R.id.frag1_container, fragment1, TAG1); 
        }
        Bundle args = new Bundle();
        String message="Message from Fragment 1";  
        if(null==fragmentManager.findFragmentByTag(TAG2)){
            Fragment2Activity fragment2 = new Fragment2Activity();
            args.putString("msg", message);
            fragment2.setArguments(args);
            fragmentTransaction.add(R.id.frag2_container, fragment2, TAG2); 
        }
        fragmentTransaction.commit();
        }

    public void onOptionSelected(String msg){
        Fragment2Activity frag2 = (Fragment2Activity) getFragmentManager().findFragmentById(R.id.frag2_container);
        frag2.dispOption(msg);             
    }
}


보시면 FragmentManager 객체를 보실 수 있을 겁니다. fragment에 접근할 수 있도록 해주는 클래스 입니다. fragment를 추가하거나 제거하거나 replace를 해야 될 때 사용할 FragmentTransaction도 이 FragmentManager의 beginTransaction() 메소드를 사용해서 정의했습니다.



그리고 frag1_container에 첫번째 fragment를 넣고 frag2_container에 두번째 fragment를 넣었습니다. 넣기 전에 이미 존재하는지 여부를 먼저 체크했습니다. 이때 Fragmentmanager의 findFragmentByTag() 메소드를 사용했죠. 두번째 fragment에는 메세지도 argument로 세팅했습니다. 그 다음에 FragmentTransaction 클래스의 commit()메소드를 사용해서 작업을 완료합니다.



그 아래에 onOptionSelected() 메소드가 있는데요. 이것은 ListView에서 아이템이 선택됐을 때 실행될 메소드 입니다. 선택된 제품을 fragment2의 TextView에 표시하도록하는 메소드죠.



이로서 동적으로 fragment를 생성하고 할당해서 사용하는 코드가 완성됐습니다.

반응형

[CookBook] Fragments 이해하기 -5-

2013. 9. 28. 23:28 | Posted by 솔웅


반응형

Creating Fragments Dynamically at Runtime



layout xml 파일에 fragment 가 <fragment> element를 사용해서 정의 되었어도 runtime 시 자바코딩에 의해서 이 fragment를 재정의 할 수 있습니다. 액티비티에 fragment를 dynamic 하게 생성,추가,replace 하기 위해 FragmentManager를 사용하실 수 있습니다.



이와 관련한 예제를 다룰건데요. FragmentsByCodeApp이라는 안드로이드 프로젝트를 생성하겠습니다. 이 앱에서는 두개의 fragment를 dynamic하게 생성할 겁니다. Fragment1과 Fragment2인데요. Fragment1은 선택 위젯인 ListView를 가지게 되고 여기에 product들이 display 될 겁니다. Fragment2는 TextView를 가지고 있고 Fragment1의 리스트뷰에서 선택된 제품이 display 될 겁니다.



이 두 Fragment들을 표시하기 위해 적당한 layout xml을 만들어야 합니다.



activity_fragments_by_code_app.xml



<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >
    <LinearLayout
        android:id="@+id/frag1_container"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:orientation="horizontal"/>
    <LinearLayout
        android:id="@+id/frag2_container"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_weight="0"
        android:orientation="horizontal"/>
</LinearLayout>




여기 보시면 두개의 LinearLayout가 있습니다. 각각 id를 가지고 있죠. 하나는 frag1_container이고 다른 하나는 frag2_container 입니다. 자바 코드에서 이 아이디를 가지고 동적으로 fragment들을 생성하고 다룰 겁니다. 전체 틀을 구성하는 LinearLayout은 horizontal 로 돼 있죠. 그러니까 두 fragment들은 좌우로 배치 될 겁니다. 첫번째 fragment에는 제품을 표시할 리스트뷰가 들어갈 것이고 두번째 fragment에는 이 제품을 표시할 텍스트 뷰가 들어갈 겁니다. 이 두 fragment들에 view를 정의하기 위해 두개의 xml 파일을 만들겠습니다. fragment1.xml과 fragment2.xml 인데요. res/layout 폴더 밑에 만들어 넣습니다.
첫번째 fragment에 리스트뷰를 넣기 위해 아래와 같이 만듭니다.



fragment1.xml



<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#0000FF"  >
    <ListView
        android:id="@+id/products_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:drawSelectorOnTop="false" />
</LinearLayout>



안에 리스트 뷰가 있죠? id 는 products_list 로 했습니다. 두개의 fragment를 구별하기 쉽게 첫번째는 배경색을 파란색으로 했습니다.
두번째 fragment에 텍스트뷰를 정의하기 위해 아래와 같은 xml 파일을 만듭니다.


fragment2.xml



<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >   
    <TextView 
        android:id="@+id/selectedopt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text=" Please select a product "
        android:textSize="@dimen/text_size"
        android:textStyle="bold"  />  
</LinearLayout>



selectedopt라는 아이디를 가진 텍스트뷰가 있습니다. 그리고 text가 이미 정해져 있는데요. "Please select a product" 라고 돼 있습니다. 텍스트 사이즈는 dimention 리소스 안에 있는 사이즈를 불러다 쓰구요.
디바이스의 화면 크게에 맞게 리스트 아이템들을 표시하기 위해 아래 xml 하일을 하나 더 만들겠습니다.



list_item.xml



<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="6dp"
      android:textSize="@dimen/text_size"
      android:textStyle="bold" />
     

여기를 보면 각 아이템은 리스트 뷰 내에서 6dp 만큼 패딩을 가질 겁니다. 그리고 bold체로 설정을 했고 폰트 싸이즈는 dimention 리소스 안에 있는 사이즈를 불러다 씁니다.
이제 fragment1.xml과 fragment2.xml 에 설정된 UI를 로드할 자바코드를 만들 차례입니다. 두개의 자바코드가 만들어 져야겠죠. 하나는 Fragment1Activity.java 이고 나머지 하나는 Fragment2Activity.java 입니다.


이 자바 코드는 다음 글에서 다뤄 보겠습니다.

반응형

[CookBook] Fragments 이해하기 -4-

2013. 9. 27. 22:06 | Posted by 솔웅


반응형

Understanding the Role of FragmentManager and FragmentTransaction in Handling Fragments




FragmentManager는 이름 그대로 액티비티 내에서 fragments를 관리하는데 사용됩니다. 액티비티에서 사용 가능한 fragment에 접근할 수 있게 해 주고 fragments를 추가하거나 제거하거나 재배치할 필요가 있을 때 FragmentTransaction을 사용합니다. FragmentManager에 접근하려면 getFragmentManager() 메소드를 사용합니다.



FragmentManager fragmentManager = getFragmentManager();



fragment transaction을 사용하려면 FragmentTransaction의 인스턴스를 사용합니다.


FragmentTransaction fragmentTransaction = fragmentMaanger.beginTransaction();




새로운 FragmentTransaction은 FragmentManager의 beginTransaction() 메소드를 사용해서 생성합니다.



private static final String TAG1 = "1";
FragmentManager fragmentManager = getFragmentManager()
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Fragment1Activity fragment = new FragmentActivity();
fragmentTransaction.add(R.id.fragment_container, fragment, TAG1);
fragmentTransaction.commit();


여기 보시면 Fragment1Activity는 fragment의 자바 클래스입니다. 이것은 XML 파일로부터 fragment의 UI를 로드해서 사용하죠. 밑에서 두번째 줄을 보시면 fragment_container가 id라는 걸 알 수 있을 겁니다. 아마 이 id는 LinearLaout이나 FrameLayout 일 거라고 예상할 수 있을 겁니다. 그리고 commit()메소드가 보이는데요. 이것은 변화된 사항을 적용하기 위해 사용하는 메소드 입니다. 이 commit()은 즉시 발효되는 것은 아니고 쓰레드가 준비 됐을 때 발효가 될 겁니다. 그러니까 방금 생성한 fragment에 대한 reference를 곧바로 get하는 것은 문제가 생길 수 있습니다.



Note
fragment를 dynamic 하게 추가하려면 container view는 fragment 가 display될 view 가 있는 layout에 존재해야 합니다.



fragment를 추가하기 전에 이것이 존재하는지 확인할 필요가 있을 겁니다. 아래처럼 하시면 됩니다.



private static final String TAG1 = "1";
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
if(null == fragmentManager.findFragmentByTag(TAG1)){
    Fragment1Activity fragment = new Fragment1Activity();
    fragmentTransaction.add(R.id.fragment_container, fragment, TAG1);
}
fragmentTransaction.commit();



FragmentManager의 findFragmentByTag() 메소드가 주어진 tag의 fragment가 있는지 여부를 체크 하고 있습니다. 이 findFragmentById() 메소드는 activity layout 에 추가된 fragment를 identify 합니다. 아니면 findFragmentByTag() 메소드를 사용할 수도 있습니다. 위에 있는 Fragment1Activity는 fragment의 layout 파일에서 정의된 view들이 로드되는 자바 클래스 입니다.



fragment나 content를 replace하기위해 FragmentTransaction의 replace()메소드를 사용합니다.



private static final String TAG2 = "2";
fragmentTransaction.replace(R.id.fragment_container, fragment2, TAG2);



여기 보시면 fragment2의 view는 액티비티 layout의 fragment_container안에있는 view를 다시 replace할 겁니다. fragment를 없애려면 findFragmentById()나 findFragmentByTag()메소드를 사용해서 그 fragment 구분해 내야 합니다. 아래 코드는 findFragmentById()메소드를 사용해서 fragment를 정의하고 그 fragment를 remove 하는 과정을 보여줍니다.


FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Fragment fragment = fragmentManager.findFragmentById(R.id.fragment);
fragmentTransaction.remove(fragment);
fragmentTransaction.commit();



위에 보시면 없애고자 하는 fragment를 정의하기 위해 findFragmentById()를 사용하신 걸 보실 수 있습니다. 이것을 findFragmentByTag()를 사용하시려면 아래와 같이 사용하실 수 있습니다.
Fragment fragment = fragmentManager.findFragmentByTag(TAG1);

반응형