텍스트 그림자 효과를 넣는 법을 살펴보도록 하겠습니다.

    <style name="TextShadow">

    <item name="android:shadowColor">#000000</item>

    <item name="android:shadowDx">1</item>

    <item name="android:shadowDy">1</item>

    <item name="android:shadowRadius">4</item>

    </style>


우선 shadow를 위한 attribute는 위와 같습니다.
지정할수 있는건, Color/위치 (상대 좌표)/ 범위 정도 입니다.

뭐 딱히 설명 드릴만한게 없군요 ^^

저 같은 경우에는 위처럼 Style을 정의 해서 사용하고 있긴한데,

TextView등의 Attribute로 바로 지정해도 무방합니다. ^^




Android Activity는 Device 상태가 변경되면, Activity ReCreation(onDestroy->onCreate)가 일어 납니다. 
만약에, Activity가 세로로만 보여지길 원하고, 변경이 필요 하지 않다면,

"android:configChanges" property 를 이용하여, 무시하도록 할수 있습니다.

 <activity android:name=".MainActivity"

                  android:configChanges="orientation|keyboardHidden|keyboard"/>


"android:configChanges" property 를 이용하여, 무시하도록 할수 있습니다.
위와 같이 설정을 하게 되면 더이상 Activity ReCreation이 일어 나지 않습니다.

그러나, 위의 같은 경우는 "세로모드로만 동작" 하는 설정이 아닙니다.
Device LandScape인 상태에서 실행하면,  App역시도 LandScape모드로 실행됩니다.

이를 방지 하기 위해서 


 

      <activity android:name=".WakeMeUpMain"

                  android:label="@string/app_name"

                  android:screenOrientation="portrait"

                  android:configChanges="orientation|keyboardHidden|keyboard"/>


android:screenOrientation 속성을 이용하여, portrait로만 보여지게 하면,
"세로모드로만" 보여지는 App 이 됩니다. 

Android Application 은 Activity단위로 움직이기 때문에,
모든 Activity를 세로모드로만 보여줄것이라면, Activity별로 모두 세팅해줘야 합니다. 

AVD 에서 Orientation 바꾸기


Emulator의 메뉴에 봐도, AVD Orientation을 바꾸는게 없다. OTL.

구글링을 해본결과.
"Ctrl + F11", "Ctrl + F12" 로 가능하다 .


구글님들아, 메뉴에 좀 등록해주면 오죽 좋아 ㅎ

TabStrip ?

TabWidget의 Strip(줄) 이미지를 "TabStrip"이라고 한다. 


    android:tabStripEnabled="false"

Default로 "true"로 세팅되어 있고, "false를 주게 되면 하단이 사라지게 된다. 


Android Level 8 API 이기 때문에,  2.1 이하 사용할 수 없는 점을 주의해야 한다. 

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

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

    android:orientation="vertical"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent">


<Button

android:id="@+id/button"          

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:text="Button"

>

</Button>

<Button

android:id="@+id/button"          

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:text="Button"

/>

</LinearLayout>


위와 같이 android:id 가 동일한게 연속적으로 있을 때, 동작할까? 


동작한다 !

 Button button = (Button) findViewById(R.id.button);

        button.setText("First");


위와 같은 Code로 접근하면 어떤 Button의 값이 바뀔까 ? 


그럼 두번쨰 버튼을 접근하려면 ?

<Button

android:id="@+id/button"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:text="Button"

>

</Button>


<LinearLayout

android:id="@+id/linear"

    android:orientation="vertical"

    android:layout_width="fill_parent"

    android:layout_height="wrap_content">

<Button

android:id="@+id/button"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:text="Button"

>

</Button>

</LinearLayout>



두번째 Button을 ViewGroup으로 묶어서, " ContentView -> ViewGroup -> 두번째 Button " 으로 묶어서 접근한 것이다. 
findViewsById() 같은 녀석이 있으면 좋을것 같은데, 일단 이렇게 해서 접근 가능합니다.




android:src="@android:drawable/ic_input_delete"


위와 같이 @drawble이 아닌 "@android:drawable"과 같이  접근하면 된다. 

사용가능한 리소스


참조 : http://androiddrawableexplorer.appspot.com/

What is a "Preference Activity" ? 

App. 등 설정에 관련된 UI 구성에 특화 되어 있는 Activity
설정 Item 구성 , Scrolling등을 지원합니다. 

Write XML Layouts

1. Activity Layout 


Class 관계를 살펴보면 PreferenceActivity는 ListActivity를 상속받는다. 
ListActivity에서 ListView를 접근할때,"@android:id/list"로 접근하기 때문에, Layout XML 작성시 유의 해야 한다. 

 <ListView android:id="@android:id/list"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:layout_weight="1"

        android:drawSelectorOnTop="false"/>


2. Preference Items 

addPreferenceFromResource() / addPreferenceFromIntent() 등을 통해 Preference Item을 삽입
나는 addPreferenceFromResource() 를 사용하는 것을 선호한다. 


위와 같이 Preference 관련 resource를 추가 한다. 

<PreferenceScreen

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

    android:title="@string/settings">


    <CheckBoxPreference

        android:key="alarm_in_silent_mode"

        android:title="@string/alarm_in_silent_mode_title"

        android:summary="@string/alarm_in_silent_mode_summary" />


    <VolumePreference

        android:title="@string/alarm_volume_title"

        android:summary="@string/alarm_volume_summary"

        android:dialogTitle="@string/alarm_volume_title"

        android:persistent="false"

        android:streamType="alarm" />


    <ListPreference

        android:key="snooze_duration"

        android:title="@string/snooze_duration_title"

        android:entries="@array/snooze_duration_entries"

        android:entryValues="@array/snooze_duration_values"

        android:defaultValue="10"

        android:dialogTitle="@string/snooze_duration_title" />


    <ListPreference

        android:key="volume_button_setting"

        android:title="@string/volume_button_setting_title"

        android:dialogTitle="@string/volume_button_dialog_title"

        android:entries="@array/volume_button_setting_entries"

        android:entryValues="@array/volume_button_setting_values"

        android:summary="@string/volume_button_setting_summary"

        android:defaultValue="2" />


</PreferenceScreen>


각각의 Entry는 View Entry등과 마찬가지로, Android Class와 Match 된다. 

Write your Code

1. 구현해야 할것들

다른 Activity 사용법과 마찬가지로, 만약 "Setting"화면이 필요하다고 하면,
"PreferenceActivity"를 상속받는 "SettingActivity"를 생성합니다. 

onCreate 
- addPreferenceFromResource를 통해 Preference Item을 구성
onPreferenceTreeClick
- PreferenceClick Event 처리
onPreferenceChanged
- Preference Value Change 처리

2. Source Code

 @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        addPreferencesFromResource(R.xml.settings);

    }



    @Override

    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,

            Preference preference) {

        if (KEY_ALARM_IN_SILENT_MODE.equals(preference.getKey())) {

            CheckBoxPreference pref = (CheckBoxPreference) preference;

            int ringerModeStreamTypes = Settings.System.getInt(

                    getContentResolver(),

                    Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0);


            if (pref.isChecked()) {

                ringerModeStreamTypes &= ~ALARM_STREAM_TYPE_BIT;

            } else {

                ringerModeStreamTypes |= ALARM_STREAM_TYPE_BIT;

            }


            Settings.System.putInt(getContentResolver(),

                    Settings.System.MODE_RINGER_STREAMS_AFFECTED,

                    ringerModeStreamTypes);


            return true;

        }


        return super.onPreferenceTreeClick(preferenceScreen, preference);

    }


    public boolean onPreferenceChange(Preference pref, Object newValue) {

        final ListPreference listPref = (ListPreference) pref;

        final int idx = listPref.findIndexOfValue((String) newValue);

        listPref.setSummary(listPref.getEntries()[idx]);

        return true;

    }


위의 코드는 실제로 addPreferenceFromResource를 통해서, Preference를 구성하고,
onPreferenceTreeClick을 이용하여, Preference Click 이벤트를 처리 하는 부분이다. 

이처럼 PreferenceActivity를 이용하면, 쉽게 Setting 화면을 구성할 수 있다. 



부팅시에 코드를 실행하는것은 간단합니다.

Android는 Booting시에 BOOT_COMPLETED라는 BroadCast를 생성합니다.
그걸 Catch하는 Receiver를 구현하면됩니다.

1. Permission 설명

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />


2. Receiver에 IntentFilter 걸기

 <intent-filter>

                <action android:name="android.intent.action.BOOT_COMPLETED" />

 </intent-filter>


3. Receiver 구현

@Override

    public void onReceive(Context context, Intent intent) {

}



BroadcastReceiver Class를 상속받는 Receiver Class를 하나 만들고,


onReceiver Method를구현해주면 됩니다. 


참 쉽죠? ㅎㅎ



[2009-11-02 16:28:51 - Android]Android Launch!
[2009-11-02 16:28:51 - Android]adb is running normally.
[2009-11-02 16:28:51 - Android]Could not find ********.apk!

라는 녀석이 개발하다 보면 가끔 발생된다. 

이거 같은 경우는 Build 가 제대로 안되는 경우인데,

이경우 Android Project의 .classpath 파일이 꼬인 경우가 많다. 

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry kind="output" path="bin"/>
</classpath>

Android Project의 경우 일반적으로 위와 같이 되어야 하고,

Android Test Project의 경우는 아래와 같이 Dependancy가 추가 되어야한다.

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry combineaccessrules="false" kind="src" path="/SomeAndroidProject"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry kind="output" path="bin"/>
</classpath>

수정하고, 나면 apk 파일이 잘 생성됨을 확인 할 수 있따. 


App Widget 이란 Home Screen에 노출되는 miniature Application입니다.
보통 시계 어플등이 Widget 형태로 존재 하게 됩니다.

App Widget을 구현에 필요 한것들

A. 꼭 필요 한것들
1. AppWidgetProviderInfo object
- App Widget을 위한 MetaData, update frequecy 나 layout에 대한 정의.
- XML 에 정의 되어야함.
2. AppWidgetProvider
- Programming Interface
- AppWidget이 Update/Enabled/Disabled/Delete되었을때, BroadCast를 받는 Receiver역할을 한다.
3. View Layout
- AppWidget Design , Android Layout XML 로 정의한다.
B. 추가로 할 수 있는것
App Widget Configuration Activity
- AppWidget이 생성될때, User가 설정하게 할수 있는 Optional Feature

요약
Android Manifest에 AppWiget을 정의하고, AppWidgetProvider를 구현함으로써 Programming 하고,
Layout을 통해 App Widget을 디자인한다.

Manifest에 App Widget 선언하기.

앞서 언급한대로, AppWidget에는 AppWidgetProvider라는 BroadCast Receiver가 필요 합니다.

<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>

  • AppWidget Broadcast Reciver 등록
  • MetaData Resource 설정 

AppWidgetProviderInfo MetaData


res/xml/ folder에 <appwidget-provider /> 태그를 작성한 yourappwidget-info.xml을 추가합니다.

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
   
android:minWidth="294dp"
   
android:minHeight="72dp"
   
android:updatePeriodMillis="86400000"
   
android:initialLayout="@layout/example_appwidget"
   
android:configure="com.example.android.ExampleAppWidgetConfigure" >
</appwidget-provider>

  • minWidth/minHeight 설정
    • 사실상 width값대로 표기되는게 아니라, 현재의 Cell Size에 따라 자동 계산된다.
    • Cell Size는 Device별로 다르고, 같은 Device일때도, Vertical이냐 Horizontal에 따라서 또 다르다.
    • ( Number of Cells ) * 74 -2 의 계산식으로 계산하여 설정하도록 한다.
  • updatePeriodMillis 설정
  • layout 명시
    • AppWidget Layout XML
  • configure(optional)
    • 유저가 AppWidget 설정시 사용될 Activity

AppWidget Layout

AppWidget의 Layout은 기본적으로 Activity용 Layout과 다를 바가 없다.
다만, AppWidget은 RemoteView를 기반으로 하고 있기 때문에, 사용할 수 있는 종류에 제약이 있다.

사용가능한 Layout Classes

사용가능한 Widget Classes

AppWidgetProviderClass 구현하기

아래 소스는 appWidget을 Click했을 때, 특정 Activity를 띄우는 AppWidget의 예이다.

public class ExampleAppWidgetProvider extends AppWidgetProvider {

   
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
       
final int N = appWidgetIds.length;

       
// Perform this loop procedure for each App Widget that belongs to this provider
       
for (int i=0; i<N; i++) {
           
int appWidgetId = appWidgetIds[i];

           
// Create an Intent to launch ExampleActivity
           
Intent intent = new Intent(context, ExampleActivity.class);
           
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);

           
// Get the layout for the App Widget and attach an on-click listener to the button
           
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider_layout);
            views
.setOnClickPendingIntent(R.id.button, pendingIntent);

           
// Tell the AppWidgetManager to perform an update on the current App Widget
            appWidgetManager
.updateAppWidget(appWidgetId, views);
       
}
   
}
}

AppWidget의 기본적인 목적은 주기적으로 화면을 구성해주서 보여주는것이다.
그럼으로 특별히 Enable/Disable를 처리할 이유가 없다면, 내가 해야 할일은 onUpdate() Method를 구현하는것 뿐이다.

이제 AppWidget을 띄울 수 있는 기본적인 개념은 알게 되었다.

+ Recent posts