출처 : http://ismydream.tistory.com/136


안드로이드 Loader 활용하기



Loader

- 안드로이드 3.0 에서 소개된 Loader 를 사용하면 액티비티와 프래그먼트에서의 비동기 데이터 로딩을 쉽게 처리할 수 있습니다.



특징

- 모든 액티비티와 프래그먼트에서 사용할 수 있습니다.

- 어플리케이션 UI를 Blocking 하지 않도록 비동기 데이터 로딩을 제공합니다.

- 데이터를 모니터 하기 때문에 데이터가 변경되었을때 변경사항을 확인할 수 있습니다.



API

LoaderManager 

- LoaderManager는 액티비티, 프래그먼트 와 1:1 의 관계를 갖습니다. 액티비티 하나당 하나의 LoaderManger 가 존재하는 셈이죠

그리고 하나의 LoaderManager 는 여러개의 Loader 를 관리하게 됩니다.


LoaderManager.LoaderCallbacks

- Loader 를 컨트롤하기 위해 제공되는 콜백 메소드입니다. 콜백 메소드를 통해서 Loader 를 생성하고 변경할 수 있습니다.


Loader

- 비동기 데이터 로딩을 수행하는 추상 클래스입니다.


AsyncTaskLoader

- AsyncTask 를 제공하는 추상 로더입니다.


CursorLoader

- AsyncTaskLoader 의 하위 클래스로서 ContentrResolver 에 쿼리를 하여 Cursor 를 리턴 받도록 합니다.

- AsyncTaskLoader 를 사용하기 때문에  처리하는 작업이 어플리케이션 UI 를 블락킹하지 않습니다.



Loader 적용하기


Loader 시작하기

- Loader 를 초기화하기 위해서 아래코드를 Activity 의 onCreate(), Fragment 의 onActivityCreated() 콜백함수내에 추가한다.

getLoaderManager().initLoader(

0,  // Loader 를 구분하기 위한 ID 값

null,  // 추가 인자

this // Loader 로 부터 콜백을 받기 위해서 LoaderManager.LoaderCallbacks 를 구현한 객체를 넘겨준다.

);

※ initLoader 메소드는 두가지의 결과를 갖게되는데

- initLoader 에 넘겨준 ID 값을 갖는 Loader 가 이미 존재하는 경우 이미 존재하는 LOader 를 재사용하게 됩니다.

- 존재하지 않는 경우에는 LoaderManager.LoaderCallbacks 인터페이스에 있는 onCreateLoader() 콜백함수를 호출하게 됩니다.


Loader 재시작하기

initLoader 메소드에서 ID 가 이미 존재하는 경우에는 기존 Loader 를 재사용 한다고 했는데 재사용 하더라도 데이터를 초기화하고 싶을 때가 있습니다. 그런 경우에 Loader 를 재사용하며 데이터는 초기화하고 싶을때 재시작하게 됩니다.

// 검색시 검색어가 변경되었을 경우 호출

public boolean onQueryTextChanged( String newText){

mCurFilter = !TextUtils.isEmpty( newText) ? newText : null;

getLoaderManager().restartLoader( 0, null, this);

return true;

}



LoaderManager 콜백 사용하기


LoaderManager.LoaderCallbacks

- onCreateLoader()

initLoader 에 넘겨준 ID 를 갖는 Loader 를 생성하여 넘겨준다. 직접 생성하여야 한다.


- onLoaderFinished()

Loader 가 로딩을 끝내을 때 호출한다.


- onLoaderReset()

Loader 가 리셋 됬을 때 호출한다.


onCreateLoader 예제

public Loader<Cursor> onCreateLoader( int id, Bundle args){

Uri baseUri;

if( mCurFilter != null){

baseUri = Uri.withAppendedPath( Contacts.CONTENT_FILTER_URI, 

Uri.encode( mCurFilter));

} else {

baseUri = Contacts.CONTENT_URI;

}

String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("

+ Contacts.HAS_PHONE_NUMBER + "=1) AND ("

+ Contacts.DISPLAY_NAME + " != '' ))";

return new CursorLoader(

getActivity(),

baseUri, // 가져올 컨텐트의 uri

CONTACTS_SUMMARY_PROJECTION,  // 가져올 컬럼의 정보, null 일 경우 모든 컬럼을 리턴한다.

select, // 가져올 데이터를 필터링 하는 정보 SQL 의 WHERE 절과 유사하다., 모든 데이터를 가져올 경우 null 을 설정한다.

null, // selectionArgs 

Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC" // 정렬 순서 sortOrder

);

}


onLoadFilnished 예제

로딩이 끝난후 adapter 에 Cursor를 설정하는 예제

SimpleCursorAdapter mAdapter;


public void onLoadFinished( Loader<Cursor> loader, Cursor data){

mAdapter.swapCursor( data);

}


onLoaderReset 예제

Loader 가 리셋 되었을 때 호출된다. 그러므로 기존 데이터를 해제해야 한다.

SimpleCursorAdapter mAdapter;


public void onLoaderReset( Loader<Cursor> loader){

mAdapter.swapCursor( null);

}


LoaderManager.LoaderCallbacks 를 구현한 Fragment 예제입니다.

public static class CursorLoaderListFragment extends ListFragment

        implements OnQueryTextListener, LoaderManager.LoaderCallbacks<Cursor> {


    // This is the Adapter being used to display the list's data.

    SimpleCursorAdapter mAdapter;


    // If non-null, this is the current filter the user has provided.

    String mCurFilter;


    @Override public void onActivityCreated(Bundle savedInstanceState) {

        super.onActivityCreated(savedInstanceState);


        // Give some text to display if there is no data.  In a real

        // application this would come from a resource.

        setEmptyText("No phone numbers");


        // We have a menu item to show in action bar.

        setHasOptionsMenu(true);


        // Create an empty adapter we will use to display the loaded data.

        mAdapter = new SimpleCursorAdapter(getActivity(),

                android.R.layout.simple_list_item_2, null,

                new String[] { Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS },

                new int[] { android.R.id.text1, android.R.id.text2 }, 0);

        setListAdapter(mAdapter);


        // LoaderManger 를 초기화합니다. ID 가 존재하는 경우는 존재하는 Loader 를 재사용합니다.

// Fragment 는 onActivityCreated 메소드내에서 초기화를 진행합니다.

        getLoaderManager().initLoader(0, null, this);

    }


    @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {

        // Place an action bar item for searching.

        MenuItem item = menu.add("Search");

        item.setIcon(android.R.drawable.ic_menu_search);

        item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);

        SearchView sv = new SearchView(getActivity());

        sv.setOnQueryTextListener(this);

        item.setActionView(sv);

    }


    public boolean onQueryTextChange(String newText) {

// ActionBar 에서 검색시 검색어가 변경되었을 경우에 기존 로더를 재사용하기 위해 Loader의 데이터를 초기화해 줍니다.

        mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;

        getLoaderManager().restartLoader(0, null, this);

        return true;

    }


    @Override public boolean onQueryTextSubmit(String query) {

        // Don't care about this.

        return true;

    }


    @Override public void onListItemClick(ListView l, View v, int position, long id) {

        // Insert desired behavior here.

        Log.i("FragmentComplexList", "Item clicked: " + id);

    }


    // CursorLoader 에서 가져올 컬럼 정의

    static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {

        Contacts._ID,

        Contacts.DISPLAY_NAME,

        Contacts.CONTACT_STATUS,

        Contacts.CONTACT_PRESENCE,

        Contacts.PHOTO_ID,

        Contacts.LOOKUP_KEY,

    };


    // Loader 를 생성하는 콜백 메소드. Loader 를 생성해서 넘겨주면 LoaderManager 에서 알아서 실행하게 됩니다.

    @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) {

        // This is called when a new Loader needs to be created.  This

        // sample only has one Loader, so we don't care about the ID.

        // First, pick the base URI to use depending on whether we are

        // currently filtering.

        Uri baseUri;

        if (mCurFilter != null) {

            baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,

                    Uri.encode(mCurFilter));

        } else {

            baseUri = Contacts.CONTENT_URI;

        }


        // Now create and return a CursorLoader that will take care of

        // creating a Cursor for the data being displayed.

        String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("

                + Contacts.HAS_PHONE_NUMBER + "=1) AND ("

                + Contacts.DISPLAY_NAME + " != '' ))";

        // CursorLoader 를 생성해서 넘겨줍니다.

        return new CursorLoader(getActivity(), baseUri, 

                CONTACTS_SUMMARY_PROJECTION, select, null,

                Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");

    }

    

    // Loader 작업이 끝난후 결과 데이터를 처리하는 콜백 메소드

    @Override public void onLoadFinished(Loader<Cursor> loader, Cursor data) {

        // Swap the new cursor in.  (The framework will take care of closing the

        // old cursor once we return.)

        mAdapter.swapCursor(data);

    }

    

    // Loader 가 리셋되었을때 기존 데이터를 해제하는 콜백 메소드

    @Override public void onLoaderReset(Loader<Cursor> loader) {

        // This is called when the last Cursor provided to onLoadFinished()

        // above is about to be closed.  We need to make sure we are no

        // longer using it.

        mAdapter.swapCursor(null);

    }

}



https://github.com/grantland/android-autofittextview

출처 : http://ankri.de/autoscale-textview/

I was in need of a TextView that has a fixed with but dynamic content, so I needed the content to automatically scale.

The AutoScaleTextView takes the android:textSize value and uses it as the preferred text size. You can also set the minimum text size. The default for the minimum text size is 10dp. TheAutoScaleTextView now tries to take the maximum value between the preferred and minimum size that fits into the Views width (with regarding the padding).

Here is the result:

The AutoScale TextView in action displaying the android version names

You can see that the AutoScaleTextView automatically scales the text to fit in the Views width. For the different views I used layout_width: 130dp and layout_height=30dptextSize: 16dp and 10dp for the minTextSize. On the second Ice Cream Sandwich TextView I used 13dp for the minTextSizeand layout_height: wrap_content.

Get the source and explanation after the break.

The code itself is pretty simple. I improved a snippet I found on stackoverflow.com. I sadly cannot remember the exact post.

You can checkout the demo project: https://bitbucket.org/ankri/autoscaletextview/src

Or download the project: https://bitbucket.org/ankri/autoscaletextview/downloads

Please feel free to leave feedback or report bugs here:https://bitbucket.org/ankri/autoscaletextview/issues?status=new&status=open

Or view the code below:

The important part is the refitText(String, int) method. Note: If you are dealing with big textsizes you should set the treshold to a higher value.

Here is a snippet from the main.xml I used in the demo project

The values from the res/values/dimens.xml are 100dp for the width and 30dp for the height.

The content of the res/values/attrs.xml to alter the minTextSize in the layout files is:

 

And the content of the res/values/styles.xml to set the default minTextSize or other default styles for the AutoScaleTextView

 

Have fun using the code. I uploaded the code under the Beerware License. You can take the code and do whatever you want with it, as long as you mention me somewhere in your code, or your final app. If we ever meet and you think that the code, or explanation was helpful, feel free to buy me a beer and have a chat.

Or you could help a fellow out by donating some money.

Updated licence

When I uploaded this code I never thought anyone would use it, but since some people actually are using it, I updated the licence to Apache 2.0. But still… If you’re in the mood to buy me a beer. Please do :)

'Android > GUI & Activity' 카테고리의 다른 글

Animation 종류  (0) 2014.10.28
[펌[] Android ActionBar 활용  (0) 2014.10.22
AutoScaleTextView 추천 소스  (0) 2014.10.16
CustomView lifeCycle  (0) 2014.09.30
리스트뷰 밑의 내용 스크롤시 애니메이션 붙이는 방법  (0) 2014.09.25



20개 정도 규칙이 있으며 출처는 source.android.com에서 좀 더 자세한 내용을 볼 수 있다.

build된 sdk에는 없지만 sdk 소스를 다운받으면 이클립스용 코딩 포맷과 import순서가 정보가 적힌 xml파일도 같이 받을 수 있는데, 이 글에 첨부했다.

android-formatting.xml은 "Window › Preferences › Java › Code Style > Formatter 에 import하고,
android.importorder "Organize Imports에 import하면
Shift+command+F로 자동포멧정리 기능을 안드로이드에 맞게 사용할 수 있다.

  1. Exceptions: 예외 무시하지말고 처리하기.
  2. Exceptions: 상위 Exception으로 싸잡아서 처리하지 않기.
  3. Finalizers: 왠만하면 쓰지않기 (언제 적용될지 모름)
  4. Imports: *쓰지말고 정확하게 풀네임 적기.

Java Library Rules

표준 코딩컨벤션이 바뀌어서 예전 코딩컨벤션과 충돌이 난다면 예전 코딩컨벤션으로 작성해서 일관성을 유지하기.

Java Style Rules

자바표준 컨벤션에서 추가사항:

  1. Comments/Javadoc: 표준대로 작성하기.
  2. Short methods: 메소드는 40줄이 넘지않게 짧게 작성하기
  3. Fields: 초기에 선언하기나 사용하기 바로 전에 선언할 것.
  4. Local variables: 지역변수 범위는 최소화하기.
  5. Imports: 안드로이드, 서드파티(알파벳 순), java, javax 순으로 import하기.
  6. Indentation: 탭안쓰고 공백 4개 사용하기.
  7. Line length: 한줄에 100칸 이하 유지하기.
  8. Field names: Non-public, non-static 변수는 m으로 시작하고, static변수는 s로 시작하기.
  9. Braces: { 는 줄넘기지말고 사용하기
  10. Annotations: 표준 어노테이션 사용하기.
  11. Acronyms are words: XMLHTTPReques처럼 적지말고 XmlHttpRequest로 적기
  12. TODO style: "TODO: write this description"
  13. Consistency: 일관적으로 작성하기
  14. Logging: 로그도 비용이 드니 적절하기 사용하기
    ERROR > WARNING > INFORMATION > DEBUG > VERBOSE 사용할 것.
    한줄에 출력할 수 있는 80~100글자가 적당.
    StringBuilder는 기본버퍼가 16character라 String보다 항상 좋다고 할 수 없으니 확신이 없으면 그냥 String연산이 무난.
    System.out.print는 어차피 /dev/null로 던져버리니 절대 쓰지말 것. 괜히 비용만 잡아먹음.

Javatests Style Rules

  1. Naming test methods: testMethod_specificCase 이런식으로 이름짓


리스트뷰 밑의 내용 스크롤시 애니메이션 붙이는 방법


https://github.com/cuub/sugared-list-animations

https://github.com/nhaarman/ListViewAnimations

오픈소스 사용하시면 됩니다.

'Android > GUI & Activity' 카테고리의 다른 글

Animation 종류  (0) 2014.10.28
[펌[] Android ActionBar 활용  (0) 2014.10.22
AutoScaleTextView 추천 소스  (0) 2014.10.16
AutoScale TextView (4.4버전 테스트완료)  (0) 2014.10.15
CustomView lifeCycle  (0) 2014.09.30

http://blog.naver.com/PostView.nhn?blogId=iflowerpot&logNo=80121408847&categoryNo=13&parentCategoryNo=0&viewDate=&currentPage=3&postListTopCurrentPage=&userTopListOpen=true&userTopListCount=5&userTopListManageOpen=false&userTopListCurrentPage=3

'Android > Tip&Tech' 카테고리의 다른 글

[펌]안드로이드 Loader 활용하기  (0) 2014.10.21
자바 표준 스타일 정의  (0) 2014.09.30
kitkat(4.4)에서 맞닥뜨린 이슈 및 해결  (0) 2014.08.14
홈버튼 제어하기  (0) 2014.06.24
안드로이드 투명도 코드  (0) 2014.06.05

출처 : https://medium.com/marojuns-android/kitkat-4-4-%EC%97%90%EC%84%9C-%EB%A7%9E%EB%8B%A5%EB%9C%A8%EB%A6%B0-%EC%9D%B4%EC%8A%88-%EB%B0%8F-%ED%95%B4%EA%B2%B0-1ecb94c24694




'Android > Tip&Tech' 카테고리의 다른 글

자바 표준 스타일 정의  (0) 2014.09.30
[링크]아날로그 시계 만드는 소스  (0) 2014.08.26
홈버튼 제어하기  (0) 2014.06.24
안드로이드 투명도 코드  (0) 2014.06.05
[펌]SeekBar 스타일링 방법  (0) 2014.03.12

http://hns17.tistory.com/entry/App-개발-잠금화면-HomeKey-Control-Problem

100%  FF
95%  F2
90%  E6
85%  D9
80%  CC
75%  BF
70%  B3
65%  A6
60%  99
55%  8C
50%  80
45%  73
40%  66
35%  59
30%  4D
25%  40
20%  33
15%  26
10%  1A
5%  0D
0%  00


출처 :  http://stackoverflow.com/questions/16163215/android-styling-seek-bar

 

I would extract drawables and xml from Android source code and change its color to red. Here is example how I completed this for mdpi drawables:

Custom red_scrubber_control.xml:

<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/red_scrubber_control_disabled_holo" android:state_enabled="false"/>
    <item android:drawable="@drawable/red_scrubber_control_pressed_holo" android:state_pressed="true"/>
    <item android:drawable="@drawable/red_scrubber_control_focused_holo" android:state_selected="true"/>
    <item android:drawable="@drawable/red_scrubber_control_normal_holo"/>
</selector>

Custom: red_scrubber_progress.xml

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >

    <item
        android:id="@android:id/background"
        android:drawable="@drawable/red_scrubber_track_holo_light"/>
    <item android:id="@android:id/secondaryProgress">
        <scale
            android:drawable="@drawable/red_scrubber_secondary_holo"
            android:scaleWidth="100%" />
    </item>
    <item android:id="@android:id/progress">
        <scale
            android:drawable="@drawable/red_scrubber_primary_holo"
            android:scaleWidth="100%" />
    </item>

</layer-list>

Then copy required drawables from Android source code, I took them here: https://github.com/android/platform_frameworks_base/tree/ics-factoryrom-2-release/core/res/res It is good to copy these drawables for each hdpi, mdpi, xhdpi. For example I use only mdpi:

Then using Photoshop change color from blue to red:

red_scrubber_control_disabled_holo.png: red_scrubber_control_disabled_holo

red_scrubber_control_focused_holo.png: red_scrubber_control_focused_holo

red_scrubber_control_normal_holo.png: red_scrubber_control_normal_holo

red_scrubber_control_pressed_holo.png: red_scrubber_control_pressed_holo

red_scrubber_primary_holo.9.png: red_scrubber_primary_holo.9

red_scrubber_secondary_holo.9.png: red_scrubber_secondary_holo.9

red_scrubber_track_holo_light.9.png: red_scrubber_track_holo_light.9

Add SeekBar to layout:

<SeekBar
    android:id="@+id/seekBar1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:progressDrawable="@drawable/red_scrubber_progress"
    android:thumb="@drawable/red_scrubber_control" />

Result:

enter image description here

Edited:

Here is nice resource Android Holo Colors Generator that will help to create elements with different colors much faster. Just select color and element and it will create required drawable for xhdpi, hdpi and mdpi.

share|improve this answer

출처 :     http://stackoverflow.com/questions/12411060/get-listview-height-after-setadapter

 

ListView lv_marca;

    lv_marca
.setAdapter(adapter_marca);

   
int list_height = getListViewHeight(lv_marca);



   
private int getListViewHeight(ListView list) {
         
ListAdapter adapter = list.getAdapter();

         
int listviewHeight = 0;

          list
.measure(MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED),
                      
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));

          listviewHeight
= list.getMeasuredHeight() * adapter.getCount() + (adapter.getCount() * list.getDividerHeight());

         
return listviewHeight;
   
}

출처 : http://arabiannight.tistory.com/55

 

안드로이드/Android 부모의 속성을 동일 하게 가져 가자!


안드로이드 XML을 개발하면서 List나 뷰의 이벤트 발생에 따라 화살표(Arrow)버튼 이미지도 Press 처리 해야 할 경우가 많은데요. 이런 경우게 onTouchEvent로 터치 했을 경우에 Pressed 처리하거나 터치를 종료할 경우 Normal 처리 해주는 경우가 있었을 겁니다.  하지만 부모 뷰의 속성에 따라 Child뷰의 속성들이 이벤트를 받는 XML 속성이 있는데요.


이 속성을 쓰면 훨씬더 간결하고 편하게 코드를 작성할 수 있습니다.
그 속성의 이름은 바로 요놈 입니다.


 

android:duplicateParentState="true"
 
 



보통 요즘의 화면 구성에는 하나의 레이아웃에 여러개의 뷰들이 들어가는 경우가 많은데요. duplicateParentState 속성을 이용하면 레이아웃안에 Child 뷰들을 부모의 상태와 동일한 상태(State)를 적용 할 수 있습니다.



결국 레이아웃에 onClickListener를 사용한 경우 Child View들에 Selector를 이용하여 Background를 작성해 주면 부모의 이벤트에 따라 Chiled View의 속성이 변하겠죠?



주의!! : 부모의 클릭이벤트를 동일하게 받을 차일드View에 해당 속성을 적용 하시기 바랍니다.

출처 : http://hmkcode.com/android-custom-listview-titles-icons-counter/

Android | Custom ListView with Titles, Icons & Counter

android-pro-listviewYou can customize the ListView by providing a new layout for the list items “rows”. The new layout can be more than just a single TextView. Here will see how to develop a custom ListView with items having leading icons “ImageView“, trailing counters “TextView” and some text in between.  Also, we will see how to add items that will act as a group header “title” for a set of other items.

 

 

Objectives:

  • How to create ListView with custom View?
  • How to create ListView items with leading icons “ImageView” and trailing counters?
  • How to create ListView items that act as header of group of items?

Environment & Tools:

  • Android Developer Tools (ADT) (or Eclipse + ADT plugin)
  • AVD Nexus S Android 4.3 “emulator” or,
  • Min SDK 8

( 1 ) Create Layout “UI” for ListView Items

We will define the items layout. We need two different layouts one for the target item and one for the group header item.

1. target_item.xml

2. group_header_item.xml

1. Target Item

  • res/layout/target_item.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="48dp"
    android:background="#F3F3F3">
  
     <!-- icon -->
     <ImageView
         android:id="@+id/item_icon"
         android:layout_width="32dp"
         android:layout_height="32dp"
         android:layout_alignParentLeft="true"
         android:layout_marginLeft="8dp"
         android:layout_marginRight="8dp"
         android:layout_marginTop="8dp"
         android:src="@drawable/action_help"
         />
  
    <!-- title -->
    <TextView
         android:id="@+id/item_title"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_toRightOf="@+id/item_icon"
         android:layout_alignBaseline="@+id/item_counter"
         android:textSize="18dp" />
  
        <!-- counter -->
        <TextView
            android:id="@+id/item_counter"
            android:layout_width="32dp"
            android:layout_height="32dp"
            android:layout_alignParentRight="true"
            android:layout_marginRight="8dp"
            android:layout_marginTop="8dp"
            android:background="@drawable/rectangle"
            android:gravity="center"
            android:textColor="#FFFFFF"
            android:textSize="12sp"
            android:textStyle="bold" />
  
</RelativeLayout>

Note: @drawable/rectangle is defined in res/drawable/rectangle.xml

1
2
3
4
5
6
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
   <solid android:color="#5490CC"></solid>
   <corners android:radius="8px"></corners
   <stroke  android:width="2dp" android:color="#A4C2E0"></stroke>  
</shape>

2. Group Header Item

  • res/layout/group_header_item.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="48dp"
  
    android:background="#F3F3F3">
  
    <!-- title -->
    <TextView
         android:id="@+id/header"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:gravity="center_vertical"
         android:textSize="16dp"
         android:layout_marginLeft="12dp"
         android:layout_marginBottom="4dp"
         android:layout_alignParentBottom="true" />
  
    <!--  divider -->
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:layout_marginBottom="1dp"
        android:layout_alignParentBottom="true"
        android:background="#DADADC" ></View>
  
</RelativeLayout>

( 2 ) Model.java Class “Model”

  • Create a model class and call it “Model.java” to hold data to be displayed on list items.
  • We need to define an object of type Model to hold the resources “data” for each list item.
  • The way we define the Model object “which constructor we use” will determine which list item layout “target item or group header item” will be displayed. Basically we set the a boolean property “isGroupHeader” to be always false “if we are creating the Model object for target item layout“ unless we define the Model object “for group header item layout” using the single argument constructor then isGroupHeader will be true.
  • For target_item we need a Model object to be declared as following:
new Model(R.drawable.action_help_32,"Menu Item 1","1")
//R.drawable.action_help_32 is a png image in res/drawable folder

  • For group_header_item we need a Model object to be declared as following:
new Model("Group Title")

  • src/com/hmkcode/android/Model.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.hmkcode.android;
  
public class Model{
  
    private int icon;
    private String title;
    private String counter;
  
    private boolean isGroupHeader = false;
  
    public Model(String title) {
        this(-1,title,null);
        isGroupHeader = true;
    }
    public Model(int icon, String title, String counter) {
        super();
        this.icon = icon;
        this.title = title;
        this.counter = counter;
    }
  
//gettters & setters...
}

( 3 ) MyAdapter.java

  • MyAdpater is the class that will fill the gap between step 1 & 2 i.e. the item layout and Model data.
  • MyAdapter extends ArrayAdapter<Model>
  • MyAdapter(Context context, ArrayList<Model> modelsArrayList) constructor takes context i.e. “Activity” & array of objects of type Model.
  • Override getView() method
      • getView() method will basically go over the passed array of objects “Model”
      • If the Model object isGroupHeader = false then inflate target_item, get its views, set their values and return View with target_layout
      • else return View with group_header_layout.
  • src/com/hmkcode/android/MyAdapter.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package com.hmkcode.android;
  
import java.util.ArrayList;
  
import com.hmkcode.android.R;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
  
public class MyAdapter extends ArrayAdapter<Model> {
  
        private final Context context;
        private final ArrayList<Model> modelsArrayList;
  
        public MyAdapter(Context context, ArrayList<Model> modelsArrayList) {
  
            super(context, R.layout.target_item, modelsArrayList);
  
            this.context = context;
            this.modelsArrayList = modelsArrayList;
        }
  
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
  
            // 1. Create inflater 
            LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  
            // 2. Get rowView from inflater
  
            View rowView = null;
            if(!modelsArrayList.get(position).isGroupHeader()){
                rowView = inflater.inflate(R.layout.target_item, parent, false);
  
                // 3. Get icon,title & counter views from the rowView
                ImageView imgView = (ImageView) rowView.findViewById(R.id.item_icon); 
                TextView titleView = (TextView) rowView.findViewById(R.id.item_title);
                TextView counterView = (TextView) rowView.findViewById(R.id.item_counter);
  
                // 4. Set the text for textView 
                imgView.setImageResource(modelsArrayList.get(position).getIcon());
                titleView.setText(modelsArrayList.get(position).getTitle());
                counterView.setText(modelsArrayList.get(position).getCounter());
            }
            else{
                    rowView = inflater.inflate(R.layout.group_header_item, parent, false);
                    TextView titleView = (TextView) rowView.findViewById(R.id.header);
                    titleView.setText(modelsArrayList.get(position).getTitle());
  
            }
  
            // 5. retrn rowView
            return rowView;
        }
}

( 4 ) MainActivity.java

  • For MainActivity class we have two options either to extend Activity or ListActivity, comments on the code explain how to use each one.
  • src/com/hmkcode/android/MainActivity.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.hmkcode.android;
  
import java.util.ArrayList;
  
import android.app.Activity;
import android.app.ListActivity;
import android.os.Bundle;
import android.widget.ListView;
  
public class MainActivity extends ListActivity {
  
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
  
        // if extending Activity
        //setContentView(R.layout.activity_main);
  
        // 1. pass context and data to the custom adapter
        MyAdapter adapter = new MyAdapter(this, generateData());
  
        // if extending Activity 2. Get ListView from activity_main.xml
        //ListView listView = (ListView) findViewById(R.id.listview);
  
        // 3. setListAdapter
        //listView.setAdapter(adapter); if extending Activity
        setListAdapter(adapter);
    }
  
    private ArrayList<Model> generateData(){
        ArrayList<Model> models = new ArrayList<Model>();
        models.add(new Model("Group Title"));
        models.add(new Model(R.drawable.action_help_32,"Menu Item 1","1"));
        models.add(new Model(R.drawable.action_search_32,"Menu Item 2","2"));
        models.add(new Model(R.drawable.collections_cloud_32,"Menu Item 3","12"));
  
        return models;
    }
  
}

Run the app you will get the following UI

Icons used in this sample are downloaded from Download the Action Bar Icon Pack

Source Code @ GitHub

출처 : http://www.kmshack.kr/323

 

Android View와 관련된 오픈소스들이 많이 공개 되고 있다. 그래서 많이 쓰이고 유용한 오픈소스를 정리 해보았다.  아직 국내에서는 오픈소스가 인색한지 모두 외국에서 만든것들이다. 나도 View관련 오픈소스를 하나준비 하겠다고 준비중인데.. 준비중이기만 하다.

 

참고로, 잘 알려지고 검증된 오픈소스라도 코드를 하나하나씩 보고 어떻게 구현되어 있는지 꼭 살펴보고 썼으면 좋겠다. 그리고 이제 개발을 시작한지 얼마 안된 분들이라면 이런 오픈소스를 사용함으로 자기 실력을 죽일 수도 있으니 한번씩 구현해보는 것도 좋을듯 하다.

 

그리고 국내 개발 커뮤니티에 보면 자기가 개발할 것에 대해 오픈소스를 찾음으로써 개발해서 삽질 하기전에 찾아서 다행이다라는 글들을 보면 씁쓸하다. 오픈소스는 좋은점도 있지만 그에 반하는 양면성을 가지고 있다는 것에 조심했으면 좋겠다.

 

 

아무튼 아래것들은 이미 유명하고 잘만들어진 오픈소스들이다.

 

 

 

 

1. ActionbarSherlock

허니컴부터 적용된 액션바를 이전버전에도 사용할 수 있게 해준다.

 

http://www.actionbarsherlock.com/
https://github.com/JakeWharton/ActionBarSherlock

 

ActionBarSherlock is an standalone library designed to facilitate the use of the action bar design pattern across all versions of Android through a single API.

The library will automatically use the native ActionBar implementation on Android 4.0 or later. For previous versions which do not include ActionBar, a custom action bar implementation based on the sources of Ice Cream Sandwich will automatically be wrapped around the layout. This allows you to easily develop an application with an action bar for every version of Android from 2.x and up.

 

 

 

2. Android-PullToRefresh

ListView, ScrollView, Viewpager, WebView 등 새로고침 기능의 View를 만들어 준다.

 

https://github.com/chrisbanes/Android-PullToRefresh

 

This project aims to provide a reusable Pull to Refresh widget for Android. It was originally based on Johan Nilsson's library (mainly for graphics, strings and animations), but these have been replaced since.

 

 

 

 

3. StickyListHeaders

ListView의 Section Header 정보를 넣을 수 있다.

 

https://github.com/emilsjolander/StickyListHeaders

 

StickyListHeaders is an Android library that makes it easy to integrate section headers in your ListView. These section headers stick to the top like in the new People app of Android 4.0 Ice Cream Sandwich. This behavior is also found in lists with sections on iOS devices. This library can also be used for without the sticky functionality if you just want section headers.

StickyListHeaders actively supports android versions 2.3 (gingerbread) and above That said, it should be compatible with much older versions of android as well but these are not actively tested.

Here is a short gif showing the functionality you get with this library:

 

 


4. MenuDrawer
좌측 또는 우측의 슬라이드 메뉴를 구성 할 수 있다.


https://github.com/SimonVT/android-menudrawer

 

A slide-out menu implementation, which allows users to navigate between views in your app. Most commonly the menu is revealed by either dragging the edge of the screen, or clicking the 'up' button in the action bar.

 

 


5. SlidingMenu
MenuDrawer와 같다.

 

https://github.com/jfeinstein10/SlidingMenu


SlidingMenu is an Open Source Android library that allows developers to easily create applications with sliding menus like those made popular in the Google+, YouTube, and Facebook apps. Feel free to use it all you want in your Android apps provided that you cite this project and include the license in your app.]

 

 


6. FadingActionBar

리스트뷰 스크롤시 헤더 컨텐츠에 따라 액션바의 알파값이 변한다. 구글 음악플레이어의 아티스트정보 페이지

 

https://github.com/ManuelPeinado/FadingActionBar

 

FadingActionBar is a library which implements the cool fading action bar effect that can be seen in the new Play Music app.

 


7. DragSortListView

리스트 소팅

 

https://github.com/bauerca/drag-sort-listview

 

DragSortListView (DSLV) is an extension of the Android ListView that enables drag-and-drop reordering of list items.

 

 


8. IndexableListView

리스트뷰의 알파벳 인덱스 기능

 

https://github.com/woozzu/IndexableListView

 

 


9. ListViewAnimations

ListView 스크롤시 애니메이션(구글 플러스)

 

https://github.com/nhaarman/ListViewAnimations

 

ListViewAnimations is an Open Source Android library that allows developers to easily create ListViews with animations. Feel free to use it all you want in your Android apps provided that you cite this project and include the license in your app.

 

 


10. ViewPagerIndicator

ViewPager 인디케이터

 

https://github.com/JakeWharton/Android-ViewPagerIndicator

 

Android-ViewPagerIndicator is presented as an Android library project. A standalone JAR is not possible due to the theming capabilities offered by the indicator widgets.


 


11. PagerSlidingTabStrip

ViewPager 인디케이터

 

https://github.com/astuetz/PagerSlidingTabStrip

 

Interactive paging indicator widget, compatible with the ViewPager from the Android Support Library.

 

 


12. JazzyViewPager

ViewPager 스크롤시 애니메이션

 

https://github.com/jfeinstein10/JazzyViewPager

 

An easy to use ViewPager that adds an awesome set of custom swiping animations. Just change your ViewPagers to JazzyViewPagers and you're good to go!

 

 


14. ViewPager3D

ViewPager 스크롤시 3D 효과

 

https://github.com/inovex/ViewPager3D

 

 


15. DirectionalViewPager

ViewPager 좌우, 아래위 스크롤

 

https://github.com/JakeWharton/Android-DirectionalViewPager

 

Implementation of the compatibility library ViewPager class that supports paging both vertically and horizontally as well as changing between the two at runtime.

 

 

 

16. VerticalSeekBarAndroid
수직 SeekBar

 

https://github.com/AndroSelva/Vertical-SeekBar-Android

 

This project is all about Customizing the normal SeekBar to Vertical Seekbar.

 

 


17. HoloCircleSeekBar
원형으로 생긴 SeekBar

 

https://github.com/JesusM/HoloCircleSeekBar

 

A Circle SeekBar inspired by Android Holo ColorPicker designed by Marie Schweiz and developed by Lars Werkman.

 

 


18. MultiChoiceAdapter
ListView, GridView에서 다중선택을 쉽게 할 수 있도록 도와준다.

 

https://github.com/ManuelPeinado/MultiChoiceAdapter

 

MultiChoiceAdapter is an implementation of ListAdapter which adds support for modal multiple choice selection as in the native Gmail app.

 

 


19. TwoWayGridView
GridView를 가로, 세로방향으로 스크롤 되도록 한다.

 

https://github.com/jess-anders/two-way-gridview

 

An Android GridView that can be configured to scroll horizontally or vertically.

 

 


20. ScrollBarPanel
스크롤바 옆에 View를 생성(Path 2.0에서 볼 수 있는 기능)

 

https://github.com/rno/Android-ScrollBarPanel

 

Android-ScrollBarPanel allows to attach a View to a scroll indicator like it's done in Path 2.0.

출처 : http://kahdev.wordpress.com/2008/09/13/making-a-custom-android-button-using-a-custom-view/

 

Creating a custom view is as simple as inheriting from the View class and overriding the methods that need to be overridden. In this example, a custom button is implemented in this way. The button shall feature a labelled image (i.e. an image with text underneath).



1   public class CustomImageButton extends View {
2       private final static int WIDTH_PADDING = 8;
3       private final static int HEIGHT_PADDING = 10;
4       private final String label;
5       private final int imageResId;
6       private final Bitmap image;
7       private final InternalListener listenerAdapter = new InternalListener();
8

The constructor can take in the parameters to set the button image and label.


9       /**
10       * Constructor.
11       *
12       * @param context
13       *        Activity context in which the button view is being placed for.
14       *
15       * @param resImage
16       *        Image to put on the button. This image should have been placed
17       *        in the drawable resources directory.
18       *
19       * @param label
20       *        The text label to display for the custom button.
21       */
22      public CustomImageButton(Context context, int resImage, String label) 
23       {
24           super(context);
25           this.label = label;
26           this.imageResId = resImage;
27           this.image = BitmapFactory.decodeResource(context.getResources(),
28                  imageResId);
29  
30           setFocusable(true);
31           setBackgroundColor(Color.WHITE);
32
33           setOnClickListener(listenerAdapter);
34           setClickable(true);
35       }
36

With the constructor defined, there are a number of methods in the View class that needs to be overridden to this view behave like a button. Firstly, the onFocusChanged gets triggered when the focus moves onto or off the view. In the case of our custom button, we want the button to be “highlighted” when ever the focus is on the button.


37       /**
38       * The method that is called when the focus is changed to or from this
39       * view.
40       */
41       protected void onFocusChanged(boolean gainFocus, int direction,
42                      Rect previouslyFocusedRect)
43       {
44           if (gainFocus == true)
45           {
46               this.setBackgroundColor(Color.rgb(255, 165, 0));
47           }
48           else
49          {
50              this.setBackgroundColor(Color.WHITE);
51          }
52      }
53      

The method responsible for rendering the contents of the view to the screen is the draw method. In this case, it handles placing the image and text label on to the custom view.


54      /**
55       * Method called on to render the view.
56       */
57      protected void onDraw(Canvas canvas)
58      {
59          Paint textPaint = new Paint();
60          textPaint.setColor(Color.BLACK);
61          canvas.drawBitmap(image, WIDTH_PADDING / 2, HEIGHT_PADDING / 2, null);
62          canvas.drawText(label, WIDTH_PADDING / 2, (HEIGHT_PADDING / 2) +
63                  image.getHeight() + 8, textPaint);
64      }
65      

For the elements to be displayed correctly on the screen, Android needs to know the how big the custom view is. This is done through overriding the onMeasure method. The measurement specification parameters represent dimension restrictions that are imposed by the parent view.


 66        @Override
 67        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
 68        {
 69         setMeasuredDimension(measureWidth(widthMeasureSpec),
 70                 measureHeight(heightMeasureSpec));
 71        }
 72    

The call to setMeasuredDimension in the onMeasure method is important. The documentation states that the call is necessary to avoid a IllegalStateException.


 73     private int measureWidth(int measureSpec)
 74     {
 75         int preferred = image.getWidth() * 2;
 76         return getMeasurement(measureSpec, preferred);
 77     }
 78    
 79     private int measureHeight(int measureSpec)
 80     {
 81         int preferred = image.getHeight() * 2;
 82         return getMeasurement(measureSpec, preferred);
 83     }
 84    

To calculate the width and height measurements, I’ve chosen to keep the logic simple by using a simple formula to calculate the dimensions. This simple formula computes the dimensions based on the dimensions of the image. The measureSpec parameter specifies what restrictions are imposed by the parent layout.


 85     private int getMeasurement(int measureSpec, int preferred)
 86     {
 87         int specSize = MeasureSpec.getSize(measureSpec);
 88         int measurement = 0;
 89        
 90         switch(MeasureSpec.getMode(measureSpec))
 91         {
 92             case MeasureSpec.EXACTLY:
 93                 // This means the width of this view has been given.
 94                 measurement = specSize;
 95                 break;
 96             case MeasureSpec.AT_MOST:
 97                 // Take the minimum of the preferred size and what
 98                 // we were told to be.
 99                 measurement = Math.min(preferred, specSize);
100                 break;
101             default:
102                 measurement = preferred;
103                 break;
104         }
105    
106         return measurement;
107     }
108

To make the customised button useful, it needs to trigger some kind of action when it is clicked (i.e. a listener). The view class already defines methods for setting the listener, but a more specialised listener could be better suited to the custom button. For example, the specialised listener could pass back information on the instance of the custom button.


109     /**
110      * Sets the listener object that is triggered when the view is clicked.
111      *
112      * @param newListener
113      *        The instance of the listener to trigger.
114      */
115     public void setOnClickListener(ClickListener newListener)
116     {
117         listenerAdapter.setListener(newListener);
118     }
119    

If the custom listener passes information about this instance of the custom button, it may as well have accessors so listener implementation can get useful information about this custom button.


120     /**
121      * Returns the label of the button.
122      */
123     public String getLabel()
124     {
125         return label;
126     }
127    
128     /**
129      * Returns the resource id of the image.
130      */
131     public int getImageResId()
132     {
133         return imageResId;
134     }
135    

Finally, for our custom button class that is using a custom listener, the custom listener class needs to be defined.


136     /**
137      * Internal click listener class. Translates a view’s click listener to
138      * one that is more appropriate for the custom image button class.
139      *
140      * @author Kah
141      */
142     private class InternalListener implements View.OnClickListener
143     {
144         private ClickListener listener = null;
145    
146         /**
147          * Changes the listener to the given listener.
148          *
149          * @param newListener
150          *        The listener to change to.
151          */
152         public void setListener(ClickListener newListener)
153         {
154             listener = newListener;
155         }
156        
157         @Override
158         public void onClick(View v) 
159         {
160             if (listener != null)
161             {
162                 listener.onClick(CustomImageButton.this);
163             }
164         }
165     }
166    }
167    

출처 : http://javaexpert.tistory.com/179#comment9420256

 

 기본적으로 SlidingDrawer 는 오른쪽에서 왼쪽으로 밖에 지원이 안되는가?? --

 

왼쪽에서 밀면훨씬편한데.. ㅋㅋ

 

<SlidingDrawer xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/slidingDrawer"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:gravity="center_horizontal"
    android:handle="@+id/handle"
    android:content="@+id/content"
    android:rotation="180">
    <LinearLayout android:id="@+id/handle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <ImageView android:id="@+id/imageView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_launcher"
            android:rotation="180" />
    </LinearLayout>
    <ImageView android:id="@+id/content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#FF0000"
        android:src="@drawable/ic_launcher"
        android:rotation="180" />
</SlidingDrawer>

 

 

이것이 xml 코드

 

 

public void onCreate(Bundle savedInstanceState){

super.onCreate(savedInstanceState);

requestWindowFeature(Window.FEATURE_NO_TITLE);

setContentView(R.layout.subware);

drawer = (SlidingDrawer)findViewById(R.id.slidingDrawer);

drawer.setOnDrawerScrollListener(new SlidingDrawer.OnDrawerScrollListener() {

@Override

public void onScrollStarted() {

// TODO Auto-generated method stub

}

@Override

public void onScrollEnded() {

// TODO Auto-generated method stub

}

});

 

drawer.setOnDrawerCloseListener(new SlidingDrawer.OnDrawerCloseListener() {

@Override

public void onDrawerClosed() {

// TODO Auto-generated method stub

}

});

drawer.setOnDrawerOpenListener(new SlidingDrawer.OnDrawerOpenListener() {

@Override

public void onDrawerOpened() {

// TODO Auto-generated method stub

}

});

}

요건 java코드

 

 

출처 :  http://blog.naver.com/PostView.nhn?blogId=rosaria1113&logNo=107988257&parentCategoryNo=&categoryNo=76&viewDate=&isShowPopularPosts=false&from=postView

 

 

 

 

펌 : http://muzesong.tistory.com/38

 

안드로이드를 하다보면 액티비티가 계속 쌓이는 경우가 있다. 이 경우는 시스템 적으로 아무래도

부담이되고, 물론 눈에 보일정도로 그런다기보다 계속 그렇게 쌓다보면 뒤로가기를 한참을 눌러야

밖으로 빠져나가게 되는 불상사가 생긴다.

이럴 경우 현재 액티비티나 현재액티비티가 아닌 다른 액티비티를 종료시켜서 액티비티를 줄이는

방법이있는데, 우선 현재 액티비티를 죽이는 방법은 간단하다.

어떠한 작업을 완료하고 액티비티를 종료하기를 원한다면 작업 완료 다음줄에

finish();


이것만 적어주면 된다. 이렇게 되면 저 함수를 만나는 즉시 현재 액티비티가 종료된다. 

하지만 A 액티비티에서 B액티비티를 갔는데 A액티비티를 죽이고 싶다면 이렇게 하면된다.

우선 A 클래스에 

public static Activity AActivity;


라고 스테틱으로 액티비티를 선언한다. 그리고 onCreate 안에 

AActivity = Aclass.this;


이렇게, 액티비티 객체에 현재 클래스를 담아준다. 그럼 이제 B클래스로가서

Aclass aActivity = (Aclass)Aclass.AActivity;


이렇게 aActivity 라는 객체를 만드는데 그 객체는 Aclass의 스테틱변수인 AActivity를

넣어 둔다는 의미이다 보면 복잡해 보이는데 글로 쓰면 이렇다 .

A클래스  A클래스객체  =  (A클래스)A클래스.A클래스에서 스태틱 액티비티 변수


이정도 순서이다. 헷갈리기 쉬울 것 같다. 

그 다음 아래에 이렇게 만든 객체를 피니시하면된다

aActivity.finish();


이렇게 써주면 B클래스에서 아까 앞에 A액티비티를 종료 시킬 수 있다.

출처 : http://www.kmshack.kr/249

mainActivity.java

 

public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);     
     
        intentMyService = new Intent(this,PersistentService.class);        // 죽지않는 좀비 서비스
        receiver = new RestartService();                                                    // 리시버 등록
       
  try{
   IntentFilter mainFilter = new IntentFilter("com.jongbum.ServiceTest.ssss");      // xml에서 정의해도 됨
   registerReceiver(receiver, mainFilter);                                               // 리시버 저장

   startService(intentMyService);                                                           // 서비스 시작 
  }
  catch (Exception e) {
   Log.d("RestartService",e.getMessage()+"");
  }
}
   
 @Override
 protected void onDestroy() {
  unregisterReceiver(receiver);                                                               //리시버 삭제(?) 안하면 에러!!
  super.onDestroy();
 }

 

PersistentService.java

 

public class PersistentService extends Service {
 
 @Override
 public void onCreate() {
  Log.d("PersistentService","onCreate");
  unregisterRestartAlarm();                                                 //이미 등록된 알람이 있으면 제거
  super.onCreate();
 }
 
 @Override
 public void onDestroy() {
  Log.d("PersistentService","onDestroy");
  registerRestartAlarm();                                                   // 서비스가 죽을때 알람을 등록
  super.onDestroy();

 }

 

 // support persistent of Service
 public void registerRestartAlarm() {
  Log.d("PersistentService", "registerRestartAlarm");
     Intent intent = new Intent(PersistentService.this, RestartService.class);
     intent.setAction("ACTION.RESTART.PersistentService");
     PendingIntent sender = PendingIntent.getBroadcast(PersistentService.this, 0, intent, 0);
     long firstTime = SystemClock.elapsedRealtime();
     firstTime += 10*1000;                                               // 10초 후에 알람이벤트 발생
     AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
     am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstTime, 10*1000, sender);
  }

  public void unregisterRestartAlarm() {
     Log.d("PersistentService", "unregisterRestartAlarm");
     Intent intent = new Intent(PersistentService.this, RestartService.class);
     intent.setAction("ACTION.RESTART.PersistentService");
     PendingIntent sender = PendingIntent.getBroadcast(PersistentService.this, 0, intent, 0);
     AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
     am.cancel(sender);
   }

 

 @Override
 public IBinder onBind(Intent intent) {
  Log.d("RestartService", "onBindonBindonBindonBindonBindonBindonBind");
  return null;
 }
 
}

 

RestartService .java

 

public class RestartService extends BroadcastReceiver {
   

   @Override
   public void onReceive(Context context, Intent intent) {
    Log.d("RestartService", "RestartService called! :" + intent.getAction());

   

    /* 서비스 죽일때 알람으로 다시 서비스 등록 */

     if(intent.getAction().equals("ACTION.RESTART.PersistentService")){
     Log.d("RestartService", "ACTION_RESTART_PERSISTENTSERVICE");
     Intent i = new Intent(context,PersistentService.class);
     context.startService(i);
    } 

    /* 폰 재부팅할때 서비스 등록 */
    if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
     Log.d("RestartService", "ACTION_BOOT_COMPLETED");
     Intent i = new Intent(context,PersistentService.class);
     context.startService(i);
    }
   }
}

 

 

Manifest.xml

  




출처 : https://github.com/johannilsson/android-pulltorefresh

 

Pull To Refresh for Android

This project aims to provide a reusable pull to refresh widget for Android.

Screenshot

Repository at https://github.com/johannilsson/android-pulltorefresh.

Usage

Layout

<!--
  The PullToRefreshListView replaces a standard ListView widget.
-->
<com.markupartist.android.widget.PullToRefreshListView
    android:id="@+id/android:list"
    android:layout_height="fill_parent"
    android:layout_width="fill_parent"
    />

Activity

// Set a listener to be invoked when the list should be refreshed.
((PullToRefreshListView) getListView()).setOnRefreshListener(new OnRefreshListener() {
    @Override
    public void onRefresh() {
        // Do work to refresh the list here.
        new GetDataTask().execute();
    }
});

private class GetDataTask extends AsyncTask<Void, Void, String[]> {
    ...
    @Override
    protected void onPostExecute(String[] result) {
        mListItems.addFirst("Added after refresh...");
        // Call onRefreshComplete when the list has been refreshed.
        ((PullToRefreshListView) getListView()).onRefreshComplete();
        super.onPostExecute(result);
    }
}

출처 : http://www.kmshack.kr/346

 

 

얼마전 ListView 포퍼먼스 팁에 관한 블로그 포스팅을 한적이 있다.  Adapter에서 View의 재활용과 함께 ViewHolder Pattern으로 findViewById를 View생성 시점에 setTag()를 하여 재활용에 대해 언급 했다. 


이 방법은 각 ListView의 ViewItem별로 각각의 ViewHolder를 가지고 있어야 한다.  

ListView의 아이템별로 서로 다른 디자인이 필요하기에 View의 종류가 달라 질 수 밖에 없기때문에 ViewHolder도 각각 존재 할 수 밖에 없다. 이렇게 static하게 ViewHolder을 가지고 있는것 보다 유연하게 ViewHolder를 생성 할 수 있는 코드를 생성하는 방법에 대해서 알아보자.


아래처럼 Adapter에 static class로 만들어 ViewHolder를 사용하는것이 일반적이다.  ViewHolder는 같은 기능을 하는데 단순히 View의 종류가 달라져 각각 생성 할수 밖에 없는 상황이다. 


 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
private static class ViewHolder {
 
    public final ImageView bananaView;
    public final TextView phoneView;
 
    public ViewHolder(ImageView bananaView, TextView phoneView) {
        this.bananaView = bananaView;
        this.phoneView = phoneView;
    }
}
 
@Override
public View getView(int position, View convertView, ViewGroup parent) {
 
    ImageView bananaView;
    TextView phoneView;
 
    if (convertView == null) {
        convertView = LayoutInflater.from(context).inflate(R.layout.banana_phone, parent, false);
        bananaView = (ImageView) convertView.findViewById(R.id.banana);
        phoneView = (TextView) convertView.findViewById(R.id.phone);
        convertView.setTag(new ViewHolder(bananaView, phoneView));
    } else {
        ViewHolder viewHolder = (ViewHolder) convertView.getTag();
        bananaView = viewHolder.bananaView;
        phoneView = viewHolder.phoneView;
    }
 
    BananaPhone bananaPhone = getItem(position);
    phoneView.setText(bananaPhone.getPhone());
    bananaView.setImageResource(bananaPhone.getBanana());
 
    return convertView;
}

 



해결책으로 아래와 같이 ViewGroup의 View들에 대해 동적으로 생성하는 코드를 만들 수 있다.


 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class ViewHolder {
    @SuppressWarnings("unchecked")
    public static <T extends View> T get(View view, int id) {
        SparseArray<View> viewHolder = (SparseArray<View>) view.getTag();
        if (viewHolder == null) {
            viewHolder = new SparseArray<View>();
            view.setTag(viewHolder);
        }
        View childView = viewHolder.get(id);
        if (childView == null) {
            childView = view.findViewById(id);
            viewHolder.put(id, childView);
        }
        return (T) childView;
    }
}

 



모든 View들은 View를 상속 받고 있기 때문에  SparseArray를 통해서  ChildView의 Id가 없으면 findViewById()를 통해 put해주고 있으면 get으로 가져오는 방식이다. 


 

사용하는 간단한 예를 알아보면:

 


 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Override
public View getView(int position, View convertView, ViewGroup parent) {
 
    if (convertView == null) {
        convertView = LayoutInflater.from(context).inflate(R.layout.banana_phone, parent, false);
    }
 
    ImageView bananaView = ViewHolder.get(convertView, R.id.banana);
    TextView phoneView = ViewHolder.get(convertView, R.id.phone);
 
    BananaPhone bananaPhone = getItem(position);
    phoneView.setText(bananaPhone.getPhone());
    bananaView.setImageResource(bananaPhone.getBanana());
 
    return convertView;
}


 

기존의 방법보다 더 간결화되고 심플해진 것을 볼 수 있다.


출처 :  http://www.techrepublic.com/blog/software-engineer/create-a-transparent-progress-dialog-on-android/

 

A game development hobby project inspired this app developer to figure out a way to create a transparent progress dialog that animates an image. He describes how to do it.

 

Over the last year I've been working hard in my spare time writing a multiplayer game for mobile devices. It's slow going, and often after putting in eight or more hours at my day gig (where I also write applications), I start thinking I need to get a new hobby that doesn't involve computers, cell phones, or tablets.

Still, I do it not just because I enjoy seeing my games out there in the market, but also because game programming is unique in that it often tends to veer from the standard platform conventions. Game developers frequently find themselves thinking creatively, particularly when it comes to user experience and user interface. 

What's all this got to do with transparent progress dialogs on Android? Well, Android's out-of-the-box progress dialog is anything but exciting (Figure A).

Figure A

 

AndroidProcessDialog_FigA_082713.png

 

See what I mean?

 

For my game I needed the functionality of a blocking progress dialog without the dialog part. After poking around the Android documentation, a number of developer forums, and a lot of trial and error, I succeeded in creating a transparent progress dialog that simply animates an image of my choosing. This tutorial walks you through the steps, so you can do the same. If you prefer, you can download and import the project directly in Eclipse.

1. Create a new Android project in Eclipse targeting Android 2.2 or better.

2. In the /res/layout folder, create a linear layout in activity_main.xml. Add a text label and a button.

 

activity_main.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:gravity="center_horizontal"
        android:padding="8dp"
        android:textSize="20sp"
        android:text="Transparent Progress Indicator" />
    
    <Button 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Check it out!"
        android:layout_marginTop="40dp"
        android:layout_gravity="center"
        android:id="@+id/the_button" />

</LinearLayout>

 

3. In the /res/values folder, open styles.xml, which is where you will add the style for our transparent dialog. Be sure to specify the parent attribute, or you will have problems at runtime.

 

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="android:Theme.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>
    
    <!--  Transparent dialog -->
    <style name="TransparentProgressDialog" parent="@android:Theme.Dialog">
        <item name="android:windowFrame">@null</item>
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowIsFloating">true</item>
        <item name="android:windowContentOverlay">@null</item>
        <item name="android:windowTitleStyle">@null</item>
        <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
        <item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
        <item name="android:backgroundDimEnabled">true</item>
        <item name="android:background">@android:color/transparent</item>
    </style>

</resources>

 

4. Create a /drawable folder in the /res directory and add an image to represent our spinner. The animation is a simple rotation, so you'll want to use something that is exactly as wide as it is tall. Here's the image I chose (Figure B).

Figure B

 

AndroidProcessDialog_FigB_082713.png

 

5. Now you can implement your MainActivity.java file. First, you override the on create and wire up your button handler. Note that in the on create you are instantiating a dialog and a handler; these reference an inner class that you will get to shortly. The last thing MainActivity.java is responsible for is releasing the handler and the dialog when the activity gets destroyed.

 

MainActivity.java
package com.authorwjf.transparentprogressdialog;

import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.LinearLayout;

public class MainActivity extends Activity implements OnClickListener {

	private TransparentProgressDialog pd;
	private Handler h;
	private Runnable r;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		h = new Handler();
		pd = new TransparentProgressDialog(this, R.drawable.spinner);
		r =new Runnable() {
			@Override
			public void run() {
				if (pd.isShowing()) {
					pd.dismiss();
				}
			}
		};
		findViewById(R.id.the_button).setOnClickListener(this);
	}
	
	@Override
	public void onClick(View v) {
		pd.show();
		h.postDelayed(r,5000);
	}
	
	@Override
	protected void onDestroy() {
		h.removeCallbacks(r);
		if (pd.isShowing() ) {
			pd.dismiss();
		}
		super.onDestroy();
	}

}

 

6. Add the inner class just below your on destroy method. The constructor builds your transparent dialog, and the show method displays it and starts the animation running.

 

private class TransparentProgressDialog extends Dialog {
		
	private ImageView iv;
		
	public TransparentProgressDialog(Context context, int resourceIdOfImage) {
		super(context, R.style.TransparentProgressDialog);
        	WindowManager.LayoutParams wlmp = getWindow().getAttributes();
        	wlmp.gravity = Gravity.CENTER_HORIZONTAL;
        	getWindow().setAttributes(wlmp);
		setTitle(null);
		setCancelable(false);
		setOnCancelListener(null);
		LinearLayout layout = new LinearLayout(context);
		layout.setOrientation(LinearLayout.VERTICAL);
		LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
		iv = new ImageView(context);
		iv.setImageResource(resourceIdOfImage);
		layout.addView(iv, params);
		addContentView(layout, params);
	}
		
	@Override
	public void show() {
		super.show();
		RotateAnimation anim = new RotateAnimation(0.0f, 360.0f , Animation.RELATIVE_TO_SELF, .5f, Animation.RELATIVE_TO_SELF, .5f);
		anim.setInterpolator(new LinearInterpolator());
		anim.setRepeatCount(Animation.INFINITE);
		anim.setDuration(3000);
		iv.setAnimation(anim);
		iv.startAnimation(anim);
	}
}

 

Load the resulting application to a device or the emulator to have a look (Figure C).

Figure C

 

AndroidProcessDialog_FigC_082713.png

 

It's not every day you want a big red sunburst in the middle of your application UI, but the point is you can put any image of any size there. You can apply any of Android's built-in animations, and adding floating text is as easy as instantiating a text view in the class constructor and pushing it into the layout.

Once you have a chance to play around with it, share your thoughts in the discussion thread.

 

 

About William J. Francis

William J Francis began programming computers at age eleven. Specializing in embedded and mobile platforms, he has more than 20 years of professional software engineering under his belt, including a four year stint in the US Army's Military Intellige...

[안드로이드] Event 처리 메커니즘

출처 : http://ecogeo.tistory.com/251 

안드로이드의 이벤트 처리 과정에 대한 글(http://blog.naver.com/osk1004?Redirect=Log&logNo=50069078782 )을 참조하여 나름대로 분석하여 메모한 결과를 적어본다.

개략적인 이벤트 처리 과정
  1. 액티비티 생성시 액티비티의 윈도우를 WindowManagerService에 등록해둠
  2. 이벤트 발생시 네이티브 라이브러리(EventHub)를 통해 이벤트 읽음
  3. 이벤트 큐(KeyInputQueue)에 이벤트 쌓임
  4. 이벤트 디스패치 쓰레드(InputDispatcherThread)는 이벤트큐에서 이벤트를 꺼내어
    WindowManagerService의 디스패치 메소드 호출
  5. WindowManagerService는 등록된 애플리케이션의 윈도우에 이벤트를 전달
  6. 이벤트를 전달받은 윈도우는 하위 UI 컴포넌트 트리를 찾아가며 리스너 콜백함수 실행


이벤트 전달을 위한 준비

WindowManagerService는 system_server 프로세스에서 실행중인 서비스이다. WindowManagerService에서 감지된 이벤트를 애플리케이션 프로세스의 UI 컴포넌트에 전달하기 위해서 둘 사이에 연결고리가 미리 만들어져 있어야 한다. 통신은 AIDL을 통해서 이루어진다.

애플리케이션의 윈도우를 WindowManagerService에 등록하는 과정

  1. ActivityManagerService는 ActivityThread를 호출하여 액티비티 런치.
    ActivityThread.performLaunchActivity()에서 Activity인스턴스 생성하고 activity.attach() 호출
  2. Activity는 attach()에서 PhoneWindow 객체 생성. 이 PhoneWindow는 액티비티내 뷰들의 root로서 DecorView 인스턴스 포함.

    mWindow = PolicyManager.makeNewWindow(this);
     
  3. ActivityManagerService는 ActivityThread를 호출하여 액티비티를 resume시킴.
    WindowManager 인스턴스가 생성되고 decorView가 WindowManager에 추가됨.

    ActivityThread.handleResumeActivity()
     
  4. WindowManager의 addView(decor)에서 ViewRoot 인스턴스를 생성하고 viewRoot.setView(decor) 호출
  5. viewroot.setView(decor)에서 IWindowSession을 통해 WindowManagerService에 IWindow인스턴스를 추가

    IWindowSession.add(window) 
     

DecorView 클래스
- FrameLayout을 상속받으며, PhoneWindow의 내부 클래스로 정의됨
- 표준 윈도우 프레임 및 데코레이션을 포함하는 최상위 윈도우 뷰
- 윈도우 매니저에 윈도우로서 추가됨

ViewRoot 클래스
- WindowManager와 View 사이의 protocol을 위한 구현 포함
- Handler를 상속받음
- IWindow 서비스 구현 클래스(W)를 내부 클래스로 포함 :  class W extends IWindow.Stub

관련 AIDL
IWindowSession.aidl : 애플리케이션 --> WindowManagerService

    int add(IWindow window, ... ...); // 윈도우를 WindowManagerService에 추가
    void remove(IWindow window);   

IWindow.aidl : WindowManagerService --> 애플리케이션

    void dispatchKey(in KeyEvent event); //이벤트를 애플리케이션에 전달
    void dispatchPointer(in MotionEvent event, ...);
    void dispatchTrackball(in MotionEvent event, ...);

KeyEvent.aidl, MotionEvent.aidl : 프로세스간 전달되는 이벤트 정보


이벤트 감지 및 디스패치
이벤트를 검출하고 애플리케이션으로 디스패치하는 로직은 WindowManagerService.java에 구현되어 있다. WindowManagerService는 InputDispatcherThread와 KeyInputQueue 구현 클래스를 이용하여 이벤트를 읽어들이고 적절한 윈도우에 전달하는 일을 한다.

WindowManagerService 클래스
- KeyInputQueue 구현 클래스(KeyQ) 및 InputDispatcherThread 클래스 포함
- WindowManagerService 인스턴스 생성시 KeyInputQueue 생성 및 InputDispatcherThread 쓰레드 시작
- InputDispatcherThread는 이벤트 타입에 따라 WindowManagerService의 디스패치 메소드 호출.

       dispatchKey(KeyEvent); // 예를들어 키보드 이벤트인 경우

- 디스패치 메소드는 현재 포커스를 가진 윈도우를 찾아 이벤트 전달

     mKeyWaiter.waitForNextEventTarget(); // WindowState 찾음
     windowState.mClient.dispatchKey(event); // windowState.mClient는 IWindow 객체

- IWindow 객체는 액티비티가 resume인 상태가 되면서 ViewRoot가 WindowServiceManager에 전달한 것

KeyInputQueue 클래스
- 안드로이드에서 진짜 이벤트 큐 역할
- 인스턴스 생성시 새로운 쓰레드가 시작되면서 native boolean readEvent() 메소드를 무한루프 호출.
- 리눅스 입력 디바이스로부터 실제 이벤트를 읽어들이는 로직은 네이티브 코드로 구현됨 : EventHub
- 이벤트 읽는 과정 

   KeyInputQueue.java -> JNI -> com_android_server_KeyInputQueue.cpp -> EventHub.cpp -> Device

InputDispatcherThread 클래스
- Event-Dispatch Thread 구현 클래스(?)
- 무한루프 돌면서 이벤트 큐에서 이벤트를 꺼내 WindowManagerService의 디스패치 메소드 호출

이벤트 유형
- 키보드 : RawInputEvent.CLASS_KEYBOARD
- 트랙볼 : RawInputEvent.CLASS_TRACKBALL
- 터치스크린 : RawInputEvent.CLASS_TOUCHSCREEN
- 설정 변경 : RawInputEvent.CLASS_CONFIGURATION_CHANGED

이벤트 정보를 담고 있는 핵심 클래스
- 키보드 이벤트 : KeyEvent
- 터치 or 트랙볼 이벤트 : MotionEvent


애플리케이션에서 이벤트 처리 과정(키 이벤트 중심)

이벤트를 전달받은 애플리케이션 윈도우는, 뷰 트리의 최상위부터 시작해서 실제 포커스를 가진 뷰까지 경로를 따라 이벤트를 디스패치한다.

  1. 이벤트가 발생하면 WindowManagerService는 이벤트 큐의 이벤트를 IWindow에 전달

    IWindow.dispatchKey(event);
     
  2. IWindow(ViewRoot.W 내부클래스가 구현)는 이벤트를 ViewRoot의 dispatchKey(event)에 다시 전달
  3. ViewRoot.dispatchKey()에서는 sendMessageAtTime(msg) 메소드를 통해 메시지 형태로 이벤트를 전달(왜 갑자기 여기서 Handler 메시지 형태로 이벤트를 전달하는가?)
  4. 보내진 이벤트 메시지는 Handler를 상속받은 ViewRoot의 handleMessage(Message)가 처리
  5. handleMessage()는 deliverKeyEventToViewHierarchy(event)를 호출
  6. deliverKeyEventToViewHierarchy()는 decor view의 dispatchKeyEvent(event) 호출

    mView.dispatchKeyEvent(event);
     
  7. decor view의 dispatchKeyEvent()에서는 현재 뷰에 리스너가 등록되어 있으면 현재 view의 리스너 콜백함수를 호출함(즉 드디어 이벤트가 처리됨)
  8. 등록된 리스너가 없으면 KeyEvent의 dispatch(callback) 호출 : callback은 view 자신
  9. KeyEvent.dispatch()는 다시 callback view의 onKeyDown() 호출 : 키 누름 이벤트인 경우
  10. view의 onKeyDown()은 setPressed() 호출 : setPressed() ->dispatchSetPressed()
  11. dispatchSetPressed()는 하위 View 클래스(예를들어 ViewGroup)에서 적절히 오버라이드됨
  12. ViewGroup의 dispatchSetPressed()에서는 자식 뷰들의 setPressed()를 호출
  13. 이런식으로 최종 타겟 UI 컴포넌트까지 이벤트가 디스패치됨


View 클래스
- KeyEvent.Callback 구현
- 주요 디스패치 메소드 :

    dispatchKeyEvent(KeyEvent event);
    dispatchTouchEvent(MotionEvent event);
    dispatchTrackballEvent(MotionEvent event);

ViewGroup 클래스
- XXXLayout 들의 부모 클래스
- dispatchSetPressed(boolean pressed) 메소드 코드 :

        final View[] children = mChildren;
        final int count = mChildrenCount;
        for (int i = 0; i < count; i++) {
            children[i].setPressed(pressed);
        }

출처 : http://www.coremodeling.com/android/tutorial/AppWidget/AppWidget.html

 

App Widget

  1. 작성자 : 고덕한(deokhan.koh@gmail.com)
  2. 소속 : 코아모델링(www.coremodeling.com)
  3. 작성일자 : 2011년 9월 22일

Android 홈페이지에 있는 App Widget 문서를 번역하면서 AppWidget 에 대한 개념과 개발하는 방법을 익히도록 합니다.

URL 은 http://developer.android.com/guide/topics/appwidgets/index.html 클릭하면 됩니다.

App Widget 은 Home Screen 에 보여지는 것과 같이 다른 Application 에 Embedded 될 수 있고 주기적으로 update 가 되는 미니어처 어플리케이션 View 라 할 수 있다. 이러한 View 들은 User Interface 에서 Widget 이라 일컬어진다. 그리고 App Widget Provider 를 사용하여 개발하여 설치가능하다. App Widget 을 포함한 어플리케이션 컴포넌트를 App Widget host 라 일컫는다. App Widget 은 아래와 같은 Music App Widget 같은 것을 말한다.

1. The Basics

App Widget 을 개발하기 위해서는 아래와 같이 따른다.

1.1 AppWidgetProviderInfo 객체

AppWidget 에 대한 metadata 를 표현하는 것으로써, App Widget 의 layout, update 주기, 그리고 AppWidgetProvider 클래스 등의 정보를 표시한다. 이러한 내용을 XML 파일에 정의해야만 한다.

위치는 /res/xml 디렉토리에 파일을 위치한다.

1.2 AppWidgetProvider 클래스구현

AppWidget 이 동작하기 위해서 AppWidgetProvider 를 상속받아서 구현해야 한다. AppWidget 으로써 동작하기 위해서 필요한 메소드를 Override 해야하며, 이는 Broadcast 이벤트를 수신하여 필요한 기능이 동작하기 위함이다. updated, enabled, disabled, 그리고 deleted 메소드를 Override 한다.

1.3 View layout

Layout XML 파일이며, Widget 이 초기에 보여기 위한 layout 파일이다.

추가적으로 App Widget 의 환경설정을 위한 Configuration Activity 를 추가할 수 있다. 이것은 옵션 사항으로써 AppWidget 에 처음 생성될 때 사용자가 AppWidget 에 환경을 설정하도록 지원하는 기능이다.

2. Declaring an App Widget in the Manifest

첫번째로 AppWidgetProvider 클래스를 AndroidManifest.xml 파일에 등록한다. 예제는 아래와 같다.

<receiver android:name="ExampleAppWidgetProvider" >

    <intent-filter>

        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />

    </intent-filter>

    <meta-data android:name="android.appwidget.provider"

               android:resource="@xml/example_appwidget_info" />

</receiver>

AppWidgetProvider 는 BroadcastReceiver 를 상속받아서 작성된 클래스이다. 따라서 AndroidManifest.xml 에 등록하려면, <receiver> 태그를 사용하여 등록을 한다.

위 예제에서 보듯이 <intent-filter> 안에 <action> element를 android.appwidget.action.APPWIDGET_UPDATE 를 추가한다. 이는 이 APPWIDGET_UPDATE action 에 대한 broadcast message 가 발생하면, 이 AppWigetProvider 가 동작하게끔 처리하는 것이다. AppWidgetManager 는 다른 모든 AppWidget 에게 broadcast message 를 필요한 경우에 자동으로 전송을 한다.

<meta-data> element 를 AppWidgetProviderInfo 에 해당하는 Resource 의 xml 파일을 지정한다.

3. Adding the AppWidgetProviderInfo Metadata

AppWidgetProviderInfo 는 xml 파일로 정의하며, App Widget 을 작성하기 위해서 반드시 필요한 파일이다. 이 XML 파일에는 initial layout resource, App Widget 의 upate 주기, 그리고 옵션으로 처음 생성 시점에 실행되는 configuration Activity 정보를 설정한다. XML 파일에 <appwidget-provider> element 로 정의하며, XML 파일은 /res/xml 디렉토리에 위치한다.

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"

    android:minWidth="294dp"

    android:minHeight="72dp"

    android:updatePeriodMillis="86400000"

    android:previewImage="@drawable/preview" <!-- android 3.0 이후에 추가 -->

    android:initialLayout="@layout/example_appwidget"

    android:configure="com.example.android.ExampleAppWidgetConfigure"

    android:resizeMode="horizontal|vertical"> <!-- android 3.1 이후에 추가 -->

</appwidget-provider>

다음은 각 attribute 에 대한 설명이다.

3.1 minWidth 와 minHeight

AppWidget layout 의 최소 폭과 높이의 값을 설정한다.

Home Screen 에 보여질 Widget 에 대한 높이와 폭을 지정하는 것이다. Home Screen 은 아이콘 크기의 Cell 형태로 이루어지져 있다. 따라서 Widget 의 폭과 높이를 지정할 때, HomeScreen 에 놓여질 Cell 의 크기를 기준으로 계산을 해야한다. 기본적인 Cell 의 크기는 74 dp 이며, 그 값을 계산하는 방식은 아래와 같다.

(number of cell * 74)  - 2

주의 : Home Screen 에서 Widget 이 가질 수 있는 최대의 Cell 의 갯수는 4 x 4 이다, 이보다 크게 Widget 의 크기를 디자인해서는 안된다.

3.2 updatePeriodMillis

AppWidget Framework 가 AppWidgeProvider.onUpdate() 메소드를 얼마나 자주 호출해야 하는지를 정의한다. 하지만 실제로 onUpdate() 가 정확한 시간에 호출되는지는 보증할 수 없다. 가능한한 제 시간에 호출되는 것으로 가정해야 하며, 어떨 때는 Battery 문제로 인하여  한시간에 한번도 호출되지 않을 수도 있다. 주로 사용자가 15분 주기 또는 1시간 주기등으로 설정한다.

주의 : updatePeriodMillis 를 설정해 놓으면 Device 가 sleep mode(주로 화면이 꺼진 상태) 로 되어있을 지라도 update 를 수행하기 위해서 Device 를 깨워서 동작을 한다. 이러한 작업이 1시간 주기로 동작하면, Battery 문제가 없지만, 자주 호출이 되면 Battery 를 많이 소모하게 된다. 따라서 Device 가 꺠어있는 상태에서만 동작하도록 하려면 updatePeriodMillis 의 값은 “0” 으로 설정하고, AlarmManager 를 사용하여 주기적으로 동작하도록 설정해야 한다. 이때 Alarm 의 Type 은 ELASPED_REALTIME 또는 RTC  로 설정하면 된다.

3.3 initialLayout

AppWidget layout 을 정의하기 위한 layout resource 를 지정한다.

3.4 configure

사용자가 App Widget 을 추가할 때 실행할 Activity 를 지정한다. 이 Activity 는 App Widget 의 환경설정을 하는데 주로 사용한다.

3.5 previewImage

App Widget 을 추가하기 위해서 Menu 를 선택하고 App Widget 목록에서 해당 Widget 에 대한 미리보기 이미지를 지정한다. 이 항목이 지정되지 않았을 경우에는 디폴트 Icon 으로 나타난다. 이 속성은 Android 3.0 부터 지원한다.

3.6 autoAdvanceViewId

해당 Widget host 에 의해서 auto-advanced 되어야 하는 App Widget subview 의 view ID 를 기술한다. 이 속성은 Android 3.0 부터 지원한다.

3.7 resizeMode

Home Screen 에서 Widget 의 폭과 높이에 대해서 Resize 할 것인지를 정의한다. 값은 “vertical”, “horizontal”, “none” 으로 설정한다. 이 속성은 Android 3.1 부터 지원한다.

4. Creating the App Widget Layout

Widget 이 처음 실행되었을 때, Home Screen 보여질 Layout 을 설정해야 한다. 우선 /res/layout 디렉토리에 Layout 을 생성해야 한다.

Layout 을 생성하는 것은 기존의 Layout 을 작성하는 것과 별반 차이가 없으나, Widget 에서는 사용할 수 있는 View 가 한정되어 있다.

Home Screen 에 보여지는 View 는 RemoteViews 에 기반하고 있으며, RemoteViews 하위에 디자인한 View 가 속하게 된다.

기존의 모든 layout class 들을 모두 지원하지는 않고, 아래의 클래스들을 지원한다.

FrameLayout, LinearLayout, Relativelayout

AnalogClock, Button, Chronometer, ImageButton, ImageView, ProgressBar, TextView, ViewFlipper

5. Using the AppWidgetProvider Class

AppWidgetProvider 클래스는 BroadcastReceiver 클래스를 상속받는다. 이로 인해서 App Widget broadcast message 손쉽게 처리할 수 있다. AppWidgetProvier 클래스는 AppWidget 에 관련된 broadcast message 만 수신한다. 이 메시지는 updated, deleted, enabled, 그리고 disabled 이다. 이 메시지를 받을 때마다 이에 관련된 다음 메소드들이 호출된다.

5.1 onUpdate()

이 메소드는 AppWidgetProviderInfo 로 지정된 XML 파일에서 updateMillis 속성에 정의된 주기로 호출된다. 또한 이메소드는 사용자가 Home Screen 에서 App Widget 을 추가했을 때 호출된다. 이때 View 에 이벤트 핸들러를 추가하거나 임시 Service 를 호출하는 등의 필요한 초기 설정 작업을 수행해야 한다.

하지만 configuration Activity 가 정의된 경우에는 사용자가 Home Screen 에 App Widget 을 추가할 때, 이 메소드는 호출되지 않는다. 단지 주기적으로 호출될 때 실행된다. 따라서 Activity 를 지정하였을 경우에는, Configuration 을 완성하기 위해서 Activity 에서 onUpdate() 메소드를 처음에 호출하도록 구현해야 한다.

5.2 onDeleted(Context, int[])

App Widget host 에서 삭제될 때 호출된다.

5.3 onEnabled(Context)

App Widget 이 처음으로 instance 가 생성될 때 호출된다. 예를 들어 사용자가 두 개의 App Widget instance 를 추가한다 하더라도, 처음에 한번만 호출이 된다. 이 메소드에 초기에 필요한 작업들을 구현한다. 주로 데이터베이스 설정같은 작업을 구현한다.

5.4 onDisabled(Context)

App Widget host 에서 마지막 App Widget instnace 가 삭제될 때 호출된다. 이 메소드에서는 onEnabled() 에서 초기화된 작업을 모두 제거하는 기능을 주로 구현한다.

onDeleted() 는 여러개의 Instance 중에서 각각을 삭제할 때 호출되지만, onDisabled() 는 마지막 Instance 가 삭제될 때 호출된다.

5.5 onReceive(Context, Intent)

위의 메소드가 호출되기 이전에 먼저 호출된다. 일반적으로 이 메소드를 구현할 필요는 없으며, 공통적으로 처리할 내용이 있을 경우에 구현한다.

AppWidgetProvider 에서 가장 중요한 메소드가 onUpdate() 이다. 왜냐하면 이 메소드는 사용자가각각의  App Widget 을 host 에 추가할 때 호출되기 때문이다. 만약 App Widget 이 사용자의 Event 를 수용한다면, 이 메소드에서 Event handler 를 등록해야 한다. 아래 코드는 onUpdate() 메소드에서 Click 이벤트를 등록하는 코드이다.

public class ExampleAppWidgetProvider extends AppWidgetProvider {

    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {

        final int N = appWidgetIds.length;

        // 이 Provider 에 속하는 각각의 App Widget 에 대해서 순차적으로 Loop 을 수행

        for (int i=0; i<N; i++) {

            int appWidgetId = appWidgetIds[i];

            // ExampleActivity 를 실행할 Intent 를 생성

            Intent intent = new Intent(context, ExampleActivity.class);

            PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);

            // 버튼에 onClick listener 를 설정하기 위해서 App Widget 에 대한 layout 의 참조를 얻는다.

            RemoteViews views = new RemoteViews(context.getPackageName(), 

                                                                                  R.layout.appwidget_provider_layout);

            views.setOnClickPendingIntent(R.id.button, pendingIntent);

            // AppWidgetManager 이 현재 App Widget 에 update 를 수행하도록 처리한다.

            appWidgetManager.updateAppWidget(appWidgetId, views);

        }

    }

}

위 소스의 내용을 설명하자면, Activity 를 실행하기 위해서 PendingIntent 를 사용한다. 또한 버튼에 클릭이벤트를 OnClickPendingIntent 로 지정한다. 그리고 하나의 App Widget 에 여러개의 Instance 를 생성했을 경우( Home Screen 에 똑같은 Widget 을 두개 이상 추가했을 경우) 에 모든 Widget 에 동일한 효과를 주기 위해서 Loop 을 사용하여 설정하였다.

주의 : AppWidgetProvider 는 BroadcastReceiver 클래스를 상속받았기에, 시간이 많이 소요되는 작업은 그 처리 결과를 보증할 수 없다. 따라서 시간이 많이 걸리는 작업은 별도의 Service 를 만들어서 실행해야 한다.

5. 7 Receiving App Widget broadcast Intents

AppWidgetProvider 클래스는 BroadcastReceiver 클래스를 상속받아서 편리하게 사용하기위해 작성된 클래스이다. 따라서 BroadcasetRecevier 로 구현하듯이 작성한 후에, 아래의 Intent 를 사용하면 된다.

  1. ACTION_APPWIDGET_UPDATE
  2. ACTION_APPWIDGET_DELETED
  3. ACTION_APPWIDGET_ENABLED
  4. ACTION_APPWIDGET_DISABLED

6. Creating an App Widget Configuration Activity

사용자가 App Widget 을 처음 만들고 나서, App Widget 에 대한 환경설정을 하기 위해서는 App Widget Configuration Activity 를 생성할 수 있다. 이 Activity 는 App Widget host 에 의해서 자동으로 실행되며, 사용자가 App Widget 을 처음 설치할 때 설정을 할 수 있도록 하는 것이다. 이 Activity 로 App Widget 에 대한 색, 크기, 업데이트 주기 또는 다른 설정들을 할 수 있다.

Configuration Activity 는 일반적인 다른 Activity 처럼 AndroidManifest.xml 에 등록이 되어야 하며, “ACTION_APPWIDGET_CONFIGURE” action 으로 실행되어진다. 아래 예제와 같이 작성하면 된다.

<activity android:name=".ExampleAppWidgetConfigure">

    <intent-filter>

        <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>

    </intent-filter>

</activity>

또한 이 Activity 는 AppWidgetProviderInfo XML 파일에 android:configure 항목에 정의가 되어야 한다. 아래와 같이 작성한다.

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"

    ...

    android:configure="com.example.android.ExampleAppWidgetConfigure"

    ... >

</appwidget-provider>

주의 : Activity 를 정의할 때, fully-qualified namespace 를 사용하여 정의해야 한다.

지금까지 Activity 를 설정하는 것을 살펴보았으며, 설정은 이것으로 간단하게 처리할 수 있다. 하지만 Activity 내에서는 두가지 중요한 기능을 구현해야 한다.

  1. App Widget host 에서 Configuration Activity 를 실행할 때, Activity 는 result 를 리턴 받는다. result 는 Intent 로 받으며, 이 Intent 에 App Widget ID 값이 저장되어서 리턴받는다. Intent 에 EXTRA_APPWIDGET_ID 값으로 저장되어 있다.
  2. App Widget 이 생성될 때, onUpdate() 메소드가 호출되지 않는다. Configuration Activity 가 실행될 때 시스템에서 ACTION_APPWIDGET_UPDATE broadcast message 를 전송하지 않는다. 이것은 App Widget 이 처음으로 생성될 때, Configuration Activity가 AppWidgetManager 에서 update 를 요청해야하는 책임이 있다는 것이다. 즉, onUpdate() 메솓느는 처음에는 호출되지 않고, 지속적인 update 에서 호출된다.

6.1 Updating the App Widget from the configuration Activity

App Widget 이 configuration activity 를 사용할 때, 설정이 완료되어질 때, Activity 에서는 App Widget 이 update 되는 책임이 있다. AppWidgetManager 에서 직접 update 를 요청할 수 있다.

다음은 적절히 App Widget 을 update 하는 절차와 Activity 완료하는 절차를 요약했다.

6.1.1 첫번쨰, 실행되어진 Activity 에서 Intent 로부터 App Widget ID 를 얻는다.

Intent intent = getIntent();

Bundle extras = intent.getExtras();

if (extras != null) {

    mAppWidgetId = extras.getInt(

            AppWidgetManager.EXTRA_APPWIDGET_ID,

            AppWidgetManager.INVALID_APPWIDGET_ID);

}

6.1.2 App Widget 환경설정을 수행한다.
6.1.3 환경설정이 완료되었을 때, getInstance(Context) 메소드를 호출하여 AppWidgetManager 의 객체를 얻는다.

AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);

6.1.4 updateAppWidget(int, RemoteViews) 메소드를 호출하여 RemoteViews layout 을 사용하여 App Widget 화면을 업데이트 한다.

RemoteViews views = new RemoteViews(context.getPackageName(),

R.layout.example_appwidget);

appWidgetManager.updateAppWidget(mAppWidgetId, views);

6.1.5 마지막으로 리턴할 Intent 를 생성하고, Activity result 에 설정하고, Activity 를 종료한다.

Intent resultValue = new Intent();

resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);

setResult(RESULT_OK, resultValue);

finish();

팁 : configuration Activity 가 처음 실행될 때, Activity result 를 RESULT_CANCELED 로 설정한다. 이는 사용자가 최종적으로 완료되기 전에 취소할 경우 App Widget host 에서 환경설정이 최소되었다는 것을 알아야 하고, App Widget 이 추가되지 않는다.

7. Setting a Preview Image

Android 3.0 에서 previewImage 속성을 AppWidgetProviderInfo XMl 에 추가하였다. 이 항목은 Home Screen 에서 Widget 을 추가할 때, Widget 을 선택할 수 있는 목록에서 보여질 Preview 내용을 나타내는 것이다. 다음과 같이 XML 에 설정을 한다.

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"

  ...

  android:previewImage="@drawable/preview">

</appwidget-provider>

8. Using App Widgets with Collections

Android 3.0 에서는 Collection 을 포함한 App Widget 을 새로 추가했다. 이 AppWidget 은 백그라운드에 있는 Collection으로 된 Remote Data 를보여주기 위해서 RemoteViewsService 를 사용한다. 이 collection data 는 아래의 collection view 에 의해서 보여진다.

  1. ListView : Vertically scrolling list 를 보여주는 View
  2. GridView : two-dimensional scrolling grid 형태로 item 을 보여주는 View
  3. StackView : 마치 카드처럼 아래/위로 밀어서 내용을 보여주는 View
  4. AdapterViewFlipper : Adapter 기반으로 되어 있으며, 여러개의 View 를 애니매이션처리하는 ViewAnimator

위에서 언급했듯이, Remote data 를 Collection view 에 보여지기 위해서는 Adapter 를 사용해서 UI 에 bind 시켜야 한다. Adapter 각각의 Item 들을 개별적인 View 에 bind 시켜야 한다. Android Framework 에서는 app widget 에 이 데이터들을 bind 시켜야 하며, Adapter 가 이러한 역할을 수행해야 할 것을 RemoteViewFactory 가 대신 하고 있다.

Collection 에서 특정 item 이 요청될 때, 이 RemoteViewFactory 를 생성하고 해당 Item 에 대해서 RemoteViews 객체를 리턴한다. app widget 에 collection view 를 포함하기 위해서는 반드시 RemoteViewsService 와 RemoteViewsFactory 를 구현해야 한다.

RemoteViewsService 는 Service로써 RemoteViews 객체를 요청하는 원격 adapter 역할을 수행한다. RemoteViewsFactory 는 collection view 와 view 에 보여질 데이터 사이의 adpater 를 위한 interface 이다.

아래 예제코드를 참고한다.

public class StackWidgetService extends RemoteViewsService {

    @Override

    public RemoteViewsFactory onGetViewFactory(Intent intent) {

        return new StackRemoteViewsFactory(this.getApplicationContext(), intent);

    }

}

class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {

//... include adapter-like methods here. See the StackView Widget sample.

}

http://blog.naver.com/PostView.nhn?blogId=huewu&logNo=110099015747&parentCategoryNo=&categoryNo=&viewDate=&isShowPopularPosts=false&from=postView

http://blog.daum.net/hopefullife/226

- Eclipse 자주 쓰는 단축키 -

- Eclipse 자주 쓰는 단축키 -

 

----- 실행 -----

Ctrl + F11 : 바로 전에 실행했던 클래스 실행

 

----- 소스 네비게이션 -----

Ctrl + 마우스커서(혹은 F3) : 클래스나 메소드 혹은 멤버를 상세하게 검색하고자 할때

Alt + Left, Alt + Right : 이후, 이전

Ctrl + O : 해당 소스의 메소드 리스트를 확인하려 할때

F4 : 클래스명을 선택하고 누르면 해당 클래스의 Hierarchy 를 볼 수 있다.


Alt + <-(->) : 이전(다음) 작업 화면

 

----- 문자열 찾기 -----

Ctrl + K : 찾고자 하는 문자열을 블럭으로 설정한 후 키를 누른다.

Ctrl + Shift + K : 역으로 찾고자 하는 문자열을 찾아감.

Ctrl + J : 입력하면서 찾을 수 있음.

Ctrl + Shift + J : 입력하면서 거꾸로 찾아갈 수 있음.

Ctrl + F : 기본적으로 찾기

 

----- 소스 편집 -----

Ctrl + Space : 입력 보조장치(Content Assistance) 강제 호출 => 입력하는 도중엔 언제라도 강제 호출 가능하다.

F2 : 컴파일 에러의 빨간줄에 커서를 갖져다가 이 키를 누르면 에러의 원인에 대한 힌트를 제공한다.

Ctrl + L : 원하는 소스 라인으로 이동

   로컬 히스토리 기능을 이용하면 이전에 편집했던 내용으로 변환이 가능하다.

Ctrl + Shift + Space : 메소드의 가로안에 커서를 놓고 이 키를 누르면 파라미터 타입 힌트를 볼 수 있다.

Ctrl + D : 한줄 삭제

Ctrl + W : 파일 닫기

Ctrl + I : 들여쓰기 자동 수정

Ctrl + Shift + / : 블록 주석(/* */)

Ctrl + Shift + \ : 블록 주석 제거

Ctrl + /여러줄이 한꺼번에 주석처리됨. 주석 해제하려면 반대로 하면 된다.

Alt + Up(Down) : 위(아래)줄과 바꾸기

Alt + Shift + 방향키 : 블록 선택하기

Ctrl + Shift + Space : 메소드의 파라메터 목록 보기

Ctrl + Shift + O : 자동으로 import 하기

Ctrl + Shift + F4 : 열린 파일 모두 닫기

Ctrl + M : 전체화면 토글

Ctrl + Alt + Up(Down) : 한줄(블럭) 복사

Ctrl + , or . : 다음 annotation(에러, 워닝, 북마크 가능)으로 점프

Ctrl + 1 : 퀵 픽스

F3 : 선언된 변수로 이동, 메소드 정의부로 이동

Ctrl + T : 하이어라키 �b업 창 띄우기(인터페이스 구현 클래스간 이동시 편리)

Ctrl + O : 메소드나 필드 이동하기

Ctrl + F6 : 창간 전환, UltraEdit  Editplus Ctrl + Tab 과 같은 기능

 

----- 템플릿 사용 -----

sysout 입력한 후 Ctrl + Space 하면 System.out.println(); 으로 바뀐다.

try 입력한 후 Ctrl + Space 하면 try-catch 문이 완성된다.

for 입력한 후 Ctrl + Space 하면 여러가지 for 문을 완성할 수 있다.

템플릿을 수정하거나 추가하려면 환경설정/자바/편집기/템플릿 에서 할 수 있다.

 

----- 메소드 쉽게 생성하기 -----

클래스의 멤버를 일단 먼저 생성한다.

override 메소드를 구현하려면, 소스->메소드대체/구현 에서 해당 메소드를 체크한다.

기타 클래스의 멤버가 클래스의 오브젝트라면, 소스->위임메소드 생성에서 메소드를 선택한다.

 

----- organize import -----

자바파일을 여러개 선택한 후 소스->가져오기 체계화 해주면 모두 적용된다.

 

----- 소스 코드 형식 및 공통 주석 설정 -----

환경설정 -> 자바 -> 코드 스타일 -> 코드 포멧터 -> 가져오기 -> 프로파일.xml 을 불러다가 쓰면 된다.

또한 다수의 자바파일에 프로파일을 적용하려면 패키지 탐색기에서 패키지를 선택한 후 소스 -> 형식화를 선택하면 된다.

환경설정 -> 자바 -> 코드 스타일 -> 코드 템플리트 -> 가져오기 -> 템플리트.xml 을 불러다가 쓰면 된다.

 

----- 에디터 변환 -----

에디터가 여러 파일을 열어서 작업중일때 Ctrl + F6 키를 누르면 여러파일명이 나오고 F6키를 계속 누르면 아래로

Ctrl + Shift + F6 키를 누르면 위로 커서가 움직인다.

Ctrl + F7 : 뷰간 전환

Ctrl + F8 : 퍼스펙티브간 전환

F12 : 에디터로 포커스 위치

 

 

 

 

 

- 이클립스 자주쓰는 단축키 -

 

Ctrl + / : 주석 처리 - 한 라인/블록에 대해 주석 처리 (추가 및 제거)

Ctrl + L : 특정 라인으로 이동

Ctrl + F6 : Editor 창간의 이동

Ctrl + F7 : View 이동 메뉴

Ctrl + F8 : Prespectives 이동 메뉴

Ctrl + D : 한라인 삭제 - 커서가 위치한 라인 전체를 삭제 한다.

Ctrl + J : Incremental find 이클립스 하단 상태 표시줄에 Incremental find 라고 표시되어 한 글자자씩 누를 때 마다 코드내의 일치하는 문자열로 이동 , 다시 Ctrl + J 를 누르면 그 문자열과 일치 하는 부분을 위/아래 방향키로 탐색이 가능하다.

Ctrl + N : 새로운 파일 / 프로젝트 생성

Ctrl + 1 (빠른교정) - 문 맥에 맞게 소스 교정을 도와 준다. 변수를 선언하지 않고 썼을경우 빨간색 에러 표시되는데 이 단축키를 적용하면 변수에 맞는 선언이 추가 되도록 메뉴가 나타난다.

Ctrl + 0 : 클래스 구조를 트리로 보기

Ctrl + Space :  Cotent Assist - 소스 구문에서 사용 가능한 메소드, 멤버들의 리스트 메뉴를 보여준다.

Ctrl + PageUp , Ctrl + PageDown : Edit 창 좌우 이동 - Edit 창이 여러개 띄워져 있을경우 Edit 창간의 이동 한다.

Ctrl + Shift + Down : 클래스 내에서 다음 멤버로 이동

Ctrl + Shift + M : 해당 객체의 Import 문을 자동 생성 - import 추가 할 객체에 커서를 위치 시키고 단축키를 누르면 자동적으로 import 문이 생성

Ctrl + Shift + O : import 문을 자동 생성 - 전체 소스 구문에서 import 안된 클래스의 import 문을 생성해 준다.

Ctrl + Shift + G : 해당 메서드 / 필드를 쓰이는 곳을 표시 - View 영역에 Search 탭에 해당 메서드 / 필드를 사용하는 클래스를 표시 해준다.

Alt + Shift + R : Refactoring (이름변경) - Refactoing 으로 전체 소스에서 이름변경에 의한 참조 정보를 변경해 준다.

F3 : 선언 위치로 이동

F11 : 디버깅 시작

F8 : 디버깅 계속

F6 : 디버깅 한줄씩 실행(step over)

F5 : 디버깅 한줄씩 실행 함수 내부로 들어감 (step into)

F12 : Editor 창으로 이동 (Debugging 등 자동적으로 포커스가 이동 됐을경우 편리)

Alt + Up , Alt + Down : 줄 바꿈 - 해당 라인을 위 / 아래로 이동 시킨다.

Alt + Shift + S : Source Menu - 소스메뉴 (Import 추가 , Comment 추가 , 각종 Generator 메뉴) 가 나타난다.

Alt + Shift + Up : 블록설정 - 소스 코드를 블록 단위로 설정해 준다.

Alt + Shift + Down : 블록해제 - 소스 코드를 블록 단위로 해제한다.

Alt + Shift + J : 주석 생성 - 해당 메서드/클래스에 대한 주석을 템플릿을 생성해 준다.

sysout + (Ctrl + Space) : System.out.println() 문장 삽입 - 코드 템플릿을 이용해서 소스 구문을 추가

(Windows -> Preferences -> JAVA -> Editor -> Templates 에서 자주 쓰는 소스 구문을 추가시키면 <템플릿 이름> + (Ctrl + Space) 로 소스 문장을 완성 시킬 수 있다.)

Alt + Shift + Z : Surround With 메뉴 - try / catch 문이나 for , do , while 등을 해당 블록에 감싸주는 메뉴가 나타난다.

Ctrl + Shift + F : 코드 포맷팅 - 코드 내용을 문법 템플릿에 맞게 포맷팅(들여쓰기) 해준다.

Ctrl + Alt + Down: 한줄 복사후 아래에 복사 넣기 - Copy&Paste 대체하는 단축키. 커서가 위치한 라인을 복사해 밑줄에 생성해 준다.

Ctrl + Shift +X : 대문자로 변환

Ctrl + Shift + Y : 소문자로 변환

Ctrl + Shift + L : 모든 단축키의 내용을 표시해준다.

Ctrl + Shift + B : 현재 커서 라인에 Break point 설정

Ctrl + Shift + T : 클래스 찾기

 

http://arabiannight.tistory.com/trackback/346

+ Recent posts