顯示具有 android 標籤的文章。 顯示所有文章
顯示具有 android 標籤的文章。 顯示所有文章

2011年8月29日

Android在XML中透明顏色



我想因該很多人都與我存在同樣的問題,我們可以使用
Color.argb(alpha,red,green,blue)
來進行透明顏色的調製

但是如果是在XML呢? 那該怎麼辦,相信大家都知道怎麼使用十六進位方式定義顏色,就類似這樣 :

#FF0000

表示紅色,但是如果要調製透明度為150的紅色該怎麼辦呢?或許你嘗試過Android:alpha這個屬性,但是卻沒有找到對吧!!!其實使用透明的方式非常的簡單,只需要在十六進為前再加兩個位數即可,所以我們可以這樣設定 :

#AAFF0000

這樣就是一個稍微透明的紅色。

怎樣~夠簡單吧!! 

2011年8月20日

Android動畫系列 – GONE無法使用動畫解決方法


相信大家都有嘗試過,在為元件設定動畫的時候會使用Visiable與invisiable來操作,這樣子可以很檢的的實現動畫效果,但是有時候並不是只是要讓元件不可見而已,而真正的將他從畫面移除,也就是GONE屬性,這時候大家有沒有發現設置GONE的元件,即使設定了動畫效果但是卻看不到,原因很簡單,因為它在動畫開始前就先消失了。

此篇文章在這裡找到一個解決辦法,也就是為我們的動畫註冊監聽器,來監測目前動畫的狀態。


參考以下程式碼:
Animation alphaAnim = AnimationUtils.loadAnimation(getApplicationContext(), android.R.anim.fade_out);
alphaAnim.setAnimationListener(new AnimationListener() {
     public void onAnimationStart(Animation arg0) {
     }
     public void onAnimationRepeat(Animation arg0) {
     }
     public void onAnimationEnd(Animation arg0) {
         mDrawPaneLayout.setVisibility(View.GONE);
     }
});

mLayout.setAnimation(alphaAnim);
mLayout.setVisibility(View.INVISIBLE);


首先我們宣告一個動畫,該動畫使用android內建的fade_out效果,再來我們為這個動畫類別註冊一個監聽動畫的監聽器,這邊是重點,我們在onAnimationEnd寫入將元件從畫面移除的程式碼,而外部依然使用INVISIBLE屬性來達到元件隱藏,這時候我們會看到動畫撥放,當動畫撥放結束,這時候會被監聽到,此時會執行GONE將元件移出。

雖然這是個很簡單的思維,但相信對大家會有幫助。

2011年6月12日

PopupWindow使用EditText鍵盤無法響應解決辦法

PopupWindow是一個非常好用的東西,它可以跳出我們的排版以類似對話框的方式顯示我們的UI,但是如果在PopupWindow放進EditText來做為輸入的對話視窗時,會出現一個問題,點擊但不顯示原本因該出現的鍵盤,為什麼呢?

原因 : PopupWindow內的EditText無法取得焦點(focus)
解決辦法 : 在顯示調用setFocusable(true),並且調用popup window的更新方法。


PopupWindow.setFocusable(true);
PopupWindow.update();

2011年6月8日

Android 顯示超連結的方法

使用

Html類別裡面的formHtml()方法

static Spanned
fromHtml(String source)
Returns displayable styled text from the provided HTML string.
static Spanned
fromHtml(String source, Html.ImageGetter imageGetter, Html.TagHandler tagHandler)
Returns displayable styled text from the provided HTML string.

2011年5月26日

PopupWindow 動畫用法


1.          首先必須要定義動畫的Style,在這裡就先用android裡面定義的吧
2.          調用popupwindow的setAnimationStyle()方法
3.          在顯示前記得調用update()方法


完成!!!

看看程式碼吧 !

menuWindow = new PopupWindow(gridView,LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
menuWindow.setAnimationStyle(android.R.style.Animation_Dialog);
// 顯示的觸發
menuWindow.update();
menuWindow.showAsDropDown(mControlsLayout, 0, 0);

效果圖 :


2011年5月7日

自定義Layout系列 - 伸縮Layout

最近需要一種可以隱藏、出現的Layout,發現Android沒有提供,因此就寫了一個...
效果圖如下 : 



程式碼部分待補齊

2011年5月5日

(待整理)Android中的配接器模式 - Adapter

我在剛玩android 時候,對這個adapter很不理解,到底是什麼原理呢? 適配器,哎,只知道setAdapter()把參數傳進去,系統就顯示出來了。

今天,針對這個東西,我們做個系統詳細的分析.

listview
載入adapter過程是這樣的.

1 先判斷adapter 有多少資料項目,根據這個資料確定有多少item. 
2 確定每個item裡載入哪個View. 
3 把View裡載入要顯示的資料.

問提一個一個來解決. 第一個問題: 因為adapter都要關聯一個list .有來存儲資料.list的項數就是Item的數目. 我們在重載BaseAdapter 時候,都要實現這個函數

public int getCount() {                           
        return weatherList.size();   
    }   

哎,這個函數就是確定關聯條目的.

第二個問題 哪來的view 呢, 當然我們自己創建的.重載BaseAdapter時候你要實現getView()這個函數,就是這個view.

第三個問題,你自己創建的view.載入哪些資料你該知道的.呵呵.

張豪就喜歡看例子,這個小夥子技術,管理都很牛,得以他為榜樣. 得努力.

public class CustomAdapterActivity extends ListActivity   
{   
    /** Called when the activity is first created. */  
    @Override  
    public void onCreate(Bundle savedInstanceState)   
    {   
        super.onCreate(savedInstanceState);   
        setContentView(R.layout.main);   
        ArrayList<Weather> weatherList = new ArrayList<Weather>();   
        Weather w = new Weather( "London", 17, Weather.OVERCAST );   
        weatherList.add( w );   
        w = new Weather( "Paris", 22, Weather.OVERCAST );   
        weatherList.add( w );   
        w = new Weather( "Athens", 29, Weather.SUNNY );   
        weatherList.add( w );   
        w = new Weather( "Stockholm", 12, Weather.RAIN );   
        weatherList.add( w );   
        WeatherAdapter weatherAdapter = new WeatherAdapter(    
                this,   
                weatherList );    
        setListAdapter( weatherAdapter );   
    }   
}  

哎,這個大家都很清楚,關鍵問題是weatherAdapter 哪來的呢? 自己創建的啊,如果創建呢?

public class WeatherAdapter extends BaseAdapter {   
  
    private Context context;   
    private List<Weather> weatherList;  
 這就是adapter關聯的List,用來存儲資料.還記的ArrayList 要往裡傳參數嗎? 傳的也是這個類型啊.呵呵
  
    public WeatherAdapter(Context context, List<Weather> weatherList ) {    
        this.context = context;   
        this.weatherList = weatherList;   
    }   
  
    public int getCount() {                           
        return weatherList.size();   
    }   
  
    public Object getItem(int position) {        
        return weatherList.get(position);   
    }   
  
    public long getItemId(int position) {     
        return position;   
    }   
  
    public View getView(int position, View convertView, ViewGroup parent) {    
        Weather weather = weatherList.get(position);   
        
return new WeatherAdapterView(this.context, weather );   
    }   
  
}  

哎,這段告訴了我們,有多少個Item, 可以通過getCount()得到了。 可是View 哪來的呢?
當然是getView ()這個函數提供.

這個view 的獲取就多中多樣了,我們可以傳個LayoutID. 通過Inflater出來,也可以自己創建個,只要出來就行.

在這裡,我們自己創建個View. 這個View.是個VIewGroup.


class WeatherAdapterView extends LinearLayout {           
        public static final String LOG_TAG = "WeatherAdapterView";   
  
        public WeatherAdapterView(Context context,    
                                Weather weather ) {   
            super( context );   
  
            this.setOrientation(HORIZONTAL);           
            LinearLayout.LayoutParams cityParams =    
                new LinearLayout.LayoutParams(100, LayoutParams.WRAP_CONTENT);   
            cityParams.setMargins(1, 1, 1, 1);   
  
            TextView cityControl = new TextView( context );   
            cityControl.setText( weather.getCity() );   
            addView( cityControl, cityParams);          
  
            LinearLayout.LayoutParams temperatureParams =    
                new LinearLayout.LayoutParams(20, LayoutParams.WRAP_CONTENT);   
            temperatureParams.setMargins(1, 1, 1, 1);   
  
            TextView temperatureControl = new TextView(context);   
            temperatureControl.setText( Integer.toString( weather.temperature ) );   
            addView( temperatureControl, temperatureParams);               
  
            LinearLayout.LayoutParams skyParams =    
                new LinearLayout.LayoutParams(25, LayoutParams.WRAP_CONTENT);   
  
            ImageView skyControl = new ImageView( context );   
            Log.d( LOG_TAG, weather.getCity()+" -> "+weather.sky );   
            skyControl.setImageResource( weather.getSkyResource() );   
            addView( skyControl, skyParams );   
        }   
}   

Android中Bitmap轉byte

        有時候我們需要將Bitmap轉換成Byte格式做I/O的存取,因此我們可以使用Bitmap類別裡面的compress()方法來做轉換,compress方法提供兩種轉換格式一種為PNG另一種為JEPG,詳細轉換模式請參考下面代碼 :

    /**
     * 將bitmap轉成byte[]格式
     * @param bm 欲轉換的bitmap
     * @return 回傳該bitmap的byte[]
     */
    private byte[] Bitmap2Bytes(Bitmap bm){ 
        ByteArrayOutputStream baos = new 
        ByteArrayOutputStream();  
        bm.compress(Bitmap.CompressFormat.PNG, 100, baos); 
        return baos.toByteArray(); 
    }

Activity中的setContentView( )分析

相信每個人都有看過setContentView(),但你可能沒有注意,這個方法有兩種版本,分別為 :
    public void setContentView (int layoutResID)
    public void setContentView (View view)

    我們在使用的時候使否注意過呢,這裡必須要注意的是layoutResID這個項目,雖然它是傳入整形的參數,但是它一定要是一個layout的資源,怎麼說呢,相信很多人都碰過,在findViewById(R.id.XX),奇怪沒有打錯啊,為什麼老是跟我說Null Value Exception,其實這時候你因該要去檢查你的setContentView(R.layout.XXX)放置的位置或是名稱了,因為findViewById它會對應你在onCreate()中所設定的layout文件,到該xml文件取出該id的view,如果找不到,它會回傳一個空值,所以下再碰到Null Value Exception先去檢查你的setContentView()位置吧!!。

findViewById(R.id.XX)它的說明如下 :  


 額外測試了一下這樣會發生甚麼效果

 setContentView(R.drawable.icon);




結果如下 :


至於為什麼大家自己想想吧!!
本篇就簡單的介紹到這邊囉。

在TextView中顯示HTML語法

來自網路上的網由提供的一個技術 : (待整理)
這段時間在做一個短信專案,需要實現短信中插入表情的功能,本一位非常困難,經過一段時間的研究,發現還是比較簡単的,現在總結如下。
      
以短信輸入框為例,短信的輸入框是一個EditText,它的append方法不僅可以加入字串,還可以添加HTML標記。以下就是使用HTML標記添加表情的具體操作。

   
首先需要構建一個ImageGetter,作用是通過HTML標記獲得對應在res目錄下的圖片:
       ImageGetter imageGetter = new ImageGetter() {  
        @Override
       public Drawable getDrawable(String source) {
       int id = Integer.parseInt(source);
      //
根據id從資源檔中獲取圖片物件
       Drawable d = getResources().getDrawable(id);
       d.setBounds(0, 0, d.getIntrinsicWidth(),d.getIntrinsicHeight());
        return d;
       }
       };          
然後就可以直接往EditText視圖中添加
      
inputLable.append(Html.fromHtml(\"<img src=\'\"+clickedImageId+\"\'/>\", imageGetter, null));                  
  
其中 Html.fromHtml(\"<img src=\'\"+clickedImageId+\"\'/>\"就是HTML的圖片標記,在Android中支援了部分HTML標記的使用(這方面我還在繼續研究),HTML標記必須被Html.fromHtml修飾。imageGetter即為之前創建的ImageGetter類型的對象。
很簡單的幾句代碼就解決了問題,不僅在EditText中,在TextView中同樣可以這樣插入圖片。

android
的短信實現方式普通使用者適應的話需要長時間的使用才能習慣,將andorid的短信模式設置成我們常用的(一般人用戶)的習慣。在查看字元轉圖片的過程中可以猜測出騰訊的QQ表情的原理應該是一樣的

只是在傳送非常用的表情時是將byte資料轉換為image.

/***
     * 
         *
此方法描述的是:   注意此方法在做表情轉換的準備了
         * @author:wujun@cqghong.com,
ppwuyi@sohu.com
         * @version: 2010-5-13
下午03:31:13
     */
    private void bindCommonMessage(final MessageItem msgItem) {
        if (mDownloadButton != null) {
            mDownloadButton.setVisibility(View.GONE);
            mDownloadingLabel.setVisibility(View.GONE);
        }
        // Since the message text should be concatenated with the sender's
        // address(or name), I have to display it here instead of
        // displaying it by the Presenter.
        mBodyTextView.setTransformationMethod(HideReturnsTransformationMethod.getInstance());

        // Get and/or lazily set the formatted message from/on the
        // MessageItem. Because the MessageItem instances come from a
        // cache (currently of size ~50), the hit rate on avoiding the
        // expensive formatMessage() call is very high.
        CharSequence formattedMessage = msgItem.getCachedFormattedMessage();
        if (formattedMessage == null) { //
肯定為null應為msgItem.formattedMessage從誕生來就沒被注意過一次
            formattedMessage = formatMessage(msgItem.mContact, msgItem.mBody,   //
重點到了
                                             msgItem.mSubject, msgItem.mTimestamp,
                                             msgItem.mHighlight);
            msgItem.setCachedFormattedMessage(formattedMessage);
        }
        mBodyTextView.setText(formattedMessage);

        if (msgItem.isSms()) {
            hideMmsViewIfNeeded();
        } else {
            Presenter presenter = PresenterFactory.getPresenter(
                    "MmsThumbnailPresenter", mContext,
                    this, msgItem.mSlideshow);
            presenter.present();

            if (msgItem.mAttachmentType != WorkingMessage.TEXT) {
                inflateMmsView();
                mMmsView.setVisibility(View.VISIBLE);
                setOnClickListener(msgItem);
                drawPlaybackButton(msgItem);
            } else {
                hideMmsViewIfNeeded();
            }
        }

        drawLeftStatusIndicator(msgItem.mBoxId);
        drawRightStatusIndicator(msgItem);
    }
//------------------------------------------------------------------------------

/***
     * 
         *
此方法描述的是:   開始轉換了哦
         * @author:wujun@cqghong.com,
ppwuyi@sohu.com
         * @version: 2010-5-13
下午03:32:52
     */
    private CharSequence formatMessage(String contact, String body, String subject,
                                       String timestamp, String highlight) {
        CharSequence template = mContext.getResources().getText(R.string.name_colon); //
遇到鬼了     &lt;主題:<xliff:g id="SUBJECT">%s</xliff:g>&gt;"
        SpannableStringBuilder buf =                   //
把他當作StringBuffer只是它可以放的不是 String 而已他能放跟多類型的東西
            new SpannableStringBuilder(TextUtils.replace(template,
                new String[] { "%s" },
                new CharSequence[] { contact })); //
替換成連絡人

        boolean hasSubject = !TextUtils.isEmpty(subject); //
主題
        if (hasSubject) {
            buf.append(mContext.getResources().getString(R.string.inline_subject, subject)); //buff
先在是 連絡人 主題 XXXX      eg wuyi <主題:dsadasdsa> 我愛我家
        }

        if (!TextUtils.isEmpty(body)) {
            if (hasSubject) {
                buf.append(" - "); //
如果內容有主題有就+ " - "    eg wuyi <主題:sdsadsadsa> - 
            }
            SmileyParser parser = SmileyParser.getInstance(); //
獲得表情類了哦
            buf.append(parser.addSmileySpans(body)); //
追查 急切關注中
        }
        if (!TextUtils.isEmpty(timestamp)) {
            buf.append("\n");
            int startOffset = buf.length();

            // put a one pixel high spacer line between the message and the time stamp as requested
            // by the spec.
            //
把之間的資訊和時間戳記的要求間隔一個圖元的高線
            //
由規範
            buf.append("\n");
            buf.setSpan(new AbsoluteSizeSpan(3), startOffset, buf.length(),
                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

            startOffset = buf.length();
            buf.append(timestamp);
            buf.setSpan(new AbsoluteSizeSpan(12), startOffset, buf.length(),
                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            // Make the timestamp text not as dark
改變某區域顏色   時間的地方為特殊顏色
            int color = mContext.getResources().getColor(R.color.timestamp_color);
            buf.setSpan(new ForegroundColorSpan(color), startOffset, buf.length(),
                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        if (highlight != null) {
            int highlightLen = highlight.length();

            String s = buf.toString().toLowerCase();
            int prev = 0;
            while (true) {
                int index = s.indexOf(highlight, prev);
                if (index == -1) {
                    break;
                }
                buf.setSpan(new StyleSpan(Typeface.BOLD), index, index + highlightLen, 0);
                prev = index + highlightLen;
            }
        }
        return buf;
    }

//------------------------------------------------------------

/**
     * Adds ImageSpans to a CharSequence that replace textual emoticons such
     * as :-) with a graphical version.
     * 
     * @param text A CharSequence possibly containing emoticons
     * @return A CharSequence annotated with ImageSpans covering any
     *         recognized emoticons.
     *
添加ImageSpans一個CharSequence的表情符號代替文字等     *如用圖形版本:-)。
     *
核心是把表情字元替換成ImageSpans的物件
     */
    public CharSequence addSmileySpans(CharSequence text) {
        SpannableStringBuilder builder = new SpannableStringBuilder(text);

        Matcher matcher = mPattern.matcher(text);
        while (matcher.find()) {
            int resId = mSmileyToRes.get(matcher.group());
            //
注意下面的一塊有點不好理解哦但是是核心
            builder.setSpan(new ImageSpan(mContext, resId), matcher.start(), matcher.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }

        return builder;
    }

總結:

     android
在將字元轉化為表情圖像其核心代碼為

builder.setSpan(new ImageSpan(mContext, resId), matcher.start(), matcher.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
原理過程是先匹配到表情字元然後通過new ImageSpan(上下文,表情位址)繪製出一個ImageView然後替換掉表情字元。

ShareThis