0

Hi I am trying to setup custom font for the TextView and I get an error as cannot make a static reference to non-static method getAssets() from the contextWrapper. How do I set the custom font? . My code is as follows. Is there any way to set the font in the XML layout file itself. It is present in assets.

public class MainActivity extends Activity {

    private static class EfficientAdapter extends BaseAdapter {
        Typeface tfTab = Typeface.createFromAsset(getAssets(),"fonts/tabkovai.ttf");
        private LayoutInflater mInflater;

        public EfficientAdapter(Context context) {
            // Cache the LayoutInflate to avoid asking for a new one each time.
            mInflater = LayoutInflater.from(context);

            // Icons bound to the rows.
        }

        /**
         * The number of items in the list is determined by the number of speeches
         * in our array.
         *
         * @see android.widget.ListAdapter#getCount()
         */
        public int getCount() {
            return DATA.length;
        }

        /**
         * Since the data comes from an array, just returning the index is
         * sufficent to get at the data. If we were using a more complex data
         * structure, we would return whatever object represents one row in the
         * list.
         *
         * @see android.widget.ListAdapter#getItem(int)
         */
        public Object getItem(int position) {
            return position;
        }

        /**
         * Use the array index as a unique id.
         *
         * @see android.widget.ListAdapter#getItemId(int)
         */
        public long getItemId(int position) {
            return position;
        }

        /**
         * Make a view to hold each row.
         *
         * @see android.widget.ListAdapter#getView(int, android.view.View,
         *      android.view.ViewGroup)
         */
        public View getView(int position, View convertView, ViewGroup parent) {
            // A ViewHolder keeps references to children views to avoid unneccessary calls
            // to findViewById() on each row.
            ViewHolder holder;

            // When convertView is not null, we can reuse it directly, there is no need
            // to reinflate it. We only inflate a new View when the convertView supplied
            // by ListView is null.
            if (convertView == null) {
                convertView = mInflater.inflate(R.layout.rowlayout, null);

                // Creates a ViewHolder and store references to the two children views
                // we want to bind data to.
                holder = new ViewHolder();
                holder.text = (TextView) convertView.findViewById(R.id.text);
                convertView.setTag(holder);

            } else {
                // Get the ViewHolder back to get fast access to the TextView
                // and the ImageView.
                holder = (ViewHolder) convertView.getTag();
            }

            // Bind the data efficiently with the holder.
            holder.text.setText(DATA[position]);
            return convertView;
        }

        static class ViewHolder {
            TextView text;
        }
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ListView lv = (ListView) findViewById(R.id.list);
        lv.setFocusable(true);
        lv.setFastScrollEnabled(true);
        lv.setAdapter(new EfficientAdapter(this));
        lv.setOnItemClickListener(new OnItemClickListener()
        {
            @Override public void onItemClick(AdapterView<?> arg0, View arg1,int position, long arg3)
            { 
                Toast.makeText(getApplicationContext(), "Hello : " + position, Toast.LENGTH_SHORT).show();
            }
        });

    }

    private static final String[] DATA = {"Üô¢ ð£î¢î¤ý£ - «î£ø¢Áõ£ò¢"};// Lot of strings
} 
Geobits
  • 22,218
  • 6
  • 59
  • 103
xtreak
  • 1,376
  • 18
  • 42
  • In the future, remember you don't need to edit `[SOLVED]` into the title. Just marking an answer as "accepted" will change the look of the question to "solved". – Geobits Oct 21 '13 at 17:44

1 Answers1

0

Your EfficientAdapter class is static. This means no instance of the activity is available, and so you can't call its methods like getAssets() directly. Make EfficientAdapter non-static to get the enclosing class' methods.

...
private class EfficientAdapter extends BaseAdapter {
...

EDIT: As Raghunandan pointed out this is bad practice. Here's better code. We don't even need a reference to the activity as we only use it for a Context for the assets.

public class MainActivity extends Activity {

    private static class EfficientAdapter extends BaseAdapter {

        Typeface tfTab; // We can't initialize the font yet as we have no Context

        private LayoutInflater mInflater;

        public EfficientAdapter(Context context) {
            // Cache the LayoutInflate to avoid asking for a new one each time.
            mInflater = LayoutInflater.from(context);

            // Now get the font from the assets as we have a Context to do it with
            tfTab = Typeface.createFromAsset(context.getAssets(),"fonts/tabkovai.ttf");

            // Icons bound to the rows.
        }

        /**
         * The number of items in the list is determined by the number of speeches
         * in our array.
         *
         * @see android.widget.ListAdapter#getCount()
         */
        public int getCount() {
            return DATA.length;
        }

        /**
         * Since the data comes from an array, just returning the index is
         * sufficent to get at the data. If we were using a more complex data
         * structure, we would return whatever object represents one row in the
         * list.
         *
         * @see android.widget.ListAdapter#getItem(int)
         */
        public Object getItem(int position) {
            return position;
        }

        /**
         * Use the array index as a unique id.
         *
         * @see android.widget.ListAdapter#getItemId(int)
         */
        public long getItemId(int position) {
            return position;
        }

        /**
         * Make a view to hold each row.
         *
         * @see android.widget.ListAdapter#getView(int, android.view.View,
         *      android.view.ViewGroup)
         */
        public View getView(int position, View convertView, ViewGroup parent) {
            // A ViewHolder keeps references to children views to avoid unneccessary calls
            // to findViewById() on each row.
            ViewHolder holder;

            // When convertView is not null, we can reuse it directly, there is no need
            // to reinflate it. We only inflate a new View when the convertView supplied
            // by ListView is null.
            if (convertView == null) {
                convertView = mInflater.inflate(R.layout.rowlayout, null);

                // Creates a ViewHolder and store references to the two children views
                // we want to bind data to.
                holder = new ViewHolder();
                holder.text = (TextView) convertView.findViewById(R.id.text);
                convertView.setTag(holder);

            } else {
                // Get the ViewHolder back to get fast access to the TextView
                // and the ImageView.
                holder = (ViewHolder) convertView.getTag();
            }

            // Bind the data efficiently with the holder.
            holder.text.setText(DATA[position]);
            return convertView;
        }

        static class ViewHolder {
            TextView text;
        }
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ListView lv = (ListView) findViewById(R.id.list);
        lv.setFocusable(true);
        lv.setFastScrollEnabled(true);
        lv.setAdapter(new EfficientAdapter(this));
        lv.setOnItemClickListener(new OnItemClickListener()
        {
            @Override public void onItemClick(AdapterView<?> arg0, View arg1,int position, long arg3)
            { 
                Toast.makeText(getApplicationContext(), "Hello : " + position, Toast.LENGTH_SHORT).show();
            }
        });

    }

    private static final String[] DATA = {"Üô¢ ð£î¢î¤ý£ - «î£ø¢Áõ£ò¢"};// Lot of strings
} 
PurkkaKoodari
  • 6,703
  • 6
  • 37
  • 58
  • 1
    http://android-developers.blogspot.in/2009/01/avoiding-memory-leaks.html. Avoid non-static inner classes in an activity if you don't control their life cycle, use a static inner class and make a weak reference to the activity inside. The solution to this issue is to use a static inner class with a WeakReference to the outer class, as done in ViewRoot and its W inner class for instance. workaround use a weak reference to the activity context http://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html – Raghunandan Oct 21 '13 at 17:25
  • @user2610955 but in your case making adapter class non static is fine. http://stackoverflow.com/questions/7924834/should-adapters-in-android-be-static-inner-classes-or-non-static-inner-classes. Adapters are usually tied to the lifecycle of their Context (an Activity) so it's fine – Raghunandan Oct 21 '13 at 17:32
  • @Raghunandan Well, I just implemented a simple solution in my answer. No reference is needed as the activity is only used when getting the font on initialization. – PurkkaKoodari Oct 21 '13 at 17:36
  • @Pietu1998 you do have reference to the activity which is the context is passed as a param to the constructor of the adapter and you have used the same. check the previous comment and link posted there. Its not harmful to have the adapter as non static inner class as it is tied to the activity – Raghunandan Oct 21 '13 at 17:38