2014. 2. 6. 15:40

오늘은 저번에 참고했던 SlidingMenu를 이용해서,

기본적인 앱 구조를 구현 코드입니다.

예제 소스를 돌려도 실제로 제가 돌리기 위한 소스를 만들기까지는

한참 시간이 걸리기때문에 포스팅합니다.


이를 이용하기 위해서는 사전 작업이 필요한데,

안보신분은 

http://naddola.tistory.com/entry/androidSliding-Menu-%EB%A9%94%EB%89%B4-%EB%8F%8C%EB%A0%A4%EB%B3%B4%EA%B8%B0jfeinstein10%EC%98%A4%ED%94%88%EC%86%8C%EC%8A%A4

를 먼저 해보시고 오는걸 추천드립니다.


새 프로젝트를 SlidingSimpleSample로만들고,

저번에 이용했던, library를 참조합니다.


 

추가했더니 또

 Found 2 versions of android-support-v4.jar in the dependency list,

라는 경고가 뜨네요.

 이미 설명했던 것이니, 가볍게 libs폴더에 있는

android-support-v4.jar

삭제해버렷!

 

이제 필요한 자바파일입니다.

BaseActivity.java

적용시켰던 ExampleListActivity에서 수정했습니다.

package com.example.slidingsimplesample;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.app.ListFragment;

import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu;
import com.jeremyfeinstein.slidingmenu.lib.app.SlidingFragmentActivity;

public class BaseActivity extends SlidingFragmentActivity {

	protected ListFragment mFrag;

	public BaseActivity() {
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);


		// set the Behind View
		setBehindContentView(R.layout.menu_frame);
		if (savedInstanceState == null) {
			FragmentTransaction t = this.getSupportFragmentManager().beginTransaction();
			mFrag = new MenuListFragment();
			t.replace(R.id.menu_frame, mFrag);
			t.commit();
		} else {
			mFrag = (ListFragment)this.getSupportFragmentManager().findFragmentById(R.id.menu_frame);
		}

		// customize the SlidingMenu
		SlidingMenu sm = getSlidingMenu();
		sm.setShadowWidthRes(R.dimen.shadow_width);
		sm.setShadowDrawable(R.drawable.shadow);
		sm.setBehindOffsetRes(R.dimen.slidingmenu_offset);
		sm.setFadeDegree(0.35f);
		sm.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);

		getSupportActionBar().setDisplayHomeAsUpEnabled(true);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case android.R.id.home:
			toggle();
			return true;
		
		}
		return super.onOptionsItemSelected(item);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getSupportMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
	

	public void fragmentReplace(int reqNewFragmentIndex) {
		 
        Fragment newFragment = null;
 
        newFragment = getFragment(reqNewFragmentIndex);
 
        final FragmentTransaction transaction = getSupportFragmentManager()
                .beginTransaction();
 
        transaction.replace(R.id.fragment_mainContainer, newFragment);
 
        getSlidingMenu().showContent();
        transaction.commit();
    }
	
	private Fragment getFragment(int idx) {
        Fragment newFragment = null;
 
        switch (idx) {
        case 0:
            newFragment = new Fragment1();
            break;
        case 1:
            newFragment = new Fragment2();
            break;
        case 2:
            newFragment = new Fragment3();
            break;
        default:
            break;
        }
 
        return newFragment;
    }
}


MainActivity.java

메인 액티비티입니다.

package com.example.slidingsimplesample;

import android.os.Bundle;
public class MainActivity extends BaseActivity{

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

}


MenuListFragment.java

메뉴에 있는 아이템을 실질적으로 채워주는 부분입니다.

package com.example.slidingsimplesample;
 
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class MenuListFragment extends ListFragment {
 
     
    public MenuListFragment(){
    }
 
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        return inflater.inflate(R.layout.list, null);
    }
 
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        SampleAdapter adapter = new SampleAdapter(getActivity());
        adapter.add(new SampleItem("Fragment1", android.R.drawable.ic_menu_search));
        adapter.add(new SampleItem("Fragment2",
                android.R.drawable.ic_menu_search));
        adapter.add(new SampleItem("Fragment3", android.R.drawable.ic_menu_search));
 
        setListAdapter(adapter);
    }
 
    private class SampleItem {
		public String tag;
		public int iconRes;

		public SampleItem(String tag, int iconRes) {
			this.tag = tag;
			this.iconRes = iconRes;
		}
	}

	public class SampleAdapter extends ArrayAdapter<SampleItem> {

		public SampleAdapter(Context context) {
			super(context, 0);
		}

		public View getView(int position, View convertView, ViewGroup parent) {
			if (convertView == null) {
				convertView = LayoutInflater.from(getContext()).inflate(
						R.layout.row, null);
			}
			ImageView icon = (ImageView) convertView
					.findViewById(R.id.row_icon);
			icon.setImageResource(getItem(position).iconRes);
			TextView title = (TextView) convertView
					.findViewById(R.id.row_title);
			title.setText(getItem(position).tag);

			return convertView;
		}
	}

 
    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
         
        switch (position) {
        case 0:
            ((BaseActivity)getActivity()).fragmentReplace(0);
            break;
        case 1:
            ((BaseActivity)getActivity()).fragmentReplace(1);
            break;
 
        case 2:
            ((BaseActivity)getActivity()).fragmentReplace(2);
            break;
        }
        super.onListItemClick(l, v, position, id);
    }
}


Fragment1.java

메뉴 1입니다.

package com.example.slidingsimplesample;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

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


Fragment2.java

메뉴 2입니다.

package com.example.slidingsimplesample;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

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


Fragment3.java

메뉴 3입니다.

package com.example.slidingsimplesample;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

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




xml파일입니다.

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <LinearLayout
        android:id="@+id/fragment_mainContainer"
        android:layout_gravity="center_horizontal"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical"
        android:gravity="center_horizontal"
         />

</RelativeLayout>


fragment1.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    
    <TextView
        android:id="@+id/tv1"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:text="fragment1"/>

</LinearLayout>


fragment2.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    
    <TextView
        android:id="@+id/tv2"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:text="fragment2"/>

</LinearLayout>


fragment3.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    
    <TextView
        android:id="@+id/tv3"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:text="fragment3"/>

</LinearLayout>


list.xml

<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
     />


menu_frame.xml

<?xml version="1.0" encoding="utf-8"?>

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/menu_frame"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />


row.xml

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

    <ImageView
        android:id="@+id/row_icon"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:padding="10dp"
        android:src="@drawable/ic_launcher" />

    <TextView
        android:id="@+id/row_title"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center_vertical"
        android:padding="10dp"
        android:text="Medium Text"
        android:textAppearance="@android:style/TextAppearance.Medium" />

</LinearLayout>


다음으로 value폴더에 있는 dimens.xml 도 변경합니다.

dimens.xml

<resources>
  <!-- Default screen margins, per the Android Design guidelines. -->
    <dimen name="activity_horizontal_margin">16dp</dimen>
    <dimen name="activity_vertical_margin">16dp</dimen>
     <dimen name="slidingmenu_offset">60dp</dimen>
    <dimen name="list_padding">10dp</dimen>
    <dimen name="shadow_width">15dp</dimen>

    <integer name="num_cols">1</integer>
</resources>


마지막으로 그림자 효과에 대한 xml을 넣어야하는데 이친구는

drawable폴더에 넣어야됩니다.

shodow.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >

    <gradient
        android:endColor="#33000000"
        android:centerColor="#11000000"
        android:startColor="#00000000" />

</shape>


여기까지 하시고 돌려보면



다음과 같은 결과를 얻을 것입니닷!

그럼 열코딩 하시길~


밑에는 아예 세개 프로젝트를 압축해놨습니다.

SlidingSimpleSample.zip

import하시면 됩니다.


Posted by 나돌라
2014. 1. 20. 10:41

안녕하세요.

앱을 개발하다가 페이스북같은 슬라이드 메뉴를 구현하고 싶었는데,

참고할 만한 오픈소스가 jfeintsein10이라는 소스가 굉장히 유명하더군요.


그래서 참고하고 싶었는데, 예제만 돌리는데 정말 힘들었습니다.

혹여나 저같은 분들이 있을까봐 포스팅합니다.


먼저 이 예제파일을 실행하기 위해서는 두가지를 다운 받아야합니다.


1. jfeinstein10 오픈소스

우리가 사용하려고 하는 오픈소스죠.

https://github.com/jfeinstein10/SlidingMenu


2. ActionBarSherlock

저도 자세한건 모르겠으나 위의 오픈소스가 이걸 사용하더군요.

http://actionbarsherlock.com/




다운 받은 zip들은 압축을 풀어줍니다.

이제 이클립스를 키고,

[NEW] - [other] - [Android] - [Android Project from Existing Code]를 선택

압축 풀린 Slidingmenu폴더를 선택하면

이런 식으로 나올텐데요.

두개다 추가하면 됩니다. 이때 밑에 Copyprojects into workspace는 꼭 체크해주세요.

이걸 체크해야 복사해서 추가하기때문에 원본은 그대로 있습니다.


같은 방법으로 ActionBar도 추가해보면

이런 식으로 뜹니다.

이때 다른 프로젝트들은 다 필요 없으니까 첫번째 프로젝트(actionbarsherlock)만 체크하고,

나머지는 전부 풀어줍니다.

마찬가지로 Copy projects into workspace는 체크해줍니다.


자 여기까지 하셨다면 아마 이런 결과 일겁니다.


자 이제 할 일은 서로 엮어주고 고쳐주면 됩니다.

구조는 이런식입니다.

actionbarsherlock은 라이브러리화 되서 library가 참고하고,

library 또한 라이브러리화 되서 ExamplelistActivity가 참고하는 구조입니다.


 actionbarsherlock프로젝트library프로젝트properties로 들어가 Islibrary를 체크해줍니다.

(아마 되있을겁니다.)



다음, library프로젝트 Properties에서 Add버튼을 누른 후 actionbarsherlock을 추가시킵니다.


그러면 Console창에

Found 2 versions of android-support-v4.jar in the dependency list,~~~

같은 어마무시한 경고가 뜨는데 이것은 android-support-v4.jar라는 파일이 둘 다 있어서 중복된다는 소리입니다.

library프로젝트의 libs폴더에 있는 android-support-v4.jar파일을 삭제 합니다.


다음 library프로젝트의 SlidingFragmentActivity를 찾아서, 

public class SlidingFragmentActivity extends FragmentActivity implements SlidingActivityBase {

이부분을

public class SlidingFragmentActivity extends SherlockFragmentActivity implements SlidingActivityBase {

으로 바꿉니다.


그럼 아마 모든 에러는 사라질 것이고

ExampleListActivity프로젝트를 실행하면,

이 화면을 보실 수 있을 겁니다.



 ps. Unable to resolve target 'android-16' 류의 경고가 뜬다면 Properties에서 Buildtarget을 GoogleAPIs로 바꿔보세요.


다음에는 이 코드를 이용해서 실질적으로 사용하는 예제 소스를 준비하겠습니다.



Posted by 나돌라
2013. 11. 28. 19:36

안녕하세요.

오늘은 교내 공학경진대회에 출품했던 WSummary 중 요약 API의 작동 원리에 대해 말씀드리겠습니다.


먼저 요약 할 본문이 필요하겠죠?


내년부터 수입·국산차 66개 모델의 자차보험료가 오르고, 국산차 60개 모델은 싸진다.

보험개발원은 상한등급을 올린 ‘차량모델등급제도 개선안’을 최근 금융감독원에 신고했다고 27일 밝혔다. 차량모델등급제도란, 자가용 승용차의 ‘자기차량손해담보’(자차보험)에 대해 모델별로 등급을 정해 보험료를 매기는 제도다. 부품값이 비싼 고급차나 단독 수리가 어려운 경우 자차보험료가 더 많이 책정된다.

보험개발원은 개선안에서 기존 21등급에 상위 등급을 5개 신설해 26개 등급으로 늘렸다. 최고적용율도 중간등급 기준 최고 150%에서 200%로 높아진다. 예컨대, 16등급(기존 11등급) 기준으로 자차보험료를 10만원 냈다면, 1등급 차량은 두 배인 20만원을 내야 한다는 이야기다. 또 수입차는 브랜드 단위로 차종을 세분화했다. 기존엔 수입차는 제작사 기준으로 분류해, 고급 브랜드인 렉서스가 일반 도요타 차량과 요율이 같았다.

이에 따라 수입차 34종 가운데 32종의 자차보험료가 인상되며, 국산차는 172종 가운데 34종이 오른다. 보험료가 오르는 모델은, 1600㏄미만 소형급에선 스파크, 올뉴모닝, 올뉴프라이드, 벨로스터, K3, 쏘울 등이다. 중형급(1600~2000㏄)에선 YF쏘나타, 제네시스쿠페, i40, 크루즈 등이다. 3000㏄이상 대형에서는 뉴체어맨, 올뉴SM7 등이, 다인승 차량은 무쏘, 카렌스Ⅱ, 렉스턴, 싼타페(DM) 등이다. 특히 수입차 중에서는 크라이슬러, 푸조, 인피니트, 폭스바겐 골프 등이 5등급씩 대폭 올랐다. 이들 차량은 자차보험료가 최대 33% 인상될 것으로 보인다.

반면 인하 모델은 뉴마티즈, 마티즈2, 모닝, 아반떼(신형), 쏘나타(신형), 뉴그랜저XG, 뉴에쿠스, 제네시스, 스타렉스 등이다. 그 외 모델명은 손해보험협회 누리집에서 확인 가능하다.

변경된 제도에 따라 손해율이 높은 외제차의 자차보험료는 평균 11.3%, 국산차의 자차보험료는 평균 2.9%가 인하된다. 자동차보험의 전체원수보험료 가운데 자차보험료가 차지하는 비율은 지난해 기준 24%다.


-한겨례신문에서 발췌

http://www.hani.co.kr/arti/economy/economy_general/613049.html


 STEP1

 이러한 본문은 하나의 String이 되서 요약 API에게 가게 됩니다.




STEP2  

이 후 직접 문장 구별법으로 문장을 나누고,

형태소 분석기를 이용하여 단어들만 추출합니다.

추출한 단어들은 전체 단어장에 개수와 함께 저장합니다.

(밑에 보기는 제가 보여드리기 위해 ppt로 임의로 만든겁니다. 실제 결과와는 다릅니다.)


문장 구별은 제가 직접 구했습니다. 

처음에는 '.'에 관하선 나누다가 ".hwp"라는 단어가 나오면 꼬이더군요 그런부분 수정하고,

-이에 나돌라는 "이건 아니지 않냐."라고 말했다.

같이 인용구도 구분 못하길래 전부 구별 할 수 있도록 수정했습니다.


형태소 분석기는

ShineWare님의 Komoran 형태소분석기를 사용했습니다.

링크는 아래주소로

http://shineware.tistory.com/entry/KOMORAN-ver-112-%EC%9E%90%EB%B0%94-%ED%95%9C%EA%B8%80-%ED%98%95%ED%83%9C%EC%86%8C-%EB%B6%84%EC%84%9D%EA%B8%B0

원래 Kaist에서 개발한 한나눔 형태소 분석기를 처음에 사용 했었는데,

이게 전부 닫혀있어서 신조어는 새로 추가 시킬 수 없어서

추가 가능한 Komoran을 사용했습니다.



STEP3

전체 단어들과 현재문장의 단어들, 그리고 문장의 길이 등을 고려하여

각 문장의 가중치를 구합니다.

이론을 바탕으로 전부 직접 구현입니다.

(임의의 표현이여서 실제와 다릅니다.)

이부분에서 Google페이지랭크라던가 통상적인 알고리즘들도 많이 봤지만,

실제적으로 거의 적용 시킨 논문은 통계적 요약 알고리즘이였습니다.

http://m.riss.kr/search/detail/DetailView.do?p_mat_type=be54d9b8bc7cdb09&control_no=9edf8efd93e9161c

그 외로

http://semanticweb.kaist.ac.kr/home/images/1/15/Sentence_Summarization_of_News_Articles.pdf

도 좀 봤었습니다.



STEP4

뉴스는 두괄식이라는 이론에 따라

 앞문장에 있을 수록 가중치 분배를 달리 해줍니다.




STEP5

이제 가장 높은 가중치의 문장들만을 추출합니다.

추출할 문장의 개수는 본문의 길이에 따라 다르게 설정했습니다.

여기서는 임의로 두개를 추출한다 하면



STEP6

이 후 접속사같은 것들을 제거하고,

문장들을 return합니다.







Posted by 나돌라
2013. 11. 28. 00:03



최근 트위터에서 이 책을 추천 하는 글이 있기에 읽기 시작했습니다.


전체 내용은 IT 와 비지니스에 관해서

실리콘 벨리 이야기들을 펼쳐냈습니다.


출판한지 1년도 채 안되서 이름만 들어도 아는 회사들이 주루루룩~

그들이 어떤 마인드로 했는지, 

어떤 과정을 거쳤는지를 알려주는데..


IT 전문가 지망생으로서

읽을 수록 실리콘벨리에서 살고 싶은 욕구가 마구마구 생겨납니다.

IT인이라면 꼭 읽어봐야 할 강추 도서였습니다.





Posted by 나돌라
2013. 9. 29. 17:32




2학년 2학기 게임그래픽 기말 프로젝트

캐릭터부터 소품까지 전부 직접 제작했다(나무만 max내에 있는 오브젝트 사용)

진짜 며칠 밤을 샜는지 모르겠다 ㅠ

인코딩이 잘못 되서 화질이 후진게 아쉽다.

꼬마 돼지들 목소리는 조원들과 직접 녹음작업까지 ! ! ! ㅋㅋ






'Archive > 3DMax' 카테고리의 다른 글

2학년 그래픽 기말프로젝트 - 공학관 201호  (0) 2013.09.29
수족관 만들기  (0) 2013.09.29
Posted by 나돌라
2013. 9. 29. 17:15


2학년 그래픽 과목 개인 프로젝트였다.

당시 교수님의 눈빛을 달라지게 했던  기말프로젝트.

공학관 201호를 표현해본 것이다.

지금은 201호를 리모델링해서 달라진 것이 아쉽기는 하지만,

 지금봐도 뿌듯하군..

'Archive > 3DMax' 카테고리의 다른 글

아기 돼지 삼형제 - 게임그래픽 기말프로젝트  (0) 2013.09.29
수족관 만들기  (0) 2013.09.29
Posted by 나돌라
2013. 9. 29. 17:04


3D Max를 처음 배울 당시 3번째로 나왔던 과제...


수족관 만들기였는데,

 나는 조금 독특하게 횟집을 만들었다 ㅎㅎ

Posted by 나돌라
2013. 7. 31. 19:49

간만에 하려다가 여기서 막혔는데 한참 헤맸습니다.


OnTouchEvent를 override하면 처음에 이런식으로 나옵니다.

이상태로 코드를 완성하면 자주 잊는데요.

여기서

  return super.onTouchEvent(event);

부분을

  return true;

로 바꿔주면 됩니다.


  return super.onTouchEvent(event)는 false값을 return하게 되는데 그렇게 되면

ACTION_MOVE, ACTION_UP을 불러 올 수 없다고 그러네요


Posted by 나돌라
2013. 7. 31. 19:38

처음에 직접 하다가 zoom에서 막혔는데,

stackover flow보니까 잘 설명해놓은게 있네요 ㅎㅎ

영어만 있길래 한글로 옮겼습니다.


MainActivity

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(new TouchExampleView(this,null,0));
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

}



TouchExampleView

public class TouchExampleView extends View {
	private Drawable mIcon;
	private float mPosX;
	private float mPosY;

	private float mLastTouchX;
	private float mLastTouchY;

	private static final int INVALID_POINTER_ID = -1;
	private ScaleGestureDetector mScaleDetector;
	private float mScaleFactor = 1.f;

	// The ‘active pointer’ is the one currently moving our object.
	private int mActivePointerId = INVALID_POINTER_ID;

	public TouchExampleView(Context context) {
		this(context, null, 0);
	}

	public TouchExampleView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public TouchExampleView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		mIcon = context.getResources().getDrawable(R.drawable.ic_launcher);
		mIcon.setBounds(0, 0, mIcon.getIntrinsicWidth(),
				mIcon.getIntrinsicHeight());
		mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
	}

	@Override
	public void onDraw(Canvas canvas) {
		super.onDraw(canvas);

		canvas.save();
	    canvas.translate(mPosX, mPosY);
	    canvas.scale(mScaleFactor, mScaleFactor);
	    mIcon.draw(canvas);
	    canvas.restore();
	}

	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		// Let the ScaleGestureDetector inspect all events.
	    mScaleDetector.onTouchEvent(ev);
	    
	    final int action = ev.getAction();
	    switch (action & MotionEvent.ACTION_MASK) {
	    case MotionEvent.ACTION_DOWN: {
	        final float x = ev.getX();
	        final float y = ev.getY();
	        
	        mLastTouchX = x;
	        mLastTouchY = y;
	        mActivePointerId = ev.getPointerId(0);
	        break;
	    }
	        
	    case MotionEvent.ACTION_MOVE: {
	        final int pointerIndex = ev.findPointerIndex(mActivePointerId);
	        final float x = ev.getX(pointerIndex);
	        final float y = ev.getY(pointerIndex);

	        // Only move if the ScaleGestureDetector isn't processing a gesture.
	        if (!mScaleDetector.isInProgress()) {
	            final float dx = x - mLastTouchX;
	            final float dy = y - mLastTouchY;

	            mPosX += dx;
	            mPosY += dy;

	            invalidate();
	        }

	        mLastTouchX = x;
	        mLastTouchY = y;

	        break;
	    }
	        
	    case MotionEvent.ACTION_UP: {
	        mActivePointerId = INVALID_POINTER_ID;
	        break;
	    }
	        
	    case MotionEvent.ACTION_CANCEL: {
	        mActivePointerId = INVALID_POINTER_ID;
	        break;
	    }
	    
	    case MotionEvent.ACTION_POINTER_UP: {
	        final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) 
	                >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
	        final int pointerId = ev.getPointerId(pointerIndex);
	        if (pointerId == mActivePointerId) {
	            // This was our active pointer going up. Choose a new
	            // active pointer and adjust accordingly.
	            final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
	            mLastTouchX = ev.getX(newPointerIndex);
	            mLastTouchY = ev.getY(newPointerIndex);
	            mActivePointerId = ev.getPointerId(newPointerIndex);
	        }
	        break;
	    }
	    }
	    
	    return true;
	}

	private class ScaleListener extends
			ScaleGestureDetector.SimpleOnScaleGestureListener {
		@Override
		public boolean onScale(ScaleGestureDetector detector) {
			mScaleFactor *= detector.getScaleFactor();

			// Don't let the object get too small or too large.
			mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));

			invalidate();
			return true;
		}
	}
}
Posted by 나돌라
2013. 6. 23. 17:33

항상 Gitbash를 사용하다가 오랜만에 Github에 들어갔더니

환경이 달라져서 당황했던 적이 있었다.

그려려니 하고 설치를 했는데 왠걸? Gitbash가 없어?!!!!


혹시나 저같은 분들을 위해 포스팅 합니다.


일단 Github를 다운 받아야겠죠?

아래 사이트로 갑니다.


https://help.github.com/articles/set-up-git


스크린샷1

초록색 버튼을 누르시고 다운을 받습니다.


이래저래 뭐라는거 다 설치하시고


스크린샷2

바탕화면에 새로 생겼을 아이콘을 클릭 합니다.


스크린샷3

tools - options...


스크린샷4

 default shell을 Git Bash로 바꾸고 같이 설치 되있던 Git Shell을 실행 하시면 됩니다!


끝! 




Posted by 나돌라