블로그 이미지
엡뽀
피난(?) 오신걸 환영합니다.

calendar

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

Notice

2012. 12. 20. 13:17 Programing/Android

2. 리스트 View

이번엔 리스트 View를 만들어 볼껀데요. 별다른거 없이. STATE BAR, ACTION BAR, LISTVIEW, NAVIGATION BAR로 화면 구성을 하도록 하겠습니다. 


- ListViewActivity -


최종 프로젝트의 목적은 하나의 Activity 에 두개의 View를 만들어서 네비게이션 바를 통해 화면 전환이 일어나도록 하는 것이지만, 우선은 새로운 Activity를 만들어서 MainActivity에서 ACTION BAR -> ORDER ACTION 버튼으로 화면 전환이 일어나도록 하겠습니다. 반대로 ListActivity 에서는 홈버튼을 누르면 MainActivity로 되돌아가는(하지만 사실상 ActivityStack에 의하여 back키 한번만 눌러도 되죠 ㅎㅎ)식으로 구성하겠습니다. 


또한 기본 ListView를 그대로 사용하는 것보다 오픈소스를 이용하여 아래로 스크롤시 아이템이 추가 되는 리스트를 사용하여 화면 구성을 하도록 하겠습니다. 


▶ android-pulltorefresh 오픈소스.

 URL : https://github.com/johannilsson/android-pulltorefresh

(또 다시 오픈 소스를 프로젝트에 추가를 해야하는군요... 그렇습니다, 또 다시 복사 붙여넣기!!!)



파일 다운로드 및 압축 풀기.




다운로드를 풀게 되면, pulltorefresh폴더와 pulltorefreshexample 폴더가 나오게 되는데 이중 pulltorefresh 폴더 내용물들을 복사하여 프로젝트에 붙여넣기 하시면 됩니다. 



res\drawable



res\drawable-hdpi (전체 붙여넣기)



res\drawable-ldpi (전체 붙여넣기)



res\drawable-mdpi (전체 붙여넣기)



res\layout (전체 붙여넣기)



res\values

strings.xml 파일은 프로젝트에 존재하니깐 이번에도 내용 복사로 하겠습니다.



res\values\strings.xml

    <string name="pull_to_refresh_pull_label">Pull to refresh...</string>
    <string name="pull_to_refresh_release_label">Release to refresh...</string>
    <string name="pull_to_refresh_refreshing_label">Loading...</string>
    <string name="pull_to_refresh_tap_label">Tap to refresh...</string>



src\com\markupartist\android\widget 

(소스 파일은 기존에 추가 하였던 com.markupartist.android.widget 패키지에 넣으시면 됩니다.)


이것으로 android-pulltorefresh 오픈 소스를 사용할 준비가 다 되었구요. 새로운 Activity와 레이아웃 파일을 만들어 보도록 하겠습니다. 


- activity_list.xml -

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

    <com.markupartist.android.widget.ActionBar
        android:id="@+id/actionbar"
        style="@style/ActionBar" />

    <com.markupartist.android.widget.PullToRefreshListView
        android:id="@+id/android:list"
        android:layout_width="fill_parent"
        android:layout_height="0dip"
        android:layout_weight="1" />

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="48dip"
        android:background="#a0ff0000"
        android:gravity="center"
        android:text="@string/navigation"
        android:textColor="#000000"
        android:textSize="22sp" />

</LinearLayout>

레이아웃 파일에서 리니어레이아웃을 최상위로 잡고, actionbar, listview, textview를 추가하였습니다.
여기서 하나 짚고 넘어가야하는 부분이, com.markupartist.android.widget.PullToRefreshListView 뷰의 id 설정 부분을 보시면 

android:id = "@+id/android:list" 

로 되어있는데요. 이는 activity를 만들때 ListActivity 클래스를 상속받아 만들기 위해서 지켜야하는 약속(?) 같은 것입니다. ListActivity 클래스는 Listview를 꼭 포함해야하며, Listview의 id가 android:list 값을 가져야합니다. (Android Developers 참조

하지만 사실상 Activity로 만든 다음에 findViewByID 메소드를 이용해서 list 객체를 얻어와도 상관없지만, 오픈소스의 예제를 충실히 따르기 위해서 id값을 저렇게 설정 하도록 하겠습니다. 



- ListViewActivity.java -

public class ListViewActivity extends ListActivity {
	//리스트 아이템.
	private String[] mStrings = {
            "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam",
            "Abondance", "Ackawi", "Acorn", "Adelost", "Affidelice au Chablis",
            "Afuega'l Pitu", "Airag", "Airedale", "Aisy Cendre",
            "Allgauer Emmentaler"};
	private LinkedList<String> mListItems;    //adapter 데이터 객체.
	
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_list);
		
                 //action bar 객체 얻기. 
		final ActionBar actionBar = (ActionBar) findViewById(R.id.actionbar);
        actionBar.setTitle("ListView");  //action bar 타이틀 설정.
        
        //action bar에 홈 action 설정. 
        actionBar.setHomeAction(new IntentAction(this, MainActivity.createIntent(this), R.drawable.ic_title_home_default));
        actionBar.setDisplayHomeAsUpEnabled(true); //action bar에 홈 버튼 보이기
        
         //OnRefreshListener 리스너 설정.
        ((PullToRefreshListView) getListView()).setOnRefreshListener(new OnRefreshListener() {
            public void onRefresh() {
                // Do work to refresh the list here.
                new GetDataTask().execute(); //Task 실행.
            }
        });
        
        mListItems = new LinkedList<String>(); //adapter 데이터 객체 생성
        mListItems.addAll(Arrays.asList(mStrings)); //데이터 설정
        
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, mListItems); //adapter 생성. 

        setListAdapter(adapter); //리스트에 어뎁터 설정.
        
	}
	
	//데이터 추가 Task
	private class GetDataTask extends AsyncTask<Void, Void, String[]> {

        protected String[] doInBackground(Void... params) {
            // Simulates a background job.
            try {
                Thread.sleep(2000); //2초동안 프로세스 중지.
            } catch (InterruptedException e) {
                ;
            }
            return mStrings; //onPostExecute 함수에 넘겨줄 데이터 리턴.
        }

        protected void onPostExecute(String[] result) {
            mListItems.addFirst("Added after refresh..."); //"Added after refresh..." 데이터 추가
            // Call onRefreshComplete when the list has been refreshed.
            ((PullToRefreshListView) getListView()).onRefreshComplete(); //변경 완료.

            super.onPostExecute(result);
        }
    }

}



ListViewActivity 코드에선 두가지 정도만 짚고 넘어가면 될 것 같습니다. 홈 action과 listview. 


1. action bar의 홈 action 

홈 action을 설정하는 코드를 보게 되면, 

actionBar.setHomeAction(new IntentAction(this, MainActivity.createIntent(this), R.drawable.ic_title_home_default));

로 되어있는데요. IntentAction 이라는 객체는 Context, intent, int를 매개변수로 받는 생성자를 가지고있습니다. 여기서 intent를 넘겨줄때 MainActivity의 static 메소드를 호출하여, 인텐트를 넘겨주고있습니다.

- MainActivity.java -

    public static Intent createIntent(Context context) {
        Intent i = new Intent(context, MainActivity.class);
        i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        return i;
    }


자 그럼 여기서, 홈 acion, 즉 홈키를 누르면 뒤로 가야하는데, 왜 인텐트를 생성해서 넘겨주느냐? 하는 문제점이있는데요. 여기에서 제가 짚고 넘어가고 싶었던 인텐트의  속성(?)이 키워드입니다.

만약 소스코드에서 intent에 addFilags 를 하지않았다고 가정하게되면, ActivityStack이 아래와 같이 될것입니다. 

(출처 : 휴휴휴님 블로그)

즉, 뒤로 가기와 같은 효과가 아니라 새로운 Activity가 하나더 생성되게 되는거죠. 이러한 문제점을 intent의 flag로 해결할 수 있습니다. 


아래는 intent에 FLAG_ACTIVITY_CLEAR_TOP이라는 FLAG를 사용한 ActivityStack입니다. 



FLAG_ACTIVITY_CLEAR_TOP 플레그는 실행하고자 하는 Acitivity가 존재할 경우, 해당 Activity 위에있는 모든 activity를 종료시켜 줍니다. 따라서 홈으로 돌아가는 듯한 효과를 받게 되는 거죠. 이 FLAG 외에도 여러가지 FLAG가 존재 하는데요. 휴휴휴님의 블로그에서 자세히 소개 되고있습니다. (안드로이드 알아두면 요긴한 FLAG_ACTIVITY 네가지 :: http://huewu.blog.me/110087045138?Redirect=Log&from=postView )


2. android-pulltorefresh

오픈소스의 listview  "setOnRefreshListener"라는 메소드를 통해서 유저가 새로고침을 하게 될 경우 해야할 작업을 실행 할 수 있도록 해줍니다. 하지만 여기서 OnRefreshListener 리스너는 실행완료까지 자동으로 해주는 것은 아닙니다. 실제 작업이 완료된 이후에. listview의 onRefreshComplete() 메소드를 호출해주어야하죠.

이 소스코드에선 setOnRefreshListener 메소드를 통해 GetDataTask 를 실행하는 OnRefreshListener 를 구현한 임시 객체를 넘겨주고, 사용자가 새로고침(스크롤이 맨위로 올라가있는 상황에서 아래로 내렸을때) GetDataTask를 실행합니다.

GetDataTask 클래스는 AsyncTask 클래스를 상속받은 객체이며, doInBackground 메소드에선 하는 일없이, 2초간 쓰레드를 멈추후 작업을 종료합니다. 작업이 종료되면 onPostExecute 메소드가 호출되게 되는데 이때 adapter에서 사용하는 객체의 맨 처음 부분에 "Added after refresh..."라는 데이터만 추가한뒤에 listview의 onRefreshComplete() 메소드를 호출합니다.


여기까지가 두번째 Acitivity를 생성하여 호출하는 작업입니다. 마지막으로 Activity를 추가하였으니, 매니페스트 파일을 수정하여줍니다. 


- AndroidManifest.xml -

    <activity
            android:name=".ListViewActivity"
            android:label="@string/title_activity_list" >
    </activity>


(위 부분을 application 태그 안에다 추가 해주시면 됩니다. )


여기까지가, 기본뷰를 만들고, Activity를 추가하여 listview를 만드는 과정이었습니다. 여기까지 된 전체 소스를 올려드리도록 하겠으며, 다음 포스팅에선 두개의 Activity로 되어있는 구성을 하나의 Activity로 구성하면서, Tabbar로 두개의 화면을 보여줄수 있도록 수정하는 작업을 하도록 하겠습니다. 


현재 까지 작업된 전체 소스 파일.

AndroidUI.zip







posted by 엡뽀
2012. 12. 2. 00:58 낙서장

최근 Android 관련 몇가지를 포스팅 하기 시작하였는데.. 분명 누군가 들어오는 것 같다. 나 이외에 아직 들어올 만한 사람이 없는데 들어오고 있다. 확실하다. 


하지만 모든 글에 댓글 0,  방명록도 0


하하하하하하하하하하하하하하하 희뱀

'낙서장' 카테고리의 다른 글

블로그의 시작  (0) 2012.11.28
posted by 엡뽀
2012. 11. 29. 16:50 Programing/Android


1. 기본 View 만들기.

기본 View를 만들기 전에 Example 그림을 다시 한번 보면서 어떤 어떤 View들이 들어가있느지 부터 확인을 해 보겠습니다. 


Example


STATUS BAR, ACTION BAR, TextView, EditText, ImageView(혹은 ImageButton), Spinner, Button NAVIGATION BAR
구성이 되어있네요. 


여기서 STATUS BAR, ACTION BAR는 API 4.0이상으로 빌드 타겟으로 프로젝트를 생성한다면 다른 레이아웃 수정없이 자동적으로 구성이 됩니다. 하지만 여기서 짚고 넘어가야할게 사실상 4.0 이상 버젼보다 2.2(프로요)와 2.3(진져브레드) 가 더 많지요.


VersionCodenameAPI

Distri

1.5Cupcake30.1%
1.6Donut40.3%
2.1Eclair73.1%
2.2Froyo812%
2.3 - 2.3.2Gingerbread90.3%
2.3.3 - 2.3.71053.9%
3.1Honeycomb120.4%
3.2131.4%
4.0.3 - 4.0.4Ice Cream Sandwich1525.8%
4.1Jelly Bean162.7%







(출처 : http://developer.android.com/about/dashboards/index.html)


물론 앱의 빌드 타겟 대상은 개발자 마음대로라 하시고 싶으신 대로 하면됩니만, 제 개인적인 판단으로는 4.0이상으로 해서 현재 약 65%되는 사용자들을 놓치는 것보단 2.2로 빌드하여 많은 사용자들이 이용 할 수 있도록 하는 주의 입니다. 

그럼 여기서 ACTION BAR가 2.2에선 사용 할 수 없는 문제가 발생합니다. 그냥 텍스트 뷰를 ACTION BAR의 크기처럼 만들어도 상관은 없겠지만,  ACTION BAR를 하위 버젼에서도 사용할 수 있는 Open source가 있습니다.


* android-actionbar Open source

URL : https://github.com/johannilsson/android-actionbar



이렇듯 오픈 소스로 이클립스에서 git 연동하여 자신의 프로젝트에 해당 소스를 첨부하여 사용가능한듯 한듯 하나 제가 아직 사용할 줄 몰라서 ㅜㅜ (차후에 공부를 해서;; 이클립스와 git 연동 관련해서 포스팅을 하도록 하겠습니다.ㅜㅜ)


그리하여 제가 한 방법은 소스파일을 다운로드해서 그냥 프로젝트에다 붙여넣기!! ㅎㅎㅎㅎㅎ
우선 AndroidUI 라는 프로젝트를 생성한 후에 다운로드 한 소스파일을 붙여넣는거죠. (프로젝트 생성은 다들 아실꺼라 믿고 그냥 넘어가겠습니다. ㅎㅎ)


76 commits 라고 되어있는 윗부분에 보시면 Downloads 라는 부분이있습니다. 해당 페이지로 가시면 zip 파일 또는 tar.gz 파일로 다운을 받을 수가 있는데, zip 파일을 다운 받은 후 압축풀어서 res에있는 레이아웃 파일이든, 이미지 파일이든 혹은 소스 파일이든 전부 그냥 복사해서 제 프로젝트에다가 추가하겠습니다.





압축을 푸시면 actionbar 폴더와 actionbarexample 폴더가 나옵니다. actionbar 폴더가 오픈 소스라고 보시면 되고, actionbarexample 폴더가 해당 오픈소스로 만든 프로젝트라고 보시면 됩니다. 




actionbar 폴더안에는 res 폴더,src 폴더 및 매니페스트 파일과 몇가지 파일이 나오는데요, 제가 필요한건 소스파일과 res안에있는 파일들이니 다른건 신경쓰고 붙여넣기 해야할 파일들만 보여드릴께요. (해당 파일들을 프로젝트의 같은 이름의 폴더에 넣으시면 됩니다.)



res\drawable



res\drawable-hdip



res\layout


res\values (strings.xml, styles.xml 두 파일은 기본프로젝트에 포함되어있어서 파일 복사가 아니라 내용 복사로 하였습니다.)



string.xml

Failed to open intent...



style.xml








src\com\markupartist\android\widget (소스는 com.markupartist.android.widget 패키지를 새로 만드신 후에 붙여 넣기 하시면 됩니다.)



자 드디어 android-actionbar 소스를 사용할 준비다 다되었군요. (진짜 드디어;;) 그럼 이제 다시 프로젝트로 넘어와서 메인레이아웃 소스를 만들어보도록 하겠습니다.



    
    

    

        
        

        
            
        
		

            
            

            
            
        

        

            
            
        

        
        

        
        

        

            
            

            
            
        

        

            
            

            
        
    

    
        
    


(코드하이라이터가 왜 이렇게 나타나는지 모르겟네요;; 이클립스에 붙여넣기 하신담에 Ctrl + Shift + F :: 소스 정리 단축키 누르셔야할듯;;)

그럼 몇가지 부분만 짚고 넘어가도록 하겠습니다. 

(1) 우선 오픈소스의 커스텀 뷰입니다.



com.markupartist.android.widget.actionbar 라는 태그가 있는 이 태그는 현제 프로젝트의 특정 소스를 xml 파일에서 뷰로 만들어주는 커스텀 태그라고 보시면 됩니다. 해당 소스를 붙여넣기 할때 com.markupartist.android.widget라는 패키지를 만든후에 복사를 한다고 말씀을 드렸었는데요. 혹시나 다른 패키지의 이름으로 하신분이있다면 이부분을 변경해야하며, res\layout에 붙여넣은 xml파일 내용물에 들어가있는 패키지 명도 바꾸어 주어야 합니다. 


(2) view



Session이라는 글자밑에있는 밑줄을 어떻게 구현할까하다가 그냥 view에다가 배경화면으로 검은색을 준다음 view의 높이를 1dip만 줘서 라인처럼 보이게 구현하였습니다. (이 외에 방법론 Shape를 만들어서 추가하면 될것같은데 이것과 관련해선 다음에 기회 봐서 포스팅을 하도록 하겠습니다. :: 점점 일이 많아 지는 느낌이네요;; ㅎㅎ;;)


(3) Navigation Bar


    


Navigation Bar는 기본 View와 리스트 View 둘다 완성이 된 이후에 또 오픈 소스를 사용하여 구성을 할 예정이라 단순하게 TextView를 만들어서 배치하여보았습니다. 그 외적인 다른 뷰들은 단순한 마진 값들만 준거라 찬찬히 살펴보시면 될 것이라 믿고, 소스부분으로 넘어가도록 하겠습니다.


(4)MainActivity.java




public class MainActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);	
        
        //ActionBar 객체 얻기
        final ActionBar actionBar = (ActionBar) findViewById(R.id.actionbar);
        actionBar.setTitle("Home"); //액션바에 타이틀 설정
        
        //공유 엑션 객체 생성
        final Action shareAction = new IntentAction(this, createShareIntent(), R.drawable.ic_title_share_default);
        actionBar.addAction(shareAction); //공유 엑션을 엑션바에 추가
        
        //새로운 엑션 추가
        //final Action otherAction = new IntentAction(this, new Intent(this, ListViewActivity.class), R.drawable.ic_title_export_default);
        //actionBar.addAction(otherAction);
        
        //Spinner 설정
        Spinner sp1 = (Spinner)findViewById(R.id.androidui_sp_1);
        Spinner sp2 = (Spinner)findViewById(R.id.androidui_sp_2);
        
        Vector data1 = new Vector();
        Vector data2 = new Vector();
        
        data1.add("2011-12-25");
        data2.add("8:00 am");
        
        ArrayAdapter adapter1 = new ArrayAdapter(
				this,
				android.R.layout.simple_spinner_item,
				data1);

        adapter1.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		sp1.setAdapter(adapter1);
		
		ArrayAdapter adapter2 = new ArrayAdapter(
				this,
				android.R.layout.simple_spinner_item,
				data2);

		adapter2.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		sp2.setAdapter(adapter2);
        
    }

    
    public static Intent createIntent(Context context) {
        Intent i = new Intent(context, MainActivity.class);
        i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        return i;
    }
    
    
    //공유 엑션 인텐트 만드는 메소드
    private Intent createShareIntent() {
        final Intent intent = new Intent(Intent.ACTION_SEND);	//묵시적 인텐트 선언
        intent.setType("text/plain");	//인텐트 타입지정
        intent.putExtra(Intent.EXTRA_TEXT, "Shared from the ActionBar widget.");	//인텐트 데이터 설정 
        return Intent.createChooser(intent, "Share");	//인텐트 리턴
    }
}
소스도 뭐 그다지 어려운게 없습니다. 그냥 findviewById 로 action 객체를 얻어오고, 타이틀 설정 및 버튼을 추가하는겁니다. createIntent 메소드는 쫌 짚고 넘어가고 싶은데.... 이에 대해서는 차후 ListViewActivity 클래스를 다 만들고 난 이후에 설명을 하도록 하겠습니다. (어짜피 MainActivity에선 만들기만 했지 사용하는 곳이 없어서 대략 난감하네요 ㅎㅎ)


이렇게 하여 실행한 화면입니다.





프로젝트 전체 파일은 ListView까지 작성한 후에 올리도록 하겠습니다. (이미 다 만들어 놓고 압축시켜놔서 따로 분리하기가 귀찮....)

P.S 혹시나 main layout 부분에서 에러가 나시는 분들은 string.xml에 제가 추가했던 텍스트가 추가 되지 않아서 그런거 일수 있으니, 그냥 text = "섹션" 과 같은 방식으로 변경하신 후 실행 해보세요.


posted by 엡뽀
prev 1 2 3 4 5 next